DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

VCPr0j3k7 /

VCPr0j3k7/dsh-mcp-manager

Verified

Graphical MCP server manager for the DeepSeek Harness desktop shell — add, remove, toggle, test, and scan Model Context Protocol servers

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@aa9301e6

dsh-mcp-manager

License: MIT Node.js

English | 简体中文

为 DeepSeek Harness (DSH) 提供 MCP(Model Context Protocol)服务器的图形化管理界面:列出、添加、删除、 启用停用、测试连接,并可从本机已有的 MCP 配置中扫描导入。

本插件以独立 bundle 形式装入 DSH profile,不修改官方任何源码。


目录

  • 问题背景
  • 环境要求
  • 安装
  • 卸载
  • 工作原理
  • 界面
  • 宿主接口
  • 配置的落地方式
  • 内置服务器目录
  • 启用条件
  • 测试
  • 已知限制
  • 许可

问题背景

官方 base bundle 已包含 MCP 客户端 @deepseek-ai/dsh-mcp-client,但没有配套的管理界面。每台 MCP 服务器需要作为一条 insert 条目手工写入 profile 用户层的 cordis.patch.yml:

- insert:
    - id: mcp-filesystem
      name: "@deepseek-ai/dsh-mcp-client"
      config:
        serverName: filesystem
        transport: stdio
        command: npx
        args: ["-y", "@modelcontextprotocol/server-filesystem", "D:\\work"]

问题在于该文件同时是 boot 阶段的输入:

  • 顶层必须是一个 YAML 数组,每个元素是一个 patch;
  • 解析由官方 dsh-app-boot 使用 js-yaml 加自定义 schema 完成,解析失败属于致命错误 —— 应用直接无法启动,而界面上没有任何修复入口;
  • 同一个文件还是用户自己的 patch 层,手工编辑时容易破坏其它内容。

因此需要一个带校验的图形化编辑入口:把配置当作结构化数据读写,写入前先验证,并且只修改自己负责的那一段。

环境要求

项 要求
Node.js ^22.19.0 || >=24
DeepSeek Harness 官方桌面版(Windows)。本插件依赖其 dsh-desktop-host 的 process.argv 布局与随包 Node / pnpm
官方 base bundle 需包含 @deepseek-ai/dsh-mcp-client(官方 base bundle 已自带)
可选 运行时 node_modules 中存在 @modelcontextprotocol/sdk,「测试连接」功能需要它

安装

安装分两步。第二步不可省略 —— 只执行 pnpm add 不会把插件加入 bundle 层栈。

第一步:把包装进 profile

# 1. 进入目标 profile 目录(官方桌面版使用 desktop profile)
cd ~/.dsh/profiles/desktop

# 2. 用官方桌面版随包的 pnpm 安装
#    随包 pnpm 位于 <安装目录>/resources/runtime/pnpm/bin/pnpm.cjs,
#    可用随包 node 执行:node "<该路径>" add ...
pnpm add "file:<插件目录绝对路径>"

也可以直接从 GitHub 安装:

pnpm add "github:VCPr0j3k7/dsh-mcp-manager"

第二步:登记进 dsh.profile.bundles

编辑 profile 目录下的 package.json,把包名加入 dsh.profile.bundles 数组:

{
  "name": "dsh-profile-desktop",
  "private": true,
  "dependencies": {
    "dsh-mcp-manager": "file:<插件目录绝对路径>"
  },
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-mcp-manager"
      ]
    }
  }
}

dsh.profile.bundles 是 profile 的 bundle 层栈:DSH 只从这里列出的 bundle 装配插件树。包已安装但未登记时, 插件不会加载,界面上也不会出现任何提示 —— 现象只是「侧边栏里没有 MCP 连接器」。这是本插件最常见的安装问题。

第三步:重启

配置装配发生在启动阶段。修改 package.json 或 cordis.patch.yml 之后必须重启 DSH 桌面版, 运行中的实例不会热更新。重启后侧边栏应出现「MCP 连接器」入口。

卸载

cd ~/.dsh/profiles/desktop
pnpm remove dsh-mcp-manager

随后从 dsh.profile.bundles 中删除 dsh-mcp-manager 这一项,并重启 DSH。

卸载不会删除已经写入 cordis.patch.yml 的 MCP 服务器条目 —— 它们位于标记区块内,会继续由官方 @deepseek-ai/dsh-mcp-client 使用。如需一并清除,手工删除该区块(含起止标记行)即可。

工作原理

两个半边

半边 运行位置 装载方式
宿主半边 index.js + host/ Node.js(官方宿主进程) Cordis 插件:导出 name / inject / apply(ctx)
客户端半边 client.js 浏览器(桌面外壳内的 SPA) window.__ModuleLoader__.load({ id, factory })

