Agentic Data Plane
beta

Metabase Managed MCP Server

The Metabase managed MCP server lets agents read and query a Metabase analytics instance. The tool surface is a hybrid of Metabase’s semantic-layer primitives (tables, metrics, fields, dimensions) and SQL-first escape hatches (native queries and saved questions), wrapping the Metabase REST API with a long-lived API key.

After reading this page, you will be able to:

  • Configure the Metabase managed MCP server with a v0.49+ API key bound to the right Metabase group

  • Identify when to use semantic-layer tools (search, get_metric, query) versus the native-SQL escape hatches (run_native_query, run_card)

  • Run a metric-first analysis against your Metabase instance from the Inspector or an agent

What this MCP server does

Metabase is a self-service analytics platform that exposes data through a semantic layer (tables, metrics, fields) plus a SQL editor for ad-hoc native queries. This MCP wraps the Metabase REST API so an LLM can:

  • Search the semantic layer for relevant tables, metrics, saved questions, and dashboards.

  • Retrieve a table or metric’s structure (fields, dimensions, related tables).

  • Run a structured query against a metric or table with filters, group-by, and limits.

  • Run a saved question (card) or a hand-written native SQL query.

The agent’s preferred path is metric-first: discover what already exists, fetch the metric’s definition, and call query against it so the aggregation logic stays human-vetted. The SQL escape hatches (run_native_query, run_card) are available when the semantic layer cannot express the question, but a metric is strictly safer because it forecloses common analytics mistakes (averaging averages, double-counting joined rows).

It is not a Metabase admin tool. Creating dashboards, editing cards, configuring data sources, and managing users live in the Metabase admin UI.

Authentication model

Metabase API keys (v0.49+) inherit the permissions of the group they’re bound to. The MCP sends the resolved key in the X-API-Key header on every upstream request.

The Metabase MCP uses one API key per MCP instance, applied to every tool call, with no per-user delegation. To give different agents different access, mount multiple MCP instances bound to different Metabase groups.

Auth is implemented as oneof auth { StaticKeyAuth api_key } (single variant today, future-proof for adding session or OAuth modes without a wire-format break).

Prerequisites

Before you create the server, make sure you have:

  • A Metabase instance on v0.49 or later (API keys are not available on older versions).

  • Admin access to the Metabase instance to mint an API key.

  • A Metabase group with the right permissions for the data you want the agent to access (typically Native query editing on the relevant databases plus View on the relevant collections).

  • One Redpanda ADP secret-store entry for the API key. Secret references must be UPPER_SNAKE_CASE, for example METABASE_API_KEY.

Get a Metabase API key

Mint the key in the Metabase admin UI:

  1. Sign in to your Metabase instance as an admin.

  2. Open Settings > Authentication > API keys.

  3. Click Create API key.

  4. Give the key a descriptive name, for example redpanda-mcp.

  5. Bind the key to a group whose permissions match the access you want the agent to have. For an analytics agent, an Analytics group with Native query editing on the relevant databases and View on the relevant collections is typical.

  6. Copy the key. Metabase shows it only once.

  7. Save the key in your ADP secret store under a name like METABASE_API_KEY.

Permission errors surface from the upstream Metabase API as metabase API error (status 4xx). Fix by adjusting the bound group’s permissions in Metabase, not by re-issuing a different key.

Configure

Create a new Metabase MCP server in ADP:

  1. Open MCP Servers > Create Server.

  2. Pick Metabase from the marketplace picker.

  3. Fill in identity fields (name, description).

  4. In the Metabase configuration form:

    Field Notes

    Base URL

    Your Metabase instance URL, for example https://metabase.mycompany.com. No trailing slash.

    API key ref

    Secret-store reference for the Metabase API key (UPPER_SNAKE_CASE). Example: METABASE_API_KEY.

  5. Click Create.

Configure from the CLI

Run rpk ai mcp create with the Metabase managed-config payload:

rpk ai mcp create --name metabase --managed-config '{
  "@type": "type.googleapis.com/redpanda.mcps.metabase.v1.MetabaseMCPConfig",
  "base_url": "https://metabase.mycompany.com",
  "api_key": {
    "key_secret_ref": "METABASE_API_KEY"
  }
}'

The api_key field wraps the shared StaticKeyAuth; key_secret_ref is the bare secret-store key name (UPPER_SNAKE_CASE).

Tools

The Metabase MCP exposes tools across a semantic-layer surface and a SQL-first surface. The agent’s preferred path is the semantic-layer surface; the SQL-first surface is an escape hatch.

Semantic-layer tools

These six tools cover discovery, schema lookup, and structured queries against pre-vetted metrics.

Tool Description

search

Run Metabase’s universal search across tables, metrics, saved questions, dashboards, and collections. Use this first to discover existing analyses before constructing a fresh query.

get_table

Retrieve a table’s fields, related tables, and metrics defined on it. The field list is what the agent uses to write correct filters and group-bys.

get_table_field_values

Sample values plus a small statistical summary for one field on a table. Useful before writing a filter; the agent can check actual cardinality and value shape rather than guessing.

get_metric

Retrieve a metric definition with its queryable dimensions. Metrics are pre-vetted aggregations; calling query against a metric is strictly preferred over hand-rolled SQL when the measure already exists.

get_metric_field_values

Sample values for a dimension of a metric. Same role as get_table_field_values, scoped to a metric’s queryable dimensions.

query

One-shot structured query against a table OR a metric, with optional group_by_field_ids, filters (MBQL JSON snippets), and limit. Returns typed columns and rows.

