基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-02 12:27

MCP 协议切换导致采集静默中断三天

dev.to · AI#MCP#协议兼容#可观测性
Editor brief · 编辑速览

HISTOR 在三天内停止读取 2195 个 MCP 服务器,现有监控却未报警,直到对照另一团队的日志才发现异常。文章围绕新旧协议的会话初始化差异,分析兼容处理与监控盲区。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

HISTOR 连续几天没能读取 2,195 个 MCP 服务器,监控上的成功率却有 98.8%。问题不是服务器集体宕机,而是客户端升级协议后,把大量旧服务器挡在了兼容逻辑之外。最后揭开缺口的,是另一支团队维护的独立日志。

这次事故值得程序员花几分钟读:它把协议兼容、重试退避和监控盲区串到了一起。一个局部看起来更严格的判断,怎样造成大面积漏读,又怎样被漂亮的指标掩盖,作者给出了具体记录。

协议升级为什么会让旧服务器突然读不了

HISTOR 是一个公开记录 MCP 工具定义变化的服务,按 30 分钟到 6 小时的间隔读取官方注册表中的远程服务器。它需要知道服务器提供哪些工具,并记录变化。

事故发生在连接流程升级之后。

截至 2025-11-25 的旧版 MCP,客户端先发送 initialize,双方协商协议版本,再请求 tools/list。2026-07-28 修订版取消了这次握手,改用 server/discover,每个请求自行携带协议版本和能力信息。

同时支持新旧协议的客户端,需要先判断对端属于哪一种。按作者对 Streamable HTTP 兼容规则的说明,客户端应先尝试新请求;如果收到 HTTP 4xx,且响应体不属于新版协议定义的错误,就尝试旧版 initialize。

他们团队在 10 月底接入新协议,却额外收紧了回退条件:HTTP 状态必须是 400、404 或 405,JSON-RPC 错误码必须是 −32600、−32601 或 −32602,而且响应 id 必须与请求一致。

动机可以理解:回退太宽松,客户端可能被诱导使用双方原本都支持的较旧协议。但实际服务器没有那么整齐。

下面是 mcp.quotewise.io 拒绝新协议时的真实响应,它已经明确列出了支持的旧版本:

{"jsonrpc": "2.0", "id": "server-error",
 "error": {"code": -32600,
  "message": "Bad Request: Unsupported protocol version: 2026-07-28. Supported versions: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25"}}

关键在 "id": "server-error"。HISTOR 因为它与请求 ID 不符而终止读取。作者指出,官方 Python SDK 的 1.x 系列在尚未读取请求 ID 就发生错误时,也会使用这个值。

另一个例子是 mcp.kaiku.tech:它只允许匿名访问 initialize 和 tools/list,其他请求都要求 Bearer token。陌生的 server/discover 因而得到 401,但发送 initialize 就能正常读取。

2,195 个失联服务器的最后错误分布,展示了严格匹配的代价:

2,195 个服务器的最后错误分布,其中 789 个返回不同 ID,746 个返回 401 或 403

其中,789 个返回其他 ID 下的旧式错误,746 个返回 401 或 403,304 个给出的版本列表不含客户端版本,120 个返回格式有问题的 JSON-RPC,37 个没有共同版本,另有 199 个属于其他失败。

旧协议也远没有退出主流。作者统计的 21,474 个成功读取过的远程服务器中,最新成功记录使用 2026-07-28 的有 4,097 个,占 19%;2025-06-18 有 13,744 个,占 64%。其余分别是 2025-11-25 的 126 个、2025-03-26 的 2,853 个,以及 2024-11-05 的 650 个。

21,474 个远程 MCP 服务器的协议版本分布,2025-06-18 占 64%

这个分布还有偏差:165 个可能同时支持新旧协议的服务器,最后一次读取发生在 10 月 29 日之前,因此仍被计入旧版本。它是这批服务器的观测结果,不能直接当作整个 MCP 生态的普查。

为什么漏了两千多个服务器,成功率还这么高

修复前一小时,HISTOR 发起 9,514 次远程读取,成功 9,400 次,成功率为 98.8%。

这个数字没有算错,问题出在分母。

读取失败的服务器,会先后等待 6 小时、12 小时、24 小时再重试;遇到 401,至少等一天。连续失败的服务器逐渐退出高频任务队列,剩下的请求自然越来越集中在正常服务器上。

重试退避改变了请求样本,成功率就不再能代表覆盖情况。

对这个采集服务,更接近业务目标的指标是:今天究竟有多少个不同服务器至少成功读取过一次。这个数从 10 月 29 日约 28,200 个,跌到 10 月 31 日约 23,000 个,可惜他们没有给它配置告警。

严格读取逻辑上线后覆盖数量下降,直到独立日志比对才发现缺口

