Metabase

io.github.metabase由 GitHub 帳號 metabase 發布v0.1.0更新於 Oct 24, 2026

Lets AI clients search, explore, query, and visualize data in a Metabase instance.

已驗證Streamable HTTP可網頁執行資料庫資料與分析

概覽

AI 產生的概覽

Metabase 內建的遠端 MCP 伺服器,讓 AI 用戶端在使用者權限範圍內搜尋、瀏覽、查詢與視覺化資料,並建立或更新 Metabase 內容。

可以做什麼
  • 搜尋與瀏覽內容:在執行個體中搜尋、瀏覽集合以及資料庫→結構描述→資料表→欄位階層、依類型與 ID 取得內容、查詢業務術語與篩選器可選值
  • 查詢資料:執行結構化 MBQL 查詢或已儲存問題、執行原始 SQL,並將結果呈現為對話內的圖表或表格
  • 建立與編輯內容:寫入問題、模型、儀表板、文件、集合、指標、量值與區段,複製內容,管理書籤
  • 安排推送:建立或更新警示與儀表板訂閱
  • 透過 learn 工具與 MCP 資源讀取任務文件與欄位路徑目錄
適用情境
適合讓助理依據 Metabase 執行個體中的資料回答問題、探索儀表板與已儲存問題,或在對話中直接建立與維護問題、儀表板、警示等 Metabase 內容時使用。
執行需求
需要一個可連線的 Metabase 執行個體,並在其 /api/metabase-mcp 路徑提供 MCP 端點(舊的 /api/mcp 別名仍可用)。用戶端以 Streamable HTTP 連線,並透過 Metabase 內建的 OAuth 2.0 授權伺服器驗證;MCP 路徑不接受工作階段 Cookie 與 API 金鑰。使用者須登入並在授權頁面同意所要求的權限範圍。
安裝前請注意
存取受 OAuth 權限範圍限制,授權頁面預設勾選全部範圍,包含寫入、原始 SQL 與推送;不需要的應取消勾選,因為已授權的權杖可建立、重新命名、移動、封存或還原內容、執行原始 SQL,並設定警示與訂閱。部分用戶端需手動重新連線才能取得額外權限。企業版中管理員還可依權限群組進一步限制工具。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Metabase,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

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.

Connecting a client

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

sh
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.

MCP accepts only an OAuth access token. On the MCP paths the session middleware ignores session cookies and API keys, so such a request gets the same 401 discovery challenge as a request with no credential. An mb:full token holds no MCP scope, so it can connect but call no scoped tool.

Scopes

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

ScopeTools it grants
agent:content:readbrowse_collection, browse_data, get_content, get_parameter_values, glossary, learn, search, and the catalog://metabase/fields data resource (see Resources)
agent:content:writebookmark_content, collection_write, dashboard_write, document_write, duplicate_content, measure_write, metric_write, question_write, segment_write
agent:delivery:writealert_write, subscription_write
agent:query:runexecute_query, refresh_ui_credential, render_drill_through, run_saved_question, visualize_query
agent:sql:runexecute_sql

A tool matches only the exact scope in the table. A wildcard such as * or agent:*, and the ::unrestricted sentinel, are not MCP scopes, so they grant no tool.

These scopes gate the MCP surface only. No REST endpoint may declare one as its :scope, so a new token issued to an MCP client grants nothing on the REST API.

The protected-resource metadata's scopes_supported and the scope of the 401 challenge both list every scope in the table, so a fresh connection asks for all of them. Some clients do not step up after a 403: a manual reconnect from Claude's connector settings registers a new client and asks for exactly what these list. When they listed only the baseline, that reconnect never offered writes, raw SQL, or delivery, and the user had no way to grant them (ENG-11089). The authorization server metadata advertises all of them too.

The baseline (agent:content:read agent:query:run) is locked on the consent screen: when a client requests one of these, the user cannot untick it. 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, every scope the client requested starts ticked, and the baseline scopes are also locked. Only the scopes left ticked 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 grant 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 leaving the permission ticked on the consent screen. The instructions are one static string, the same for every caller: there is no per-connection permission list.

Per-group tool access

