分析 MCP 服务器 — 意图与错误分析
生成一份报告,回答关于已使用 Amplitude MCP 分析 SDK 进行插桩的 MCP 服务器的三个问题:
- 哪些工具被使用,哪些会失败?(按工具统计的调用量 + 错误率)
- 调用者试图用每个工具做什么,以及每个意图在哪里中断?(每个工具内部的 rationale 与 错误消息)
- 团队应该优先修复什么?(基于错误证据的修复方案,而非主观感受)
使此分析有价值的核心操作是:工具定位修复点;rationale 解释其背后的意图。 全局错误率只说“4.5% 的调用失败”。按工具分解后,它会说“query_chart 失败率为 22%”——现在你知道该打开什么了。在该工具内部添加 rationale,它会说“失败的是仪表板刷新 agent 遇到了批量大小限制”——现在你知道了原因,修复方案就自动清晰了。Rationale 在很大程度上是限定在工具范围内的(每个工具都有自己的调用原因),因此工具是主轴,rationale 是其中的第二轮分析——全局聚类 rationale 只会重新推导出工具边界,同时混合了不可比较的意图。
前提条件
-
Amplitude MCP 连接器已激活。如果未激活,请停止并让用户在工具/连接器设置中添加 Amplitude 连接器——没有备用数据源。
-
一个包含 SDK 事件的项目。SDK 会发出SDK 拥有的默认事件,所有事件均以
[MCP]为前缀,并且——至关重要的是——它们携带的每个默认属性也以[MCP]为前缀,它们可能还有自定义属性。事件:
[MCP] Tool Call Response— 主力:每次工具调用(成功或错误)到达工具回调时产生一个事件。[MCP] Tool Call Rejected— 在任何工具运行之前失败的tools/call(未知/禁用的工具、输入模式验证)。这里包含幻觉/拼写错误的工具名称,通过[MCP] Attempted Tool Name属性承载(避免使用保留属性[MCP] Tool Name)。[MCP] Session Initialized、[MCP] Session Ended、[MCP] Tools Listed。
[MCP] Tool Call Response的关键属性:[MCP] Tool Name、[MCP] Client Name、[MCP] Client Version、[MCP] Session ID、[MCP] Auth Type、[MCP] Rationale、[MCP] Is Error、[MCP] Error Message、[MCP] Error Type(returned_error与thrown_exception——区分是工具报告了失败还是工具崩溃)、[MCP] Response Duration、[MCP] Response Size、[MCP] Request Size。 -
事件/属性名称在不同 SDK 版本之间可能发生变动。永远不要假设——在阶段 0 中使用分类工具进行验证。上述规范名称源自 SDK 的
constants.ts(EVENT_PROPERTY_KEYS);如果项目的数据存在差异,则以项目为准并进行调整。
阶段 0 — 定位并验证数据
- 调用 Amplitude 上下文工具(不带 projectId)以列出项目。如果存在多个看似相关的项目且用户未指定,请询问。
- 确认选定项目中存在
[MCP]事件(搜索事件或列出事件;get_events仅按确切名称过滤,因此对[MCP]前缀发现使用搜索)。 - 拉取
[MCP] Tool Call Response(和[MCP] Tool Call Rejected)的事件属性,以确认确切的属性名称——记住它们以[MCP]为前缀且采用标题大小写(例如[MCP] Rationale,而不是tool rationale)。将你找到的名称绑定到下面查询中使用的名称。 - 运行一次体量/近因查询:过去 60 天内
[MCP] Tool Call Response、[MCP] Session Initialized的总量,按周间隔。这告诉你可用的日期窗口以及是否有足够的数据。如果总工具调用量低于约 5000,请警告用户按工具的细分将很薄弱且百分比不稳定——但仍要进行分析,但在报告中说明此情况。
记录:项目 ID、日期窗口、总调用量。之后的所有查询使用相同范围,以便数字保持可比性。
阶段 1 — 按工具分解(主轴)
这是主映射图;其他所有内容都深入其中。
- 按工具统计调用量:
[MCP] Tool Call Response的总量,按[MCP] Tool Name分组,groupByLimit ~100。 - 按工具统计错误: 同上,但增加过滤器
[MCP] Is Error is "true"。 - 按尝试名称统计被拒绝的调用:
[MCP] Tool Call Rejected的总量,按[MCP] Attempted Tool Name分组。这些调用永远不会到达回调,因此对上述两个查询不可见——但一个高体量的尝试名称并非真实工具,这是最具可操作性的发现之一(重命名或 agent 一直猜错的幻觉)。
计算每个工具的调用量、错误计数和错误率,并按两种方式对工具进行排名:按调用量(哪些是承载负载的)和按错误量(哪些造成最多的失败)。为深入分析选择前 3-5 个工具——倾向于高错误量,而不仅仅是高流量,如果用户指定了特定工具,则尊重他们的选择。一个低流量但错误率为 90% 的工具可以排在一个繁忙但健康的工具前面。
阶段 2 — 每个重要工具内部的 Rationale(“原因”)
对于每个重要工具,采样其 rationale——[MCP] Tool Call Response 的总量,按 [MCP] Rationale 分组,过滤到该特定工具([MCP] Tool Name is "<tool>"),groupByLimit ~150。然后读取它们,并按调用者试图使用此工具完成什么(而不是按措辞)进行分组。指导原则:
- 在单个工具内部,你通常会找到 2-5 个意图组,而不是九个——工具已经缩小了用途。按意图命名它们(例如,对于
query_chart工具:“实时仪表板刷新”、“即席探索”、“计划报表生成”)。 - 按调用量加权(每个 rationale 值都带有其总计),而不是按不同的字符串。
- 注意“垃圾”组: "placeholder"、"ignore"、"noop"、"test"、"dummy"、单个字母。其大小是一个 rationale 卫生发现,垃圾信息绝不能污染真实意图。
- 像 "Retry after rate limit" / "Retrying X" 这样的 Rationale 表明存在重试循环——请注意它们。
- 非英语 Rationale 是正常的;按含义对它们进行分组。
- 计算每个工具的 Rationale 覆盖率(该工具调用中带有非空 rationale 的占比)。如果覆盖率较低(<50%),则意图仅描述了其中一部分——请说明这一点,并且“在插桩时提高 rationale 覆盖率”本身就成为一项建议。
- 计算每个工具的顶级意图份额(最大的意图组占该工具有 rationale 覆盖的调用量的百分比)。这是集中度信号:约 90% 意味着该工具服务于一项任务,你可以为此进行硬优化(围绕该路径收紧模式/描述);而扁平分布(顶级意图约 30%)意味着该工具过载,可能需要拆分,或者其错误将分散在不同意图之间。报告该数字,当顶级意图占主导地位时,在旁边命名该工具及其意图。
跨工具工作流(次要): 某些 rationale 描述了一个多工具目标(“在刷新仪表板之前解析图表 ID”)。当一个意图明显跨越多个工具时(例如 search_events → create_chart → create_dashboard),在跨领域部分将其作为工作流指出——这是纯按工具视图会遗漏的唯一一件事。
阶段 3 — 每个工具的错误深入分析
对于每个重要工具,运行(过滤到该工具 + [MCP] Is Error is "true"):
- 按
[MCP] Error Message分组 → 为什么失败 - 可选地按
[MCP] Error Type(returned_error与thrown_exception)拆分,当消息有歧义时——崩溃和格式良好的拒绝都会引发[MCP] Is Error,但只有一种情况是工具中的错误。
对于阶段 2 中具有主导意图组的工具,通过 rationale 限定错误(添加 rationale-contains 过滤器)以得到“此意图以这种方式中断”的描述。
将每个显著错误消息分类为一个原型——原型决定了修复方案:
| 原型 | 特征 | 修复模式 |
|---|---|---|
| 过时/幻觉的工具名称 | [MCP] Tool Call Rejected,其中 [MCP] Attempted Tool Name = 一个重命名或看似合理的工具名称 | 为重命名的工具提供服务器端别名;拒绝响应中命名最近接的真实工具,以便 agent 能够一次性自我纠正 |
| 缺少必需参数 | 验证错误,“Required”,路径命名一个参数 | 放宽模式(接受单个值或数组,添加默认值),或在工具描述中说明要求,以便 agent 在调用前正确处理 |
| 模式形状不匹配 | "Expected object, received string" 等 | 在服务器端添加强制类型转换,或在工具描述中添加内联示例 |
| 硬限制冲突 | "Maximum of N …"、"too_big" | 提高限制,在服务器端自动分块,或在参数描述中说明限制——agent 目前只能通过失败来了解限制 |
| 范围/留存违规 | "time range too large"、"does not retain data before …" | 自动强制(例如降低粒度)而不是报错;在上下文负载中宣传留存/范围限制 |
| 鸡生蛋蛋生鸡参数 | 一个上下文/发现工具需要它本身就旨在提供的 ID | 使发现工具在零必需参数下工作,从认证令牌中默认获取 |
| 拒绝访问 | 角色/权限相关语言 | 使用不同的错误类,以便“不允许”可与“已损坏”区分;通常也是文档/入门方面的差距 |
| 重复的计划错误 | 每天在同一工具上重复相同的错误消息 | 如果是内部调用则修复作业的调用者;对于产品,标记为静默降级的自动化——没有人监视聊天窗口 |
| 临时/上游错误 | 5xx、超时、速率限制 | 在错误体中提供重试提示;检查是否实际进行了重试(参见循环漏斗) |
最好的错误消息会说明修复方法(“以 start >= ... 重新运行”)。衡量每个高流量错误消息是否达到该标准——“让这个错误像你最好的错误一样可操作”通常是一个合理的建议。
阶段 4 — 可选的上下文指标
如果时间允许则添加;它们会使分析故事更清晰:
- 重复错误循环: 3 步漏斗,每一步
[MCP] Tool Call Response且[MCP] Is Error is "true",保持[MCP] Tool Name恒定,转换窗口约 1 小时。显示有多少比例的错误用户在同一工具上陷入循环。(步骤不需要是连续事件——可以说“同一工具上 1 小时内出现 3 次以上错误”,而不是“连续 3 次”。) - 错误 → 恢复: 2 步漏斗,然后是成功,保持工具名称恒定。高恢复率加上高循环率共同意味着成本是浪费的令牌/延迟,而不是用户放弃——这是一个实质上不同的结论。
- 客户端组合: 按
[MCP] Client Name分组的唯一用户。大量“未知”份额或近乎重复的客户端名称(大小写、插件前缀变体)是值得报告的插桩发现。
阶段 5 — 验证,然后编写
在编写之前,至少通过第二种方式重新验证一个最重要的数字(例如,通过单独的两次事件总计查询验证总体错误率)。根据原始总计重新计算你引用的每个百分比。如果无法验证某个数字,则删除它或将其标记为估计值。
报告结构
使用此模板——按工具优先组织:
# MCP 服务器分析 — <服务器/项目名称>
数据:<项目>、<日期窗口>、<N> 次工具调用、总体错误率 <X>%。
方法说明:工具细分是精确查询结果;工具内意图是从 rationale 推导出的模型结果(方向性)。被拒绝的调用名称来自 [MCP] Tool Call Rejected。
## 工具概览
<table: 工具 | 调用量 | 错误数 | 错误率 | 顶级意图(份额%) | Rationale 覆盖率>
<一行关于拒绝/尝试过的工具名称(如果重要);如果重要,指出垃圾 rationale>
## 深入分析:前 3-5 个工具(按错误量排名)
对于每个工具:
**工具:<名称> — <调用量>、<错误率> — 用途:<一句话>**
- 意图(此工具内的 rationale):<组 : 份额>,…
- 1-4 条编号的建议。每条都陈述证据(错误消息 + 计数)、原型和具体修复方法。以消除最多错误量的修复方法开头。
## 跨领域发现
<跨工具工作流、循环/恢复率、客户端名称卫生、rationale 卫生、内部测试流量…>
## 一句话总结
<移除最多失败量的那个更改,及其数字>
风格:每个声明旁边都要有数字;逐字引用错误消息(可截断),以便工程师可以用 grep 搜索;建议应表达为行动(“为 query_chart → query_charts 提供别名”),而不是观察(“工具命名可能改进”)。
输出中的图表
在客户端支持的地方,使用即席图表查询 + 渲染工具渲染支持性的 Amplitude 图表(构建 eventsSegmentation/funnels 定义,然后渲染它)。仔细考虑哪些可以且不能作为图表:
- 可图表化——任何由查询支持的数据。 这些是真实的 Amplitude 分段/漏斗结果,因此渲染它们:按工具划分的调用和错误(按
[MCP] Tool Name分组)、错误率随时间的变化、按[MCP] Attempted Tool Name划分的被拒绝调用、每个工具的重复错误循环和恢复漏斗,以及按[MCP] Client Name划分的客户端组合。工具分解是自然的主角图表。 - 不可图表化——工具内的意图组。 将 rationale 分组为意图是在该模型中发生的;这些分组在 Amplitude 中不作为属性存在,因此没有保存的“按意图划分的调用”图表。将意图作为基于 rationale 总计构建的表格呈现,并明确指出意图数据是模型推导的(方向性),而渲染的图表是精确查询结果。不要暗示渲染的图表支持意图分组。
查询食谱
所有查询都是针对阶段 0 中的项目 ID 的 eventsSegmentation 或 funnels 定义。将事件/属性名称调整为阶段 0 验证后的名称。已知有效的形状:
工具分解(阶段 1):
{"type":"eventsSegmentation","app":"<PROJECT_ID>","name":"[MCP] 按工具划分的调用",
"params":{"range":"过去 30 天",
"events":[{"event_type":"[MCP] Tool Call Response",
"group_by":[{"type":"event","value":"[MCP] Tool Name"}]}],
"metric":"totals","countGroup":"User","groupBy":[],"int
…
[为翻译而截断]