菜单

11.9 万份签名的 MCP server 检测结果:在线情况与工具列表漂移

2026-10-25MCP Checkup

英文版更新于 2026 年 10 月 22 日,这是它的中文译本,数据截至 10 月 21 日。之后有一处变化:10 月 22 日起,探测器会读完 tools/list 的全部分页。下文「只读第一页」的说法,指的是截止时的情况。

从 2026 年 8 月 20 日起,我们按固定排期探测公开的远程 MCP server,不带任何凭据;从 8 月 22 日起,对观察到的结果签名。这篇汇总截至 2026 年 10 月 21 日 23:00 UTC 的数据。每个数字都来自对我们生产数据库的只读查询,并在出现的地方说明口径。

这些数据我们不合成任何分数,也都不是对某个 server 的结论。它们是观察结果,以及得出这些观察时的条件。

数据集

截止时,探测列表里有 5,916 个远程 MCP endpoint。它们不都签了名,也不都被观察了整整一个月。对每个 endpoint,我们取截止前 7 天内最近的一轮检测,5,912 个有这样的一轮。

最近一轮 endpoint 数 占比
已签名,完整覆盖 3,564 60.3%
已签名,部分覆盖(需登录) 1,898 32.1%
未签名 450 7.6%

450 个未签名的检测里:

  • 412 个没有完成 MCP 握手;
  • 36 个完成了握手,但没返回能做指纹的工具列表;
  • 2 个被我们的出站网络防护拦下。

统计在线情况至少要 7 天的观察。951 个 endpoint 不够 7 天,大多是 10 月才加进来的,所以在线情况一节覆盖 4,961 个。

针对这些 endpoint,我们存有 194,352 轮探测,第一轮在 8 月 20 日。其中 119,510 轮带签名的证明:114,398 轮是完整覆盖,5,112 轮是需登录覆盖(10 月 20 日起才有)。这 119,510 轮里有一轮是 8 月 20 日的测试,用的是开发密钥签名,那把密钥不在我们公布的密钥列表里,所以我们的验证器会拒绝它。

「完整覆盖」的意思是每项检查都尝试过了,不是每项都有结论。一轮典型的完整覆盖检测,在我们 15 项检查里对 10 项给出结论,另外 5 项记为 UNVERIFIED 并写明原因:

  • TLS 和延迟检查,当时还没有开始运行;
  • 鉴权元数据,server 没出示登录质询的时候;
  • 和已批准基线对比的两项,还没有基线的时候。

我们首页的统计口径不一样:

  • 目录里的 server(10 月 22 日 00:23 UTC 查时是 3,770 个)只算至少返回过一次工具列表的 server。本文统计探测列表上的每个 endpoint,包括先要求登录的、从没完成过握手的。
  • 检测次数和签名结果是累计总数,包括已按保留策略删掉的检测。
  • **「近 30 天工具集有变化」**只比较工具名,范围是所有列出的 server。
  • 协议面板统计最近一次结果为完整覆盖签名的 3,564 个 server;本文统计完成握手的 3,602 个。

签名能说明什么、不能说明什么

签名表明这条记录是我们发出的,并且之后没被改动过。它不表明 server 好不好,不表明它明天还会这样,也说明不了登录后面有什么。详见一份签名证明能证明什么。

在线情况:server 多常应答

我们按 UTC 日来看每个 server。

  • 在线: 当天每一轮检测都连上了 server。
  • 不在线: 有一轮检测发现 server 没应答:域名解析不出来、连接失败、在时间预算内没收到完整响应,或者握手拿到了 HTTP 5xx。
  • 不计入: 只有我们的探测器得不出结论的日子,比如被限流了。

一个 server 的比率,是在线天数除以计入的天数。

这段时间里规则有过调整:握手时的 HTTP 5xx 从 9 月 23 日起算作不在线,连接失败从 9 月 27 日起算作不在线。在那之前,这样的一天可能被算作在线,也可能不计入,所以窗口的开头会稍微偏向「在线」。

我们用 9 月 22 日到 10 月 20 日这 29 个完整的 UTC 日,其间有 4,961 个 server 至少有 7 个计入的天。9 月 21 日没有算进来:那天有 81 个 server 被记为没应答,前后几天只有 7 到 22 个。那天我们部署了三次探测器,而那天的检测记录已经按保留策略删掉了,所以说不清原因是不是在我们这边。如果把 9 月 21 日算进来,每个计入日都应答的 server 占比会从 89.4% 降到 88.3%。

分组(按最近一轮) server 数 100% 95–99% 80–94% 50–79% 低于 50%
已签名,完整覆盖 2,967 2,692(90.7%) 118 130 21 6
已签名,需登录 1,593 1,485(93.2%) 63 41 4 0
最近一轮未签名 401 258(64.3%) 16 33 39 55
全部 4,961 4,435(89.4%) 197 204 64 61

比率先四舍五入到整数百分比,再分档。