On Enterprise instances with the ai_controls feature, an admin can narrow the surface per permissions group on Admin > AI > Usage controls > MCP tools access (shown whenever the MCP server is on, with or without an LLM provider). Each group has a row in mcp_group_permission saying whether its members may connect at all and, per tool name, the admin's explicit "yes" or "no"; a tool with no entry takes the default its author declared, so every deftool carries a required :default-access of :allowed or :denied and a tool released later gets exactly that default in every group until an admin overrides it. Entries are keyed by tool name, so renaming a tool needs :renamed-from with its former names (a stored entry under a former name still applies and the admin API presents it under the current name), or the author accepts that every admin's choice for it is discarded; metabase.mcp.v2.tool-names-test pins the live names so neither happens by accident. A user's effective policy is the tool_access of each group of theirs whose row enables MCP: MCP is on when any such group exists, and a tool is allowed when any of those groups resolves it to yes. The rows alone decide it, and they also record the permission mode: simple mode (Administrators, All Users, and All tenant users) or group-level mode (every other group), which is the state in which All Users has no row. A switch deletes the rows of the groups the new mode hides and seeds the groups it enables on entry that have no row (Data Analysts on entering group-level mode, All Users and All tenant users on leaving it), and PUT refuses a group the current mode hides, so no request reads a cached mode. The policy is applied on top of OAuth scopes in tools/list and tools/call (v2/registry.clj), and a user whose groups grant no access is refused at initialize and at resources/read (for sessions opened before MCP was turned off) with an error naming the fix. App-only tools (_meta {:ui {:visibility ["app"]}}, i.e. refresh_ui_credential) are not on the admin page: they are allowed while the policy allows any MCP Apps tool. Superusers and internal callers are never narrowed; OSS allows everything. On Enterprise the stored rows are enforced even without the ai_controls feature (an expired or unverifiable token keeps the restrictions an admin configured); the feature only gates the admin page and API. The resolver is permissions.clj (defenterprise, EE implementation in metabase-enterprise.mcp.permissions) and the admin API is /api/ee/ai-controls/mcp-permissions.

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), 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.

ToolScopeDescription
alert_writeagent:delivery:writeCreate or update an alert: a notification sent on a schedule when a saved question's results meet a condition.
bookmark_contentagent:content:writeAdd or remove a bookmark on content for the calling user — the same starred/favorites list the Metabase sidebar shows.
browse_collectionagent:content:readBrowse 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_dataagent:content:readBrowse the data hierarchy: databases → schemas → tables → fields.
collection_writeagent:content:writeCreate, rename, move, archive, or restore a collection — the folders that hold questions, dashboards, models, and documents.
dashboard_writeagent:content:writeCreate or update a dashboard and edit its layout with ordered ops.
document_writeagent:content:writeCreate or update a document.
duplicate_contentagent:content:writeCopy 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_queryagent:query:runThe default way to answer a question from data: validate and execute a structured (MBQL) query, returning rows plus a query_handle.
execute_sqlagent:sql:runEscape hatch: execute a raw SQL string against a database, returning rows plus a query_handle.
get_contentagent:content:readFetch content by {type, id} — the typed read for anything found via search or browse_collection.
get_parameter_valuesagent:content:readFetch the valid values for one filter on a dashboard or saved question, so you filter with real values instead of guessing.
glossaryagent:content:readLook up a business term as this Metabase instance defines it; the defined term names ride the tool's own description.
learnagent:content:readRead this server's task docs (skills) for the write dialects the schemas can't fully describe.
measure_writeagent:content:writeCreate or update a measure: a named, reusable MBQL aggregation attached to one table, referenced inside another query's aggregation as ["measure", id].
metric_writeagent:content:writeCreate 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_writeagent:content:writeCreate, update, or archive a saved question or model.
refresh_ui_credentialagent:query:runRefresh the scoped credential used by a Metabase MCP App.
render_drill_throughagent:query:runRender the drill-through visualization the user just navigated into.
run_saved_questionagent:query:runRun a saved question (card) by numeric id or entity_id, returning rows inline.
searchagent:content:readFind content across the Metabase instance by relevance.
segment_writeagent:content:writeCreate or update a segment: a named, reusable MBQL filter attached to one table, referenced from other queries' filters.
subscription_writeagent:delivery:writeCreate or update a dashboard subscription — scheduled delivery of a whole dashboard, e.g.
visualize_queryagent:query:runVisualize 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 URIScopeDescription
ui://metabase/visualize-query.htmlagent:query:run (UI credential only)The MCP Apps iframe shell visualize_query points a capable client at.
ui://metabase/render-drill-through.htmlagent:query:run (UI credential only)The shell render_drill_through points at.
catalog://metabase/fieldsagent:content:readThe 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

MethodDescription
initializeInitialize the MCP connection. Returns server capabilities and a session ID.
notifications/initializedClient notification that initialization is complete.
tools/listList available tools, whatever the token's scopes.
tools/callCall a tool with arguments.
resources/listList available resources, whatever the token's scopes.
resources/readRead a resource by URI; a data resource needs its scope. Requires a session.
pingKeepalive 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. Exact matches only: wildcards, nil scopes, and the ::unrestricted sentinel match nothing.

Request flow

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

Further reading

來源:src/metabase/mcp/README.md,提交 ffebfce

工具

0
SourceWeft 尚未讀取此伺服器的工具。

版本歷史

1
  1. v0.1.0最新Sep 16, 2026

評分

已滿足適用檢查項的 40%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式必需10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

    請在儲存庫或註冊中心條目中宣告授權條款。