App Data MCP
The App Data MCP is a read-only data gateway for internal analytics platforms (Metabase and PostHog), enabling AI clients to discover, inspect, trace, and query data assets without any write access.
search_assets— Search across Metabase dashboards/cards, PostHog insights, metrics, tables, and events using keywords, business domain, platform, or asset type filters (default 10 results, max 50).get_asset— Retrieve full metadata for a specific data asset, including its source URL, SQL/query text, column definitions, child assets, and any warnings.trace_asset— Trace the lineage/provenance of a data asset, including upstream tables, events, SQL queries, and direct links to the original platform.run_asset— Execute read-only live queries against Metabase cards/dashboards or PostHog insights and return real data (default 100 rows, max 500), with fallback to local sample data if the live connector fails. Supports parameterized filters.list_domains— List all business domains (e.g. growth, product, revenue) available in the local metadata catalog.catalog_status— Verify whether the local asset catalog is initialized, how many assets it contains, and sync freshness statistics.auth_status— Check the current user's identity and Metabase authorization status; provides a login URL if authentication is missing.connector_status— Inspect Metabase and PostHog connector configuration status and access mode (always read-only) without exposing any secrets.
All operations are strictly read-only — no create, update, or delete actions are possible. Response size is capped at ~1 MB.
Integrates with Metabase to read dashboards, cards, and queries; supports search, metadata synchronization, and read-only query execution using user sessions or API keys.
Integrates with PostHog to read dashboards, insights, and events; supports search, metadata synchronization, and read-only query execution using personal API keys.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@App Data MCPsearch for weekly revenue dashboard"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
App Data MCP
这是一个面向内部数据平台的 MCP 服务。Metabase、PostHog 等元信息同步到 PostgreSQL,由管理员在后台决定是否对 MCP 用户开放,让 Codex、Claude Code 等 AI 客户端完成资产发现、详情查看、数据出处追踪和受控取数。
当前能力
search_assets: 搜索看板、卡片、Model、insight、指标、表、事件。get_asset: 查看单个资产完整元信息。trace_asset: 查看资产的 SQL / 事件 / 上游表 / 原始链接。run_asset: 只读返回支持资产的真实数据;不支持时读取本地sampleData兜底。query_audience: 使用统一uid对 2-10 个 Metabase Model 做交集、并集或差集计算。export_audience: 将完整 UID 人群导出为有期限的服务端 CSV 下载文件。query_starrocks: 治理资产无法回答后的受控 StarRocks SQL 回退;执行前会再次搜索 Metric/Model/Card。list_domains: 查看配置里已有的业务域。auth_status: 查看当前请求用户和 Metabase 授权状态。catalog_status: 查看当前个人 MCP 用户可见的元信息数量和分类统计。connector_status: 查看连接器配置状态和只读访问策略。
Related MCP server: socrata-mcp
只读访问策略
这个 MCP 只做只读数据网关,不提供任何创建、更新、删除、写回能力。
允许的操作:
搜索和读取 PostgreSQL 中已开放的元信息。
读取看板、卡片、insight、指标口径和来源链接。
追踪上游表、事件、SQL、原平台 URL。
执行 Metabase/PostHog 查询时,只允许调用读取类 API,并限制为只读查询结果。
执行 StarRocks 查询时,只允许单条
SELECT、WITH ... SELECT、SHOW、DESCRIBE/DESC或EXPLAIN。
禁止的操作:
创建、编辑、删除 Metabase dashboard/card/question。
创建、编辑、删除 PostHog dashboard/insight/cohort/action。
写数据库、执行 DDL/DML、保存 AI 生成的 SQL 到平台。
通过 MCP 修改任何业务数据、平台配置或权限配置。
后续新增 connector 或 tool 时,命名和实现都必须维持这个边界。connector_status 会返回 accessMode: "read-only",用于让 AI 客户端确认当前服务策略。
数据量限制
默认会限制返回数据量,避免 AI 平台一次拉取过大的结果。
search_assets默认返回 10 条,最多 50 条。run_asset默认返回 100 行,最多 500 行。单次 MCP 响应默认最大约 1 MB,超过会返回
response_too_large,提示缩小查询范围。query_starrocks与run_asset共用行数上限;同时在 StarRocks 会话设置sql_select_limit和query_timeout。
可以通过环境变量调整,但建议生产环境保持保守:
DATA_DEFAULT_SEARCH_LIMIT=10
DATA_MAX_SEARCH_LIMIT=50
DATA_DEFAULT_RESULT_ROW_LIMIT=100
DATA_MAX_RESULT_ROW_LIMIT=500
DATA_MAX_RESPONSE_BYTES=1000000Metabase/PostHog connector 会继续在返回侧做行数和响应字节限制。connector_status 会返回当前 dataLimits。
真实数据读取
run_asset 现在会优先调用平台只读 API 获取真实数据:
metabase:card:*/metabase:model:*/metabase:metric:*: 调用 Metabase card query endpoint;Model 和 Metric 在 Metabase API 中同样通过 card query 执行。metabase:dashboard:*: 读取 dashboard 下的卡片,并按 dashboard 筛选器映射逐个执行卡片查询。posthog:insight:*: 调用 PostHog insight read endpoint,并请求刷新/返回当前结果。
仍然不支持写入操作,也不会保存查询、修改看板或更新 insight。
注意:
Dashboard 取数会限制最多执行 20 张卡片,可用
DATA_MAX_DASHBOARD_CARDS调整。每张卡片/insight 结果继续受
DATA_MAX_RESULT_ROW_LIMIT和DATA_MAX_RESPONSE_BYTES限制。资产声明了
parameters时,可以给run_asset传维度/日期参数;未声明的友好参数会被拒绝,避免 AI 临时拼接不受控条件。Metabase dashboard 会读取
parameter_mappings,只把已经映射到对应 card 的筛选参数下发,并在返回里给出每张 card 的parameterMappingStatus。如果 live connector 失败且资产里配置了
sampleData,会回退返回 sampleData。如果既无法 live 查询又没有 sampleData,会返回
live_connector_failed或asset_not_runnable。
Metabase 友好参数示例:
{
"asset_id": "metabase:card:81",
"params": {
"date": {
"from": "2026-07-01",
"to": "2026-07-09"
},
"country": "US"
},
"limit": 100
}Model / Metric / Card 指标集语义查询
run_asset.semantic 可以在不修改 Metabase 对象、不拼接 SQL 的情况下,对已经同步的 Model、Metric 和声明为 semantic.role=metric_set 的 Card 进行受控分析。所有字段都必须来自 get_asset 返回的治理元数据,服务端会校验字段引用、操作符、数量上限和数据类型。
Metric 保持已经治理的公式不变,只允许追加筛选和替换拆分维度:
{
"asset_id": "metabase:metric:480",
"semantic": {
"filters": [
{ "field": "country_ad_ch", "operator": "eq", "value": "CN" }
],
"breakouts": [
{ "field": "data_source" },
{ "field": "date(t1.event_date)", "unit": "month" }
]
},
"limit": 100
}传入 "breakouts": [] 可以移除 Metric 的默认时间分组并返回总值;省略 breakouts 则保留 Metric 原有默认分组。
Model 可以选择明细字段:
{
"asset_id": "metabase:model:479",
"semantic": {
"fields": ["uid", "data_source", "date(t1.event_date)"],
"filters": [
{ "field": "is_active_on_date", "operator": "eq", "value": 1 }
]
},
"limit": 100
}也可以动态聚合和拆分:
{
"asset_id": "metabase:model:479",
"semantic": {
"filters": [
{ "field": "is_active_on_date", "operator": "eq", "value": 1 }
],
"aggregations": [
{ "operator": "distinct", "field": "uid", "alias": "有效用户数" }
],
"breakouts": [
{ "field": "data_source" }
]
},
"limit": 100
}Card 指标集由管理员在资产编辑页通过可视化表单维护:可以直接为同步到的 Card 输出列勾选“维度”或“指标”,配置基础粒度、默认时间维度、时间粒度、单位、同义词、Rollup、重算分子/分母和运行累计。后台仍保存下面的结构化语义覆盖;“高级:JSON 预览与导入”只用于排障或批量迁移,不要求日常手写。
{
"role": "metric_set",
"baseGrain": ["stat_date", "region"],
"defaultTimeDimension": {
"field": "stat_date",
"defaultUnit": "day",
"supportedUnits": ["day", "week", "month"],
"timezone": "Asia/Shanghai",
"dateMeaning": "支付成功日期"
},
"dimensions": [
{ "field": "stat_date", "label": "统计日期" },
{ "field": "region", "label": "地区" }
],
"measures": [
{
"name": "revenue",
"label": "支付金额",
"synonyms": ["成交金额"],
"unit": "CNY",
"rollup": {
"strategy": "sum",
"allowedGroupBy": ["stat_date", "region"]
},
"cumulative": {
"supported": true,
"strategy": "running_sum"
}
},
{
"name": "paid_users",
"label": "支付用户数",
"rollup": {
"strategy": "forbidden",
"reason": "基础结果已经去重,跨日期或地区相加会重复计算用户"
}
}
]
}查询 Card 指标集:
{
"asset_id": "metabase:card:123",
"semantic": {
"measures": ["revenue"],
"breakouts": [
{ "field": "stat_date", "unit": "day" },
{ "field": "region" }
],
"cumulative": [
{
"measure": "revenue",
"orderBy": "stat_date",
"partitionBy": ["region"],
"alias": "revenue_running"
}
]
},
"limit": 100
}Card 查询省略 breakouts 时采用指标级时间维度或 Card 的 defaultTimeDimension;传入空数组表示请求跨时间总值,仅 sum/min/max/recompute 等安全 Rollup 会执行。forbidden 指标只能保持完整 baseGrain。recompute 可用治理过的分子、分母重新计算比率。运行累计只支持显式声明为 running_sum 的可加指标,且结果必须在行数限制内完整返回;日去重用户数等不可加指标会被拒绝。
筛选操作符包括 eq、neq、gt、gte、lt、lte、in、not_in、contains、is_null、not_null、between;Model 聚合包括 count、distinct、sum、avg、min、max。语义查询与 params 不能同时使用,普通 Card、Dashboard 和 PostHog Insight 不接受 semantic。
用户人群组合查询
Metabase 同步会为包含 uid 字段的 Model 生成 audience 元数据。query_audience 要求所有输入 Model 位于同一个 Metabase database,并使用当前用户的 Metabase Session 在 /api/dataset 内完成集合计算。每个 Model 会先在数据源侧应用筛选并按 uid 去重,再执行集合连接,不会先把各 Model 的 UID 拉回 MCP 客户端。
{
"operator": "intersection",
"models": [
{
"asset_id": "metabase:model:101",
"filters": [
{ "field": "event_time", "operator": "gte", "value": "2026-07-01" }
]
},
{
"asset_id": "metabase:model:102",
"filters": [
{ "field": "topic", "operator": "eq", "value": "母婴" }
]
}
],
"output": "count",
"limit": 100
}operator 支持 intersection、union 和 difference;difference 表示第一个 Model 减去后续所有 Model。output=count 默认只返回去重用户数;output=uids 返回去重 UID,并受全局最大行数和响应大小限制。每个 Model 最多包含 20 个受控语义筛选条件。
需要完整 UID 文件时使用 export_audience,不要循环调用有限的 query_audience 结果:
{
"operator": "intersection",
"models": [
{ "asset_id": "metabase:model:493", "filters": [{ "field": "deleted", "operator": "eq", "value": 0 }] },
{ "asset_id": "metabase:model:496", "filters": [{ "field": "status", "operator": "eq", "value": 1 }] }
],
"filename": "community-active-users.csv"
}服务端通过 Metabase CSV endpoint 获取完整的单列 UID 结果,生成随机 capability 下载地址,默认 24 小时后失效,并由后台定时清理。超过行数或文件字节上限时整个导出失败,不会生成截断文件。下载地址相当于临时访问凭证,不应公开分享。
治理资产优先与 SQL 回退
普通数据问题必须先调用 search_assets。搜索支持直接传入中文长句,会拆分中文二元/三元语义片段,并在召回后按问题意图动态重排。普通指标、趋势和拆分查询采用 Metric > Card > Model > Dashboard 的安全顺序:先检查标准 Metric,再检查可能包含多个现成指标的 Card,最后才用 Model 重算;明细查询仍优先 Model,总览优先 Dashboard,固定报表优先 Card,漏斗/留存/路径分析优先 PostHog Insight。类型只是意图适配后的兜底排序,AI 仍需用 get_asset 核对字段、维度、参数和公式。返回值中的 selection.intent、recommendedAssetId、candidateOrder,以及每项资产的 selection.suitability/reasons/missingCapabilities 会解释推荐结果。只有管理后台已开放且有效的资产会参与搜索和治理检查。
当 AI 在 Model 上使用 semantic.aggregations 重新计算 count、distinct、sum 等指标时,run_asset 会进行第二次服务端检查:
必须传入用户原始
question,否则返回asset_question_required。如果仍有匹配的 Metric 或 Card,返回
higher_priority_asset_available并拒绝执行 Model。AI 必须逐个
get_asset检查候选 Metric 与 Card;确认不适用后,把所有相关 ID 放入rejected_asset_ids并提供具体fallback_reason。拒绝 Metric 或 Card 却不说明原因时返回
fallback_reason_required。Model 的
semantic.fields明细查询不属于重新计算指标,不受这项拦截影响。
例如只有在治理 Metric 和现有 Card 都无法覆盖用户要求的维度时,才允许这样显式降级:
{
"asset_id": "metabase:model:492",
"question": "查询按实验分组拆分的中国地区绑定设备用户数",
"rejected_asset_ids": ["metabase:metric:483", "metabase:card:530"],
"fallback_reason": "Metric 483 没有实验分组维度,Card 530 也未提供该筛选参数",
"semantic": {
"filters": [{ "field": "country_ad_ch", "operator": "eq", "value": "中国" }],
"aggregations": [{ "operator": "distinct", "field": "uid", "alias": "user_count" }],
"breakouts": [{ "field": "experiment_group" }]
}
}query_starrocks 要求同时传入用户原始问题,并在执行 SQL 前由服务端再次搜索治理资产:
{
"question": "最近15天有效绑定M9设备的社区活跃用户数趋势",
"sql": "select ...",
"purpose": "data_question",
"limit": 100
}如果存在匹配的 Metric/Model/Card,服务端返回 governed_assets_available、候选资产和下一步说明,且 sqlExecuted=false。AI 应先使用 get_asset 和 run_asset。检查后确认候选资产不适用,才可显式拒绝并回退:
{
"question": "最近15天有效绑定M9设备的社区活跃用户数趋势",
"sql": "select ...",
"purpose": "data_question",
"rejected_asset_ids": ["metabase:metric:480", "metabase:model:479"],
"fallback_reason": "候选资产没有所需的实验组字段",
"limit": 100
}purpose=user_requested_sql 只能用于用户明确要求直接执行 SQL 的场景;purpose=metadata_inspection 只允许 SHOW、DESCRIBE/DESC 和 EXPLAIN。
Metabase dashboard 参数执行结果会包含筛选器覆盖情况:
{
"requestedParameters": ["date", "country"],
"parameterCoverage": [
{
"parameter": "date",
"mappedCardCount": 3,
"mappedCards": [
{
"cardId": "81",
"title": "APP 日活"
}
]
}
],
"cards": [
{
"cardId": "81",
"parameterMappingStatus": {
"status": "partially_mapped",
"requestedParameters": ["date", "country"],
"appliedParameters": ["date"],
"unmappedParameters": ["country"],
"mappedParametersAvailable": ["date"]
}
}
]
}Metabase 原生参数仍可透传:
{
"asset_id": "metabase:card:81",
"params": {
"parameters": [
{
"type": "date/range",
"target": ["variable", ["template-tag", "date"]],
"value": "2026-07-01~2026-07-09"
}
]
}
}PostHog insight 支持常见只读覆盖参数:
{
"asset_id": "posthog:insight:abc123",
"params": {
"date_from": "-30d",
"date_to": "now",
"breakdown": "country",
"properties": [
{
"key": "country",
"value": "US",
"operator": "exact",
"type": "event"
}
]
}
}PostHog 参数不会再作为裸 date_from / properties 查询参数发送。服务端会读取已经同步并由管理员开放的
PostHog 公共属性,将显示名称、翻译或同义词解析成原生字段名,并校验是否允许过滤/分组。普通筛选使用 Insight
Retrieve API 的 filters_override 参数;动态分组基于已保存 Insight 构造临时只读 Query API 请求。未开放、
已下线、歧义、禁止过滤或禁止分组的属性会被拒绝。
例如管理员可以把 $geoip_country_code 配置为“国家代码”,并将“国家码、country”维护为同义词;调用方随后
可以在 properties[].property 或 breakdown 中使用任意一个已治理名称。原生 properties[].key 继续兼容,
但也必须对应一条有效且已开放的公共属性。
StarRocks 自助 SQL
query_starrocks 仅用于治理资产无法回答问题后的 SQL 回退。服务端强制执行下面的顺序:
必须先调用
search_assets,优先检查 Metric、Model,再检查 Card、Dashboard 或 Insight。能由治理资产回答时使用
get_asset和run_asset。没有合适资产、已明确拒绝候选资产,或用户明确要求 SQL 时,才使用
query_starrocks。不熟悉表结构时,先执行
SHOW TABLES、DESCRIBE table_name或SHOW CREATE TABLE table_name。根据真实字段生成带明确日期范围和过滤条件的
SELECT,避免扫描无关数据。
示例:
{
"question": "最近15天活跃用户数趋势",
"sql": "SELECT dt, count(*) AS active_users FROM ads_app_daily WHERE dt >= '2026-07-01' GROUP BY dt ORDER BY dt",
"purpose": "data_question",
"limit": 100
}服务会拒绝 DDL、DML、多语句、INTO OUTFILE、LOAD_FILE、FILES、SLEEP、可执行注释和自定义查询 Hint 等危险或消耗型 SQL。每次执行还会设置 StarRocks 当前会话的查询超时与最大返回行数,并继续受 MCP 响应字节数限制。
StarRocks 配置放在 .env,不要写入元信息表:
STARROCKS_HOST=127.0.0.1
STARROCKS_PORT=9030
STARROCKS_USER=app_data_mcp_reader
STARROCKS_PASSWORD=your-password
STARROCKS_DATABASE=your_database
STARROCKS_CONNECTION_LIMIT=10
STARROCKS_CONNECT_TIMEOUT_MS=10000
STARROCKS_QUERY_TIMEOUT_MS=30000
STARROCKS_MAX_SQL_LENGTH=50000
STARROCKS_SSL=false必须使用专用只读账号。MCP token 负责识别和审计查询人,真正的数据表权限由这个 StarRocks 账号控制。管理员可以按实际数据库创建最小权限账号,例如:
CREATE USER 'app_data_mcp_reader' IDENTIFIED BY 'replace-with-a-strong-password';
GRANT SELECT ON ALL TABLES IN DATABASE your_database TO USER 'app_data_mcp_reader';
GRANT SELECT ON ALL VIEWS IN DATABASE your_database TO USER 'app_data_mcp_reader';不要给该账号授予 INSERT、UPDATE、DELETE、CREATE、DROP、ALTER、EXPORT 或管理角色。配置后可先调用 connector_status 确认 starrocks.configured=true,再让 AI 执行 SHOW TABLES 验证连接。
本地运行
第一次部署先配置 PostgreSQL。服务或同步脚本首次访问时会自动创建 DB_SCHEMA.METADATA_TABLE,默认是 public.app_data_mcp_assets。
stdio 模式,适合本机 Codex / Claude Code 通过命令启动:
npm install
npm run devHTTP 模式,适合部署成团队共享服务:
npm run dev:http默认地址:
http://127.0.0.1:3000/mcp健康检查:
http://127.0.0.1:3000/health如果当前用户没有可见资产,catalog_status 会显示 scope: "current_user" 和 assetCount: 0,search_assets 会返回空列表。先确认该用户的 Metabase 权限,再检查管理员是否已在 http://127.0.0.1:3000/admin 勾选开放相应资产。
同步平台元信息
可以运行只读同步脚本,把 Metabase/PostHog 元信息 upsert 到 PostgreSQL。
同步 Metabase:
npm run sync:metabase同步 PostHog:
npm run sync:posthog全部同步:
npm run sync:all同步脚本只读取平台 API,然后更新元信息表:
已存在的资产更新
metadata和同步时间,不覆盖管理员设置的is_published和人工配置。新资产默认
is_published=false;可通过METADATA_DEFAULT_PUBLISHED=true调整,但生产环境不建议。平台中已经消失的资产会标记为 inactive,并自动设置
is_published=false,不再对 MCP 暴露;未来重新同步出现时也不会自动恢复开放。不会创建、更新、删除 Metabase/PostHog 平台内的任何对象。
PostHog 同步会继续读取 Dashboard 详情,建立 Dashboard 到 Insight 的 children 关系;Insight 会自动抽取 analysisType、事件、拆分字段和过滤属性到 insightSemantic。同步任务还会读取 event/person/session/group 四类 Property Definitions,保存 PostHog 原始元数据并保留后台人工覆盖字段。负责人优先使用 PostHog 用户姓名,其次使用邮箱,只有两者都不存在时才回退到 distinct_id。
管理后台的“PostHog 公共属性”页面用于维护属性的开放状态、显示名称、翻译、类型、过滤能力、分组能力、说明和 同义词。PostHog 新发现的属性默认关闭;后续同步只更新源元数据,不覆盖人工配置。PostHog 已消失的属性会标记 为下线并立即停止供 MCP 查询使用。
Metabase 同步会为 dashboard/card/model/metric 写入权限快照 asset.access,包括 collection、creator、archived、personal collection、同步时间等。MCP 使用两级过滤:
Card、Model 与 Metric 同步会在读取 /api/card 列表后,以受限并发继续读取 /api/card/:id 详情,并优先使用详情中的 dataset_query、result_metadata、参数和更新时间。Model 保存为 metabase:model:<id>,Metric 保存为 metabase:metric:<id>。包含 uid 的 Model 会额外保存 audience 元数据和 database id,用于服务端人群组合查询。Metric 还会保存公式、筛选条件、数据来源、默认时间维度、可拆分维度和上下游资产依赖;字段元信息区分 name、displayName 与真实 description。对象在 Card、Model、Metric 之间转换时,会迁移原记录并保留开放状态和后台人工配置。详情请求失败时会保留列表数据,并在同步日志和资产 warnings 中标记。
search_assets: 用本地权限快照缩小候选集,再对候选资产做实时权限校验。list_domains/catalog_status: 先做快照过滤,再批量读取当前用户可见的 Metabase Card 与 Dashboard ID。get_asset/trace_asset: 先做本地快照过滤,再用当前用户 Metabase session 实时请求GET /api/card/:id或GET /api/dashboard/:id校验可见性。run_asset: 继续使用用户 Metabase session 执行只读查询,保留平台实时权限判断。query_audience: 对每个输入 Model 做快照和实时权限校验,再使用同一用户 Session 执行组合查询。
需要统计整个可见目录时,服务会优先并行读取 Metabase /api/card 与 /api/dashboard 列表,一次取得当前用户可见 ID,而不是逐资产请求详情;读取失败时才回退逐资产校验。结果默认按用户 Session 缓存 30 秒,可通过 METABASE_LIVE_ACCESS_CACHE_SECONDS 调整,以减少连续调用 list_domains、catalog_status 的重复开销。
Dashboard 的开放状态会被其直接子 Card、Model、Metric 继承。未单独开放的子资产不会出现在
search_assets 中,但只要它仍属于一个已开放 Dashboard,且当前用户能实时访问该 Dashboard,
就可以通过子资产 id 使用 get_asset、trace_asset 和 run_asset。返回结果中的
access.mode=dashboard_inherited 会列出授权来源 Dashboard。Card 数据查询仍由 Metabase 使用
当前用户 Session 做最终权限判断;从 Dashboard 移除子 Card 后,继承访问会在下一次元信息同步后失效。
部署或升级后执行一次完整同步:
npm run sync:metabase同步频率建议:
METABASE_METADATA_SYNC_INTERVAL_HOURS=6
METABASE_PERMISSION_SYNC_INTERVAL_HOURS=6
POSTHOG_METADATA_SYNC_INTERVAL_HOURS=12如果 Metabase 权限、collection、核心看板变化频繁,可以把 Metabase 调整到 1 小时;如果变化少,6 小时通常够用。权限大调整、核心看板发布后建议手动运行:
npm run sync:metabase生产环境可以用 cron 或调度器定时执行:
0 */6 * * * cd /path/to/app-data-mcp && npm run sync:metabase
15 */12 * * * cd /path/to/app-data-mcp && npm run sync:posthogcatalog_status 需要个人 MCP token,并按该账号的 Metabase 实时权限统计可见资产;同时返回 metadata/access snapshot 的 latestSyncedAt、ageHours 和 stale,超过上述间隔时会提示重新同步。
如果同步失败,常见原因是 .env 里平台地址或凭据未填完整。可以先在 MCP 里调用 connector_status 检查配置。
HTTP 模式可配置:
MCP_HTTP_HOST=0.0.0.0 MCP_HTTP_PORT=3000 npm run dev:httpMCP_HTTP_BEARER_TOKEN 是旧的共享 HTTP 保护 token。多人使用时更推荐后面的“Metabase 用户授权”流程,由每位用户登录后生成自己的个人 MCP token。
如果仍设置 MCP_HTTP_BEARER_TOKEN,客户端需要带共享 token 或用户个人 token 才能进入 /mcp。共享 token 只做传输入口保护;当 APP_DATA_REQUIRE_AUTH_TOKEN=true 时,数据类 tools 仍然需要用户个人 token 才能识别具体权限。
Authorization: Bearer <token>Codex / Claude Code 配置示例
stdio:
{
"mcpServers": {
"app-data": {
"command": "npm",
"args": ["run", "dev"],
"cwd": "/Users/lute/code/app-data-mcp"
}
}
}HTTP / Streamable HTTP:
{
"mcpServers": {
"app-data": {
"url": "http://127.0.0.1:3000/mcp",
"headers": {
"Authorization": "Bearer appdata_your-personal-token"
}
}
}
}不同 AI 平台的配置字段名可能略有差异,但核心就是把 MCP endpoint 指到 /mcp。
Metabase / PostHog API 配置
不要把 API key、用户名、密码写入元信息表。密钥只通过部署环境变量提供。
复制 .env.example 为 .env,在部署环境里填写:
METABASE_BASE_URL=https://metabase.example.com
METABASE_PUBLIC_URL=https://metabase.example.com
METABASE_API_KEY=...
POSTHOG_BASE_URL=https://posthog.example.com
POSTHOG_PROJECT_ID=...
POSTHOG_PERSONAL_API_KEY=...run_asset 会使用这些环境变量调用 Metabase/PostHog 只读 API。资产不可 live 查询或连接失败时,才会按配置回退到本地 sampleData。
METABASE_BASE_URL 是 MCP 服务端访问 Metabase API 的地址;METABASE_PUBLIC_URL 是返回给 AI 用户点击的数据来源地址。远程部署时如果服务端通过本机端口访问 Metabase,例如:
METABASE_BASE_URL=http://127.0.0.1:3000
METABASE_PUBLIC_URL=http://54.226.190.74:3000这样 MCP 查询仍走服务器本地 API,但返回的 asset.url / source.url 会是远程可访问地址。修改后建议重新运行 npm run sync:metabase;即使暂时不重同步,服务读取时也会按 METABASE_PUBLIC_URL 重写 Metabase 来源链接。
如果没有拿到 METABASE_API_KEY,可以用 Metabase 用户名密码:
METABASE_BASE_URL=https://metabase.example.com
METABASE_USER=your-user@example.com
METABASE_PASS=your-passwordMetabase connector 会用这组配置调用 POST /api/session 换取 session id,再用 X-Metabase-Session 请求 dashboard/card API。也兼容旧变量名 METABASE_USERNAME 和 METABASE_PASSWORD。
可以通过 MCP tool connector_status 检查配置是否齐全;它只返回是否配置和认证模式,不返回密钥或密码。
Metabase 用户授权与后台管理员登录
每个用户配置个人 MCP token,服务端用 token 反查对应的 Metabase 账号和 Session,并严格按该账号权限查询:
METABASE_BASE_URL=https://app-data.luteos.site
METABASE_LOGIN_URL=https://app-data.luteos.site
METABASE_AUTH_MODE=user-session
METABASE_ALLOW_SERVICE_FALLBACK=false
APP_DATA_MCP_PUBLIC_BASE_URL=http://127.0.0.1:3000
APP_DATA_REQUIRE_AUTH_TOKEN=true
APP_DATA_SESSION_FILE=.data/metabase-sessions.json个人 MCP token 本身不按时间过期,MCP 也不再使用 METABASE_SESSION_TTL_HOURS 主动判定底层 Session 过期。只要 Metabase 接受该 Session,服务就持续使用它。只有 Metabase 实际返回 HTTP 401 时,才返回 reauth_required,要求对应账号重新授权以替换平台 Session;同一账号重新授权时会生成新的个人 MCP token,并立即使该账号之前的 token 失效,也不会自动切换到统一服务账号绕过用户权限。
用户首次授权打开:
http://127.0.0.1:3000/auth/metabase/login授权后将页面生成的 Authorization: Bearer appdata_xxx 配置到 AI 助手。服务端只保存 token 哈希和 Metabase Session,不保存用户密码。
管理后台仍然要求使用 Metabase 管理员账号登录:
http://127.0.0.1:3000/admin只保存随机后台 Session 的哈希、CSRF token 和管理员邮箱到 PostgreSQL,不保存管理员密码。设置 ADMIN_SESSION_PERSISTENT=true 后,后台 Session 默认不设置服务端过期时间,并在管理员访问后台时滚动刷新浏览器 Cookie;服务重启不会要求重新登录。主动退出、清理数据库 Session 或浏览器清除 Cookie 后仍需重新登录。
审计日志
MCP tool 调用会写入 Postgres 审计表,默认表名:
public.app_data_mcp_audit_logs本地配置示例:
AUDIT_LOG_ENABLED=true
AUDIT_LOG_TABLE=app_data_mcp_audit_logs
AUDIT_REQUEST_PREVIEW_BYTES=12000
AUDIT_RESULT_PREVIEW_BYTES=16000
AUDIT_RESULT_PREVIEW_ITEMS=5
DB_TYPE=postgres
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=superset
DB_PASSWORD=123456
DB_NAME=cubecore
DB_SCHEMA=public
DB_SSL=false
DB_SSL_REJECT_UNAUTHORIZED=true
DB_SSL_CA_FILE=Amazon RDS 等要求加密连接的 PostgreSQL 需要设置:
DB_SSL=true
DB_SSL_REJECT_UNAUTHORIZED=true
DB_SSL_CA_FILE=/path/to/global-bundle.pemDB_SSL_CA_FILE 应指向数据库服务商提供的 CA bundle。仅在临时排障且无法立即安装 CA 时,可以设置 DB_SSL_REJECT_UNAUTHORIZED=false;连接仍会加密,但不会验证数据库服务器证书身份,不建议长期使用。
服务首次写入时会自动执行 create table if not exists,表名前缀为 app_data_mcp_,避免和业务表冲突。已存在的审计表会自动补新增列。审计日志记录:
用户邮箱、鉴权方式、AI 助手平台、request id、IP、user agent。
tool 名称、asset id、平台、资产类型、用户原始数据问题
question_text、查询文本query_text、limit。客户端传入的
conversation_id、turn_id、tool_call_id;未提供tool_call_id时使用服务端 request id。对
query_starrocks记录 SQL 文本、默认数据库和 SQL limit,便于追责与排障。问题、参数和实际返回内容的 SHA-256 哈希,便于判断内容是否变化。
脱敏后的完整工具请求参数预览,包括
question、调用关联 ID、资产、筛选条件和语义查询参数;默认最多 12 KB。返回行数、返回字节数、耗时、状态、错误摘要和结果预览。
每个 MCP tool 都要求 AI 在 question 参数中原样传递用户当前轮次的完整问题,并要求同一轮问题触发的多次调用复用相同 turn_id。conversation_id 和 tool_call_id 在客户端可以提供时一并传入。通用 MCP 客户端仍由模型填写这些参数;如果可以控制 AI 客户端或 MCP 网关,建议在发送 tools/call 前自动注入,以保证问题文本和关联 ID 完全准确。
请求参数预览默认最多保存 12 KB,普通工具的结果预览默认最多保存 16 KB。对象结构、计数、列信息等会保留;数组只保存前 5 项,并附带总项数和省略项数,因此大型 Dashboard、Card 或 SQL 查询不会把全部数据写入审计表。search_assets 是资产治理链路的核心审计信息,会完整保存本次返回的全部资产及其元数据,不受结果预览条数和字节数限制。所有预览中的 Authorization、token、Session、下载 URL、本地路径等敏感字段仍会被遮盖。普通工具的限制可通过 AUDIT_REQUEST_PREVIEW_BYTES、AUDIT_RESULT_PREVIEW_BYTES 和 AUDIT_RESULT_PREVIEW_ITEMS 调整。
AI 助手平台优先读取请求头:
X-App-Data-Client: claude-code
X-App-Data-Client-Version: 1.2.3客户端名称和版本优先读取上述请求头;未提供时,服务会读取 MCP 标准初始化请求中的 clientInfo,并按个人 MCP Token 将该身份关联到后续工具请求。Codex 的无状态工具调用还会通过请求 _meta 中的 Codex turn metadata 直接识别,不依赖 User-Agent 或服务进程内缓存;其他客户端最后再尝试从 user_agent 推断。当前可识别 WorkBuddy、Claude Code、Claude Desktop、Codex、ChatGPT、Cursor、Windsurf、Roo Code、Cline、Continue、GitHub Copilot、Gemini CLI、Kiro、Amazon Q、Goose、OpenCode、Zed、VS Code、JetBrains、MCP Inspector、Dify、Coze、n8n、LobeChat、Cherry Studio、AnythingLLM、Open WebUI、LangChain,以及常见 HTTP 调试客户端。未知但具有标准 产品名/版本 格式的客户端会保留产品名;确实没有可用标识时才记录为 unknown。历史审计记录如果曾写成 unknown 或未保存版本,后台列表也会根据已保存的 user_agent 重新识别。
不会记录完整的大型数据结果,也不会记录用户密码、Metabase session、个人 MCP token 明文。审计后台的“查看”操作可以看到用户原始问题、调用关联 ID、查询文本、返回大小、结果预览和各类哈希。
查看最近调用:
select
created_at,
user_email,
ai_client,
tool_name,
question_text,
turn_id,
asset_id,
status,
row_count,
result_bytes,
result_truncated,
duration_ms,
error_code
from public.app_data_mcp_audit_logs
order by created_at desc
limit 50;如果要临时关闭审计:
AUDIT_LOG_ENABLED=falsePostHog 同步脚本访问的是 private API,例如 dashboards 和 insights,需要 Personal API key。不要使用 Project API key / project token。POSTHOG_API_KEY 仍作为兼容别名支持,但建议新配置统一使用:
POSTHOG_PERSONAL_API_KEY=phx_...Personal API key 还需要 property_definition:read,用于只读同步公共属性定义。运行 Insight 需要
insight:read;执行动态 breakdown 还需要 query:read。
资产 ID 规范
建议使用统一 ID,避免 AI 客户端理解不同平台的内部 ID:
metabase:dashboard:101metabase:card:456或metabase:model:388posthog:dashboard:abcposthog:insight:activation-funnelmetric:activation_rate
后台管理与元信息配置
HTTP 服务启动后访问:
http://127.0.0.1:3000/admin后台使用 Metabase 账号登录,并通过 /api/user/current 校验 is_superuser=true。管理员可以:
在 Metabase、PostHog 导航中查看同步状态和元信息。
勾选或取消
is_published,也可以选择多条后批量开放或关闭;变更会立即影响 MCP 搜索和读取。点击列表字段标题可按开放状态、标题、类型、业务域、有效状态和同步时间排序。
Metabase、PostHog 和审计列表使用固定默认列宽;拖拽表头右侧分隔线可调整列宽,结果保存在当前浏览器。
业务域使用可搜索组合框,支持输入过滤候选项;也可按资产类型和开放状态筛选,并与关键词搜索、排序和分页组合使用。
编辑标题、描述、业务域、搜索别名/业务叫法、适用问题正例、不适用问题反例和 Card 指标集语义;业务域可选择已有值,也可输入新名称加入候选项,标签和负责人在编辑弹窗中只读展示。人工配置保存在
admin_overrides,后续同步不会覆盖。在详情弹窗查看 URL、SQL/查询定义、字段、参数、Dashboard 映射、血缘、权限快照、警告、样例数据和完整 JSON;同步字段只读。
在审计导航查看
AUDIT_LOG_TABLE中的用户、AI 客户端、tool、用户数据问题、资产、状态、行数和耗时。新日志直接展示question_text;旧日志兼容读取metadata.question或query_text。在 MCP 工具管理导航查看工具名称、分类、风险、详情描述和开放状态;关闭后工具不会出现在未授权账号的新 MCP 连接
tools/list中。query_starrocks和export_audience支持在操作列按用户邮箱授权。全局开放表示所有账号可见;全局关闭时只有显式授权账号能看见和调用,撤销授权后立即失效。MCP 工具管理页可查看和编辑连接时发送给 AI 的中文全局
instructions,并在工具详情中查看调用时机和参数说明;工具标识和参数名保留英文,确保客户端能准确调用。未授权工具不会出现在
tools/list中,实际发送给 AI 的说明也会移除所有提及该工具的语句,不暴露工具名称或禁用状态;服务端调用层会再次校验权限。
管理员登录会话持久化到 PostgreSQL 的 app_data_mcp_admin_sessions 表。浏览器 Cookie 只保存随机令牌,数据库只保存令牌哈希;服务重启后在有效期内无需重新登录。默认有效期为 168 小时,可配置:
ADMIN_SESSION_TTL_HOURS=168
ADMIN_SESSION_TABLE=app_data_mcp_admin_sessions元信息表默认名为 public.app_data_mcp_assets,主要字段包括 asset_id、platform、metadata jsonb、admin_overrides jsonb、is_published、is_active 和同步时间。metadata 内的核心内容包括:
title/description: 给 AI 搜索和理解使用。businessDomain/tags: 用于业务域过滤和召回。owner: 平台同步的负责人姓名或邮箱,也可由后台人工覆盖。retrieval: 人工维护的检索同义词、适用问题正例和不适用问题反例;正例增强召回,反例按问题相似度降权而不硬过滤。analysisType/insightSemantic: PostHog Insight 的分析类型、事件、拆分字段和过滤属性。url: 必填,保证每个结果都有原始出处。queryText: SQL、PostHog insight 描述或指标口径。columns: 字段说明。parameters: 可传给run_asset的只读参数说明,例如日期、国家、渠道、PostHog properties 等。semantic: Metabase Card 的指标集定义,包括基础粒度、默认时间维度、维度、指标、Rollup 与累计能力;由后台写入admin_overrides。dashboardParameterMappings: Metabase dashboard 筛选器到下属 card 的映射关系,用于判断某个筛选参数是否会真正影响某张 card。sourceRefs: 上游表、事件、引用资产等血缘信息。sampleData: 本地样例数据;live connector 失败或不支持时可作为兜底。warnings: 数据延迟、口径注意事项、MVP 限制。
MCP 工具配置默认保存在 public.app_data_mcp_tools,全局说明保存在 public.app_data_mcp_settings,按用户授权保存在 public.app_data_mcp_tool_permissions;可以通过 MCP_TOOLS_TABLE、MCP_SETTINGS_TABLE 和 MCP_TOOL_PERMISSIONS_TABLE 修改表名。HTTP 模式每次请求都会按个人 MCP token 对应账号读取最新开关、授权和说明;stdio 或已经建立的长连接需要重新连接后才会更新工具清单。
下一步建议
接入 momcozy-data-agent 的受控语义层查询 API,作为 Metabase/PostHog curated assets 的 fallback。
增加 token 自助吊销/轮换页面。
增加敏感字段脱敏策略。
根据你们实际口径补充指标 registry 和数据负责人信息。
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jedshen123/app-data-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server