Metabase
官方官方 Metabase MCP 伺服器,用於搜尋資料、在語意層上建立查詢,並透過 MCP 客戶端視覺化結果。
你可以用 Metabase MCP 做什麼?
- 搜尋與擷取內容 — 請您的助理使用
search工具在 Metabase 中尋找問題、儀表板或模型,然後透過get_content取得詳細資訊。 - 執行查詢並視覺化結果 — 讓您的助理透過
execute_query執行結構化查詢,或使用execute_sql執行原始 SQL,然後使用visualize_query將結果呈現為互動式圖表。 - 建立與管理儀表板 — 指示您的助理使用
dashboard_write建立或更新儀表板及其版面配置,或透過duplicate_content將現有內容複製到集合中。 - 設定警示與訂閱 — 請您的助理使用
alert_write為儲存的問題建立排程警示,或使用subscription_write設定儀表板的電子郵件訂閱。 - 探索資料階層 — 引導您的助理透過
browse_data瀏覽資料庫、結構描述、資料表與欄位,或使用browse_collection以結構化方式瀏覽集合。
文件
Metabase MCP 伺服器
Metabase 內建了一個 Model Context Protocol (MCP) 伺服器,讓 AI 用戶端可以直接連線到 Metabase 實例。它使用 https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http,並建構在 Metabase 的 Agent API 之上,以公開用於搜尋、瀏覽、查詢、視覺化以及建立/更新內容的工具——所有操作都限定在連線使用者的權限範圍內。
端點
MCP 伺服器位於:
https://{your-metabase.example.com}/api/metabase-mcp
舊的 /api/mcp 路徑仍可作為現有用戶端的別名使用,但 /api/metabase-mcp 是要宣傳的正式 URL。
連線用戶端
將任何相容 MCP 的用戶端指向 /api/metabase-mcp 端點。例如,使用 Claude Code:
claude mcp add metabase https://{your-metabase.example.com}/api/metabase-mcp --transport streamable-http
對於 Claude Desktop,請使用相同的 URL 建立 自訂連接器。
對於 Cursor,請開啟 Settings > MCP,然後新增一個伺服器,類型設為 streamable-http,URL 為:
https://{your-metabase.example.com}/api/metabase-mcp
驗證
MCP 用戶端透過 OAuth 2.0 進行驗證。Metabase 執行自己的內嵌 OAuth 伺服器——不需要外部提供者。
首次連線的流程:
- 用戶端探索 Metabase 的 OAuth 端點。
- 用戶端向 Metabase 註冊自身。
- 使用者被重新導向到 Metabase 以登入並核准連線。
- 用戶端收到一個存取權杖,其範圍限定於使用者的 Metabase 權限。
基於瀏覽器的工作階段(cookie 驗證)、API 金鑰和 mb:full 權杖不具備 MCP 範圍,因此它們可以連線,但無法呼叫任何受範圍限制的工具。
範圍
存取權杖的範圍限制了用戶端可以使用的工具:
| 範圍 | 授予的工具 |
|---|---|
agent:content:read | browse_collection、browse_data、get_content、get_parameter_values、glossary、learn、search,以及 catalog://metabase/fields 資料資源(請參閱 Resources) |
agent:content:write | bookmark_content、collection_write、dashboard_write、document_write、duplicate_content、measure_write、metric_write、question_write、segment_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:* 這類萬用字元,以及 ::unrestricted 哨兵值,都不是 MCP 範圍,因此不會授予任何工具。
這些範圍僅限制 MCP 介面。沒有任何 REST 端點可以將其宣告為 :scope,因此發給 MCP 用戶端的新權杖在 REST API 上不會授予任何權限。
受保護資源元資料的 scopes_supported 和 401 挑戰的 scope 都列出了表格中的每個範圍,因此新的連線會要求所有這些範圍。有些用戶端在收到 403 後不會升級:從 Claude 的連接器設定手動重新連線會註冊一個新的用戶端,並只要求這些清單中列出的範圍。當它們只列出基準範圍時,該重新連線永遠不會提供寫入、原始 SQL 或傳遞功能,而且使用者無法授予這些權限(ENG-11089)。授權伺服器元資料也宣傳了所有這些範圍。
基準範圍(agent:content:read agent:query:run)在同意畫面上是鎖定的:當用戶端要求其中一個範圍時,使用者無法取消勾選。agent:query:run 在基準範圍內,因此圖表永遠不需要升級。Claude Desktop 在升級後會在不宣告 MCP Apps 支援的工作階段上重試工具,因此升級後的 visualize_query 會被拒絕,且其圖表永遠不會嵌入。
工具呼叫或資料資源讀取若缺少權杖所沒有的範圍,會以 HTTP 403 拒絕,並附上 WWW-Authenticate: Bearer error="insufficient_scope" 挑戰,其 scope 列出了權杖已持有的 v2 範圍加上所需的一個範圍,因此用戶端可以升級。每個工具也在 securitySchemes 中宣告其範圍,這是草案 SEP-1488,由 ChatGPT 支援。它不是 MCP 2025-03-26(此伺服器回報的版本)或最終 2026-07-28 工具規範的一部分,因此其他用戶端會從 403 中發現缺少的範圍。在 JSON-RPC 批次內,拒絕是帶內 -32600 錯誤。UI shell 讀取永遠不會被挑戰:請參閱 Resources。
OAuth 受保護資源元資料位於:
/.well-known/oauth-protected-resource/api/metabase-mcp
在同意畫面上,用戶端要求的每個範圍都會預先勾選,且基準範圍也是鎖定的。只有保持勾選的範圍會被授予,且僅限於此授權鑄造的權杖。取消勾選永遠不會影響應用程式已持有的權杖。Metabase 不會記住被取消勾選的範圍。之後的 403 可以在支援的用戶端中觸發另一次升級。其他用戶端可能需要手動重新授權。每個挑戰的 error_description 結尾都附有註記,說明使用者必須在同意畫面上授予權限。
有些用戶端會用自訂文字取代 403 的 error_description,因此 initialize 結果的 instructions 也會向模型解釋範圍失敗:驗證錯誤通常表示缺少權限而非登入過期,模型應指出失敗的工具或資源及其所需的權限,而使用者透過重新連線並在同意畫面上保持該權限勾選來授予它。這些指示是單一靜態字串,對所有呼叫者都相同:沒有每個連線的權限清單。
每群組工具存取
在具備 ai_controls 功能的 Enterprise 實例上,管理員可以在 Admin > AI > Usage controls > MCP tools access 中,依權限群組縮小介面範圍(只要 MCP 伺服器開啟就會顯示,無論是否有 LLM 提供者)。每個群組在 mcp_group_permission 中都有一列,說明其成員是否可以連線,以及每個工具名稱的管理員明確的 "yes" 或 "no";沒有條目的工具會採用其作者宣告的預設值,因此每個 deftool 都帶有必要的 :default-access,值為 :allowed 或 :denied,而之後發布的工具在每個群組中都會獲得該確切預設值,直到管理員覆寫它。條目以工具名稱作為鍵,因此重新命名工具需要 :renamed-from 包含其舊名稱(儲存在舊名稱下的條目仍然有效,且管理 API 會以目前名稱呈現它),否則作者必須接受每個管理員對它的選擇都會被丟棄;metabase.mcp.v2.tool-names-test 固定了現行名稱,因此兩者都不會意外發生。使用者的有效政策是其每個群組的 tool_access,只要該群組的列啟用了 MCP:當任何此類群組存在時,MCP 即開啟,而當任何這些群組將其解析為「是」時,工具即被允許。這些列單獨決定結果,它們也記錄了權限模式:簡單模式(Administrators、All Users 和 All tenant users)或群組層級模式(其他所有群組),後者是 All Users 沒有列的狀態。切換會刪除新模式隱藏之群組的列,並為進入時啟用但沒有列的群組建立種子(進入群組層級模式時的 Data Analysts,離開時的 All Users 和 All tenant users),且 PUT 會拒絕目前模式隱藏的群組,因此沒有請求會讀取快取的模式。該政策在 tools/list 和 tools/call(v2/registry.clj)中疊加在 OAuth 範圍之上,而其群組未授予任何存取權的使用者會在 initialize 和 resources/read(針對 MCP 關閉前開啟的工作階段)被拒絕,並附上說明修正方法的錯誤。僅限應用程式的工具(_meta {:ui {:visibility ["app"]}},即 refresh_ui_credential)不會出現在管理頁面上:只要政策允許任何 MCP Apps 工具,它們就被允許。超級使用者和內部呼叫者永遠不會被縮小範圍;OSS 允許一切。在 Enterprise 上,即使沒有 ai_controls 功能,儲存的列仍會被執行(過期或無法驗證的權杖會保留管理員設定的限制);該功能僅限制管理頁面和 API。解析器是 permissions.clj(defenterprise,EE 實作在 metabase-enterprise.mcp.permissions),管理 API 是 /api/ee/ai-controls/mcp-permissions。
可用工具
從 v2 註冊表(deftool)產生。此處命名的範圍是註冊表在工具執行前檢查的範圍;有些處理器在知道呼叫內容後會檢查進一步的範圍——當來源解析為原生 SQL 時的 agent:sql:run(question_write),以及警示或訂閱延遲執行時的 agent:query:run(alert_write、subscription_write)。這些拒絕帶有相同的 403 insufficient_scope 挑戰。tools/list 顯示所有工具,無論權杖持有什麼,而缺少該範圍的權杖可能無法呼叫它。
| 工具 | 範圍 | 說明 |
|---|---|---|
alert_write | agent:delivery:write | 建立或更新警示:當已儲存問題的結果符合條件時,依排程發送通知。 |
bookmark_content | agent:content:write | 為呼叫的使用者新增或移除內容書籤——即 Metabase 側邊欄顯示的相同星號/收藏清單。 |
browse_collection | agent:content:read | 以結構化方式瀏覽集合——所有分割區共用單一 id:數值 id、21 字元的 entity_id、「root」(依命名空間重新根植)或「trash」(已封存內容,僅限項目模式)。 |
browse_data | agent:content:read | 瀏覽資料階層:資料庫 → 結構描述 → 資料表 → 欄位。 |
collection_write | agent:content:write | 建立、重新命名、移動、封存或還原集合——即存放問題、儀表板、模型和文件的資料夾。 |
dashboard_write | agent:content:write | 建立或更新儀表板,並以有序操作編輯其版面配置。 |
document_write | agent:content:write | 建立或更新文件。 |
duplicate_content | agent:content:write | 將問題、儀表板或文件複製到集合中——比讀取原始內容再重新建立更便宜且更安全,且能保留讀取投影遺漏的所有內容。 |
execute_query | agent:query:run | 從資料回答問題的預設方式:驗證並執行結構化(MBQL)查詢,回傳資料列及 query_handle。 |
execute_sql | agent:sql:run | 逃生門:對資料庫執行原始 SQL 字串,回傳資料列及 query_handle。 |
get_content | agent:content:read | 依 {type, id} 擷取內容——針對透過搜尋或 browse_collection 找到的任何內容進行型別化讀取。 |
get_parameter_values | agent:content:read | 擷取儀表板或已儲存問題上單一篩選條件的有效值,讓您以真實值篩選,而非猜測。 |
glossary | agent:content:read | 查詢此 Metabase 執行個體定義的商業詞彙;定義的詞彙名稱隨工具自身的說明提供。 |
learn | agent:content:read | 讀取此伺服器的任務文件(技能),以了解結構描述無法完整描述的寫入方言。 |
measure_write | agent:content:write | 建立或更新量值:附加至單一資料表的具名、可重用 MBQL 彙總,可在其他查詢的彙總中以 ["measure", id] 參照。 |
metric_write | agent:content:write | 建立或更新指標:儲存於集合中的可重用彙總,可獨立查詢或從其他查詢參照。 |
question_write | agent:content:write | 建立、更新或封存已儲存的問題或模型。 |
refresh_ui_credential | agent:query:run | 重新整理 Metabase MCP App 使用的範圍憑證。 |
render_drill_through | agent:query:run | 呈現使用者剛導覽進入的鑽取視覺化。 |
run_saved_question | agent:query:run | 依數值 id 或 entity_id 執行已儲存的問題(卡片),內嵌回傳資料列。 |
search | agent:content:read | 依相關性在 Metabase 執行個體中尋找內容。 |
segment_write | agent:content:write | 建立或更新區段:附加至單一資料表的具名、可重用 MBQL 篩選條件,可從其他查詢的篩選條件參照。 |
subscription_write | agent:delivery:write | 建立或更新儀表板訂閱——整個儀表板的排程傳遞,例如 |
visualize_query | agent:query:run | 將查詢視覺化為互動式圖表或表格,內嵌呈現在對話中。 |
execute_query 每次呼叫回傳 row_limit 筆資料列(預設 100,上限 2000)——這是頁面大小,而非結果上限。
截斷的頁面會回報 truncated: true,且當查詢具有總排序時,會提供 next_cursor 作為
cursor 傳回以取得下一頁,直到某頁以 truncated: false 到達為止。只想取得前 N 筆資料列的查詢
會在其階段中攜帶 limit: N(並附 order-by);伺服器會將該上限跨頁分配,因此最後一頁
會完整回傳且無游標,分頁會自行結束。
資源
伺服器公開 MCP 資源,讓 用戶端可依 URI 擷取補充內容,而不會使工具說明過於龐大。
| 資源 URI | 範圍 | 說明 |
|---|---|---|
ui://metabase/visualize-query.html | agent:query:run(僅限 UI 憑證) | visualize_query 指向具備能力的用戶端所使用的 MCP Apps iframe 外殼。 |
ui://metabase/render-drill-through.html | agent:query:run(僅限 UI 憑證) | render_drill_through 指向的外殼。 |
catalog://metabase/fields | agent:content:read | 各內容型別在 fields 引數中接受的點路徑。 |
無論權杖的範圍為何,所有資源都會列出。資料資源(例如欄位目錄)僅由持有該範圍的權杖讀取;否則讀取會收到
Scopes 所述之 403 insufficient_scope 挑戰。UI 外殼可由任何權杖讀取,因為 MCP Apps 主機會在工具呼叫的同時讀取工具的外殼,若該讀取被拒絕,主機就不會在工具呼叫的 403 之後升級。外殼不攜帶任何資料。由不具外殼範圍的權杖讀取外殼,絕不會產生 UI 憑證。圖表資料由工具呼叫及 refresh_ui_credential(兩者皆為 agent:query:run)管控,iframe 需要這些才能查詢任何內容。未知 URI 會產生 -32602「Resource not found」錯誤。
技能包透過 learn 工具傳遞,而非以資源形式提供。
實體導覽使用 get_content 和 browse_* 工具,而非 URI 方案;上述 ui://
資源僅供能呈現 iframe 的用戶端掛載使用。
支援的 JSON-RPC 方法
| 方法 | 說明 |
|---|---|
initialize | 初始化 MCP 連線。回傳伺服器能力及工作階段 ID。 |
notifications/initialized | 用戶端通知初始化已完成。 |
tools/list | 列出可用工具,無論權杖範圍為何。 |
tools/call | 以引數呼叫工具。 |
resources/list | 列出可用資源,無論權杖範圍為何。 |
resources/read | 依 URI 讀取資源;資料資源需要其範圍。需要工作階段。 |
ping | 保持連線的 ping。 |
請求可個別傳送,或作為 JSON-RPC 批次傳送。伺服器依 Accept 標頭以 JSON 或 SSE 回應。
架構
實作位於以下檔案:
-
transport.clj- HTTP 傳輸層。解析 JSON-RPC 請求、驗證認證及 工作階段標頭、強制執行來源檢查(DNS 重新綁定防護),並分派至適當的方法。 支援 JSON 和 SSE 回應格式。 -
v2/api.clj- 工具表面處理器。將傳輸層連接至 v2 工具 + 資源登錄 並定義方法分派(tools/list、tools/call、resources/list、resources/read、ping)。 -
v2/registry.clj- v2 工具登錄。工具透過deftool自行註冊;登錄 檢查範圍、驗證引數、分派呼叫並記錄使用情況。 -
scope.clj- 範圍比對邏輯。僅精確比對:萬用字元、nil 範圍及::unrestricted哨兵值皆不比對任何項目。
請求流程
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