fishlikewater/dsh-mcp-manager

项目介绍Project Overview

这是 DSH 的 MCP 服务器管理插件,在「设置 → MCP 服务器」页可视化增删改查 MCP 服务器,保存即热挂载/卸载 dsh-mcp-client 并注册 mcp__ 工具,支持 stdio 与 streamable-http、单台开关、真实连接状态、乐观锁并发保护及 env/cred 密钥引用。适合不想手写 cordis.patch.yml、需动态管理 MCP 的场景。注意:安装或改代码后须重启 dsh 进程才生效。

This is a DSH plugin that adds a Settings → MCP Servers page for managing Model Context Protocol servers. It supports adding, editing, deleting, and toggling stdio and streamable-http servers, with hot mount/unmount of dsh-mcp-client, live connection status, optimistic-lock conflict protection, per-server timeouts, and env/cred secret references. Use it when you want UI-driven MCP configuration without editing cordis.patch.yml. Caveat: restart the dsh process after installing or changing plugin code.

或使用命令行安装(适合开发者)Or use CLI install (for developers)

命令行安装CLI Install

dsh plugin --profile web add @fishlikewater/dsh-mcp-manager

fishlikewater/dsh-mcp-manager 加入你的 DSH 配置(web profile)即可启用。

READMEREADME

dsh-mcp-manager

MCP 服务器管理器:给 DeepSeek Harness(DSH)加一个「设置 → MCP 服务器」页面,在界面上配置 MCP(Model Context Protocol)服务器,保存即生效——宿主侧自动挂载/卸载 @deepseek-ai/dsh-mcp-client 实例,我(模型)随即拿到或失去 mcp__<名称>__<工具名> 形式的工具。

无需再手写 cordis.patch.yml 里的 MCP 行,也无需重启进程。

功能

  • 设置页管理:列出 / 新增 / 编辑 / 删除 MCP 服务器,带挂载状态
  • 每台服务器可单独开启/关闭(enabled 开关):关闭立即停止实例并移除工具,开启重新挂载并注册工具,状态持久化
  • 两种传输:stdio(本地命令)与 streamable-http(远程 URL)
  • 真实挂载状态:连接失败、重连中、重连成功、放弃重连等异步事件实时反映到设置页(截获 mcp-client 日志驱动),不再只显示乐观的「已挂载」
  • 并发保存保护:GET/POST 携带 rev 修订号(乐观锁),配置被其他窗口改过时返回 409 并提示刷新,避免静默覆盖
  • 每台服务器可配置 toolCallTimeoutMs(工具调用超时)与 failOnStartupError(启动失败即报错)
  • 密钥不入盘:env / headers 的值支持 env:NAME(进程环境变量)与 cred:NAME(DSH 凭据)引用,挂载时解析,settings.yaml 只存引用
  • 配置持久化在 settings.yamlmcp 命名空间(mcp.servers),改动热生效
  • 宿主侧按配置动态挂载 @deepseek-ai/dsh-mcp-client 实例(断线自动重连、工具自动注册/注销由它负责)
  • headless profile 也能用:没有 webServer 服务时跳过 HTTP 接口,只做实例管理

安装

前置:已安装 dsh CLI(以及 pnpm;dsh plugin 命令转发给 pnpm)。

# 从 npm 安装(发布后)
dsh plugin --profile web add @fishlikewater/dsh-mcp-manager

# 或从本地 checkout 安装
dsh plugin --profile web add ./path/to/dsh-mcp-manager

dsh plugin add 会把包安装进 profile 的依赖,并因为本包声明了 dsh.bundle,自动把 @fishlikewater/dsh-mcp-manager 追加到该 profile 的 dsh.profile.bundles(即应用本包的 cordis.patch.yml 层)。验证组合树:

dsh --profile web --dump-config   # 应能看到 mcp-manager 行

重启 dsh 进程后生效(bundle 层在启动时组合;插件代码改动也需要重启,见下文「开发」)。重启后刷新浏览器页面,打开 设置 → MCP 服务器 即可。

卸载:dsh plugin --profile web remove @fishlikewater/dsh-mcp-manager(同时移除依赖与 bundle 层)。

使用

设置页各字段:

字段 传输 说明
名称(serverName) 两者 [A-Za-z0-9_-]{1,32},全局唯一,决定工具名前缀 mcp__<名称>__…
传输方式 两者 stdio / streamable-http
命令(command) stdio 可执行文件(支持绝对路径)或 npx 之类命令
参数(args) stdio 每行一个
环境变量(env) stdio 每行 KEY=VALUE;值支持 env:NAME / cred:NAME 引用
工作目录(cwd) stdio 可选
URL http http://localhost:3000/mcp
请求头(headers) http 每行 KEY: VALUE;值支持 env:NAME / cred:NAME 引用
工具调用超时(toolCallTimeoutMs) 两者 毫秒,默认 60000
启动失败即报错(failOnStartupError) 两者 是否在首次连接/工具同步失败时报错(默认否,自动重连)

