Skip to content

fix(dsh): gate MCP bridge on daemon health - #250

Merged
Windsander merged 2 commits into
mainfrom
fix/dsh-attach-bridge
Oct 25, 2026
Merged

Windsander merged 2 commits into
mainfrom
fix/dsh-attach-bridge

Conversation

@Windsander

Copy link
Copy Markdown
Owner

Follow-up to the reviewer feedback on awesome-dsh-plugin#9167.

问题

默认 attach 模式下 daemon 未运行时,面板显示「Mebular 未运行」,但 MCP bridge 仍被挂载:官方 client 初次连接失败后保持激活并后台重试,已连接后掉线时还会保留 last-known tools,工具调用可能等到 60s 超时,表现为“静默等待”。

根因:

  • apply() 在 lifecycle.start() 后立即 mountMcp(),没有等待健康状态。
  • mountMcp() 固定 failOnStartupError: false,且立即记录 mcp client mounted。
  • mountMcp() 丢弃了 ctx.plugin() 的 fiber,无法在 daemon 掉线时卸载。
  • /mebular/embed-info 走 lifecycle,MCP bridge 走独立链路,二者没有同步。

修复

  • 新增 daemon-aware MCP bridge supervisor:只在 lifecycle up 时挂载官方 client;starting/down 不挂载。
  • 掉线时 await ctx.plugin() fiber dispose,注销工具,并记录 mcp bridge detached (daemon_unreachable)。
  • daemon 恢复后自动重新挂载,不需要重启 DSH。
  • mountMcp() 改为 failOnStartupError: true,await fiber settle 并检查 active;只有真正连接/注册成功后才记录 mounted。失败时 dispose 子 fiber、返回稳定错误码,由 supervisor 重试,不影响父插件。
  • managed 的 starting 不挂载;managed_start_failed / managed_cli_missing 有稳定日志且不挂载。
  • 面板 EN/ZH 明确说明 daemon 启动前 MCP 工具不可用、启动后自动恢复。
  • 保持 attach 语义:不启动/停止 daemon;managed 只停止自己的 child。

验证

  • npm test -- --runInBand tests/dsh:4 suites / 91 tests passed
  • npm run verify:dsh-plugin:129 checks passed
  • npm run lint:passed
  • npm run check:docs:7/7
  • 真实官方 peer 集成测试:实际 Cordis + @deepseek-ai/dsh-mcp-client + 本地 Streamable HTTP MCP server;验证工具注册、dispose 注销、相同 serverName 重挂、不可达 daemon 快速失败。
  • 真实 DSH host(0.2.1-rc.2)+ 本地 Mebular daemon:
    • 无 daemon:面板显示「Mebular 未运行」,并明确说明 MCP 工具暂不可用;
    • 启动 daemon:面板在轮询窗口内变为「已连接」;
    • 停止 daemon:面板恢复「Mebular 未运行」;
    • 再次启动:面板再次「已连接」。
    • 该临时 DSH profile 未配置模型,因此未在 UI 中直接列出工具;工具侧由上述真实 peer 集成测试覆盖。

范围

  • 未 bump 版本,未发布;计划并入完整 v0.1.1。
  • 未修改根 README、awesome listing 或 PR docs(dsh): mark awesome-dsh-plugin listing live #249。
  • 已知边界:掉线检测上限约 2s;官方 client dispose 最长可能需要 5s;已发起的 in-flight call 仍受官方 transport 取消语义约束,但 dispose 后不会再保留工具供新调用静默等待。

Mount the official MCP client only while the lifecycle reports up. Await the child fiber so mounted means connected and registered, and dispose it on daemon loss so last-known tools cannot hang calls. Retry after recovery without restarting DSH or duplicating serverName.

Update panel guidance and DSH docs, and cover attach/managed transitions, peer-missing, panel:false, disposal, and a real official-peer mount/dispose cycle.
@Windsander
Windsander merged commit 1e33d8c into main Oct 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant