# Apache Pinot MCP Server (oci · ghcr.io/startreedata/mcp-pinot:4.0.0)

Query and manage Apache Pinot through MCP with typed tools and preview-first safety.

- Trust score: 40/100 (low)
- Change this week: +29
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- oci · `ghcr.io/startreedata/mcp-pinot:4.0.0`: 40/100 (this document), [markdown](https://verifymcp.io/servers/startreedata-mcp-pinot/ghcr-io-startreedata-mcp-pinot-4-0-0.md), [page](https://verifymcp.io/servers/startreedata-mcp-pinot/ghcr-io-startreedata-mcp-pinot-4-0-0)
- pypi · `mcp-pinot-server`: 10/100, [markdown](https://verifymcp.io/servers/startreedata-mcp-pinot/mcp-pinot-server.md), [page](https://verifymcp.io/servers/startreedata-mcp-pinot/mcp-pinot-server)

## Channel facts

- Registry: `oci`
- Package: `ghcr.io/startreedata/mcp-pinot:4.0.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 0/100
  - Malware scan not yet available for this package.
  - CVE data not yet available for this package.
  - Install-script risk not yet assessed.
  - Dependency-health data not yet available.
- **Provenance & Transparency**: 45/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 6 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 78/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 2807 tokens (~187/item across 15 items; 14 tools + 1 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

**Unverified: 2 categories.** Categories scored 0 because we could not verify them: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### Claude

```bash
claude mcp add startreedata-mcp-pinot -- docker run --rm -i ghcr.io/startreedata/mcp-pinot:4.0.0
```

### Codex

```bash
codex mcp add startreedata-mcp-pinot -- docker run --rm -i ghcr.io/startreedata/mcp-pinot:4.0.0
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "startreedata-mcp-pinot": {
      "type": "local",
      "command": [
        "docker",
        "run",
        "--rm",
        "-i",
        "ghcr.io/startreedata/mcp-pinot:4.0.0"
      ],
      "enabled": true
    }
  }
}
```

### Hermes

```yaml
mcp_servers:
  startreedata-mcp-pinot:
    command: "docker"
    args: ["run", "--rm", "-i", "ghcr.io/startreedata/mcp-pinot:4.0.0"]