大多数 server 在每个计入的日子都应答了。要求登录的 server 比开放的稍好一点;对它们来说,「应答」指的是返回了 401 质询,登录后面的服务是否正常,我们看不到。长尾几乎全在最近一轮未签名的 server 里:低于 50% 的 61 个里,有 55 个在这一组。这里面有一部分是选择效应,因为最近一轮失败的 server,本来就是最近出过状况的。

未认领的 server 每 12 小时探测一次,所以一天通常只有两轮检测,两轮之间的短暂中断看不到。这衡量的是客户端来的时候 server 多半在不在,不是分钟级的可用性。

漂移:工具列表多常变

每一轮拿到工具列表的检测,都会和同一个 server 的上一份列表比较。每个工具的名字、描述和输入 schema 都参与比较。排除条件和我们之前那篇MCP 工具集多久变一次相同:

  • 包含: 窗口开始时已经存有工具列表、并且窗口期间我们至少真正读到过一次工具列表的 server;
  • 排除: 3 个已认领的 server(我们读它们的频率高于每 12 小时一次),以及 7 个返回分页工具列表的 server。
窗口 server 数 有任何变化 增减了工具 schema 变了、名字没变 只改了描述 可能造成破坏
7 天(10 月 14–21 日) 3,029 780(25.8%) 376(12.4%) 234(7.7%) 170(5.6%) 115(3.8%)
30 天(9 月 21 日–10 月 21 日) 815 398(48.8%) 261(32.0%) 91(11.2%) 46(5.6%) 115(14.1%)

中间三列互斥,每个 server 只出现一次,放在第一个符合的列里。

可能造成破坏的意思是,窗口里至少有一次变化出现了下面任一情况:

  • 有工具消失了;
  • 留下的工具删掉了某个参数;
  • 某个参数声明的 type 变了;
  • 某个参数新变成了 required。

这些变化都可能让原本有效的调用失败。会不会真失败,取决于客户端和 server 的校验,所以这是上限,不是失败次数。

任意一周里,这些 server 大约四分之一有某种变化,大约八分之一增减了工具。过去五周这两个比例很稳定,任何变化在 26% 到 29% 之间,增减工具在 12% 到 14% 之间;同期统计的 server 从 171 个增加到了 3,029 个。

把这 30 天里我们读过的所有 server 都算上(不只上面的 815 个,已认领和分页的仍然排除):

  • 变化扎堆。 1,509 个 server 共存了 5,054 份变化后的列表。98 个 server 变了 10 次以上,占全部变化的 29%。
  • 很少变回去。 只有 41 份变化后的列表和同一个 server 更早的某份列表完全一样。
  • 描述变得最多,但很少单独变。 我们统计到 12,951 次单个工具的描述变化,对比之下新增工具 6,754 个、删除 2,500 个、schema 变化 9,154 次。764 次描述变化只差在数字上,比如数量、日期或版本号;31 次只差在空白字符。可在任一窗口里,只改描述的 server 只占 5.6%。
  • type 的变化大多是精度问题。 最常见的 type 变化是 number 改成 integer:13 个 server 上有 319 处参数变化,大部分来自同一个 server(见下面的案例 C)。还有很多是把参数从单一的 type 改成了 anyOf 这类组合形式。我们的规则把这也算作 type 变化,所以会高估破坏。

三个案例

这些是我们数据里的真实 server。名字、确切日期和确切的工具数我们都没写,因为还没问过它们的维护者。

分步增长的 server。 一个月里,有个 server 的工具数增加了大约 60%,分了十次。每两次之间,它还在改描述和 schema。我们为它存了 40 多份变化后的列表。一个每周刷新一次这个 server 工具列表的 agent,大多数时候都缺着它最新的那些工具。

几乎所有工具都没了。 一个有几百个工具的 server,有一轮检测没完成握手。等它再次应答时,之前的工具名几乎全没了。两份列表都不带 nextCursor,所以不是分页造成的。拿着旧列表的 agent,会一直去调用已经不存在的工具。

number 变成 integer。 一次更新里,一个大型 server 把很多数值参数从 number 改成了 integer,描述没变。按新 schema 校验参数的客户端,前一天还接受 2.5,现在会拒绝。

协议版本

3,602 个 server 在最近一轮里完成了握手并声明了协议版本。另外 2,310 个没有:1,897 个在握手时就要求登录,412 个没完成握手,1 个被网络防护拦下。(另有一个需登录的 server 完成了握手,到 tools/list 才要求登录。)

版本 server 数 占比
2025-11-25 1,803 50.1%
2026-07-28 1,043 29.0%
2025-06-18 595 16.5%
2024-11-05 85 2.4%
2025-03-26 75 2.1%
其他 1 <0.1%

探测器先试 server/discover,提出 2026-07-28。server 不支持的话,就退回 initialize,提出 2025-11-25。

路径 应答 用我们提出的版本 更早的版本 更新的版本 无法识别
server/discover,提出 2026-07-28 1,059 1,039 20 0 0
initialize,提出 2025-11-25 2,543 1,797 741 4 1
合计 3,602 2,836 761 4 1

761 个 server(21.1%)回答的版本比我们提出的更早,最常见的是 2025-06-18(592 个)。用一个更早的、自己支持的版本回答,正是协议规定的协商方式,所以这不是毛病。它说明的是:公开可见的 server 里,仍有相当一部分讲的是 2024 年和 2025 年上半年的版本。

登录

最近一轮里,有 2,182 个 endpoint 对我们的某个请求回了 HTTP 401,分成两类。

  • 1,916 个(87.8%)在握手或 tools/list 时要求登录。
    • 其中 1,898 个拿到了需登录覆盖的签名证明;
    • 17 个签不了,因为没拿到能做指纹的工具列表;
    • 1 个被网络防护拦下。
  • 266 个(12.2%)不带凭据就列出了工具。 它们只对我们调用一个不存在的工具名回了 401,签的是完整覆盖。

2,150 个带 WWW-Authenticate 质询的 401 里,2,011 个(93.5%)按 RFC 9728 的写法指向了一份 OAuth 受保护资源元数据文档。每份文档我们取了一次:

  • 1,997 份和质询一致;
  • 10 份声明的 scope 和质询矛盾;
  • 4 份返回 HTTP 错误。

139 个质询没有给出元数据地址,另有 32 个 401 根本没带质询。

需登录的签名证明只覆盖不带凭据也能观察到的四项检查:可达性、重定向策略、传输方式和鉴权元数据。其余每一项都记为 UNVERIFIED 并写明原因。签名内容里记着覆盖范围,所以部分覆盖的证明不会被误当成完整的。需登录签名是 10 月 20 日开始的,在那之前,这样的检测都不签名。

方法

  • 探测。 未认领的 server 每 12 小时从 Cloudflare Workers 探测一次。探测器从不发送凭据。它发送握手、tools/list(只读第一页),以及一次对一个不存在的工具名的调用;第一页带 nextCursor 时,这次调用跳过。

  • 检查状态。 每轮检测每项检查记一个状态:VERIFIED、FAILED、OBSERVED_RISK,或者带原因的 UNVERIFIED。

  • 签名。 符合我们签名条件的检测会被规范化,用 Ed25519 签名,装进 DSSE 信封。签名把记录和我们的密钥绑定在一起,之后任何改动都能被发现。它不是对 server 质量的评价。未签名的检测就标为未签名。

  • 公布的密钥。 密钥列表在 https://mcpcheckup.com/.well-known/mcpcheckup-keys.json。当前的密钥 ID 是 70222b3a2c05e79a,自 2026 年 8 月 22 日起生效。

  • 验证签名。 mcpcheckup/checks 里有规范化器、证明的 schema 和一个离线验证器。需要 Node.js 22.18+ 或 24+,不用安装:

    curl -fsS https://mcpcheckup.com/.well-known/mcpcheckup-keys.json -o keys.json
    node packages/verifier/verify-attestation.mjs --envelope <file> --keys keys.json
    

    验证器不发任何网络请求。它检查每个签名的密钥 ID 在密钥列表里、没被吊销,并且签名内容里的 observed_at 落在这把密钥的有效期内。keys/ 里有一份密钥列表的副本,可以完全离线验证。

局限

  • 有两项检查还没开始运行。 5,912 个最近一轮里,TLS 证书和延迟两项都是 UNVERIFIED。
  • 需登录的签名证明只覆盖四项检查。 登录之后的一切,都不在我们观察的范围内。
  • 没记录传输方式。 我们没记 server 是通过 Streamable HTTP 还是旧式 SSE 应答的。
  • 在线情况按天统计,而且窗口期间规则收紧过,见上文。
  • 工具列表只读第一页。 分页的 server 不计入漂移数据。
  • 有些描述变化是动态文本。「可能造成破坏」是只看顶层参数的近似规则:它不看嵌套 schema,还把改成 anyOf 的情况算作 type 变化。
  • 一个观察点,不带凭据。 登录后的用户,或者在其他地区的客户端,看到的情况可能不同。
  • 7 天和 30 天的统计范围不同。 10 月列表增长很快,所以 7 天的范围(3,029 个)和 30 天的范围(815 个)是两组不同的 server,不要当成趋势来读。

关于 MCP Checkup

MCP Checkup 把这些观察结果按 server 公开,并附上背后的签名证明。方法页介绍了每一项检查。

  • 免费检查。 首页可以对任何公开的 MCP endpoint 做一次免费检查。这次检查不签名,也不保存。
  • Indie 套餐。 认领了自己 server 的维护者可以加购 Indie 套餐:每月 $5.99 或每年 $49.99,可管 10 个 server,每 15 分钟检查一次,附带告警邮件。