前言¶
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