PostHog MCP 会话分析指南:从一次 Agent 运行到完整工具调用轨迹的排查实战
【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog
MCP(Model Context Protocol)会话是理解 Agent 行为的最小单元:一次 Agent 运行产生的一组$mcp_tool_call事件。本文基于 PostHog 开源仓库中products/mcp_analytics模块的会话分析技能文档,系统讲解如何使用类型化 MCP 工具(posthog:mcp-analytics-sessions-list、posthog:mcp-analytics-sessions-tool-calls、posthog:mcp-analytics-sessions-generate-intent)逐层下钻单个会话,以及在类型化工具力不能及的四类场景下降级到 HogQL。读完你不仅能回答"这个 MCP 会话做了什么""哪个会话出错了""谁在连接我的 MCP",还能掌握$mcp_*事件模型的底层原理与日期窗口陷阱。
MCP 会话的数据模型:没有独立表,一切都在 events 上
一个 MCP 会话(session)的定义非常朴素:共享同一个$session_id的一组$mcp_tool_call事件,按timestamp排序。任何用@posthog/mcpSDK 埋点的 MCP 服务器,以及 PostHog 自家的托管 MCP 服务器,都会在每次 Agent 调用工具时向共享的events表写入一条$mcp_tool_call事件。
这里有一个关键的架构事实(见共享参考文档 models-mcp.md):MCP 分析没有专门的 ClickHouse 表,所有字段都以$mcp_*属性形式挂在events行上,直接通过posthog:execute-sql查询。MCP 分析仪表盘、工具质量、工具详情页面背后的全部数据,都可以用 HogQL 在这类事件上复现。
与"会话"相关的三个核心标识符需要分清(models-mcp.md):
| 标识符 | 含义 | 持久性 |
|---|---|---|
$session_id | 物化事件列,是GROUP BY/ 关联的主键 | 与$mcp_session_id同值 |
$mcp_session_id | 传输层会话句柄(MCPextra.sessionId或框架会话 cookie) | 进程重启、重连、框架边界时轮换 |
$mcp_conversation_id | Agent 回显的稳定标识 | 跨重连稳定,需要会话跨客户端重连存活时使用 |
实践中$session_id与$mcp_session_id携带相同的值;当它们分歧时,$mcp_conversation_id是更持久的那一个。
工具总览:先上类型化工具,再考虑 SQL
探索会话有三类任务(列会话、读某会话的工具调用、总结会话目标),每种都对应一个类型化工具,应优先使用:
| 工具 | 用途 |
|---|---|
posthog:mcp-analytics-sessions-list | 列会话——每个会话一行,最新的在前 |
posthog:mcp-analytics-sessions-tool-calls | 单个会话的工具调用,按时间顺序 |
posthog:mcp-analytics-sessions-generate-intent | 会话目标的 LLM 摘要(首次调用后缓存) |
posthog:execute-sql | 出错会话、有效工具名、跨会话切分 |
三个mcp-analytics-*工具被mcp-analytics功能开关(feature flag)门控,并且与会话 UI 运行同一套代码,因此结果与屏幕一致。这一点在工具定义文件中有明确佐证:products/mcp_analytics/mcp/tools.yaml中每个会话工具都标注了feature_flag: mcp-analytics,例如mcp-analytics-sessions-list(tools.yaml)和mcp-analytics-sessions-tool-calls(tools.yaml)。
如果这些工具不在你的工具列表里,说明该项目没有开启该功能开关——此时回退到posthog:execute-sql,它不受门控限制,可以随时使用。
首先阅读:7 天窗口陷阱
两个详情工具默认只有7 天回看窗口。你在列表中看到的一个更早的会话,如果不传它的session_start作为date_from,详情查询会返回空:
posthog:mcp-analytics-sessions-tool-calls——date_from是绝对 ISO 时间戳,请传入从posthog:mcp-analytics-sessions-list拿到的session_start;posthog:mcp-analytics-sessions-generate-intent——同样的date_from查询参数,同样原因。
这个默认值在源码中有两处印证:会话列表的默认窗口是DEFAULT_SESSIONS_DATE_FROM = "-7d"(logic.py),而会话详情查询的兜底扫描范围是SESSION_EVENTS_LOOKBACK = timedelta(days=7)(intent_generation.py)。其技术原因是:$session_id不在 events 的排序键(sort key)中,没有时间戳下界,扫描会覆盖团队全部历史,所以必须用session_start让排序键剪枝。
经验法则:一个明明存在却返回空工具调用的会话,几乎总是这个原因,而不是数据问题。把
session_start从列表行一路携带到详情调用。
工作流一:列出最近的会话
posthog:mcp-analytics-sessions-list { "date_from": "-7d", "order_by": "-session_start", "limit": 100 }每行包含:session_id、tool_calls、session_start、session_end、tools_used、mcp_client_name、distinct_id(以及解析后的person_email/person_name)和intent(生成前为空)。响应格式为{ results, has_next },用limit/offset翻页。对应的后端契约在 contracts.py 中定义,分页器返回{results, has_next}而非计数封套(views.py)。
分页上下限在序列化器里是硬约束:列表默认limit为 100、最大 500(serializers.py)。
三个易踩的坑
1.order_by接收的是列名,不是响应字段名。按调用量排序要写成tool_call_count(而不是tool_calls)。duration_seconds虽然不出现在响应中,却可以正常排序。无法识别的键会静默回退到"最新在前"——所以务必核对返回的顺序是否是你要求的顺序。
合法取值:session_id、session_start、session_end、duration_seconds、tool_call_count、mcp_client_name、distinct_id;前缀-表示降序。后端的白名单实现是SESSION_SORT_FIELDS冻结集合 +_normalise_order_by校验,不在白名单的字段一律回退默认(logic.py、logic.py)。前端逻辑也明确声明了与后端保持一致的列名集合(mcpSessionsLogic.ts)。
2. 会话行上既没有错误过滤,也没有错误计数。"哪些会话出错了?"是一个 SQL 问题,见下文。
3.distinct_id_count恒为0。该字段在响应中存在,但后端从不填充——_to_session_contract中硬编码distinct_id_count=0(logic.py)。所以不要把它读成"每个会话一个 distinct id",它不表达任何含义。要统计会话内的 distinct id 数,请用 SQL。
search 参数
search在session_id、distinct_id、mcp_client_name、tools_used上进行大小写不敏感的子串匹配。底层是聚合后(折叠进 HAVING)的过滤,这样命中返回的是整个会话而不是单个事件(logic.py)。
工作流二:读取单个会话的工具调用
posthog:mcp-analytics-sessions-tool-calls { "id": "<session_id>", "date_from": "<session_start>", "limit": 500 }返回按时间顺序排列的tool_name、intent、timestamp、duration_ms、is_error、error_message——从上到下通读即可重建这次运行。limit默认为 500(也是最大值),对几乎每个会话来说这一页就是全部;has_next告诉你是否还有更多。
序列化器把默认值设成了与最大值相同(MCP_TOOL_CALLS_DEFAULT_LIMIT = 500),意味着省略limit的调用方直接拿到整个会话的调用列表(serializers.py)。后端 SQL 用$session_id物化列 +date_from下界做剪枝,按timestamp ASC, event_id ASC排序(logic.py)。
注意:这里的tool_name是原始$mcp_tool_name。与工具质量和工具详情工具不同,这个端点不解析 single-exec 包装调用中的内部工具,包装调用会显示包装器本身。当内部工具才是关键时(对比工具质量排名、追踪某个具体工具在一次运行中的轨迹),改用下面的 SQL 配方。同样的限制也适用于会话列表上的tools_used。
工作流三:总结 Agent 的目标
posthog:mcp-analytics-sessions-generate-intent { "id": "<session_id>", "date_from": "<session_start>" }该工具通过 LLM 总结会话记录的$mcp_intent值并持久化结果;后续调用返回缓存的摘要。返回{ session_id, intent }。
底层机制非常清晰(logic.py + intent_generation.py):
- 首次调用:先查
MCPSession模型是否已有持久化的intent,没有则从 ClickHouse 拉取该会话按时间排序的$mcp_intent列表(上限MAX_INTENTS = 500,intent_generation.py); - 若会话没有任何已记录意图,直接返回固定文案
"No agent intent was recorded for this session."(NO_INTENT_MESSAGE),不触发 LLM 调用也不持久化,因此保持可重试; - 否则交给
gpt-4.1-mini(temperature=0、max_tokens=90、30 秒超时)做摘要,system prompt 要求"最多两句话、20 词以内、直接陈述目标、不得以 'The agent' 开头、不得罗列工具"(intent_generation.py); - 摘要写入
MCPSession(每(team, session_id)一行),之后的调用直接返回存储值。
返回 503 表示 LLM 摘要功能未配置(OPENAI_API_KEY缺失,或组织未批准 AI 数据处理),视图层捕获IntentGenerationUnavailable后返回干净的 503 而非 500(views.py、contracts.py)。此时回退方案:从工具调用列表中直接阅读原始$mcp_intent值。
何时降级到 SQL
有四类场景,全部通过posthog:execute-sql完成——它不像上面的类型化工具那样受mcp-analytics开关门控。
场景 1:项目没有mcp-analytics功能开关
类型化工具根本不会出现在工具列表里。下面的一切仍然可用,这条查询就是普通的会话列表:
SELECT $session_id AS session_id, min(timestamp) AS session_start, max(timestamp) AS session_end, dateDiff('second', min(timestamp), max(timestamp)) AS duration_seconds, count() AS tool_calls, countIf(toBool(properties.$mcp_is_error)) AS errors, any(properties.$mcp_client_name) AS client FROM events WHERE event = '$mcp_tool_call' AND $session_id != '' AND timestamp >= now() - INTERVAL 7 DAY GROUP BY session_id ORDER BY session_start DESC LIMIT 50这段 SQL 与后端_MCP_SESSIONS_SQL的聚合形状一致(min/max/count/argMax按$session_id分组,logic.py)。
场景 2:查找出错会话
会话列表无法过滤或统计错误——给上面的查询加上HAVING errors > 0,并按errors DESC排序:
SELECT $session_id AS session_id, min(timestamp) AS session_start, max(timestamp) AS session_end, dateDiff('second', min(timestamp), max(timestamp)) AS duration_seconds, count() AS tool_calls, countIf(toBool(properties.$mcp_is_error)) AS errors FROM events WHERE event = '$mcp_tool_call' AND $session_id != '' AND timestamp >= now() - INTERVAL 7 DAY GROUP BY session_id HAVING errors > 0 ORDER BY errors DESC LIMIT 50场景 3:会话内的有效工具名
类型化工具调用端点没有应用的 coalesce,这里补上:
SELECT timestamp, coalesce(nullIf(toString(properties.$mcp_exec_tool_call_name), ''), toString(properties.$mcp_tool_name)) AS tool, toBool(properties.$mcp_is_error) AS is_error, toString(properties.$mcp_error_message) AS error_message, round(toFloat(properties.$mcp_duration_ms)) AS duration_ms FROM events WHERE event = '$mcp_tool_call' AND $session_id = '<session_id>' ORDER BY timestamp ASC这是"有效工具名"(effective tool name)的标准公式:新 SDK 事件把真实工具放在 single-exec 包装里,因此要用coalesce(nullIf($mcp_exec_tool_call_name,''), $mcp_tool_name)还原 Agent 实际调用的工具(models-mcp.md)。
场景 4:跨会话聚合
"每天的会话数""先用了工具 X 然后失败的会话"、自定义维度拆解等,配方见共享参考文档 models-mcp.md,其中包含工具质量矩阵、每日活动序列、harness(客户端)分桶、工具共现等完整 SQL 示例。
关键细节:$session_id是物化事件列
$session_id是物化事件列,与$mcp_session_id是同一个 id。请直接裸引用它,永远不要写成properties.$session_id:properties.访问器在 SELECT 中渲染为 null 包装,但在 HAVING/ORDER 中渲染为原始列,因此 HAVING 搜索会与 GROUP BY 键不匹配,ClickHouse 会直接拒绝查询(logic.py 的注释明确记录了这一陷阱)。
构造 UI 链接
- 会话列表:
https://app.posthog.com/project/<project_id>/mcp-analytics/sessions
在网页 UI 中看到会话详情时,你可以直接粘贴该 URL 给 Agent 作为分析的起点。
实战技巧
- 一个调用很多但没有错误、却突然结束的会话,通常意味着Agent 放弃了——检查最后一个调用是否返回了很大或空的结果;
$mcp_intent只在客户端提供时才存在,缺失很常见,所以generate-intent是更可靠的目标信号;- 要从一个失败的工具体(见 exploring-mcp-tool-quality)追溯到命中它的会话,用工具名
search会话列表——但要记住tools_used保存的是原始名称,所以要搜注册名而不是内部工具名。
数据口径提醒
查询时请使用规范的$前缀事件名。SDK 埋点的服务器只发出$mcp_tool_call/$mcp_initialize;PostHog 自家的托管服务器额外通过过渡 shim 双发未加前缀的旧别名。只匹配规范名称——写event IN ('mcp_tool_call', '$mcp_tool_call')会把 PostHog 自家服务器的数据重复计数(models-mcp.md)。
相关技能
- exploring-mcp-tool-usage——总入口:把宽泛的"我的 MCP 表现如何?"问题路由到正确工具;
- exploring-mcp-tool-quality——跨所有工具的错误率与延迟;
- exploring-mcp-intent-clusters——在众多会话之间按目标分组。
三个技能与本篇共同构成 MCP 分析(products/mcp_analytics模块)的完整排查链路:先看总览与工具质量,再下钻单个会话,最后横向聚合目标聚类。
【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考