已部署的 MCP 工具中,五分之三不告诉智能体自己会做什么
2026 年 9 月 10 日发布的一份 MCP 注册表概率抽样测量显示,58.8% 的已部署工具没有任何安全注解,而人工精选样本将这一差距低估了 17 个百分点。
这是什么?
2026 年 9 月 10 日,独立研究者 Haseeb Mohammed Afsar 发表了一项测量研究,对 Model Context Protocol 服务器群体做了现有文献未曾做过的事:抽取概率样本,并且拒绝修复任何东西。
该研究基于对官方 MCP 注册表的普查——2026 年 8 月 22 日的扫描记录到 24,135 个服务器,而 2026 年 7 月 14 日为 16,548 个——构建了一个包含 7,258 条 npm 发布、声明使用 stdio 的活跃条目的抽样框,用公开的随机种子抽取 400 个,并对每一个恰好探测一次。不提供凭据,不重试,不做任何修复。全部 400 次抽取均记录结果。
对安全态势而言,有两个数字值得关注。只有 48.8% 完成了 initialize 握手。 而在成功启动的 195 个服务器所公布的 2,766 个工具中,1,626 个(58.8%)没有任何安全注解。
工作原理
MCP 的 ToolAnnotations 随 2025-03-26 规范修订版推出,是四个可选布尔值,让服务器在客户端调用之前说明一个工具会做什么:readOnlyHint、destructiveHint、idempotentHint、openWorldHint。这就是该协议全部的调用前风险词汇表。
规范在两个方向上都对其保持谨慎。首先,它们是提示而非契约——2026 年 3 月 16 日 MCP 维护者的一篇文章重申,客户端必须将来自不可信服务器的注解视为不可信,因为服务器完全可以声明 readOnlyHint: true 却照样删除您的文件。其次,默认值被刻意设定得悲观:未加注解的工具应被假定为非只读、可能具有破坏性、非幂等且面向开放世界。
这个默认值是整个设计的承重部分。它只有在客户端遵守时才会产生安全行为,而在 58.8% 的缺失率下遵守它,意味着智能体可触及的工具中约有五分之三都需要向用户弹出确认。
该测量还显示了缺失集中在何处,而且分布并不分散。在公布至少一个工具的 194 个服务器中,72 个为所有工具都加了注解,122 个一个也没加。 样本中没有出现任何部分注解的服务器。作者拒绝将其表述为绝对结论——194 次观察中出现 0 次,支持的是部分注解流行率的 95% 单侧上界 1.53%,而非否定——并说明此前一次未发布的运行曾发现四个部分注解的服务器,本次运行未能复现。
从抽样框中抽取 400 个服务器
├─ 握手完成 195 48.8% ← 唯一被普遍测量的一层
├─ 从未启动 150 37.5%
├─ 需要凭据 53 13.3%
└─ 软件包不可用 2 0.5%
在启动的 195 个中 → 公布 2,766 个工具
├─ 致命 JSON Schema 违规 0 0.0%
└─ 无安全注解 1,626 58.8% (精选样本:41.5%)
关于模式(schema)的那一行值得留意,因为它与一种常见假设相反:2,766 个工具中,致命 JSON Schema 违规为零。 实践中,MCP 工具模式并不畸形。全部差异都出现在可选元数据上。
为什么重要
影响最深远的发现并非 58.8%,而是人工精选会在两个方向上同时美化生态系统的健康状况。用同一套工具测量一个由 24 个参考服务器与热门服务器组成的人工精选样本,启动率为 66.7%(高出 17.9 个百分点),注解缺失率为 41.5%(低出 17.3 个百分点)。参考服务器会加注解,而精选样本里满是参考服务器。任何取自热门榜单、参考集合,或取自”反复修复服务器直至其启动”的流水线的态势统计,衡量的都是一个因”能运行”而自我选择出来的群体。
这直接影响我们该如何阅读其余的 MCP 安全文献。Nicolás Padilla 于 2026 年 7 月 31 日发表的动态评估覆盖 414 个面向互联网的服务器——68 项可报告发现,91.8% 未启用 OAuth,且两次测量之间有 41.6% 的已确认服务器在三天内消失——从远程一侧印证了同样的高流动性。现在有两套独立的测量工具一致表明:注册表所公布的内容中,有很大一部分并不是持久运行的东西。
对客户端而言,一个未加注解的工具只留下两个选择,在这一比例下都很糟糕。遵守悲观默认值,就会在大部分工具面上产生确认弹窗,而这正是训练用户闭眼点击的方式——我们在审批对话框所拦截的与其所展示的之间的落差一文中讨论过同样的疲劳。忽略默认值,则等于悄悄自动批准了一批无人声明其行为的工具。维护者自己的文章也指出,目前没有任何 MCP 客户端允许用户按注解值筛选工具,也没有任何客户端在审批提示中呈现注解——实际上,这套词汇表的大部分并未抵达它本应支撑的那个决策。
那 37.5% 从未启动的条目是第二层面的问题。当一个注册表中五分之二的已发布条目处于惰性状态,它就充满了指向虚无的名字——而指向虚无的名字,正是攻击者可以让它指向某物的名字。这正是审批之后改写工具描述以及 Deadbugz 运行时触发型元数据活动背后的安装路径卫生问题——在那些案例中,敌意行为只在获得批准之后才出现。
最后一项结果,提供给评测智能体的人:在保持同一相似度方法的前提下,真实 MCP 工具在余弦 0.70 阈值下的近重复率为 2.8%,且在所有测试阈值下,跨独立作者的近重复率均为 0.0%。BFCL v4 为 16.7%,其中 16.4 个百分点落在彼此独立呈现的任务之间。在去重之前,BFCL 原始条目有 68.8%、UltraTool 有 85.6% 是”名称加描述”的完全重复,而真实 MCP 仅为 0.4%。去重之后,UltraTool 以 0.3% 比真实工具更”干净”,因此这是某一个语料库的属性,而非合成语料库作为一类的属性——论文对此有明确说明。可操作的结论是:在这些发布数据上不做全局去重而计算出的统计量,衡量的是重复,而不是工具。
防御措施
把缺失的注解当作一项发现,而不是一个默认值。 如果您运营内部 MCP 网关,请对每个已注册服务器枚举 tools/list,并按服务器上报注解缺失率。全有或全无的分布让这件事成本很低:您分类的是服务器,而不是工具。
不要让缺失的提示变成隐式批准。 无论您的客户端如何处理 destructiveHint: true,它都应以同样方式处理完全没有提示的工具。这正是规范默认值所要求的,也是客户端最少实际执行的一种情形。
绝不让来自不可信服务器的提示放松任何管控。 注解由服务器自行撰写且无人验证。请用它们来收紧态势——标记为 openWorldHint: true 的工具应使该会话被视为携带不可信内容——而绝不用来跳过关卡。当您需要的是保证而非提示时,请把它放在授权层、传输层或沙箱中。强制执行应当位于能够强制执行的地方。
锁定安装路径,而不是注册表名称。 在 37.5% 的未启动率之下,注册表中的大多数条目并非您的实际依赖——但您确实依赖的那些,应当按版本与完整性哈希锁定,从您自己控制的镜像解析,并在每次重连时重新校验,而不是在首次握手之后就一直信任。
重新审视您自己的态势数据。 如果某份厂商报告、内部审计或扫描器基准测试抽取的是热门或参考服务器,请假定它在启动率和注解覆盖率两方面都乐观了约 17 个百分点。在把这个数字写入风险登记册之前,先问清楚它的抽样框是什么。
为您发布的东西加上注解。 如果您编写服务器,请为只读工具设置 readOnlyHint: true,为纯增量操作设置 destructiveHint: false,为封闭域工具设置 openWorldHint: false。代价是四个布尔值,而这是客户端在调用之前能得到的唯一信号。
状态
| 项目 | 详情 |
|---|---|
| 发表 | arXiv:2609.10962v1 [cs.SE],2026 年 9 月 10 日 |
| 作者 | Haseeb Mohammed Afsar(独立研究者) |
| 普查扫描 | 2026 年 7 月 14 日(16,548 个服务器)与 2026 年 8 月 22 日(24,135 个服务器),两次均完整 |
| 样本 | 400 个 npm/stdio 服务器,种子 20260819,抽样框以 SHA-256 锁定 |
| 关键数字 | 启动率 48.8%;2,766 个工具中 58.8% 未加注解;致命模式违规 0 例 |
| 精选效应 | 在 24 个服务器的精选样本上,启动率高 17.9 个百分点,注解缺失率低 17.3 个百分点 |
| 佐证 | arXiv:2608.00150(2026 年 7 月 31 日),414 个暴露服务器,41.6% 在三天内消失 |
| 范围限制 | 仅限 npm/stdio(占群体 30.7% 且在下降);单次探测、不重试——48.8% 为下界 |
| 可复现性 | 已公开测量工具、种子、每次抽取的结果与脚本;Zenodo 概念 DOI 10.5281/zenodo.21347997 |