关于 Metabase Official MCP Server
Metabase Official MCP Server 是 Metabase 内置的 MCP 服务,用于将 AI 客户端连接到 Metabase 实例。它提供数据发现、查询、可视化和内容管理工具,并通过用户权限与 OAuth 作用域控制访问。
主要功能
- 01搜索和浏览 Metabase 内容
- 02运行查询并可视化结果
- 03创建和更新内容
- 04OAuth 2.0 身份验证与作用域访问
- 05Streamable HTTP 传输
适用场景
- 01通过 AI 客户端探索 Metabase 数据
- 02运行查询并查看可视化结果
- 03创建或更新仪表板和问题
- 04按用户权限限制可用操作
MCP 相关
该 MCP 服务通过 Streamable HTTP 向 MCP 客户端提供 Metabase 搜索、导航、查询、可视化及内容管理工具,并由 OAuth 作用域和 Metabase 权限控制访问。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://{metabase_host}/api/mcpclaude mcp add --transport http metabase-mcp-2 https://{metabase_host}/api/mcp{"mcpServers":{"metabase-mcp-2":{"type":"http","url":"https://{metabase_host}/api/mcp"}}}在 Cursor 中打开{"servers":{"metabase-mcp-2":{"type":"http","url":"https://{metabase_host}/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"metabase-mcp-2":{"type":"http","url":"https://{metabase_host}/api/mcp"}}}{"mcpServers":{"metabase-mcp-2":{"serverUrl":"https://{metabase_host}/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
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,打开 Settings > MCP,添加一个新服务,将类型设置为 streamable-http,并填入以下 URL:
https://{your-metabase.example.com}/api/metabase-mcp
身份验证
MCP 客户端通过 OAuth 2.0 进行身份验证。Metabase 运行自己的内嵌 OAuth 服务,无需外部提供方。
首次连接时的流程如下:
- 客户端发现 Metabase 的 OAuth 端点。
- 客户端向 Metabase 注册。
- 用户被重定向到 Metabase 登录并批准连接。
- 客户端收到一个受用户 Metabase 权限范围限制的访问令牌。
MCP 只接受 OAuth 访问令牌。在 MCP 路径上,会话中间件会忽略会话 Cookie 和 API 密钥,因此此类请求会收到与未提供凭据的请求相同的 401 发现质询。mb:full 令牌没有 MCP 作用域,因此可以连接,但无法调用任何受作用域限制的工具。
范围
访问令牌通过范围限制客户端可使用的工具:
| 范围 | 授予的工具 |
|---|---|
agent:content:read | browse_collection、browse_data、get_content、get_parameter_values、glossary、learn、search,以及 catalog://metabase/fields 数据资源(参见 资源) |
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 读取永远不会触发挑战:参见 资源。
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 服务已启用,无论是否配置了大模型提供方,此页面都会显示)。每个组在 mcp_group_permission 中都有一行,记录其成员是否可以连接,以及管理员针对每个工具名称明确设置的 "yes" 或 "no";没有条目的工具采用其作者声明的默认值,因此每个 deftool 都必须带有 :default-access,值为 :allowed 或 :denied,之后发布的工具在每个组中都会采用该默认值,直到管理员覆盖。条目以工具名称为键,因此重命名工具时需要使用 :renamed-from 填入其先前名称(先前名称下存储的条目仍然有效,管理员 API 会以当前名称显示),否则作者就要接受所有管理员对该工具的选择都会被丢弃;metabase.mcp.v2.tool-names-test 会固定当前名称,以避免意外发生这两种情况。用户的有效策略由其每个启用 MCP 的组所对应的 tool_access 决定:只要存在这样的组,MCP 就处于启用状态;只要这些组中有任一组将某工具解析为允许,该工具就会被允许。权限仅由这些行决定,它们也会记录权限模式:简单模式(Administrators、All Users 和 All tenant users)或组级模式(所有其他组),在组级模式下,All Users 没有对应的行。切换模式时,会删除新模式中不再显示的组的行,并为进入新模式时启用但尚无行的组创建行(进入组级模式时为 Data Analysts 创建,离开组级模式时为 All Users 和 All tenant users 创建);PUT 会拒绝当前模式中不显示的组,因此任何请求都不会读取缓存的模式。此策略会叠加在 OAuth 作用域之上,应用于 tools/list 和 tools/call(v2/registry.clj);对于没有任何组授予访问权限的用户,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”(已归档内容,仅限 items 模式)。 |
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 凭据) | MCP Apps iframe 外壳,visualize_query 会将支持该功能的客户端指向此处。 |
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
-> Scope check against requested tool
-> Synthetic request to Agent API endpoint
-> Response materialized as MCP content
-> JSON or SSE back to client
延伸阅读
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。