MCP 服务端坟场:当你的智能体依赖停止更新时
你的 Agent 每五分钟调用一次的 MCP 服务,其最后一次 commit 还是在八个月前。它所封装的上游 API 在二月份推出了新的身份验证模型。目前有 47 个未解决的 issue,其中 12 个被标记为安全风险。维护者的 GitHub 账号自十月以来就没有过任何活动。你的 Agent 仍然能够连接,仍然能够接收工具描述,仍然能够执行调用 —— 而在无声无息中,每一次调用都流经一段无人看管的基础设施。
这就是 MCP 被遗弃的现状。不是恶意的卷款跑路(rug pull),也不是被攻破的软件包,仅仅是由于疏忽。有人在 2025 年发布了一个有用的服务,被大家采用后,便转向了其他项目。该服务之所以能继续运行,是因为没有任何因素强行让它崩溃。直到它彻底崩溃 —— 而到那时,你的 Agent 每五分钟跨越一次的信任边界其实早已失效。
大多数团队采用社区 MCP 服务的方式与采用 npm 包的方式如出一辙:运行 install 并阅读 README。这种思维模型在面对 MCP 时失效了。在 MCP 中,依赖是一个动态的信任边界,LLM 在循环中携带凭据,并在生产数据上对其进行调用。
遗弃是供应链风险的隐蔽版本
主动攻击会留下痕迹。恶意的 commit 会出现在 diff 中。凭据窃取尝试会触发你的出口流量监控。被投毒的工具描述有时会出现在提示注入检测器中。即使你读取信号的速度很慢,但信号确实存在。
遗弃则没有任何信号。服务依然在它的 socket 上响应。工具描述依然渲染在 Agent 的上下文窗口中。每一次调用依然返回 200 状态码和看起来正确的 JSON 主体。其失败模式并不是“东西停止工作了”,而是“这东西在无声无息中停止了与它所对话的世界保持同步”。
与此同时,世界在变。上游 API 增加了新的必填字段。该服务的某个间接依赖项公开了一个 CVE。协议本身发布了新的功能版本。该领域的安全最佳实践也在演进。你的系统不会因此触发任何警报,因为这些变化都不会改变你的 Agent 与这个孤儿进程(orphaned process)之间的 socket 形态。
最近的行业研究表明,已公开 CVE 的平均利用时间(time-to-exploit)为五天。一个静默了六十天的 MCP 服务,从定义上讲,已经错过了该窗口期内的每一次安全更新 —— 包括它自己的代码、运行时以及其下方的传递依赖链。你不会收到任何警告,你运行的是一个已存在已知漏洞的信任边界。
基础概率比你想象的要糟糕得多
npm 生态系统是 MCP 发展趋势最接近的参照物,而其数据令人警醒。针对该注册表(registry)的学术研究发现,下载量最高的软件包中有 8.2% 已被官方弃用;如果将定义扩大到包括存档的仓库和没有 GitHub 记录的包,这一比例将推高至 15% 左右。npm 上约 61% 的软件包在过去十二个月内没有任何发布。超过一千天未触及的包在实践中被视为无人维护 —— 当它们的漏洞浮出水面时,不会有任何补丁。
用户每周从 npm 下载超过二十亿次已弃用的软件包。下载量、流行度得分、甚至是注册表中的显著排名,几乎无法告诉你代码是否正在被积极维护。
MCP 生态系统继承了这种动态,并缩短了演进的时间线。到 2026 年 3 月,Python 和 TypeScript 的 MCP SDK 每月总下载量已突破 9700 万次。公共注册表索引了大约一万二千到两万个服务,尽管目录公开指出“许多是分叉版本、变体或已被遗弃”。十八个月的爆发式增长建立在一个成熟度曲线尚未弯曲的协议之上。大多数社区服务都是个人开发者的周末项目,为了抢占命名空间而匆忙发布。MCP 维护者注意力的统计分布几乎肯定比 npm 的情况更糟,而不是更好。
这种命名方式本身就很说明问题。一个如此年轻的协议,拥有如此饥渴的社区,产生了一个坟墓数量增长速度超过园丁清理速度的墓地。
MCP 特有的失败模式
有三点使得 MCP 遗弃比过时的 npm 包更糟糕。
上游 API 漂移。 大多数社区 MCP 服务都是他人 API 的垫片(shim)—— 比如 Figma、Postmark、Linear、数据库驱动程序或云控制台。MCP 服务将工具调用转换为 API 调用。当被封装的 API 改变形态时 —— 新的必填字段、弃用的端点、变更的响应模式、收紧的身份验证 —— 一个被遗弃的垫片会在原地腐烂。有时它会返回看似合理的错误;有时它会以微妙的错误语义成功执行,因为 LLM 对响应格式的宽容度很高,并且会自信地向用户报告成功。Agent 认为它发送了邮件、应用了迁移或关闭了工单。没有人监控垫片与它所封装的对象之间的契约。
工具描述契约冻结。 MCP 工具描述的文本是 LLM 在决定是否以及如何调用工具时所读取的内容。在被遗弃的服务中,该描述会与底层 API 实际接受的内容脱节。参数名称发生漂移。速率限制发生变化。以前可选的字段变成了必填。描述依然承诺旧的行为,模型也照此调用。调用会失败,或者更糟糕的是,产生看起来像幻觉的输出,因为模型用一个看似合理的猜测修补了这种差异。没有人更新描述,因为没有人更新任何东西。
继承的 CVE 攻击面。 一个 MCP 服务不仅是一个依赖项,它是一个依赖树。MCP 运行时、语言 SDK、HTTP 客户端、认证库、序列化层以及它们下方的每一个传递依赖项都会发布各自的安全更新。一个被遗弃的服务被冻结在它发布时的版本。每多一个月的沉默,都会拉大它的依赖图与负责任维护者应保持的进度之间的差距。你运行的是某人 2025 年的快照,而这棵依赖树仅在 2026 年就收到了至少十几个与安全相关的更新。
上述每一个失败默认都是隐蔽的。而且由于你的 Agent 在每一个相关环节都带着真实的凭据对真实的系统调用该服务,这些风险会被进一步放大。