SQL-first escape hatches

These five tools let an agent enumerate databases, run native SQL, and execute saved questions when the semantic layer cannot express the question.

Tool Description

list_databases

Enumerate the databases Metabase is connected to. The id returned here is what get_table, list_tables, run_native_query, and query take as the database reference.

list_tables

List tables in a database, optionally filtered by schema. Use this when browsing schema by name; search is the right tool when looking by keyword.

run_native_query

Execute a native (raw SQL) query against a database. Escape hatch for cases the semantic layer cannot express; prefer query against a metric or table when possible.

get_card

Retrieve a saved question’s definition (name, description, database, display type, native SQL when applicable). Use this to inspect an analysis a human curated.

run_card

Execute a saved question and return its result rows. The card carries its own database, query, and parameters; this RPC just runs it as-is.

Examples

The examples in this section assume https://aigw.<cluster-id>.clusters.rdpa.co/mcp/v1/metabase is your MCP server URL and that you’ve already authenticated to the gateway.

Discover what exists, then query a metric

Search for revenue-related objects:

curl -sS -X POST https://aigw.<cluster-id>.clusters.rdpa.co/mcp/v1/metabase \
  -H 'Authorization: Bearer <oidc-access-token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0", "id": 1,
    "method": "tools/call",
    "params": {
      "name": "search",
      "arguments": {
        "q": "revenue",
        "models": ["metric", "card"],
        "page_size": 10
      }
    }
  }' | jq

If search returns a metric like { "model": "metric", "id": 200, "name": "Monthly Revenue", …​ }, fetch its dimensions:

curl -sS -X POST https://aigw.<cluster-id>.clusters.rdpa.co/mcp/v1/metabase \
  -H 'Authorization: Bearer <oidc-access-token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0", "id": 2,
    "method": "tools/call",
    "params": {
      "name": "get_metric",
      "arguments": { "metric_id": 200 }
    }
  }' | jq

Then run the metric grouped by one of its dimensions (the field_id values come from the previous response’s dimensions[]):

curl -sS -X POST https://aigw.<cluster-id>.clusters.rdpa.co/mcp/v1/metabase \
  -H 'Authorization: Bearer <oidc-access-token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0", "id": 3,
    "method": "tools/call",
    "params": {
      "name": "query",
      "arguments": {
        "database_id": 5,
        "metric_id": 200,
        "group_by_field_ids": [12],
        "limit": 1000
      }
    }
  }' | jq

Native SQL escape hatch

When a question genuinely needs raw SQL (for example, multi-CTE windowed analysis Metabase’s MBQL doesn’t express), drop down to run_native_query:

curl -sS -X POST https://aigw.<cluster-id>.clusters.rdpa.co/mcp/v1/metabase \
  -H 'Authorization: Bearer <oidc-access-token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0", "id": 4,
    "method": "tools/call",
    "params": {
      "name": "run_native_query",
      "arguments": {
        "database_id": 5,
        "query": "SELECT date_trunc(\"month\", created_at) AS m, count(*) FROM orders GROUP BY 1 ORDER BY 1 DESC LIMIT 12"
      }
    }
  }' | jq

The bound group’s permissions on the target database determine whether the call succeeds. A key bound to a group without Native query editing on the database returns a 403.

Notes and limits

Five behaviors are worth knowing before you point an agent at the server:

  • Permissions follow the API key’s group. The MCP doesn’t bypass Metabase’s permission system; permission errors surface as metabase API error (status 4xx). Fix the group, not the MCP.

  • Metric vs. saved question. In Metabase v0.50+ both metrics and saved questions are stored as cards (/api/card/:id). get_metric validates that the card’s type == "metric" and surfaces queryable dimensions; get_card works on any card. run_card runs whatever is saved.

  • Sample database. The list_databases tool exposes Metabase’s bundled Sample Database with an is_sample flag set. Agents should usually exclude it from real analyses.

  • Body cap. Query results are capped at 25 MiB on the gateway-side wrapper. Queries that exceed the cap return an error rather than blowing up the agent’s context. Lower the limit argument on query or run_native_query if you hit it.

  • Response curation. The MCP drops Metabase’s internal indexing metadata (search ranking signals, fingerprint blobs, embedded user objects, per-column metadata blobs) so each response is 60–85% smaller than the raw REST API would return. Agents see clean, action-relevant fields.

Troubleshooting

Common symptoms and fixes:

Symptom What to check

metabase API error (status 401)

API key is invalid or has been revoked. Mint a new key in Settings > Authentication > API keys and update the secret in the ADP secret store under the same name.

metabase API error (status 403)

The API key’s group lacks the required permission. Check the group’s database and collection permissions in Admin > Permissions.

metabase API error (status 404) on get_table or get_metric

The table_id or metric_id doesn’t exist in the bound database. Confirm the ID with search or list_tables first.

Query returns an error about exceeding the body cap

Result set exceeds 25 MiB. Lower limit on the query, or pre-aggregate by calling query against a metric.

Agent keeps calling run_native_query instead of query

Confirm the relevant metric exists and has queryable dimensions. The agent prefers metrics when search or get_table surfaces them.

Limitations

This page does not cover:

  • Metabase administration. Creating dashboards, editing cards, configuring data sources, and managing users live in the Metabase admin UI or its /api/setup endpoints.

  • Per-user delegation. The MCP uses one shared API key per instance. To give different agents different access, mount multiple MCP instances bound to different Metabase groups.

  • Metabase MBQL reference. See Metabase’s own documentation for the full MBQL filter shape; the MCP passes filters arguments through verbatim.