dsh-mcp-status:在 Web GUI 側邊欄看清 MCP 服務器連接狀態

前言

DSH 的理念是「一切皆插件」,MCP 服務器通常也是以插件形式掛進 profile 的。實際用下來有一個反覆出現的問題:profile 裏同時掛着多個 MCP 服務器,某次對話某條 mcp__<server>__* 工具調不通了,你很難快速判斷是「這臺服務器壓根沒連上」還是「連上之後又死了」。@deepseek-ai/dsh-mcp-client 本身不暴露連接狀態,fiber 是 active 的不代表服務器活着,工具註冊表裏還有條目也不代表現在還通。

dsh-mcp-status 解決的就是這件事:在 Web GUI 側邊欄把每個 MCP 服務器的連接狀態、工具數量、配置攤開,並支持原地開關和重連。下面介紹這個插件。

這是什麼

sonettogu14/dsh-mcp-status(維護者 SonettoGu14,分類客戶端)是 DeepSeek Harness Web GUI 的 MCP 服務器面板插件。它把宿主側 ctx.loader.entries() 裏所有 @deepseek-ai/dsh-mcp-client 行列出來——profile 補丁、home 補丁、插件包插入的行都算,與宿主實際在跑的一致——並給出連接狀態、工具數量和配置,允許在不離開面板的前提下停用 / 啓用、重試連接、單行測試連接。

它回答三個問題:有哪些 MCP 服務器;連上了沒有;沒連上的話爲什麼。

核心功能

1、側邊欄列出每個 MCP 服務器,顯示狀態、工具數、傳輸與地址、來源補丁文件、超時與重連策略。狀態由四份證據組合推導,不是客戶端自報。

2、原地開關與重連。開關只改寫當前 profile 補丁文件裏那一行的 disabled 字段:按縮進定位到 - id: <行 id> 之後的塊,插入或刪除一行 disabled: true,其餘字節原樣保留,採用臨時文件 + rename 的原子寫(保留原權限位)。寫完後補丁監聽會熱重載該行,重載即重新連接;8 秒內沒連上會主動 hmr.reconcileProfile([id]) 再排一次。不在可編輯補丁文件裏的行(例如插件包插入的 drawio)顯示「內置」,開關不可用。

3、「測試連接」用宿主同一份配置真做一次 JSON-RPC 握手(stdio 起進程 / http 打請求),把 ECONNREFUSED、HTTP 401、超時原文貼回行內。

4、狀態同時餵給 system prompt 摘要與調用閘門:有服務器不可用時註冊一個最多 6 行的健康摘要;mcp__<server>__* 的調用在派發前被判爲不可用則拒絕,並給出可讀原因。

面板提供四個同源路由:

GET  /api/dsh-mcp-status/servers   # 快照:狀態、工具數、傳輸與地址、來源補丁文件
POST /api/dsh-mcp-status/toggle    # { id, enabled }:改補丁行,等熱重載,返回新狀態
POST /api/dsh-mcp-status/retry     # { id }:重新掛載這一行
POST /api/dsh-mcp-status/test      # { id }:真握手,返回協議版本 / serverInfo / 工具數 / 失敗原因

寫操作要求同源證明,所有路由只接受迴環來源。

狀態判定

狀態由 lib/status.js 的 resolveStatus() 純函數推導,每條結論都帶依據,優先級從上到下:

順序 條件 狀態 reason
1 行被停用 已停用 disabled
2 loader fiber 失敗 加載失敗 fiber-failed
3 fiber 未就緒 啓動中 pending
4 最近一次測試失敗,且端口不通或結論在 probeAssertMs 內 不可達 probe-failed
5 streamable-http 端口拒絕連接 / 超時 不可達 tcp-refused
6 最近一次測試成功 已連接 connected
7 工具表讀不到 已連接 unknown-tools(不下結論)
8 有工具 / 沒有工具 已連接 / 未連接 connected / no-tools

第 8 條的 no-tools 刻意與 unreachable 分開:工具數爲 0 可能只是這行掛在 per-agent 作用域、全局註冊表看不見,當斷線處理會誤報也會誤攔。每行 DTO 帶 reason 與 evidence(fiber / tools / tcp / probe 四個信號及時間戳),展開區把依據壓成一行。