这里也不能把覆盖数量的全部跌幅,都归因于这次兼容问题。原文明确追出的事故集合,是 10 月 28 日正常、从 10 月 30 日到修复前一次都没读成功的 2,195 个服务器。

这类监控陷阱并不限于 MCP。只要任务失败后会降低执行频率,就需要同时回答两个问题:执行过的任务成功了多少,以及应该覆盖的对象还有多少没有成功处理。

独立日志怎样把 15 个异常追成 2,195 个

ScraperWatch 从 10 月 30 日开始记录 MCP 工具变化,每天读取一个固定随机样本,包含 3,000 个注册表服务器。它只支持 2025-06-18,始终从 initialize 开始。

11 月 1 日,HISTOR 团队逐字段路径比较对方的 98 条工具变更记录:64 条完全一致,另有 15 个服务器上的 18 条记录,HISTOR 根本没有对应数据。沿着这些失败继续查询,才找到全部 2,195 个受影响服务器。

双方实现不同,在这里形成了有效互补。不过,对照方也有错误:ScraperWatch 的 robots.txt 解析器误读了约 250 个禁止抓取的样本端点。删除相关读取后,那两天的日志剩下 81 条变更,其中 53 条与 HISTOR 逐路径一致。作者说明,握手问题的发现不依赖被删除的记录。

修复后的读取器允许进行一次旧协议回退,包括这些情况:

  • 首次新式请求返回 400、404、405、401 或 403,且符合旧式拒绝特征。
  • 旧错误码出现在任意 id 下,或者响应体根本不是 JSON-RPC。
  • 错误或发现响应列出的版本全部早于 2026-07-28,或者 server/discover 响应缺少 supportedVersions。
  • tools/list 第一页尚未读到任何内容,就遭到旧式拒绝。作者确实遇到一个宣称支持新版、随后又拒绝新版的服务器。

限流、超时、5xx、重定向、新版协议自身定义的错误,以及含义不明确的响应,仍然终止读取。

修复于 11 月 1 日 08:44:57 UTC 上线。前 90 秒的 172 次远程读取有 171 次成功,其中 145 次使用旧协议。团队没有重置重试计划,而是等待服务器按原有退避时间回来。

按正文后续统计,次日 04:21 UTC,仍在注册表中的 2,193 个受影响服务器已有 1,893 个恢复读取;剩余 300 个中,161 个因 HTTP 400、401、402、服务器错误或超时等原因失败,139 个仍被协议判断拦住,其中 73 个返回了格式有问题的 JSON-RPC 错误体。

我的判断

这篇复盘最有价值的地方,是同时提供了错误响应、生产统计和修复后的读取结果。它足以说明:他们原先的兼容条件确实拦住了大量可读取服务器。

但不能据此把「401、403 就回退」写成所有请求通用的规则。这里的前提是首次协议探测、只读取工具列表,并且只回退一次。带凭证、执行工具或产生写入的客户端,还需要结合自己的权限与协议要求判断。

相比始终使用旧协议,这次修复保留了探测新版的机会;相比无限放宽回退,它也保留了明确的停止条件。不过作者没有给出安全对照实验,无法据此证明这套边界对所有 MCP 客户端都最合适。

独立日志同样是补充手段。固定样本每天读取一次,无法覆盖全量和所有短时故障。作者已经把双向比对自动化到每周快照之后,却仍未补上每日成功覆盖数量告警,这项缺口尚未关闭。

原文还有一处口径不一致:时间线图片写着当天 18:05 已恢复 1,894 个,正文却写次日 04:21 恢复 1,893 个。原文没有解释,精确恢复进度应保留疑问。

能拿来做什么

  • 如果你维护 Node MCP 客户端,把文中的不同 id、401/403 和旧版本列表响应做成兼容性测试样例,明确验证首次探测何时允许回退。
  • 如果你维护带重试退避的采集任务,同时记录请求成功率、成功覆盖对象数和距上次成功的时间,让长期失败对象继续出现在监控里。
  • 如果你的 AI 编程工具依赖多个 MCP 服务,在升级协议前保留一组真实旧服务做回归,并用实现不同的读取器抽样比对工具列表,及时发现单一路径的盲区。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
用测试契约约束AI生成代码
下一篇
少样本提示如何选例、配比与排序

资讯速览

dev.to · AI · 2026-11-02 12:27

AI 评分 8.0 / 10

相关标签

#MCP#协议兼容#可观测性

继续阅读

  • AI应用SDK选型:协议、类型与持久化
  • 用测试契约约束AI生成代码
  • 少样本提示如何选例、配比与排序
  • 智能体跨场景复用,审批必须落到 API
  • Cursor 写完接口请求,还要过契约校验