[bug] node_repl MCP 间歇性协商失败:5s discover 探针窗口 < Windows 进程冷启动时间
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
[bug] node_repl MCP 间歇性协商失败:5s discover 探针窗口 < Windows 进程冷启动时间
环境
- ZCode 桌面端 3.7.7(Windows 11 26200,Win64)
- CLI 内核 0.16.3(
resources/glm/zcode.cjs) - browser-use 插件 0.2.1(内置包与缓存副本字节级一致,均内含 modern SDK,
FIRST_MODERN_PROTOCOL_VERSION = "2026-07-28") - Windows Defender 实时防护开启(默认)
现象
配置 ≥2~3 个全局自配 stdio MCP 服务器后,浏览器工具(node_repl)在会话启动时间歇性注册失败,报错:
Version negotiation failed: the server did not offer pinned protocol version 2026-07-28
via server/discover (no fallback in pin mode)
mcp__node_repl__* 工具不出现,内置浏览器不可用。自配 MCP 本身全部正常连接(它们走 auto 模式可降级)。
复现概率(实测,每轮全新启动):
- 0/1 个自配服务器:5/5 成功
- 2 个:1 成 1 败
- 3 个:2/2 失败
- 3 个 + 人为高压 MCP(启动期 CPU 忙 2s×4 进程):稳定复现失败
根因(反编译 + 失败现场插桩双重确认)
服务器端无辜:对 browser-use-plugin/dist/mcp/server.js 插桩捕获失败现场,discover 探针进程在自身就绪后 0.9~1.3 秒内即写出正确应答 {"supportedVersions":["2026-07-28"],...}(与成功轮逐字节同构)。
失败现场时间线(插桩 + CLI 日志对齐,连接 #1):
| 时刻 | 事件 |
|---|---|
| 14:20:12.488 | 客户端 connect.started,spawn 探针进程,exchange 计时器启动 |
| 14:20:17.500 | 5s 探针窗口到期 |
| 14:20:17.378 | 探针进程才完成 BOOT(冷启动 4.9s) |
| 14:20:18.276 | 服务器写出正确应答(迟到 0.78s,被丢弃) |
| 14:20:22.359 | 客户端上报失败(durationMs=9716 = 5s 窗口 + 4.7s 清理) |
连接 #2 更极端:窗口 19.5s 关闭时探针进程 19.9s 才就绪(冷启动 5.4s)。
代码链(zcode.cjs):
resolveBuiltInNodeReplMcpServers硬编码node_repl注册为protocolVersion: "2026-07-28"(pin 模式)+timeoutMs: 600000Ovi():探针超时 =Math.min(Rvi=5000, timeoutMs/2)—— 全局 5 秒硬上限,Rvi=5e3不可配置;600s 超时的注册也被压到 5sProbeWindow(y_i/Qsn):exchange()中 setTimeout 先于 send 注册——计时从 spawn 后瞬间起算,不含子进程冷启动时间;disposableProbe为独立 spawn 的一次性进程(需加载 7.3MB server.js)probe.maxRetries ?? 0—— 超时零重试l_i分类器:case "timeout": stdio → {kind:"legacy"}—— 超时被静默归类为 legacy- pin 模式对 legacy 无回退,抛出上述误导性文案("did not offer version",实际是窗口内未收到应答)
为何 Windows 高发:Defender 对每个新 node 进程实时扫描 7.3MB 单文件 + 多 MCP 并发 spawn 排队,实测冷启动 4.95.4s(同一文件在无竞争手动 spawn 下全链路仅 1.32.3s)。5s 窗口在进程就绪前已耗尽,服务器应答再快也无法挽救。
修复建议(按优先级)
- 探针计时起点改为子进程就绪后(stdout 可读/首字节),而非 send 前——这是根本修复,5s 窗口本意是测服务器应答速度,不应被进程冷启动侵占
- 或 pin 模式给予 ≥1 次重试(
maxRetries当前硬编码 0) - 或 node_repl 这类高
timeoutMs注册豁免Rvi上限(600s/2 = 300s 才是注册配置的本意) - 报错文案区分 "probe timed out" 与 "server answered without the pinned version"——两者现共用同一句话,严重误导排查方向(服务器端怎么查都无辜)
证据
失败现场插桩日志(BOOT 时刻 / stdout 应答原文 / EXIT)已存档,可提供。CLI 日志时间戳与上述时间线逐条对齐。
连带建议:同一注册中 timeoutMs: 600000(表达"值得等 10 分钟")与 discover 探针 5s 硬上限(不给冷启动留 1 秒)自相矛盾,建议内部评审该组合。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing resolveBuiltInNodeReplMcpServers, Ovi(), ProbeWindow, and the l_i classifier in resources/glm/zcode.cjs; use browser-use-plugin/dist/mcp/server.js only to verify the probe response timing. Reproduce on Windows with multiple stdio MCP servers, then confirm the chosen timeout behavior and error classification distinguish a probe timeout from a missing pinned version.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js
- Domain
- cli, devtools, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100