dsh-mcp-manage
by wuhobin
dsh plugin: Settings > MCP 服务 management page for DeepSeek Harness (DSH). List/add/edit/delete MCP servers registered in cordis.patch.yml and run a real MCP initialize connection handshake per server.
安装
dsh plugin --profile web add github:wuhobin/dsh-mcp-manageGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗
安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。
README
目录
- Install — one command, restart-persistent
- ✅ Recommended (use the DSH wrapper, not bare pnpm add)
- If dsh is not on your PATH
- Upgrading a later version
- Uninstalling
- What happens under the hood
- TL;DR (what you get)
- Architecture — this is a real static plugin
- Host routes
- Auto-detection (no hardcoded paths)
- Package manifest (what makes it a static, installable plugin)
- Layout
- Standalone probe (no DSH needed)
- Acknowledgements
Label:
dsh plugin· A DeepSeek Harness (DSH) static plugin that adds an MCP 服务 management page in Settings.
Manage the MCP servers DSH registers through cordis.patch.yml: list / add / edit / delete each MCP service, and — most importantly — run a real MCP initialize connection handshake against every server so you can see at a glance whether each MCP service connects normally.
Install — one command, restart-persistent
This is a static DSH plugin (the same shape as a plugin-market package): once installed it is a dependency of the
profile and is loaded by the bundle layer on every boot — it survives restarts, no pasting code, no cordis_define.
✅ Recommended (use the DSH wrapper, not bare pnpm add)
dsh plugin --profile web add dsh-mcp-manage
- This runs
pnpm add, then auto-reconcilesdsh.profile.bundlesin<profile>/package.json: because the package declaresdsh.bundle, it joins the profile layer stack automatically. No manualinsert:editing — DSH reads the package'sdsh.bundle.patch(static/cordis.patch.yml) at boot and turns it into an active loader entry. - The plugin's host and client load on the next DSH start, so restart DSH (e.g. stop and relaunch
dsh web), then open Settings → MCP 服务. If the page doesn't appear, hard-refresh the browser (Ctrl/Cmd+Shift+R).
⚠️ Gotcha: a bare
pnpm add dsh-mcp-manageinstalls the package intonode_modulesanddependenciesbut does not add it todsh.profile.bundles— so it never becomes a loaded layer and the page won't appear after restart. Always install throughdsh plugin ... add, which does the reconcile step for you.
If dsh is not on your PATH
dsh is shipped as a npx/npm-cache binary, so a terminal that lacks the right PATH may report dsh: not recognized.
Any of these works:
# 1) new terminal (often fixes PATH) then the normal form:
dsh plugin --profile web add dsh-mcp-manage
# 2) wrap in npx — independent of PATH:
npx --yes @deepseek-ai/dsh plugin --profile web add dsh-mcp-manage
# 3) invoke the packed bin directly with node (never depends on PATH):
node "<npm-cache>\_npx\<hash>\node_modules\@deepseek-ai\dsh\lib\bin.js" plugin --profile web add dsh-mcp-manage
Upgrading a later version
After you bump the version and publish a new release, update the installed copy, then restart DSH:
dsh plugin --profile web update dsh-mcp-manage
Uninstalling
dsh plugin --profile web remove dsh-mcp-manage
This runs pnpm remove and reconciles dsh.profile.bundles, so the package is removed from node_modules, from
dependencies, and from the profile layer stack in one command — no manual cordis.patch.yml edits needed. The change
takes effect on the next DSH restart (the already-running process keeps the old layer until then).
As with install, use the
dsh plugin ...wrapper rather than a barepnpm remove— the wrapper is what also drops the entry fromdsh.profile.bundles; a barepnpm removewould leave a stale bundle-layer reference.
What happens under the hood
The package carries a dsh.bundle.patch (static/cordis.patch.yml):
- insert:
- id: dsh-mcp-manage
name: 'dsh-mcp-manage'
so DSH's bundle layer turns it into an active loader entry automatically. You only need to add the dependency
once (through dsh plugin ... add); the UI page and routes appear after a restart.
Its manifest is also compatible with the built-in plugin market (
dshmarket), so it could be listed there too — but this package is primarily distributed as an npm package installed viadsh plugin ... add dsh-mcp-manage.
TL;DR (what you get)
- A Settings → MCP 服务 section (
settings.section→ idmcp-manage, order 30). - One card per configured MCP server: id / serverName / transport / command-or-url / headers-or-env plus a status badge (已连接 / 可达 / 异常 / 未知).
- 检测 (probe one) / 重新检测全部 run a real MCP
initializehandshake, not a ping:streamable-http→ a real authenticatedPOST initializesession via the official MCP SDK.stdio→ actually spawns the server command and completes an MCPinitializeover stdio.
- 添加服务 / 编辑 / 删除 persist changes straight back to
cordis.patch.yml(insert:-blocks for@deepseek-ai/dsh-mcp-client).
Architecture — this is a real static plugin
The dynamic plugin the author originally shipped used the dynamic-runner sandbox APIs (harness.handle / host.call),
which only exist inside dsh-cordis-*-runner. A static plugin runs in the normal (non-sandbox) plane and gets no
harness/host.call; it uses the real services instead. This package is ported to that model:
| layer | file | does what |
|---|---|---|
| Host (Node) | static/index.js |
ESM Cordis plugin exporting name + apply(ctx, config). ctx.inject(['webServer'], …) mounts HTTP routes /dsh-mcp/list, /dsh-mcp/check, /dsh-mcp/save. Uses real node:fs / node:os / node:child_process. |
| Client (browser) | static/client.js |
A window.__ModuleLoader__.load({ id, factory }) bundle (only external is react). Registers settings.section via ctx.slots.inject(...) and fetch()es the host routes. |
| Bundle patch | static/cordis.patch.yml |
dsh.bundle.patch → inserts { id: dsh-mcp-manage, name: 'dsh-mcp-manage' } so the loader activates it. |
| Probe | probe/dsh-mcp-probe.cjs |
Standalone real-MCP initialize handshake (official @modelcontextprotocol/sdk), self-terminating. |
Host routes
| route | method | purpose |
|---|---|---|
/dsh-mcp/list |
GET | list servers + the auto-detected profile patch path |
/dsh-mcp/check |
GET | run a real handshake per server → {id, status, message} each |
/dsh-mcp/save |
POST | persist the edited server list back to cordis.patch.yml (same-origin only) |
Auto-detection (no hardcoded paths)
The host derives the runtime layout the same way the dynamic host did, but with real Node:
DSH_HOME(an existing.dshdirectory) orHOME→<profilesRoot>.profilesRoot = <DSH_HOME>/profiles(or<HOME>/.dsh/profiles).SDK_ROOT = <profilesRoot>/node_modules.PATCH_PATH= first<profilesRoot>/<p>/cordis.patch.ymlwhose content references@deepseek-ai/dsh-mcp-client;PATCH_DIR= its directory, wheredsh-mcp-probe.cjsis written.
Package manifest (what makes it a static, installable plugin)
package.json satisfies the exact contract the DSH client loader validates, so the package loads as a real static
plugin once installed (and would also be eligible for a plugin-market listing):
main→./static/index.js(host entry artifact).exports["./client"]→./static/client.js(browser bundle).dsh.client.platform: "web"(+ optionalinject).dsh.bundle.patch→static/cordis.patch.yml.peerDependencies["@deepseek-ai/cordis"]≥^4.0.1.
These match what dshmarket itself ships and what dsh-client-modules requires
(parseDshClient needs platform:"web", clientExportOf needs exports["./client"]).
Layout
dsh-mcp-manage/
├── package.json # static-plugin manifest (dsh.bundle.patch + dsh.client.platform + main/exports)
├── README.md
├── LICENSE # MIT
├── static/
│ ├── index.js # Host: ESM Cordis plugin → webServer routes list/check/save
│ ├── client.js # Client: __ModuleLoader__.load bundle → Settings → MCP 服务 UI
│ └── cordis.patch.yml # dsh.bundle.patch → inserts { id, name } into the composed entry list
├── probe/
│ └── dsh-mcp-probe.cjs # Standalone real-MCP-initialize handshake
└── test-parse.js # YAML-subset parse test used during development
plugin/(the original dynamicharness.handle/host.callversion) is kept in the git history for reference; the installable package usesstatic/. If you want the dynamic, session-only variant instead, see theplugin/*.jssource in an earlier commit.
Standalone probe (no DSH needed)
# stdio server
node probe/dsh-mcp-probe.cjs "{\"sdkRoot\":\"/abs/path/node_modules\",\"transport\":\"stdio\",\"command\":\"/abs/path/server\",\"args\":[\"stdio\"],\"env\":{\"TOKEN\":\"...\"},\"timeoutMs\":15000}"
# streamable-http server
node probe/dsh-mcp-probe.cjs "{\"sdkRoot\":\"/abs/path/node_modules\",\"transport\":\"streamable-http\",\"url\":\"https://host/mcp\",\"headers\":{\"Authorization\":\"Bearer ...\"},\"timeoutMs\":15000}"
probe is also wired as an npm script: npm run probe -- "<spec-json>".
Credentials (e.g. Authorization: Bearer …, GITHUB_PERSONAL_ACCESS_TOKEN) go only into the probe process; the
result reports only ok / name / ver / error, never the headers.
Acknowledgements
- DeepSeek Harness for the static-plugin load path (
dsh.bundle.patch/dsh.client/webServer/ client-modules). - Model Context Protocol SDK (
@modelcontextprotocol/sdk) for the realinitializehandshake. - Cordis for the plugin/event/service framework.
原始 README: https://github.com/wuhobin/dsh-mcp-manage/blob/master/README.md ↗
同类插件
查看全部 →
k8e
k8e.sh — 开源 Agentic AI 沙箱矩阵

hol-guard
开源AI代理防病毒:运行时拦截风险工具、秘密访问、提示注入、恶意软件包、MCP服务器、插件和技能。

anolisa
ANOLISA(Agentic Nexus Operating Layer & Interface System Architecture):具备运行时、安全性、可观测性和 Tokenless 响应压缩能力的 Agentic OS,可降低 Token 使用量与成本。

mobius
首个自我演进的开源 Agent OS:连接你的团队、AI agent、设备与算力

deepseek-harness-desktop
DeepSeek Harness Tauri 桌面版 | Only 5mb installer, zero environment setup. Windows / macOS / Linux.

open-managed-agents
开源Claude管理代理API实现和自托管Claude标签式代理运行时。即插即用;在Cloudflare Workers/Durable Objects或Node.js上运行。Apache 2.0。