前言¶
DSH 的插件機制可以把能力拆出去單獨維護。MCP server 如果配在 profile 或全局層,多個項目會共用同一組工具;項目 A 的工具也可能出現在項目 B 的會話裏。若希望某個項目的 MCP 只在該項目的會話中生效,就需要按 workspace 加載。
下面介紹 Momojie-S/dsh-workspace-mcp:它在項目根讀取 .dsh/mcp.servers.yml,按會話的當前目錄自動加載/卸載 MCP server,並把工具註冊到 agent scope。
這是什麼¶
Momojie-S/dsh-workspace-mcp 是一個 DSH 插件,許可證爲 MIT。
它解決的核心問題是:不同項目的 MCP server 互不干擾。每個項目自己的 .dsh/mcp.servers.yml 只在自己的會話生效;沒有該文件的目錄不加載任何 MCP。MCP 工具註冊到 agent scope,隨 agent 生滅自動回收。
核心功能¶
- agent 創建即連接註冊(
agent/created),首個模型請求就含這些工具。 - 斷線自動重連:啓動失敗與中途斷線均按指數退避重連並重新註冊工具。重連期間舊工具保持註冊,調用會失敗;server 恢復後自動換新。
- 會話失效自愈:streamable-http server 重啓或會話驅逐後,
Session not found類錯誤會被判定爲斷線並換代重連。 - stdio 環境繼承:子進程拿到 scrubbed 父環境,並在其上用 yml 的
env覆蓋。父環境會剝KEY|PASSWORD|SECRET|TOKEN命中名與DSH_*前綴名;env是覆蓋層,不是完整環境。 - server 聲明受支持的
outputSchema時,進入structuredContent輸出契約。 - 非法工具列表或註冊名衝突時,整代拒絕/回滾。
- server 發
toolListChanged通知時自動重同步工具列表。 - 改配置文件由 chokidar 監聽,保存即重載。
- 與全局 MCP 發生同名衝突時,agent 作用域按工具名遮蔽全局。
- 該插件是組合包(
dsh.bundle),用dsh plugin安裝進 profile 後自動追加配置層,無需手編 patch。 .dsh/mcp.servers.yml中的同名項可覆蓋插件級配置。
安裝與啓用¶
環境要求:DSH >= 0.1.0-rc.6,已驗證至 0.1.1-rc.2。
GitHub 安裝命令如下。私倉安裝需要 git 憑據;pnpm >=10 首次 add 可能提示授權構建,按提示把包鍵寫進 ~/.dsh/profiles/web/pnpm-workspace.yaml 的 allowBuilds 後重新 add。tarball 安裝無授權要求。
dsh plugin --profile web add github:Momojie-S/dsh-workspace-mcp
經過上面的安裝步驟,再驗證插件層是否就位。這裏用 --dump-config 檢查 workspace-mcp 相關層:
dsh web --dump-config | Select-String workspace-mcp
headless 或 tui profile 默認沒有掛載 workspace-mcp,需要時可用 --patch 臨時掛一行 file:/// 指向其 lib/index.js。純 host 半部插件可以臨時這樣掛,帶瀏覽器半部的插件不行。下面示例中的具體路徑來自資料,未確認是否通用,需要替換爲本機實際路徑:
dsh --profile headless --patch <(echo "- insert:
- id: workspace-mcp
name: file:///D:/code/workspace/deepseek-harness-101/plugins/dsh-workspace-mcp/lib/index.js") "任務…"
開發模式下,源碼直連的做法是先構建,再在 profile 的 cordis.patch.yml 手動加行:
npm install && npm run build
手動加行時,name 指向本機 lib/index.js,並可配置 configFile 與 verbose。下面示例中的路徑同樣來自資料,未確認是否通用:
- insert:
- id: workspace-mcp
name: file:///D:/code/workspace/deepseek-harness-101/plugins/dsh-workspace-mcp/lib/index.js
config:
configFile: '.dsh/mcp.servers.yml'
verbose: true
典型用法¶
先在項目根創建 .dsh/mcp.servers.yml。stdio server 可配置 transport: stdio、command、args、env;remote server 可配置 transport: streamable-http、url、headers。示例如下:
servers:
my-server:
transport: stdio
command: npx
args: ["-y", "some-mcp-server@latest"]
env: {}
remote:
transport: streamable-http
url: https://example.com/mcp
headers:
Authorization: "Bearer <token>"
配置保存後,在會話裏讓 agent 列工具。工具名形式爲:
mcp__<serverName>__<toolName>
工具出現即說明該 workspace 加載成功;切到沒有 .dsh/mcp.servers.yml 的目錄,這些工具不再出現,說明隔離生效。
同名遮蔽¶
兩邊工具名都是 mcp__<serverName>__<tool>。當項目級 MCP 與全局 MCP 發生衝突時,agent 作用域按工具名遮蔽全局。
serverName不同:兩組工具共存,模型都可見。- 同
serverName(工具名撞車):項目級優先,模型看到並調用的是項目版;全局版對沒配此 server 的其它 workspace 不受影響。 - 全局 patch 裏兩條同
serverName:後者整代註冊回滾,日誌報already registered,該 server 一個工具都沒有。 - 同一個 yml 裏重複 server 鍵:按 YAML 後鍵覆蓋前鍵。
如果兩邊工具列表不完全一致,只有重名的那部分被遮蔽,其餘工具仍各自可見。把全局 server 指向本地 dev 實例,是同名遮蔽的一個常見用途;無意撞名就改 serverName。
配置¶
插件級配置放在 patch 的 config 字段中。已覈實用法中出現的配置項包括 configFile 與 verbose。per-server 覆蓋可配置 reconnect.enabled、reconnect.initialDelayMs、reconnect.maxAttempts。同名項優先於插件級:
servers:
flaky:
transport: stdio
command: npx
args: ["-y", "some-mcp"]
reconnect:
enabled: true
initialDelayMs: 1000
maxAttempts: 5
驗證與排障¶
驗證隔離時,先項目根放一個測試 server,然後在會話裏讓 agent 列工具;再切到無配置的目錄,確認這些工具消失。
排障時可打開詳細日誌,在掛載配置裏使用:
verbose: true
stdio 場景下,連接/註冊日誌會出現在 stderr,常見行包括:
[ws-mcp] server "xxx": 註冊 N 個工具
斷線重連相關邏輯可用測試腳本驗證:
npm test
該測試覆蓋斷線重連、啓動失敗退避、Session not found 換代重連,以及官方對齊五項。
適用場景與注意¶
適合多項目並存、且每個項目的 MCP server 不同的情況;也適合臨時把全局 server 指向本地 dev 實例調試。
使用注意:
- 插件以當前 DSH 進程權限運行,安裝前應檢查源碼、依賴和許可證。
- stdio server 的
env只是覆蓋層;需要父環境變量時,父環境會先經過 scrub,KEY|PASSWORD|SECRET|TOKEN命中名與DSH_*前綴名會被剝掉。 - 斷線重連期間舊工具仍可見,但調用會失敗。
headless/tuiprofile 默認沒有掛載該插件,臨時掛載的file:///路徑需指向本機實際目錄。- GitHub 安裝私倉需要 git 憑據;pnpm
>=10首次add可能需要授權構建。 - 該插件來自社區 GitHub 倉庫;社區目錄條目並非 DeepSeek / 幻方官方應用商店。
倉庫地址:
https://github.com/Momojie-S/dsh-workspace-mcp