云主机上自建 MCP 兼容探测:出网、npx 与超时三件事
兼容矩阵这类数据,最怕的不是跑不出来,而是跑出来不可复现。本机装过五六个宿主、挂过代理、npm 缓存里躺着几十个包,用它测出来的结果换台机器就变。所以 2026-11-02 那次全量采集(generatedAt 2026-11-02T19:53:24.631Z,mode=full,collectorVersion dev,采集机 node v22.23.2)放在一台干净的 ECS 上跑:153 个非 fixture server 与 17 个宿主两两组合,最终落库 2,737 格。这篇只讲这台机器怎么配,不讲结果怎么读。
出网:三张清单,别合成一张
探测机的出网目标其实分三类,混在一起查会反复返工。第一类是各个 server 自身的域名与端口,stdio 型的多数只需要 registry 加少量 API 域名,http 型的要连它声明的 url 主机。第二类是 registry 本身,npx 拉包全靠它。第三类是宿主 CLI 自己的登录与更新端点,装的时候不报错、跑的时候才 401,最难查。
安全组出方向默认全通,真正卡人的往往是企业侧的云防火墙和 NAT 白名单。上机第一件事不是装 Node,是把目标域名按三类写成三个文件,逐条探通。
# targets.txt 一行一个域名,先探 443 再谈采集
while read -r h; do
printf '%-44s' "$h"
nc -z -w 3 "$h" 443 >/dev/null 2>&1 && echo open || echo blocked
done < targets.txt
验收点很硬:三张清单每一行都得是 open 才允许开跑。blocked 的那几条如果不处理,落到矩阵里会变成 fail —— 而它其实只是这台机器连不出去。这是最容易把网络问题写成兼容性问题的地方,判 fail 的 873 格里有多少属于这种情况,完全取决于这一步做没做。
还要注意端口不是只有 443。http 型 server 声明的 url 里偶尔带非标端口,只放通 443 就会出现「域名能通、server 连不上」。探的时候把端口一起写进清单,别只探域名。DNS 也要单独确认一次:云上内网 DNS 与公共 DNS 返回的地址可能不同,采集机解析到哪个 IP,决定了白名单该开给谁。
npx 的第一次,不该算进任何一格
npx 首次拉包会把下载、解包、依赖解析全算进进程启动时间里。直接采,startupMs 里混着 registry 的网络往返;同一台机器第二次跑,数值就变了,前后两轮数据没法比。
做法是预热:按 server 清单先空跑一遍版本查询,把包落进 npm cache,再开始正式采集。这样采到的耗时只反映进程自身。那份快照里「中位数 4,185 ms、最短 212 ms」是在预热过的机器上测的;换一台冷缓存机器,中位数会被网络抬高,数字就不可比了。
预热还有个副作用是好的:第一次拉包时的 404、私有包、已下架的版本,会在这一步集中暴露,而不是混在采集结果里被当成宿主不支持。
Node 版本是口径的一部分
采集机是 v22.23.2,这个值要写进 README 第一行,和 generatedAt 并列。理由不是新版本更好,而是 17 个宿主里有几个对 Node 主版本敏感——引擎字段、原生模块 ABI 都会变,版本一换,同一格可能从 pass 翻成 fail。
云主机镜像自带的 Node 常常是 18 或 20,装完系统先 node -v 看一眼,别 apt install nodejs 装完就当齐活。用 nvm 或官方二进制包都行,关键是 which node 要指向你自己装的那份,别让系统包和版本管理器混着用。
顺手把 NTP 对齐也做掉。采集结果里全是时间戳,机器时钟漂几分钟,跨宿主的耗时对比就失去意义,startupMs 里还会混进负值。
并发与超时:4,185 ms 中位数给出的下界
2,737 格如果串行跑,光启动按中位 4,185 ms 算就是三个多小时,还没算协议交互。所以要并发,但并发会互相抢 CPU 与网络,把本来就慢的 server 推过超时线。
阈值该怎么定?看分布,不要拍脑袋。中位数 4,185 ms 意味着阈值压到 8 秒以内时,一半以上的 server 都贴着悬崖;而最短 212 ms 说明这个分布的跨度极大,用固定的小阈值一刀切必然误判。实践里是 30 秒硬超时,同时把真实 startupMs 全量留档——设 5 秒然后收一堆 fail,省下的只是等待时间,赔进去的是数据可信度。
并发度按核数定,不按格数开。stdio 型 server 每一个都是子进程,4 核机器跑 4 到 6 路比较稳;开太多会触发 OOM killer,日志里表现为莫名其妙的 exit 137,看起来特别像 server 自己崩了。
重试也要有上限。网络抖动导致的超时重试一次就够,重试三次以上会把一轮采集的时间拉长到不可控,而且掩盖了真正慢的那几个 server。重试次数和最终耗时一起落盘,复盘时才知道这一格的 fail 是第几次尝试的结果。
# 单格 30s 硬超时,超时与真实耗时分别留痕
xargs -P 6 -I{
} sh -c 'timeout 30s ./probe-one.sh "{}" || echo "{} TIMEOUT"' < cells.txt
磁盘与日志:597 格的协议档最占地方
每个格子都要留原始输出,事后才能判断「这格是没测到还是测失败」。stdout 与 stderr 分开写,按 server 分目录,单文件超过 4 MB 截断并打 truncated 标记,否则一个爱刷日志的 server 能把整块盘写满。
容量上,协议实测那 597 格最占地方——它每格都要存握手过程与 tools/list 的原始响应。40 GB 系统盘跑一轮够用,但日志必须按轮次清理,第二轮不清就会写满。
还要在机器上留一份 hosts.json 快照。这份快照里 CodeBuddy 与 OpenCode 的 hostAvailability 是 available:false,两列各 153 格 na、合计 306 格。这类「没测」必须在采集时就写成 na,而不是跑完之后发现失败率高再来猜原因。
目录按 /data/<run-id>/<host>/<server>/ 三层铺开,run-id 用采集时间戳。这样同一台机器可以并存多轮数据,对比时不用靠文件名猜;清理也只删整轮,不会误删某一次的关键证据。
一套能复现的最小配置
4 核 8G 内存、40 GB 盘、Node v22.23.2、预热过的 npm cache、三张出网清单全 open、30 秒硬超时、并发 4 到 6 路。七条齐了,跑出来的 byUsable 才有讨论价值:pass 1,438 / limited 59 / fail 873 / na 367,四个数相加正好回到 2,737。
少任何一条,那组数字就只是这一台机器的数字。各宿主的安装形态差异,MCP 兼容手册 里有按平台的对照,出网阶段被拦的域名也可以先去那里核一遍再动防火墙。想按平台直接查某一格,用 按平台找 MCP 更快。
总结
云上自建探测机的价值不在算力,而在干净:没有代理、没有历史缓存、没有装了一半的宿主。出网清单先探通、npx 预热后再采、Node 版本钉死、超时按 4,185 ms 的中位数放宽到 30 秒、磁盘留给 597 格协议档——这五件事做完,2,737 格才是同一把尺子量出来的。想把尺子换成自己那台机器,也从 MCP 兼容手册 的口径页开始对。
适合与不适合
适合:需要一份可复现兼容性数据的团队;要在专有云或内网复刻同一套采集的运维;已经被「明明装了却判 fail」困扰、想先把网络因素排除掉的人。
不适合:只想查某个 server 在某个宿主能不能用的人,直接看现成矩阵更快;不打算维护一台常驻机器、也说服不了安全团队开出网白名单的团队;把兼容性当成跑一次脚本就结束的项目。
另外,本文只讲云上采集这条线;想找能直接装的 DSH 插件,精选插件 Top 榜 按站内综合分排了一份。
标签:MCP、阿里云 ECS、出网白名单、采集环境
本文由 DeepSeek Harness Hub 自动整理,数据来源于 MCP 兼容性采集快照(2026-11-02)。