Skip to main content
Glama
metabase

Metabase

Official
by metabase

Metabase MCP Server

Metabase includes a built-in Model Context Protocol (MCP) server that lets AI clients connect directly to a Metabase instance. It uses the Streamable HTTP transport and builds on Metabase's Agent API to expose tools for searching, navigating, querying, visualizing, and creating/updating content - all scoped to the connecting user's permissions.

Endpoint

The MCP server is available at:

https://{your-metabase.example.com}/api/metabase-mcp

The legacy /api/mcp path still works as an alias for existing clients, but /api/metabase-mcp is the canonical URL to advertise.

Related MCP server: Metabase MCP Server

Connecting a client

Point any MCP-compatible client at the /api/metabase-mcp endpoint. For example, with Claude Code:

claude mcp add metabase https://{your-metabase.example.com}/api/metabase-mcp --transport streamable-http

For Claude Desktop, create a custom connector using the same URL.

For Cursor, open Settings > MCP and add a new server with the type set to streamable-http and the URL:

https://{your-metabase.example.com}/api/metabase-mcp

Authentication

MCP clients authenticate via OAuth 2.0. Metabase runs its own embedded OAuth server - no external provider is needed.

The flow for a first-time connection:

  1. The client discovers Metabase's OAuth endpoints.

  2. The client registers itself with Metabase.

  3. The user is redirected to Metabase to log in and approve the connection.

  4. The client receives an access token scoped to the user's Metabase permissions.

Browser-based sessions (cookie auth) are also supported and receive unrestricted scopes.

Scopes

Access tokens are scoped to limit what tools a client can use:

Scope

Tools it grants

agent:content:read

browse_collection, browse_data, get_content, get_parameter_values, glossary, learn, search

agent:content:write

bookmark_content, collection_write, dashboard_write, document_write, duplicate_content, measure_write, metric_write, question_write, segment_write, transform_write

agent:delivery:write

alert_write, subscription_write

agent:query:run

execute_query, refresh_ui_credential, render_drill_through, run_saved_question, visualize_query

agent:sql:run

execute_sql

agent:resource:read

No tools: it gates reading the catalog://metabase/fields data resource (see Resources).

Wildcard patterns (e.g. agent:*) match any scope with that prefix.

Clients start with a baseline. The protected-resource metadata's scopes_supported and the scope of the 401 challenge both list only agent:content:read agent:query:run agent:resource:read: a fresh connection can read, query, and chart. Writes (agent:content:write), raw SQL (agent:sql:run), and alerts and subscriptions (agent:delivery:write) need a step-up. The surface still accepts every scope in the table, and the authorization server metadata still advertises all of them.

agent:query:run is in the baseline so that charts never need a step-up. Claude Desktop retries a tool after a step-up over a session that doesn't declare MCP Apps support, so a stepped-up visualize_query is refused and its chart never embeds.

A tool call or data resource read the token lacks a scope for is refused with HTTP 403 and a WWW-Authenticate: Bearer error="insufficient_scope" challenge whose scope lists the v2 scopes the token already holds plus the one required, so a client can step up. Each tool also declares its scope in securitySchemes, which is draft SEP-1488, supported by ChatGPT. It is not part of MCP 2025-03-26 (the version this server reports) or the final 2026-07-28 tools spec, so other clients discover the missing scope from the 403 instead. Inside a JSON-RPC batch the refusal is an in-band -32600 error instead. UI shell reads are never challenged: see Resources.

OAuth protected resource metadata is available at:

/.well-known/oauth-protected-resource/api/metabase-mcp

On the consent screen, the baseline scopes are ticked and locked, and every other scope the client requested starts unticked. Only the scopes the user ticks are granted, and only for the token this authorization mints: an untick never touches a token the app already has. A scope left unticked is not remembered by Metabase. A later 403 can trigger another step-up in clients that support it. Other clients may require manual reauthorization. Each challenge's error_description ends with a note that the user must tick the permission on the consent screen.