保存后立即生效;删除后对应工具立即移除。

每张服务器卡片上的「关闭 / 开启」按钮会立即停止 / 启动对应实例:关闭后工具马上移除、不再重连;开启后重新挂载并注册工具。开关状态(enabled,默认 true)随配置一起持久化在 settings.yaml,重启 dsh 后保持;只影响被切换的那一台,其余服务器不受影响。

示例

examples/mcp-servers.example.yaml 给出了 settings.yaml 中 mcp 命名空间的示例(stdio 与 streamable-http 各一)。可以直接把它合并进 $DSH_HOME/settings.yaml 作为初始配置,再从设置页调整。

HTTP 接口(供设置页使用)

方法 路径 说明
GET /api/mcp/servers 返回 { rev, servers, status }rev 是命名空间修订号(乐观锁),statusserverName -> { state: 'ok'|'error'|'disabled', message }
POST /api/mcp/servers 请求体 { rev?, servers: [...] },整体替换并触发重挂载;rev 与当前修订不符返回 409 { code: 'conflict', rev };校验失败返回 400 { error }

密钥引用(env:NAME / cred:NAME)在挂载时解析:env: 读进程环境变量;cred: 经 DSH 的 credentials 服务解析(resolve),服务不可用或未配置时保留字面值并打日志。settings.yaml 里始终只存引用文本。

开发

结构:

├── package.json       # dsh.bundle.patch + dsh.client 双 manifest
├── cordis.patch.yml   # bundle 层:插入 mcp-manager 行
├── index.js           # 宿主侧:settings 注册 + 实例挂载 + HTTP 接口
├── lib/logic.js       # 纯逻辑:settings schema、校验、配置构造、指纹、日志翻译、密钥引用
├── client.js          # 客户端 bundle(手写 CJS factory,经 ./client 导出)
├── test/              # node:test 套件(见下)
├── fixtures/          # E2E 用的极简 stdio MCP 服务器(不打包、不被当作测试执行)
├── scripts/           # 发布前 pack 校验等
├── examples/
└── .github/workflows/ # CI:Node × dsh-mcp-client 版本矩阵 + pack 校验

注意:

  • 改代码后必须重启 dsh 进程:Node 的 ESM 模块缓存不会随文件变化失效。配置数据不需要重启(设置页保存即热生效)。
  • client.js 是给浏览器模块加载器的构建产物(window.__ModuleLoader__.load 格式),直接手写维护,不需要打包器。
  • 设置页导航图标:外壳按 section id 硬编码图标且没有注册点,本插件用一小段 CSS 覆盖把「MCP 服务器」行的图标换成链接图标;选择器依赖外壳的类名哈希(VOzbGW_*),DSH 升级后若失效只会安静地退回默认齿轮图标,不影响功能。
  • @deepseek-ai/dsh-mcp-client 以 peerDependency 声明,由运行时提供;@deepseek-ai/schemastery 为普通依赖。

测试(兼容性)

npm test(node:test,无需额外框架):

  • test/host-logic.test.js:settings 命名空间 schema、HTTP 校验、mcp-client 配置构造、配置指纹、mcp-client 日志 → 状态翻译(用真实日志文案做夹具)、密钥引用解析
  • test/client-logic.test.js:把 client.js 加载进 vm 沙箱,测解析/组装助手,以及「客户端表单产出 → 宿主校验」的往返契约
  • test/contract.test.js:用真实的 @deepseek-ai/dsh-mcp-client Config schema 校验 buildClientConfig 的产出——它两边的配置契约一旦偏离,测试先红
  • test/e2e.test.js:端到端冒烟——内存 Cordis 上下文 + 假 settings/tools/webServer 服务 + 极简 stdio MCP 服务器(fixtures/fake-mcp-server.mjs),走真实 HTTP 验证「保存即生效」全链路(挂载、工具注册、真实失败状态、rev 409、开关、引用)

CI(.github/workflows/ci.yml)跑 3 个 Node(18/20/22)× 3 个已发布的 dsh-mcp-client0.1.0-rc.6 / 0.1.0-rc.8 / 0.1.1-rc.2)矩阵,另有 pack job 校验发布内容白名单(node scripts/check-pack.mjs,npm publish 前由 prepublishOnly 自动执行)。

发布

npm publish

包名使用 scope 版 @fishlikewater/dsh-mcp-manager:无 scope 的 dsh-mcp-manager 已被他人占用(github.com/Nichts0v0/dsh-mcp-manager)。发布者的 npm 账号必须是 fishlikewater(scope 归属),publishConfig.access: public 已配置,无需 --access public。改包名时需同步修改 cordis.patch.yml 里的 name 行。

License

MIT

上一个 Prev dsh-download-progress 下一个 Next dsh-update-center