研究对 377 个 MCP 服务器的 7164 个工具进行分析,发现 45.8% 的服务器含有命名或描述重叠的工具对,Agent 可能误调用。
一位读者针对我上一篇文章提出了一个观点,当时我无法回答,于是我实际测量了一番。
这个观点是:“新增工具”并不天然意味着这是一次安全的变更。此前,我一直把新增工具归为无害变更,因为所有旧调用依然能够通过其 schema 的验证。但验证不等于选择。新工具如果与现有工具存在功能重叠,就可能截获原本会被路由到其他工具的调用,而且整个过程不会出现任何报错——Agent 只是悄无声息地开始执行不同的操作。
我说过,用名称重叠来判断是最显而易见的第一层近似,而且显然并不完整。这两点都没错。下面是它揭示的结果。
在 registry 中列出、且能完成匿名握手的 377 个 MCP server,共提供了 7,164 个工具。我比较了每个 server 内部的所有工具组合,总计 170,345 对。如果一对工具的名称共享了大部分 token、描述高度重叠,或者名称和描述都存在中等程度的重叠,就会被标记出来。
377 个 server 中,有 173 个(45.8%)至少存在一对容易混淆的工具。
所有工具对中只有 1.15% 被标记。换个角度看,这其实描述的是同一个事实:混淆问题集中出现在工具数量庞大的 server 中,而不是均匀分布在所有 server 里。
list_skills <-> get_skills (identical tokens)
legislation <-> list_legislation
tf_briefing <-> tf_premium_briefing
ask_pipeworx <-> ask_pipeworx_beta
ask_pipeworx <-> ask_pipeworx_grounded
paid_crypto_call_pack <-> paid_esports_call_pack (near-identical descriptions)
list_skills 与 get_skills 是一个很典型的真实案例。对人类来说,两者确实存在明确区别。但对于一个需要在 token 压力下从扁平列表中做选择的模型来说——尤其是它未必会仔细阅读描述——这几乎就是一次抛硬币,而这个选择过程还不会被任何人记录下来。
我的第一轮分析专门寻找名称仅在商业层级词上有所不同的工具,例如 free 与 premium、pro、plus。如果 Agent 在这里选错了,那就不是正确性 bug,而是计费 bug。我原本觉得这种情况可能随处可见。
第一轮结果显示:101 个 server 中存在 147 对,占 26.7%。
这个数字错了大约 33 倍。我想明确说出其中的两个原因,因为这两种错误都非常容易犯:
我把 deep、full、advanced 和 extended 也算作了层级词。但它们并不是——这些词描述的是工具会完成多少工作,而不是工具的价格。deep_research 与 bet_research 因此被标记成了一对计费工具,这显然毫无道理。
有一个 gateway(gateway.pipeworx.io)通过 13 个不同的 endpoint 发布了相同的工具设计。我把它计算了 13 次。但这只是一个设计决策,不是 13 项独立发现。
把范围收紧到含义明确的计费词,并按照工具对的 signature 去重后,结果变成了:3 个 server 中共有 47 对不同的工具,不到 1%。
所以,最鲜明的这种情况其实很少见。但它确实存在,具体是这样的:
tf_briefing <-> tf_premium_briefing
get_game_recommendation <-> get_premium_game_recommendation
gpt55_summarize <-> gpt55_summarize_plus / gpt55_summarize_pro
gpt55_translate <-> gpt55_translate_plus / gpt55_translate_pro
其中一个 server 为四种不同的操作分别提供了 free、_plus 和 _pro 版本。如果 Agent 只能根据名称相似度在这些工具之间做选择,它实际上是在进行一次购买决策,却没有任何信号提醒它正在做出这样的决定。
总体问题确实存在:大约 46% 的 server 至少会给 Agent 提供一个真正模棱两可的选择。在一个已经拥有 40 个工具的 server 中再添加一个工具,绝不是无影响的操作。那位反驳我的读者是对的。
计费问题虽然少见,却最值得设置 guard rail,因为这是唯一一种失败会产生直接成本、同时又不会暴露任何错误的类型。如果你同时提供付费和免费版本,请在描述中写明价格,并在 annotations 中标明层级,而不要只把它放在工具名称里。
此外,这项测量基于词汇分析,这是一个实实在在的局限。它无法判断两个名称完全相同的工具实际上执行着不同的操作,也会把一些有能力的模型可以轻易区分的工具对标记出来。因此,应当把 45.8% 视为歧义比例的上限,同时也视为这个问题值得投入多少思考的下限。
本次分析使用了与我之前文章相同的固定随机样本(random.seed(20260730)),样本取自能够响应匿名握手的 5,346 个 registry endpoint,因此这个系列中的结果可以相互比较。调用流程为 initialize → notifications/initialized → tools/list,并处理了 SSE frame 和 Mcp-Session-Id 的传递。工具对比较则分别对名称 token 和移除 stopword 后的描述词计算 Jaccard similarity。
原始工具 inventory 已经缓存,因此在收紧定义之后,我可以针对完全相同的数据重新运行层级分析——这也是为什么我能在发布之前发现那个 33 倍的误差,而不是等到发布之后才发现。
前文:schema drift 不是一个比率,而是一小群永远不会停止变化的 server。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。