Several clients replace the 403's error_description with their own text, so the initialize result's instructions explain scope failures to the model too: an auth error usually means a missing permission rather than an expired login, the model should name the failed tool or resource and the permission it requires, and the user grants it by reconnecting and ticking permissions on the consent screen. Because every optional permission starts unticked, the instructions tell the model to have the user tick every permission they want, not only the new one. The instructions are one static string, the same for every caller: there is no per-connection permission list.

Available tools

Generated from the v2 registry (deftool). The scope named here is what the registry checks before the tool runs; some handlers check a further scope once they know what the call does - agent:sql:run when a source resolves to native SQL (question_write, transform_write), and agent:query:run for the execution an alert or subscription defers (alert_write, subscription_write). Those refusals carry the same 403 insufficient_scope challenge. tools/list shows every tool whatever the token holds, and a token missing the scope may not call it.

Tool

Scope

Description

alert_write

agent:delivery:write

Create or update an alert: a notification sent on a schedule when a saved question's results meet a condition.

bookmark_content

agent:content:write

Add or remove a bookmark on content for the calling user — the same starred/favorites list the Metabase sidebar shows.

browse_collection

agent:content:read

Browse collections structurally — one uniform id over every partition: a numeric id, a 21-char entity_id, "root" (re-rooted per namespace), or "trash" (archived content, items mode only).

browse_data

agent:content:read

Browse the data hierarchy: databases → schemas → tables → fields.

collection_write

agent:content:write

Create, rename, move, archive, or restore a collection — the folders that hold questions, dashboards, models, and documents.

dashboard_write

agent:content:write

Create or update a dashboard and edit its layout with ordered ops.

document_write

agent:content:write

Create or update a document.

duplicate_content

agent:content:write

Copy a question, dashboard, or document into a collection — cheaper and safer than reading the original and re-creating it, and it preserves everything the read projections leave out.

execute_query

agent:query:run

The default way to answer a question from data: validate and execute a structured (MBQL) query, returning rows plus a query_handle.

execute_sql

agent:sql:run

Escape hatch: execute a raw SQL string against a database, returning rows plus a query_handle.

get_content

agent:content:read

Fetch content by {type, id} — the typed read for anything found via search or browse_collection.

get_parameter_values

agent:content:read

Fetch the valid values for one filter on a dashboard or saved question, so you filter with real values instead of guessing.

glossary

agent:content:read

Look up a business term as this Metabase instance defines it; the defined term names ride the tool's own description.

learn

agent:content:read

Read this server's task docs (skills) for the write dialects the schemas can't fully describe.

measure_write

agent:content:write

Create or update a measure: a named, reusable MBQL aggregation attached to one table, referenced inside another query's aggregation as ["measure", id].

metric_write

agent:content:write

Create or update a metric: a saved, reusable aggregation that lives in a collection and can be queried on its own or referenced from other queries.

question_write

agent:content:write

Create, update, or archive a saved question or model.

refresh_ui_credential

agent:query:run

Refresh the scoped credential used by a Metabase MCP App.

render_drill_through

agent:query:run

Render the drill-through visualization the user just navigated into.

run_saved_question

agent:query:run

Run a saved question (card) by numeric id or entity_id, returning rows inline.

search

agent:content:read

Find content across the Metabase instance by relevance.

segment_write

agent:content:write

Create or update a segment: a named, reusable MBQL filter attached to one table, referenced from other queries' filters.

subscription_write

agent:delivery:write

Create or update a dashboard subscription — scheduled delivery of a whole dashboard, e.g.

transform_write

agent:content:write

Create or update a transform: a saved query that Metabase runs to materialize its results into a real table in your warehouse, which questions and other transforms can then query.

visualize_query

agent:query:run

Visualize a query as an interactive chart or table, rendered inline in the conversation.

execute_query returns row_limit rows per call (default 100, max 2000) — a page size, not a bound on the result. A truncated page reports truncated: true and, when the query has a total order, a next_cursor to pass back as cursor for the next page, until a page arrives with truncated: false. A query that wants only its first N rows carries limit: N in its stage (with an order-by); the server spends that limit down across pages, so the last page comes back complete with no cursor and pagination ends by itself.

Resources

The server exposes MCP resources so clients can fetch supplementary content by URI without inflating tool descriptions.

Resource URI

Scope

