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