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 实例。它使用 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,打开 设置 > MCP,添加一个新服务器,类型设置为 streamable-http,URL 为:

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

身份验证

MCP 客户端通过 OAuth 2.0 进行身份验证。Metabase 运行自己的嵌入式 OAuth 服务器——无需外部提供商。

首次连接流程:

  1. 客户端发现 Metabase 的 OAuth 端点。
  2. 客户端向 Metabase 注册自身。
  3. 用户被重定向到 Metabase 登录并批准连接。
  4. 客户端收到一个限定于用户 Metabase 权限范围之内的访问令牌。

基于浏览器的会话(cookie 认证)、API 密钥和 mb:full 令牌不持有 MCP 范围,因此它们可以连接但 无法调用任何限定范围内的工具。

范围

访问令牌被限定范围,以限制客户端可以使用的工具:

范围授予的工具
agent:content:readbrowse_collection、browse_data、get_content、get_parameter_values、glossary、learn、search 以及 catalog://metabase/fields 数据资源(参见 资源)
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

一个工具只匹配表中确切的范围。诸如 * 或 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 外壳读取永远不会被质询:参见 资源。

OAuth 受保护资源元数据可在以下地址获取:

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

在同意屏幕上,客户端请求的每个范围默认勾选,基线范围也被锁定。只有 保持勾选的范围被授予,且仅授予此授权铸造的令牌。取消勾选永远不会影响 应用已有的令牌。Metabase 不会记住未勾选的范围。后续的 403 可以在支持升级的 客户端中触发另一次升级。其他客户端可能需要手动重新授权。每个质询的 error_description 末尾 都附有说明,提示用户必须在同意屏幕上授予该权限。

多个客户端会用它们自己的文本替换 403 的 error_description,因此 initialize 结果的 instructions 也向模型解释范围失败:认证错误通常意味着缺少权限而不是登录 过期,模型应指出失败的工具或资源及其所需的权限,用户通过 重新连接并在同意屏幕上保持该权限勾选来授予权限。这些指令是一个静态字符串,对每个 调用者都相同:没有针对每个连接的权限列表。

按权限组划分的工具访问

在启用了 ai_controls 功能的 Enterprise 实例上,管理员可以在 管理 > AI > 使用控制 > MCP 工具访问 中按权限组缩小范围(只要 MCP 服务器开启,无论是否配置 LLM 提供商,都会显示)。每个组在 mcp_group_permission 中有一行,说明其成员是否可以连接,以及按工具名称,管理员的显式 "yes" 或 "no";没有条目的工具采用其作者声明的默认值,因此每个 deftool 都带有必需的 :default-access,值为 :allowed 或 :denied,之后发布的工具在每个组中都会获得该默认值,直到管理员覆盖它。条目按工具名称键控,因此重命名工具需要 :renamed-from 及其旧名称(存储在旧名称下的条目仍然适用,管理 API 以当前名称呈现它),或者作者接受每个管理员对它的选择被丢弃;metabase.mcp.v2.tool-names-test 固定实时名称,因此两者都不会意外发生。用户的有效策略是其每个启用了 MCP 的组的行的 tool_access:当存在任何此类组时,MCP 开启,当任何此类组将其解析为“是”时,工具被允许。仅由这些行决定,它们还记录权限模式:简单模式(管理员、所有用户和所有租户用户)或组级模式(其他所有组),这是“所有用户”没有行的状态。切换会删除新模式隐藏的组的行,并在进入时为其启用的没有行的组播种(进入组级模式时的数据分析师,离开时的所有用户和所有租户用户),并且 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_writeagent:delivery:write创建或更新警报:当保存的问题结果满足条件时,按计划发送的通知。
bookmark_contentagent:content:write为调用用户添加或移除内容书签——即 Metabase 侧边栏显示的星标/收藏列表。
browse_collectionagent:content:read按结构浏览集合——所有分区使用统一的 id:数字 id、21 字符的 entity_id、"root"(按命名空间重新根化)或 "trash"(已归档内容,仅项目模式)。
browse_dataagent:content:read浏览数据层级:数据库 → 模式 → 表 → 字段。
collection_writeagent:content:write创建、重命名、移动、归档或恢复集合——即存放问题、仪表板、模型和文档的文件夹。
dashboard_writeagent:content:write创建或更新仪表板,并通过有序操作编辑其布局。
document_writeagent:content:write创建或更新文档。
duplicate_contentagent:content:write将问题、仪表板或文档复制到集合中——比读取原始内容再重新创建更便宜、更安全,并且保留读取投影遗漏的所有内容。
execute_queryagent:query:run从数据回答问题默认方式:验证并执行结构化(MBQL)查询,返回行以及 query_handle。
execute_sqlagent:sql:run逃生通道:对数据库执行原始 SQL 字符串,返回行以及 query_handle。
get_contentagent:content:read按 {type, id} 获取内容——用于通过搜索或 browse_collection 找到的任何内容的类型化读取。
get_parameter_valuesagent:content:read获取仪表板或保存问题上某个筛选器的有效值,以便使用真实值筛选而不是猜测。
glossaryagent:content:read按此 Metabase 实例的定义查找业务术语;定义的术语名称随工具自身的描述一起提供。
learnagent:content:read阅读此服务器的任务文档(技能),了解模式无法完全描述的写入方言。
measure_writeagent:content:write创建或更新度量:附加到单个表上的命名、可复用的 MBQL 聚合,可在另一个查询的聚合中引用为 ["measure", id]。
metric_writeagent:content:write创建或更新指标:保存在集合中的可复用聚合,可单独查询或从其他查询中引用。
question_writeagent:content:write创建、更新或归档保存的问题或模型。
refresh_ui_credentialagent:query:run刷新 Metabase MCP 应用使用的作用域凭据。
render_drill_throughagent:query:run渲染用户刚导航进入的钻取可视化。
run_saved_questionagent:query:run按数字 id 或 entity_id 运行保存的问题(卡片),内联返回行。
searchagent:content:read按相关性在 Metabase 实例中查找内容。
segment_writeagent:content:write创建或更新分段:附加到单个表上的命名、可复用的 MBQL 筛选器,可从其他查询的筛选器中引用。
subscription_writeagent:delivery:write创建或更新仪表板订阅——整个仪表板的计划投递,例如。
visualize_queryagent: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.htmlagent:query:run(仅 UI 凭据)visualize_query 指向的 MCP 应用 iframe 外壳,供有能力的客户端使用。
ui://metabase/render-drill-through.htmlagent:query:run(仅 UI 凭据)render_drill_through 指向的外壳。
catalog://metabase/fieldsagent:content:read每种内容类型在 fields 参数中接受的点路径。

无论令牌的作用域如何,每个资源都会被列出。数据资源(如字段目录)只能由持有其作用域的令牌读取;否则读取会收到 Scopes 下描述的 403 insufficient_scope 挑战。UI 外壳可由任何令牌读取,因为 MCP 应用宿主会在工具调用时同时读取工具的外壳,如果该读取被拒绝,宿主就不会在工具调用返回 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

进一步阅读