Replies: 2 comments
|
Source-level read of this crash path on master
Suggested fix: in the MCP client generation wrapper, attach an error sink (the SDK's client/transport error surfaces) so a write failure on a dying transport feeds the existing reconnect budget instead of escaping. The desired end state already exists in the supervisor — after maxAttempts it unregisters that server's tools and stops, leaving the rest of the harness alive. Workaround meanwhile: keep crash-prone stdio MCP servers out of the long-lived web profile (or wrap them in an auto-restarting shim), as the reporter already found. |
|
@FirmaSpring 那条源码级判读把两个关键环节点出来了。补一件:你踩的这条盲区不是孤立的——同一个重连监督器至少漏看了两条失败通道,而两条都已经有独立的报告。 同一个监督器,两条看不见的失败通道@FirmaSpring 说重连预算是被传输层的 close 事件驱动的,而你这次的失败是 SDK 在 #3489 报的是另一条同样看不见的通道:
那边的后果是 MCP 会话过期后工具还挂着、每次调用都返回同一个错误、模型重新规划 61 次烧掉 500 多秒。 并起来看:
重连预算做得再好,只订阅了三条通道里的一条。 我觉得这个对照值得放进原帖——它把诉求从"我这个 puppeteer 的场景要修"提到"这个监督器需要覆盖它所有的失败入口",而后者一次修完,也不需要为下一种传输再报一次。 (顺带, 关于"一个插件的 I/O 失败不该炸掉宿主"@FirmaSpring 提到的第二环——宿主的 unhandled-rejection 策略是 fail-loud——我觉得这个策略本身没错,错的是它的适用范围:
这正好是 #3437 那个"WebUI 插件故障隔离"提案在说的事,而你这条是它最强的论据——那边讨论的是"一个插件坏了会不会让界面不可用",你这条是"一个 MCP server 的子进程死了,整个服务进程退出、端口消失"。不是降级,是宕机。 建议在原帖的"预期"里把这一层写进去:不只是"应只注销该 MCP 或自动重连",还有**"第三方插件路径上的未捕获拒绝不应触发宿主的 fail-loud 退出"**。前者是这个 bug 的修复,后者是让下一个同类不再造成宕机。 一个给现在遇到的人的临时办法你自己的办法(从 (这条我没试过——是从 @FirmaSpring 定位的机制推的:崩溃来自对已死 stdio 传输的写入,换成 HTTP 就没有这个写入路径。如果你试了,不管成不成都值得贴回来,因为它能进一步确认根因边界。) npm 上做浏览器自动化的 MCP/插件不止一个( 边界与利益相关我们不修 DSH 自家组件—— 利益相关:我维护 pi2dsh(Pi 生态兼容层),它也能跑一套 Pi 生态的 MCP 运行时。这条不推销:"SDK 写入路径抛 EPIPE 时会不会被当成断连处理"这个具体分支,我一次没测过——按我们自己的规矩,没测过就不能说绕得开。你完全可能换过去踩到同一个洞。 |
Uh oh!
There was an error while loading. Please reload this page.
环境:Windows 10 · Node v24.15.0 · dsh 0.1.0-rc.6 · @hisma/server-puppeteer
复现步骤:
崩溃日志:
Puppeteer MCP Server closed
Error: Not connected
at Server.notification ... protocol.js:795
errno: -4047, code: 'EPIPE', syscall: 'write'
Node.js v24.15.0
预期:单个 MCP 断连不应使整个 dsh 进程崩溃,应只注销该 MCP 或自动重连。
临时解决:从 cordis.patch.yml 删除 puppeteer MCP 后不再崩溃。
All reactions