```

### Other

```json
{
  "mcpServers": {
    "startreedata-mcp-pinot": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "ghcr.io/startreedata/mcp-pinot:4.0.0"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-07-31 (score 40, −5)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-28 (score 45, +34)

- [functional improvement] Schema quality: unverified → 100
- [functional improvement] Tool coverage: unverified → 100
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 100
- [functional] First check of Schema quality: excellent
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 100

### 2026-07-27 (score 11)

First indexed and scored.

## MCP tools (14)

### `test_connection` (~93 tokens)

Test connection

Probe Pinot connectivity and return diagnostics.

Runs three checks — broker connection, a trivial ``SELECT 1`` query, and a
controller table listing — and reports which succeeded plus a small sample of
tables. Useful for troubleshooting configuration before using other tools.

Failure recovery:
    Individual check failures are returned in ``error``. Verify the broker and
    controller URLs, credentials, and network, then retry only failed checks.

Output parameters:

- `connection_test` (boolean): True when a broker connection was established.
- `error`: Error message when a check failed, else null.
- `query_test` (boolean): True when a trivial 'SELECT 1' succeeded.
- `sample_tables` (array): Up to five example table names.
- `tables_count`: Number of tables discovered, when available.
- `tables_test` (boolean): True when the controller table listing succeeded.

### `reload_table_filters` (~252 tokens)

Reload table filters

Preview or apply the configured table-filter YAML without restarting.

Reads only the path configured by ``PINOT_TABLE_FILTER_FILE``. The YAML must be
an object whose ``included_tables`` value is a non-empty list of glob strings.
Allowing every table requires an explicit ``allow_all: true``. The default
\``dry_run=true`` validates and reports the before/after patterns and returns a
short-lived confirmation token. Pass ``dry_run=false`` with that token to apply
the exact candidate atomically. Editing the file after preview invalidates the
confirmation and requires another preview.

Returns:
    Preview/application status, whether it was applied, old/new patterns, and
    a confirmation token on previews.

Failure recovery:
    A missing setting/file or malformed YAML is non-retryable until corrected;
    fix ``PINOT_TABLE_FILTER_FILE`` or its ``included_tables`` list, then retry.

Input parameters:

- `confirmation_token`: One-time token returned by a dry-run preview of the exact current filter-file contents. Required when dry_run is false.
- `dry_run` (boolean): When true (default), validate and preview the candidate allow-list without changing server state. Pass false explicitly to apply it.

Output parameters:

- `applied` (boolean): True only when the in-memory allow-list was changed.
- `confirmation_token`: Short-lived token bound to this exact filter preview; required to apply.
- `message` (string): Human-readable summary of the reload.
- `new_filter_count` (integer): Number of allowed tables after the reload.
- `new_filters`: Validated candidate patterns; null means all tables.
- `previous_filter_count` (integer): Number of allowed tables before the reload.
- `previous_filters`: Allow-list patterns active before the operation; null means all.
- `status` (string): Whether the candidate filters were previewed, applied, or failed.

### `read_query` (~242 tokens)

Read query

Run a read-only SQL query against Pinot and return a page of rows.

Only a single SELECT (or WITH ... SELECT) statement is allowed; the query is
rejected if it contains multiple statements or write/DDL/admin keywords.
Results are paginated to keep responses small — use ``limit``/``offset`` and
the ``has_more`` flag to page through large result sets.

Returns ``QueryResult`` with the page of rows, the column list, fetched row
count, and a ``has_more`` flag.

Failure recovery:
    SQL/allow-list/permission failures require correcting the query or access;
    do not retry unchanged. A timeout or connection failure can be retried after
    ``test_connection`` succeeds. Zero rows is a successful result.

Input parameters:

- `limit` (integer): Maximum rows to return in this page.
- `offset` (integer): Zero-based row offset for pagination.
- `query` (string, required): A single read-only statement in Pinot SQL: 'SELECT ...' or 'WITH ... SELECT ...'. Stacked statements and DML/DDL/admin keywords (INSERT, UPDATE, DELETE, DROP, SET, ...) are rejected.

Output parameters:

- `columns` (array): Column names, in result order.
- `has_more` (boolean): True when more fetched rows remain beyond this page (not necessarily more rows in the underlying table).
- `offset` (integer): Zero-based index of the first returned row.
- `row_count` (integer): Number of rows returned in this page.
- `rows` (array): Rows in this page; each row maps column name to value.
- `total_rows` (integer): Rows the query returned before this page was sliced. Pinot may have already applied its own LIMIT, so this is rows fetched, not the table total.
- `truncated` (boolean): True when the server-enforced fetch bound truncated the result.

### `list_tables` (~113 tokens)

List tables

List Pinot tables visible to this server (subject to table filters).

Returns a paginated list of table names. Use ``limit``/``offset`` and the
\``has_more`` flag to page through clusters with many tables.

Failure recovery:
    An empty page is success. For authentication/connectivity errors, verify the
    controller with ``test_connection`` and retry after access is restored.

Input parameters:

- `limit` (integer): Maximum tables to return in this page.
- `offset` (integer): Zero-based offset for pagination.

Output parameters:

- `has_more` (boolean): True when more tables remain beyond this page.
- `offset` (integer): Zero-based index of the first returned table.
- `table_count` (integer): Number of tables in this page.
- `tables` (array): Table names in this page.
- `total_tables` (integer): Total tables visible to this server.

### `get_table_size` (~206 tokens)

Table size details

Get a table's storage footprint: reported vs. estimated size in bytes.

Use this for capacity/size questions about a whole table. It does NOT list
segments (use ``list_segments``) or return row counts/time boundaries (use
\``list_segment_metadata``). ``reportedSizeInBytes`` is what the servers
currently hosting the segments report; ``estimatedSizeInBytes`` assumes every
replica is present.

Failure recovery:
    For not-found errors, copy an exact name from ``list_tables``. Fix permission
    errors before retrying; retry transient controller failures after a health
    check.

Input parameters:

- `table_name` (string, required): Exact Pinot table name, without _OFFLINE/_REALTIME. Use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier; whitespace is invalid and '__' is reserved by Pinot…

Output parameters:

- `estimatedSizeInBytes`: Estimated size assuming every replica is present, in bytes.
- `reportedSizeInBytes`: Size reported by the servers currently hosting the table's segments, in bytes.
- `tableName`: The table name.

### `list_segments` (~263 tokens)

List segments

List a table's segment names, grouped by table type (OFFLINE/REALTIME).

Use this to discover segment names — e.g. to get a ``segment_name`` for
\``get_segment_index_metadata``, or to see how a table is partitioned. For
per-segment row counts / sizes / time boundaries call
\``list_segment_metadata`` instead; for total storage call ``get_table_size``.

Segment names are paginated (a busy table can have thousands) — use
\``limit``/``offset`` and the ``has_more`` flag to page through them.

Failure recovery:
    An empty page is success. For not-found errors, use an exact name from
    ``list_tables``; correct access errors, or retry transient controller errors.

Input parameters:

- `limit` (integer): Maximum segment names to return in this page.
- `offset` (integer): Zero-based offset for pagination.
- `table_name` (string, required): Exact Pinot table name, without _OFFLINE/_REALTIME. Use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier; whitespace is invalid and '__' is reserved by Pinot…

Output parameters:

- `OFFLINE`: OFFLINE segment names in this page, when present.
- `REALTIME`: REALTIME segment names in this page, when present.
- `has_more`: True when more segments remain beyond this page.
- `offset`: Zero-based offset of the first segment in this page.
- `returned_segments`: Number of segment names returned in this page.
- `total_segments`: Total segments across all types before paging.

### `get_segment_index_metadata` (~262 tokens)

Index/column details

Get per-column index metadata for ONE segment (which indexes each column has).

Use this to inspect how a specific segment is indexed (inverted, sorted, range,
etc.). Requires a ``segment_name`` from ``list_segments``. For a segment's row
count/size/time boundaries use ``list_segment_metadata``; for the table's
declared index *configuration* (not per-segment state) use ``get_table_config``.

Failure recovery:
    A missing segment is non-retryable with the same value; refresh
    ``list_segments`` and use an exact returned name. Retry transient controller
    errors after ``test_connection`` succeeds.

Input parameters:

- `segment_name` (string, required): Exact, case-sensitive opaque segment name returned by list_segments; do not construct, trim, or add a table-type suffix. Pinot defines the length and characters, so this client only requires non-empt…
- `table_name` (string, required): Exact Pinot table name, without _OFFLINE/_REALTIME. Use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier; whitespace is invalid and '__' is reserved by Pinot…

Output parameters:

- `columns`: Per-column metadata for the segment, when present.
- `indexes`: Per-column index metadata (index types present on each column).

### `list_segment_metadata` (~214 tokens)

Segment metadata

Get a deterministic page of segment rows, sizes, and time boundaries.

Pinot can return thousands of segment objects. Results are sorted by exact
segment name, then sliced with ``limit``/``offset``; follow ``has_more`` until
false. Use ``list_segments`` when only names are needed.

Failure recovery:
    An empty page is success. For not-found errors, use ``list_tables``;
    correct permissions before retrying, and retry transient server failures
    only after ``test_connection`` succeeds.

Input parameters:

- `limit` (integer): Maximum segment metadata objects in this page.
- `offset` (integer): Zero-based segment offset for pagination.
- `table_name` (string, required): Exact Pinot table name, without _OFFLINE/_REALTIME. Use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier; whitespace is invalid and '__' is reserved by Pinot…

Output parameters:

- `has_more` (boolean): True when more fetched segment metadata remains after this page.
- `offset` (integer): Zero-based index of the first returned segment.
- `returned_segments` (integer): Number of segment metadata objects in this page.
- `segments` (object): Metadata keyed by exact segment name. Values can include row counts, sizes, time boundaries, and column/index details returned by Pinot.
- `total_segments` (integer): Total segment metadata objects fetched before paging.

### `create_schema` (~154 tokens)

Create schema

Preview or create a new Pinot schema without replacing an existing schema.

The default preview performs strict local structural validation and returns a
short-lived confirmation token bound to the exact normalized schema. Pass that
token with ``dry_run=false`` to apply. Replacement belongs in ``update_schema``.

Failure recovery:
    Invalid JSON, missing ``schemaName``, and controller validation failures are
    non-retryable until corrected. Permission failures require access changes;
    retry transient controller failures only after connectivity is restored.

Input parameters:

- `confirmation_token`: Token returned by a preview of this exact payload.
- `dry_run` (boolean): Preview safely (default); false requests application.
- `schema` (object, required): Structured Pinot schema. schemaName is required.

Output parameters:

- `applied` (boolean): True only when Pinot accepted a mutating request.
- `confirmation_token`: Short-lived token bound to this exact preview; required to apply it.
- `dry_run` (boolean): True when no mutation was sent to Pinot.
- `message`: Human-readable detail, when provided.
- `operation` (string): Stable operation identifier.
- `resource_name` (string): Exact schema or table name targeted.
- `resource_type` (string): Kind of Pinot resource targeted by the operation.
- `response_summary`: Sanitized summary returned by the Pinot controller.
- `status` (string): Whether the operation was previewed, applied, or rejected.
- `verification_tool` (string): Read tool to call after a successful mutation.
- `warnings` (array): Safety or validation warnings.

### `update_schema` (~202 tokens)

Update schema

Update an existing Pinot schema.

Accepts a typed schema object. This can change column definitions on a live
table; the default ``dry_run=true`` previews without applying and returns a
confirmation token bound to the exact replacement.

Failure recovery:
    Invalid JSON/name or schema validation failures require a corrected payload;
    do not retry unchanged. Fix permission errors first, and retry transient
    controller failures only after connectivity is restored.

Input parameters:

- `confirmation_token`: Token returned by a preview of this exact payload.
- `dry_run` (boolean): Preview safely (default); false requests application.
- `reload` (boolean): Reload affected segments after updating.
- `schema` (object, required): Complete replacement schema; schemaName must match.
- `schema_name` (string, required): Exact Pinot schema name. It normally matches the table name without an _OFFLINE/_REALTIME suffix; use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier.

Output parameters:

- `applied` (boolean): True only when Pinot accepted a mutating request.
- `confirmation_token`: Short-lived token bound to this exact preview; required to apply it.
- `dry_run` (boolean): True when no mutation was sent to Pinot.
- `message`: Human-readable detail, when provided.
- `operation` (string): Stable operation identifier.
- `resource_name` (string): Exact schema or table name targeted.
- `resource_type` (string): Kind of Pinot resource targeted by the operation.
- `response_summary`: Sanitized summary returned by the Pinot controller.
- `status` (string): Whether the operation was previewed, applied, or rejected.
- `verification_tool` (string): Read tool to call after a successful mutation.
- `warnings` (array): Safety or validation warnings.

### `get_schema` (~151 tokens)

Get schema

Get one Pinot schema, including dimensions, metrics, time, and primary keys.

This is a single-object lookup, not a list, so pagination does not apply. The
output preserves additional fields introduced by the connected Pinot version.

Failure recovery:
    For not-found errors, pass the table's exact schema name (normally the table
    name without a type suffix). Fix permissions before retrying; retry transient
    controller failures after ``test_connection`` succeeds.

Input parameters:

- `schema_name` (string, required): Exact Pinot schema name. It normally matches the table name without an _OFFLINE/_REALTIME suffix; use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier.

Output parameters:

- `dateTimeFieldSpecs`: Date/time column specifications.
- `dimensionFieldSpecs`: Dimension (attribute) column specifications.
- `metricFieldSpecs`: Metric (aggregatable measure) column specifications.
- `primaryKeyColumns`: Primary key columns, for upsert-enabled tables.
- `schemaName`: The schema name.

### `create_table_config` (~136 tokens)

Create table config

Create a new Pinot table configuration.

Accepts a typed table-config object. The default ``dry_run=true`` asks Pinot
to validate the payload and returns a confirmation token without applying.

Failure recovery:
    Invalid JSON, missing ``tableName``, and controller validation failures need
    a corrected payload; do not retry unchanged. Fix access failures first, and
    retry transient controller errors after connectivity is restored.

Input parameters:

- `confirmation_token`: Token returned by a preview of this exact payload.
- `dry_run` (boolean): Preview safely (default); false requests application.
- `table_config` (object, required): Complete structured Pinot table configuration.

Output parameters:

- `applied` (boolean): True only when Pinot accepted a mutating request.
- `confirmation_token`: Short-lived token bound to this exact preview; required to apply it.
- `dry_run` (boolean): True when no mutation was sent to Pinot.
- `message`: Human-readable detail, when provided.
- `operation` (string): Stable operation identifier.
- `resource_name` (string): Exact schema or table name targeted.
- `resource_type` (string): Kind of Pinot resource targeted by the operation.
- `response_summary`: Sanitized summary returned by the Pinot controller.
- `status` (string): Whether the operation was previewed, applied, or rejected.
- `verification_tool` (string): Read tool to call after a successful mutation.
- `warnings` (array): Safety or validation warnings.

### `update_table_config` (~215 tokens)

Update table config

Update an existing Pinot table configuration.

Accepts a typed replacement table-config object. This changes a live table;
the default ``dry_run=true`` asks Pinot to validate it, compares it with the
current configuration, and returns a token without applying.

Failure recovery:
    Invalid JSON/name or controller validation failures require a corrected
    payload; do not retry unchanged. Fix access errors first, and retry transient
    controller failures only after connectivity is restored.

Input parameters:

- `confirmation_token`: Token returned by a preview of this exact payload.
- `dry_run` (boolean): Preview safely (default); false requests application.
- `table_config` (object, required): Complete replacement table configuration.
- `table_name` (string, required): Exact Pinot table name, without _OFFLINE/_REALTIME. Use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier; whitespace is invalid and '__' is reserved by Pinot…

Output parameters:

- `applied` (boolean): True only when Pinot accepted a mutating request.
- `confirmation_token`: Short-lived token bound to this exact preview; required to apply it.
- `dry_run` (boolean): True when no mutation was sent to Pinot.
- `message`: Human-readable detail, when provided.
- `operation` (string): Stable operation identifier.
- `resource_name` (string): Exact schema or table name targeted.
- `resource_type` (string): Kind of Pinot resource targeted by the operation.
- `response_summary`: Sanitized summary returned by the Pinot controller.
- `status` (string): Whether the operation was previewed, applied, or rejected.
- `verification_tool` (string): Read tool to call after a successful mutation.
- `warnings` (array): Safety or validation warnings.

### `get_table_config` (~193 tokens)

Get table config

Get one table's indexing, retention, tenant, and ingestion configuration.

This is a single-object lookup, not a list, so pagination does not apply. Set
\``table_type`` only when one side of a hybrid table is needed.

Failure recovery:
    For not-found errors, use an exact name from ``list_tables`` and a valid
    table type. Fix permissions before retrying; retry transient controller
    failures after ``test_connection`` succeeds.

Input parameters:

- `table_name` (string, required): Exact Pinot table name, without _OFFLINE/_REALTIME. Use letters, digits, hyphens, or underscores, optionally prefixed by one 'database.' qualifier; whitespace is invalid and '__' is reserved by Pinot…
- `table_type`: Restrict to one table type; omit to return both when present.

Output parameters:

- `offline`: OFFLINE configuration, when present/requested.
- `realtime`: REALTIME configuration, when present/requested.
- `table_name` (string): Base table name requested by the caller.

## Diagnostics

Captured diagnostic sections: Provenance. The full working is on the page: https://verifymcp.io/servers/startreedata-mcp-pinot/ghcr-io-startreedata-mcp-pinot-4-0-0#diagnostics

## Score history

- 2026-08-03: 40
- 2026-08-02: 40
- 2026-08-01: 40
- 2026-07-31: 40
- 2026-07-30: 45
- 2026-07-29: 45
- 2026-07-28: 45
- 2026-07-27: 11

## Links

- Repository: https://github.com/startreedata/mcp-pinot
- Website: https://startreedata.github.io/mcp-pinot/
- Changelog RSS feed: https://verifymcp.io/servers/startreedata-mcp-pinot/ghcr-io-startreedata-mcp-pinot-4-0-0/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/startreedata-mcp-pinot/ghcr-io-startreedata-mcp-pinot-4-0-0/changelog.json
- HTML version of this page: https://verifymcp.io/servers/startreedata-mcp-pinot/ghcr-io-startreedata-mcp-pinot-4-0-0