Description

ui://metabase/visualize-query.html

agent:query:run (UI credential only)

The MCP Apps iframe shell visualize_query points a capable client at.

ui://metabase/render-drill-through.html

agent:query:run (UI credential only)

The shell render_drill_through points at.

catalog://metabase/fields

agent:resource:read

The dot-paths each content type accepts in fields arguments.

Every resource is listed whatever the token's scopes. A data resource, such as the fields catalog, is read only by a token holding its scope; otherwise the read gets the 403 insufficient_scope challenge described under Scopes. A UI shell is read by any token, because an MCP Apps host reads a tool's shell alongside the tool call, and if that read were refused, the host would not step up after the tool call's 403. The shells carry no data. A shell read by a token without the shell's scope never mints a UI credential. The chart data is gated by the tool call and by refresh_ui_credential (both agent:query:run), which the iframe needs before it can query anything. An unknown URI is a -32602 "Resource not found" error.

Skill packs are delivered through the learn tool rather than as resources.

Entity navigation is done with the get_content and browse_* tools rather than a URI scheme; the ui:// resources above exist only so a client that can render an iframe has something to mount.

Supported JSON-RPC methods

Method

Description

initialize

Initialize the MCP connection. Returns server capabilities and a session ID.

notifications/initialized

Client notification that initialization is complete.

tools/list

List available tools, whatever the token's scopes.

tools/call

Call a tool with arguments.

resources/list

List available resources, whatever the token's scopes.

resources/read

Read a resource by URI; a data resource needs its scope. Requires a session.

ping

Keepalive ping.

Requests can be sent individually or as a JSON-RPC batch. The server responds with JSON or SSE depending on the Accept header.

Architecture

The implementation lives in these files:

  • transport.clj - The HTTP transport. Parses JSON-RPC requests, validates authentication and session headers, enforces origin checks (DNS rebinding protection), and dispatches to the appropriate method. Supports both JSON and SSE response formats.

  • v2/api.clj - The tool surface handler. Wires the transport to the v2 tool + resource registries and defines method dispatch (tools/list, tools/call, resources/list, resources/read, ping).

  • v2/registry.clj - The v2 tool registry. Tools self-register via deftool; the registry checks scopes, validates arguments, dispatches calls, and records usage.

  • scope.clj - Scope matching logic. Supports exact matches, wildcard patterns, and the ::unrestricted sentinel for session-based auth.

Request flow

MCP client
  -> POST /api/metabase-mcp (JSON-RPC)
  -> Origin + session validation
  -> Auth: OAuth bearer token or browser session
  -> Scope check against requested tool
  -> Synthetic request to Agent API endpoint
  -> Response materialized as MCP content
  -> JSON or SSE back to client

Further reading

Related MCP Connectors

  • The BigQuery remote MCP server is a fully managed service that uses the Model Context Protocol to connect AI applications and LLMs to BigQuery data sources. It provides secure, standardized tools for AI agents to list datasets and tables, retrieve schemas, generate and execute SQL queries through natural language, and analyze data—enabling direct access to enterprise analytics data without requiring manual SQL coding.

  • The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.

  • The Buildkite MCP server exposes Buildkite product data (pipelines, builds, jobs, and test data) to AI tools, editors, and agents through the Model Context Protocol. It provides capabilities including pipeline creation and management, build monitoring with specialized tools like 'wait_for_build', efficient log querying using Apache Parquet conversion and caching, and OAuth-based authentication for both read-write and read-only access to Buildkite's REST API.

  • Let AI agents query data and act across all your business apps via MCP.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A Model Control Protocol server that enables AI assistants to interact with Metabase databases, allowing models to explore database schemas, retrieve metadata, visualize relationships, and execute actions.
    7
    -
  • A
    license
    B
    quality
    B
    maintenance
    Connects Metabase business intelligence platform to AI assistants, enabling users to query data, create dashboards and charts, manage databases, and interact with BI assets using natural language through the Model Context Protocol.
    30
    17
    Apache 2.0
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server that enables AI assistants to query databases, execute SQL, and manage Metabase resources like dashboards, cards, and collections through natural language.
    22
    MIT