dsh-cc-mcp
Verifieddsh-cc-mcp · v0.3.0 · MIT · Web UI
Load Claude Code MCP server configs (.mcp.json / plugin.json inline mcpServers) into DSH as runtime-registered tools: project-root .mcp.json → mcp__<server>__<tool>, plugin MCP → mcp__plugin_<name>_<server>__<tool> (official CC naming). Client bridge on t
Install
dsh plugin add dsh-cc-mcp Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Readme
dsh-cc-mcp
[!IMPORTANT] Only upgrade to this version when upgrading DSH to
0.1.5-rc.2or later. It binds to the 0.1.5 host contracts (^0.1.5-rc.2peer ranges fordsh-subprocess/schemastery) and does not work on older DSH. If your DSH is still0.1.0-rc.7–0.1.1-rc.2, do not upgrade — stay onv0.1.x. The two lines are mutually exclusive.
Load Claude Code MCP server configs into DeepSeek Harness as runtime-registered tools — no config-row writes, no restarts for config changes.
把 Claude Code 的 MCP 配置(.mcp.json / plugin.json 内联 mcpServers)以运行时注册工具的形式加载进 DSH。
What it does
| Source | Tool namespace | Notes |
|---|---|---|
Project root .mcp.json |
mcp__<server>__<tool> |
DSH-native name, same as dsh-mcp-client rows |
Plugin root .mcp.json / plugin.json inline |
mcp__plugin_<name>_<server>__<tool> |
Official CC plugin naming (e.g. mcp__plugin_asana_asana__asana_create_task) |
- Dual-form parsing (shared
dsh-cc-loader): accepts both the{"mcpServers": {...}}wrapper (project level / community plugins) and the bare server map (official plugin form). - Transports:
stdio(command) andhttp(url → streamable-http) register as tools.sse/wsare reported as unsupported (DSH has no such transport) and never crash anything. - Env secrets stay out of configs:
${NAME}placeholders are kept verbatim in the IR and expanded at runtime fromprocess.env;${CLAUDE_PLUGIN_ROOT}expands to the plugin directory. Nothing is written to disk. - Lazy connections: tool schemas register eagerly (the model must see the
list), the actual server process connects on first call, and disconnects
after
idleTimeoutMswithout calls. Dead connections reconnect on the next call. - Hot reload: editing the project
.mcp.jsonrebuilds running sessions' project MCP surface (~1 s). - Conflict semantics: a server already provided by a preset/host
dsh-mcp-clientrow is skipped by default;"override": truein the server entry forces the project/plugin connection (agent layer shadows upper layers). - Management panel (
/mcp): every server keeps a status row (connected / failed / disabled / provided-by-host) with its tool list. The Web GUI's/mcpcommand opens a panel over those rows: a failed server shows a Connect button, a connected one can be re-checked, each row opens a detail view with the server's tools, and Disable hides that server from the model until you enable it again. The session's start-up self-check reports failures as auto-dismissing toasts. - Host MCP rows are listed too (
manageHostRows, on by default): the profile's own@deepseek-ai/dsh-mcp-clientinstances (github, fetch, …) appear with the tools the host really exposes. Acting on them is workspace-scoped and never rewrites the profile config: Disable hides that row'smcp__<server>__*tools for this workspace only (via the platform'stools.restrict({ deny }), lifted again on Enable), and Connect adopts a row that exposes nothing by connecting with that row's own config and registering its tools inside the session scope.
Trust model ⚠️
.mcp.json is executable project content — the same trust as
package.json scripts. Installing this plugin enables that. Children run with a
scrubbed environment (credential-shaped and stale DSH_* variables dropped),
mirroring the official bridge.
Install (dev / local checkout)
# in packages/cc-mcp: install deps (official MCP SDK + shared loader)
npm install
# user patch layer (hot, no bundle reconcile):
# append to ~/.dsh/profiles/<profile>/cordis.patch.yml
- insert:
- id: cc-mcp
name: 'dsh-cc-mcp'
config:
enableProject: true
pluginRoots: [] # absolute paths to plugin dirs (future M4 feeds this)
idleTimeoutMs: 300000
toolCallTimeoutMs: 60000
watchProject: true
Windows absolute paths in pluginRoots need file:///? No — these are plain
directory paths inside the config, not module specifiers.
Config
| Field | Default | Meaning |
|---|---|---|
enableProject |
true |
read <projectRoot>/.mcp.json per session |
pluginRoots |
[] |
extra plugin directories to scan (.mcp.json + plugin.json) |
idleTimeoutMs |
300000 |
idle disconnect (0 = never) |
toolCallTimeoutMs |
60000 |
per-call timeout |
watchProject |
true |
hot-reload the project .mcp.json |
projectRootMarkers |
['.git', '.dsh', '.claude'] |
directory names that mark a project root when walking up from the session cwd; the first ancestor containing any marker wins. .dsh / .claude let projects without a .git repo still resolve their root |
enableManager |
true |
register the /mcp command and the panel's /cc-mcp route |
manageHostRows |
true |
list the profile's @deepseek-ai/dsh-mcp-client rows in the panel (disabling one only hides its tools in this workspace) |
statePath |
'' (→ <projectRoot>/.dsh/cc-mcp-state.json) |
explicit state-file override; empty keeps decisions per workspace (machine-wide file only when the session has no project root) |
Management panel
/mcp (bare) opens the panel in the Web GUI; /mcp <anything> prints the text
report instead, and the same report is what a headless/CLI session gets.
| Status | Meaning | Panel |
|---|---|---|
ready |
connected and its tools are visible | ✓ — click to re-check |
error |
the connection failed (host rows say whether Connect can adopt it) | Connect button, error text in the detail view |
disabled |
disabled in this workspace | Enable button |
skipped |
another layer already registers this tool prefix | shown as host-provided, with the visible tools |
checking |
a check/connect is in flight | spinner |
| Scope | Where it comes from | Disable does |
|---|---|---|
Project |
<projectRoot>/.mcp.json |
unregister this plugin's tools for that server |
Plugin |
pluginRoots (plugin .mcp.json / plugin.json) |
same, under mcp__plugin_<plugin>_<server>__ |
Host |
the profile's dsh-mcp-client rows |
hide that row's tools for this workspace only (tools.restrict({ deny }), lifted on Enable) — the profile config is never rewritten |
Connect on a host row that exposes no tools adopts it: this plugin connects
with that row's own config and registers the tools inside the session scope, so a
row whose own connection failed still gives this workspace working tools.
Decisions are remembered in <projectRoot>/.dsh/cc-mcp-state.json (per workspace;
$DSH_HOME/cc-mcp-state.json only for sessions without a project root), which is
the only file this plugin writes — your .mcp.json, the profile config and
Claude Code settings are never touched. Add .dsh/ to the project's .gitignore
if you do not want to share the choices.
Try the panel locally
A throwaway project config used to exercise the panel end to end (one server that
connects, one that fails so Connect has something to do):
{
"mcpServers": {
"cc-echo": { "command": "node", "args": ["<repo>/packages/cc-mcp/test/mcp-echo-server.mjs"] },
"cc-flaky": {
"command": "node",
"args": [
"<repo>/packages/cc-mcp/test/mcp-flaky-server.mjs",
"<repo>/.cc-mcp-marker"
]
}
}
}
cc-flaky refuses to start until <repo>/.cc-mcp-marker exists; create it and
press Connect to watch the row flip to connected.
Example
<project>/.mcp.json:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
}
}
}
Sessions in that project get mcp__github__create_issue etc. on first tool
list assembly.
License
MIT — runtime registration pattern ported from
dsh-project-mcp-bridge
(MIT, © KYinCode); parsing lives in dsh-cc-loader.