宿主半边在 ctx.webServer 上注册一条 kind: 'prefix' 路由 /dsh-mcp-manager/api, 前缀内部的派发由 host/router.mjs 完成。这样注册点只有一处,卸载时由框架统一清理。

请求与响应

所有接口统一返回信封:

{ "ok": true,  "data": { /* ... */ } }
{ "ok": false, "error": "可读的错误信息" }

业务失败同样返回 HTTP 200,状态码只用于表达传输层事实(未知路由返回 404)。请求体上限 8 MB。

基址探测

客户端页面由官方外壳提供,其来源(origin)可能是宿主的 HTTP 地址、外壳的自定义 scheme,或是不透明来源。 因此客户端在首次请求时按顺序尝试候选基址(相对路径 → http://dsh.internal),并以 /info 返回的 data.plugin 是否等于本插件 id 作为判定依据 —— 仅返回 200 不足以判定,SPA 的兜底路由会把未知路径也 返回 200 + HTML。选定后记录,后续请求直接复用。

事件通道

宿主事件(如 MCP 配置更新日志)通过 GET /events?since=<seq> 拉取,客户端以 300ms 间隔轮询。 不使用 SSE,是因为外壳对自定义 scheme 的响应体转发是否会缓冲无法确认,轮询没有这个不确定性。

配置写入

真正的 MCP 连接由官方 @deepseek-ai/dsh-mcp-client 完成,本插件只负责把条目写进 profile 的用户层 patch。 profile 的 patchReload 为 startup,因此所有写操作都返回 needsRestart: true,由界面给出重启提示条。

YAML 库的来源

写入前的校验必须使用官方同一套库,否则可能出现「本插件认为合法、boot 认为非法」的情况。因此 host/yaml-libs.mjs 按绝对路径从以下位置依次查找 js-yaml(require 目录入口,不看 exports):

  1. 运行时目录 <runtimeDir>/node_modules
  2. process.argv[2] 给出的运行时目录下的 node_modules
  3. profile 目录下的 node_modules
  4. <DSH_HOME>/profiles/node_modules

运行时中的那一份优先,profile 中的那一份(即本包声明的 js-yaml 依赖)作为兜底。

界面

侧边栏「MCP 连接器」入口,页面分三个标签页:

标签页 内容
已接入 当前 profile 中的服务器卡片:传输方式、命令或地址、条目 id、连接状态、工具数量、原始配置。支持测试连接、启用停用、删除
发现 分组展示可一键接入的服务器:其它 AI 客户端配置、其它 DSH 家目录、内置常用目录。点击「接入」会把已填好的参数带入添加表单
添加 粘贴导入(mcpServers JSON 片段或一行 npx / uvx 启动命令)与手动表单(stdio / streamable-http)

连接状态来自宿主而非本地推断:只有 mcp__<serverName>__* 的工具确实出现在宿主的工具注册表中, 才显示为「已连接」;配置已写入但尚未重启时显示为「待重启生效」。

「添加」页支持先测试再写入,避免出现「重启后才发现连不上」。

宿主接口

全部挂在 /dsh-mcp-manager/api 下。

公共路由(由 host/router.mjs 提供):

路由 说明
GET /info 插件与宿主信息;data.plugin 用于客户端校验基址
GET /config 读取共享配置
POST /config 深合并写入共享配置
POST /open-external 用系统默认程序打开网址(仅放行 http / https)
POST /pick-directory 弹出系统目录选择器
GET /restart-pending profile 关键文件的修改时间是否晚于宿主就绪时刻
POST /restart-host 请求重启宿主。插件无法重启宿主进程,该路由始终返回错误,由界面提示手动重启
GET /events?since=<seq> 拉取宿主事件(客户端 300ms 轮询)

本插件路由(由 index.js 注册):

路由 说明
GET /mcp/list 列出当前 profile 中的服务器,并附带宿主侧真实状态
POST /mcp/add 新增服务器;同名时需显式传入 overwrite: true
POST /mcp/remove 按条目 id 删除服务器
POST /mcp/toggle 启用 / 停用(写入 disabled 字段,不删除配置)
GET /mcp/scan 扫描本机可供接入的 MCP 服务器
POST /mcp/test 实际发起一次 MCP 握手并取回工具列表
POST /mcp/parse 解析粘贴的 JSON 片段或一行启动命令

配置的落地方式

本插件只修改 cordis.patch.yml 中由成对标记注释围起的区块:

# >>> dsh-desktop:mcp —— 以下内容由桌面版维护,请勿手工编辑
- insert:
    - id: mcp-filesystem
      name: "@deepseek-ai/dsh-mcp-client"
      config: { /* ... */ }
# <<< dsh-desktop:mcp

几条硬性约定:

  • 区块内容是完整的 patch 列表项(- insert: [...]),而不是片段。cordis.patch.yml 的顶层必须是 一个 YAML 数组,把 insert: 平铺进文件会导致解析失败。
  • 写入前先验证:生成的候选全文会用官方同一套 js-yaml 解析一遍,通过后才落盘。
  • 原子写入:先写临时文件再 rename,任何时刻磁盘上要么是旧版、要么是新版,不会留下半截文件。
  • 幂等:同一份配置反复写入得到同一份字节,因此每次启动的同步不会反复改写 profile。
  • 区块之外不修改任何字节:文件中手工编写的 MCP 条目会在界面上以「手工条目」列出,只读展示,不可通过 本插件修改或删除。

内置服务器目录

「发现」页附带一份内置目录,只收录官方或广泛使用、且用 npx 一条命令即可启动的服务器:

名称 说明
文件系统 让模型读写指定目录下的文件(必须指定一个目录,否则会被拒绝启动)
长期记忆 基于知识图谱的记忆服务器:把事实写进去,之后跨会话取回
顺序思考 把复杂问题拆成可回溯的思考步骤,适合需要多步推理的任务
Everything 官方演示服务器:提供一组示例工具,用于确认 MCP 通路是否打通
Playwright 浏览器 让模型真正打开一个浏览器:点击页面、填写表单、截图、抓取内容
Context7 文档 按库名获取最新的官方文档与代码示例,减少模型记错 API 的情况

首次启动这些服务器需要联网由 npx 拉取包。带参数的条目会预先填好表单字段,由用户确认后再写入。

启用条件

半边 条件
宿主半边 声明 inject = ['webServer'],需要宿主组合中存在 webServer 服务(官方 base bundle 已提供)
客户端半边 声明 dsh.client.inject = ['@deepseek-ai/dsh-client-ui-slots'],dsh.client.platform = 'web'
两者共同 包名必须登记在 profile package.json 的 dsh.profile.bundles 数组中

另外,读写 MCP 配置需要同时拿到运行时目录与 profile 目录(来自 process.argv[2] 与 process.argv[3])。 两者缺任一时,GET /mcp/list 会返回可读的错误信息,而不是抛出 ENOENT。

测试

npm test

test/check.mjs 为纯 Node 自检(37 项),不依赖 DSH 运行时,覆盖:

  • package.json 的声明与入口文件是否真实存在(dsh.bundle.patch、exports['./client']、dsh.client.platform);
  • 宿主半边的导出契约(name / inject / apply)与 apply() 是否正常注册前缀路由;
  • 路由对齐:从 client.js 中提取客户端调用的全部路由,逐条确认在宿主路由表中有实现;
  • /info 的 data.plugin、未知路由回 404、ctx.effect 登记了清理函数;
  • 共享配置的默认值包含 githubToken 字段。

自检会把 DSH_HOME 与 profile 目录指向本次运行创建的临时目录,因此不会读写真实的 ~/.dsh。

端到端验证:重启桌面版后,侧边栏应出现「MCP 连接器」;在「发现」页接入一台服务器并重启, 「已接入」页应显示「已连接 · N 个工具」。

已知限制

  • 修改必须重启宿主才生效。 profile 的 patchReload 为 startup,这是官方组合的装载时序,不是本插件的 取舍。界面会给出重启提示条。
  • 插件无法重启宿主进程。 POST /restart-host 始终返回错误(结束宿主进程会连带丢失用户会话), 因此界面上的「立即重启」会收到明确错误提示,需要手动退出并重新打开 DSH。
  • 手工编写的条目只读。 不在标记区块内的 MCP 条目会在界面上列出,但无法通过本插件修改或删除, 以免覆盖用户自己的内容。
  • serverName 有格式限制。 只允许 [A-Za-z0-9_-]{1,32},与官方 dsh-mcp-client 的校验一致。 从其它客户端导入时会按该规则做字符替换与截断。
  • 「测试连接」依赖运行时中的 MCP SDK。 需要运行时 node_modules 下存在 @modelcontextprotocol/sdk/dist/esm/client;缺失时该功能返回明确错误,其余功能不受影响。
  • 内置目录需要联网。 服务器包由 npx 在首次使用时拉取,离线环境无法启动这些服务器。
  • 扫描只覆盖各客户端的默认配置路径。 Claude Desktop / Claude Code / Cursor / VS Code / Windsurf / Cline / Roo Code 以及 ~/.dsh 之外的配置文件不会被发现。
  • 写入需要 profile 目录可写。 目录只读或运行时目录缺失时,读写类接口会返回可读的错误信息。

许可

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit aa9301e67ebb

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout