在阿里云 ECS 上复跑 MCP 兼容矩阵:出网、隔离、并发三件事
站内那份 MCP 兼容矩阵的数据是这样来的:17 个宿主 × 153 个 server,逐格判定「能不能装、装了能不能用」,一共 2,601 格。如果你想在自己的 ECS 上复现这套采集,或者只是想批量测一批 MCP 服务的可用性,下面这三件事会决定你跑不跑得出来。
先说结论:采集能不能跑通,关键不在客户端代码,在出网和隔离。因为 90.8% 的待测对象是本地 stdio 进程,它们每次判定都要真的去 npm 下包、装依赖、拉起进程。
一、采集在做什么
每一格的判定包含四个动作:
| 动作 | 产出字段 | 失败表现 |
|---|---|---|
| 解析包名与命令 | command / argsJson |
包不存在、名字拼错 |
| 拉起进程并完成握手 | startupMs |
超时、进程静默退出 |
| 能力协商 | toolCount / resourceCount |
工具数为 0 |
| 协议校验 | checks[].evidence |
协议实测不通过 |
格子的结论分四档:pass / limited / fail / na。na 表示这一宿主不支持该传输方式(比如纯本地宿主测远程服务),不算失败——这一点很重要,把 na 算进分母会得出错误的失败率。
同一批数据的结果:
| 传输方式 | server 数 | 格数 | pass | fail | na |
|---|---|---|---|---|---|
| stdio | 139 | 2,363 | 1,198 | 845 | 278 |
| http | 14 | 238 | 141 | 11 | 73 |
二、ECS 规格:别用共享型实例
采集是「大量短时进程 + 频繁网络请求」的负载,对 CPU 的持续性要求比对峰值要求高。
| 项 | 建议 | 理由 |
|---|---|---|
| 实例族 | 计算型 c 系列 / 通用型 g 系列 | 共享型(t 系列)的 CPU 积分会在批量拉起进程时耗尽 |
| 规格 | 4 核 8G 起 | 单格判定会同时存在「下载 + 装依赖 + 起进程」三种负载 |
| 系统盘 | 100G ESSD | npm 缓存会持续增长,153 个 server 的依赖树不小 |
| 系统 | Ubuntu 22.04 | node 与 npx 的兼容性最好 |
如果只是测十几个 server,2 核 4G 也够;但一旦上到 100 个以上,4 核起是底线,否则会出现「明明没报错但大量 timeout」——那是 CPU 排队导致的,不是网络问题。
三、出网:三处都要通
stdio 类采集最容易卡在这里。需要放行的目标:
| 目标 | 用途 | 不通的表现 |
|---|---|---|
registry.npmjs.org |
拉包 | 所有 stdio 类全 fail,归因 unknown |
github.com / codeload.github.com |
部分 server 从仓库直装 | 该 server 单独失败 |
| 各模型 API 端点 | 需要凭据的远程服务 | 只有那几个失败 |
安全组只配出方向即可,不需要开放任何入方向端口(采集是被动发起)。
一个实际会踩的坑:ECS 只在私有子网时,即使安全组放行,没有 NAT 网关也出不去。表现和「registry 挂了」一模一样,但排查方向完全不同。先在实例上直连验证:
curl -sI https://registry.npmjs.org | head -1
curl -sI https://codeload.github.com | head -1
两条都返回 200/301 系列再往下走。
四、隔离:这是必须做的一步
为什么不能直接在宿主 ECS 上跑所有 stdio 判定?因为每个 server 都会往系统里装东西:npm 全局包、node 版本、Python 运行时。153 个 server 跑完,宿主环境已经被改得面目全非,后面的判定结果不可信。
两种可行做法:
做法一:每个 server 一个容器。
docker run --rm -v /data/collect:/out node:20-alpine \
sh -c "npx -y <package> --probe > /out/result.json"
优点是环境干净、可复现;缺点是每次都要重新拉依赖,慢。
做法二:容器内共享 npm 缓存。
把 ~/.npm 挂进容器,只隔离进程与全局包:
docker run --rm -v /data/npmcache:/root/.npm -v /data/collect:/out node:20 \
sh -c "npx -y <package> --probe > /out/result.json"
速度能快数倍,代价是缓存里的包版本可能不是最新的——如果你的目的是测「当前最新版能不能用」,就要定期清缓存。
实际采集用的是第二种,但对每个 server 额外记录了拿到的是哪个版本,避免「缓存导致结论过期」。
五、并发:按 CPU 核数定,别按网络带宽定
单格判定的耗时主要在依赖安装,属于 CPU + IO 混合型。经验值:
- 并发数 ≈ CPU 核数 × 1.5
- 4 核机器跑 6 个并发比较稳
- 超过这个数,
startupMs会明显拉长,误判成「启动超时」
另一个不能忽略的是超时阈值。stdout 静默的 server 只能靠超时判定,设得太短会把「慢但可用」判成 fail。这批采集用的是单格 90 秒硬超时——按 153 个 server × 17 宿主全量跑,4 核机器大约需要十几个小时。
六、五个实际会踩到的坑
坑一:把 na 算进分母。
现象:算出来的失败率比预期高很多。
原因:na 是「该宿主不支持这种传输方式」,不是失败。这批数据里 stdio 有 278 格 na、http 有 73 格。
解决:分母只用 pass + limited + fail。
坑二:不记录证据类型,把推断当实测。
现象:报告说「93% 可用」,实际真机只有 22%。
原因:文档推断的通过率远高于真机。同一批数据里文档推断 1,248 格通过 1,170(93.8%),真机 756 格通过 169(22.4%)。
解决:每格必须标 evidence,报告时分开展示。
坑三:共享 npm 缓存后没记版本。
现象:昨天测的结论今天复现不出来。
原因:缓存里的包不是你以为是的那一版。
解决:判定时把实际拿到的版本号写进结果,或每天清一次缓存。
坑四:超时设太短。
现象:大量 fail 集中在 runtime_smoke_failed 或 unknown。
原因:慢启动被判死。这批数据里启动耗时中位数在秒级,长尾能到几十秒。
解决:单格超时不低于 60 秒,慢网络环境给到 90 秒。
坑五:在宿主直接跑,环境污染后结论不可信。
现象:前 20 个 server 判定正常,后面越来越差。
原因:依赖被前面的 server 改过。
解决:按第四节做容器隔离,至少每个 server 独立进程空间。
七、怎么核对结果
跑完的判定结果建议做成三个视图,缺一个就不容易看出问题:
- 按传输方式分组的通过率 —— 能立刻看出方向(stdio 50.7% vs http 59.2%)
- 按证据类型分组的通过率 —— 判断结论可信度(文档 93.8% vs 真机 22.4%)
- 按失败归因分组 —— 定位共性问题(unknown 71.2%、dependency_conflict 19.7%)
站内那份矩阵就是按这三个维度组织的,2,601 格的逐条结果可以在 MCP 兼容矩阵实测数据 按宿主、传输方式、证据类型筛选,用来对照自己跑出来的数字。
总结
在 ECS 上复跑 MCP 兼容矩阵,真正决定成败的是三件事:出网要同时放行 npm registry 与 GitHub(私有子网还需 NAT)、每个 server 必须容器隔离否则环境会被污染、并发按 CPU 核数 × 1.5 定且单格超时不低于 60 秒;这三件做好,2,601 格的采集才可复现。插件侧的分类与验证档位见 DeepSeek Harness Hub 插件清单。
适合与不适合
适合:想在自有云上批量测 MCP 可用性的团队;需要为 MCP 准入定标准、要一份可复现方法的工程负责人;已经在用容器做依赖隔离、想把这套方法搬到 MCP 场景的人。
不适合:只测几个 server 的个人用户,直接用本机跑更快;想找「哪个 MCP 最好用」的人,这套方法只测连接与协议,不测任务效果;不愿意做容器隔离的人,环境会污染,结论不可信。
标签:MCP、阿里云 ECS、兼容矩阵、容器隔离、采集
本文由 DeepSeek Harness Hub 自动整理,数据来源于站点 MCP 兼容矩阵快照。