調用閘門只有證據夠新才攔:快照超過 2 × refreshMs 視爲過期,pending、no-tools、disabled 一律放行。idle 不等於斷線。

安裝與啓用

README 給出四種裝法,任選其一:

# 1. npm(推薦):預構建包,不需要構建授權
dsh plugin --profile <profile> add dsh-mcp-status

# 2. 本地目錄(開發用)
dsh plugin --profile <profile> add link:<本目錄>

# 3. 從 GitHub
dsh plugin --profile <profile> add github:SonettoGu14/dsh-mcp-status

第四種是在 Harness 裏用插件管理器的 install_bundle 指向本目錄或本倉庫。npm 包頁:https://www.npmjs.com/package/dsh-mcp-status

安裝後在側邊欄點「MCP 服務器」即可。卸載:

dsh plugin --profile <profile> remove dsh-mcp-status

配置與典型用法

配置寫在本插件自己的 patch 行裏:

- id: mcp-status
  name: dsh-mcp-status
  config:
    refreshMs: 10000        # 後臺狀態刷新週期(≥ 2000)
    startupWaitMs: 8000     # 開關/重試後等待連接就緒的上限
    probeAssertMs: 60000    # 測試失敗後,結論壓過實時探活的窗口
    probeTimeoutMs: 15000   # 「測試連接」整次超時
    promptHealth: true      # 是否把不可用寫進 system prompt
    guardUnreachable: true  # 是否攔截髮往不可用服務器的工具調用

典型操作流程:側邊欄點開某行,看狀態徽標;是黃的(啓動中)或紅的(未連接 / 不可達 / 加載失敗)時點「測試連接」,行內會貼回握手失敗原文;確認是配置或進程問題後直接點開關或重試,不必再去翻補丁文件。系統 prompt 側不用額外操作,不可用摘要會在健康時自動註銷。

面板只讀配置,不做新增與編輯;新增和編輯仍在「設置 → 插件 → MCP 服務器配置」。

兼容與依賴

  • 需要宿主組合了 webServer(Web GUI)與 @deepseek-ai/dsh-mcp-client(MCP 客戶端),兩者都是 DSH 自帶包。
  • 包版本 0.2.0,許可證 MIT,要求 Node >=22.19.0。
  • 不依賴任何第三方運行時包:宿主半體只用 Node 內置模塊,探測模塊自己實現 MCP 握手。官方 @deepseek-ai/* 包一個都沒有 import,因此 package.json 裏沒有 dependencies / peerDependencies。

適用場景與注意

適合用 DSH Web GUI、profile 裏掛多個 MCP 服務器的人,用來替代「翻補丁文件 + 猜連接狀態」的做法。需要留意:

  • 插件以當前 dsh 進程的權限運行,安裝前應先檢查源碼與許可證(MIT)。
  • 停用 / 啓用會改寫當前 profile 補丁文件裏那一行;如果該行由其它工具生成(例如同步 MCP 配置的第三方工具),那個工具下次整表重寫時可能覆蓋本次開關結果。
  • stdio 行沒有端口可探,存活只能靠工具數 + 手動「測試連接」的結論。
  • 閘門可能誤攔,儘管只攔「快照新鮮 + 端口確實拒絕連接 / 剛測過失敗」;不放心就設 guardUnreachable: false,退回純看板行爲。
  • 狀態是推導的,不是客戶端自報的。真要讓狀態像 opencode 那樣由客戶端層擁有,需要上游 dsh-mcp-client 提供接口。

結尾

dsh-mcp-status 的價值在於把「MCP 服務器到底通不通」變成一個面板上可見、可操作的事實,而不是靠 fiber 狀態和工具註冊表間接猜。信息密度集中在狀態判定表與四份證據上,開關寫補丁的方式也刻意保守,不破壞原文件。

目錄頁:https://www.skillhub.cn/plugins/SonettoGu14/dsh-mcp-status

GitHub:https://github.com/SonettoGu14/dsh-mcp-status

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