Replies: 3 comments
|
这条缺陷在 Windows + 0.2.0-rc.2(命令行安装,不是桌面 App)+ 云端服务端上也复现,而且探测回的不止 501。 环境: 探测请求的原文(抓的是插件路径下真实的 受影响面比 501 更宽: 修法在本机验过,且是以"最小改动"的形式:在 if (outcome.status >= 500 && context.fallbackAvailable) return { kind: "legacy" };(保留对真正支持 |
补充:打包版下一条已验证的绕过路径(profile 本地覆盖)前提不变:0.2.0-rc.2 的打包客户端把协商模式写死为 做法# 1) 在带修复的源码里构建并打包这个插件
pnpm --filter @deepseek-ai/dsh-mcp-client run build
pnpm --filter @deepseek-ai/dsh-mcp-client pack --pack-destination /tmp
# 2) 把 tarball 放进目标 profile,解成真实目录(不要用 symlink,理由见下)
mkdir -p ~/.dsh/profiles/<profile>/.dsh-override
cp /tmp/deepseek-ai-dsh-mcp-client-<version>.tgz ~/.dsh/profiles/<profile>/.dsh-override/
mkdir -p ~/.dsh/profiles/<profile>/node_modules/@deepseek-ai/dsh-mcp-client
tar -xzf ~/.dsh/profiles/<profile>/.dsh-override/*.tgz \
-C ~/.dsh/profiles/<profile>/node_modules/@deepseek-ai/dsh-mcp-client --strip-components=1
# 3) 在 profile 的 package.json 里声明这个依赖(file: 指向 profile 内的 tarball)
# "@deepseek-ai/dsh-mcp-client": "file:.dsh-override/deepseek-ai-dsh-mcp-client-<version>.tgz"
# 4) 重启 Host / App为什么这样能生效
两个容易踩的点:
实测结果(macOS 桌面版 0.2.0-rc.2 + Sketch MCP 2.0)重启后:
最后经 mcp-minimal( 适用面与代价不只是这一条:任何"打包版缺一个配置开关、或上游已修但尚未发版"的内置插件行,都能这么顶一段时间。代价是重启 Host 一次,以及要记得在正式版带上修复后删掉这份覆盖(依赖行 + 目录)。 顺带一个诊断经验: |
|
profile 本地覆盖这条我记下了 —— 之前只想到"等 release"或者改 App 包,没往 补两个 Windows 侧的读数(0.2.0-rc.2,命令行安装,不是桌面 App)。探测回来的是 HTTP 500、响应体空, 我这边走的是第三条路:不碰 App 包也不动 profile 依赖,直接改宿主安装树里那份 |
Uh oh!
There was an error while loading. Please reload this page.
环境
http://127.0.0.1:31126/mcp,GCDWebServer,protocolVersion2024-11-05,8 个工具)@modelcontextprotocol/client2.0.0现象
在
~/.dsh/cordis.patch.yml里以streamable-http注册该服务端后:mcp__sketch__*;mcp-client(sketch): server is disconnected;服务端本身完全正常:
initialize返回SketchMCP 2.0,tools/list返回 8 个工具;用官方 SDK 直连也能拿到这 8 个工具。根因(三层,逐层附证据)
1. 打包版把协商模式写死为 auto,配置无从关闭
app.asar中,客户端构造处是versionNegotiation: { mode: "auto" }字面量(整个包中仅此一处),不读取 Config;dsh-mcp-clientConfig schema 中没有versionNegotiation字段(stdio 与 streamable-http 两个分支都没有)。因此"为这个 server 指定 legacy"在打包版里无法表达——用户改配置也无解。
2. 探测被回 501,而 SDK 把所有 ≥500 判为致命
server/discover,该端点对它回 HTTP 501(同一端点 GET → 405);classifyHttpError):401/403 → 致命;≥500 → 致命EraNegotiationFailed;其余状态码与无法识别的 JSON-RPC 错误 → 回退 legacy(-32001 / -32020 / -32021明确保守回退)。501 Not Implemented的语义恰恰是"本服务端不实现该方法",与 404/405 同类,却被归入"服务端故障"。3. 协商失败被并进重连预算,最终永久注销
探测失败 →
connectGeneration失败 → 重连监督器(默认maxAttempts: 10、500ms→30s)耗尽 → 注销该 server 的全部工具且不再重试。整个过程对外只表现为"工具不存在"。最小复现
结果:
对照:在带 per-server
versionNegotiation的源码构建上,同一份配置(legacy)30ms 内完成连接并暴露 8 个工具(同一 SDK、同一 transport、同一 URL)。影响面
server/discover回 5xx(501 Not Implemented是最典型的一种,常见于较老的、嵌入式 HTTP 服务器实现),在打包版上即永久不可用;建议
versionNegotiation: auto | legacy(默认仍为 auto)。这是最小、可验证的解药;实现(含中英文文档与回归测试)本地已有一份,维护者认可方向的话我可以直接提 PR。501 Not Implemented归入 legacy 回退(与 404/405 同桶),或至少在 DSH 侧对EraNegotiationFailed尝试一次降级——501 不是服务端故障。与既有报告的关系
按 @weijiafu14 在 #247 的归并,
dsh-mcp-client的连接监督器此前已有四个面:list_changed重同步替换阶段清空世代本条是第五个面:协商阶段的失败被当作连接失败,吃掉重连预算后永久注销工具——仍然落在同一个问题上,即"何时算失败、失败后保留什么、何时换代"缺少统一规范。
与 #314(streamable-http 激活挂起)相邻但根因不同:那边是零连接挂起,这边是连接被拒后放弃。
All reactions