Read-only runtime management panel for the official DSH MCP client: connection status, registered tools, errors, and reconnect counts through the /mcp command and a Settings tab, with sanitized display and enable/disable patch suggestions.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-mcp-panel
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:PerryLink/dsh-mcp-panel
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
dsh-mcp-panel
Add, edit, remove, and trial-call MCP servers from one settings page — honest status, reversible writes.
The management console for the official DeepSeek Harness MCP client: manage servers in Settings → Plugins → MCP instead of hand-writing YAML.
Install · Configuration · FAQ · 简体中文 · English · Español · Português · हिन्दी
dsh plugin --profile <name> add dsh-mcp-panel
Official repository maintained by PerryLink: https://github.com/PerryLink/dsh-mcp-panel (Gitee is a mirror). Community plugin, not affiliated with DeepSeek.
What it is
The official MCP client is the bridge: one @deepseek-ai/dsh-mcp-client row per MCP server, connecting the transport, syncing tools, and registering mcp__<server>__<tool> names. dsh-mcp-panel is the console on top — it reads facts through the mcp/status seam, the tool registry, and the loader, renders add/edit/remove operations as cordis.patch.yml fragments, and writes only append-only, approval-gated, backup-first patches verified against the loader's re-applied state. Transport, OAuth, and protocol stay untouched.
The panel is a read-only runtime view: per-server transport, target, tool count, connection status, last error, and reconnect count, plus health diagnostics, a Resources browser, and a tool trial console. The only difference from a hand-written cordis.yml is that error-prone YAML editing becomes forms, previews, and safe application.
Three-step setup
Install (pick one channel):
# git channel (latest main; equivalent to git+https://github.com/PerryLink/dsh-mcp-panel.git) dsh plugin --profile web add github:PerryLink/dsh-mcp-panel # npm channel (published releases) dsh plugin --profile web add dsh-mcp-panel # tarball channel: pnpm pack in this repo, then dsh plugin --profile web add ./dsh-mcp-panel-<version>.tgzOn the git channel the
preparescript builds with production dependencies only (typescriptandtsdownare regulardependencieson purpose).Restart and confirm the profile row is mounted:
dsh --profile web --dump-config | grep -A3 'id: mcp-panel'The defaults are usable as-is;
cordis.patch.ymldocuments each key inline, and the configuration table below lists every key.Open the panel or run a command:
Open Settings → Plugins → MCP, or run:
/mcp /mcp everything tools /mcp everything health /mcp everything call echo '{"message": "hi"}'
Uninstall: remove the mcp-panel row from cordis.patch.yml (the web surface hot-reloads it), delete the package from the profile's node_modules, and verify with dsh web --dump-config that no mcp-panel row remains.
Every PerryLink plugin is listed in the built-in DSH Desktop market: Market → Sources → Add source → paste https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json → select. Installation still requires the market's npm identity check and your confirmation.
Core capabilities
dsh-mcp-panel is the experience layer on top of the official MCP client: a read-only runtime view plus safe, reversible profile writes.
/mcpcommand — one row per server: transport, target, tool count, connection status (from the upstream seam;unknownwhen unobserved), last error, reconnect count — model-readable, session-log reconstructable, five output languages./mcp <server> tools— model-visiblemcp__*tool names and descriptions./mcp <server> health— derived self-heal suggestions (ENOENT → missing dependency, ECONNREFUSED, timeouts, 401/403/404, DNS, rate limit, reconnect exhaustion…); exit code / stderr tail honestly labeled pending upstream support until the client exposes them./mcp <server> disable/enable— turn one server row off or back on without editing the profile patch by hand./mcp <server> probe— one Streamable HTTP connectivity probe for that server (background job)./mcp <server> call <tool> [json]— trial-call through the official tool pipeline (ctx.tools.execute()); pre-execute permission policy, approval, guards, and post-execute all apply.- Settings → Plugins → MCP tab — status cards with badges, diagnostics, and probes, plus the server CRUD and the tool trial console.
- Server CRUD — add/edit/remove forms →
insertfor add and id-targeted overrides (- id:+name:+disabled:/config:) for edit/remove → clipboard copy or approval-gated write with automatic backups and loader re-verification. - Resources browse — read-only resource listing, template listing, and URI reads through the official
list_mcp_resources/list_mcp_resource_templates/read_mcp_resourcetools (bridged by the shipped@deepseek-ai/dsh-mcp-resourcesservice); results are shown in the tab only, never in model context. - Recommended directory — a built-in community MCP server catalog (filesystem, git, github, fetch, playwright…);
catalogEntriesappends/overrides entries, andcatalogToConfigInputturns one into a one-click add. - Config import/export —
exportConfigs()serializes the server rows to a versioned JSON document (a!!jsrow exports asnullwith a reason), andimportPreview()parses an export back into per-serveraddpatch fragments for review. - Tool trial console — server →
mcp__*tool → JSON args → canonical JSON result + rendered content; capped bytrialMaxResultChars; panel-only, never model context.
Commands & tools surface
| Surface | Kind | Notes |
|---|---|---|
/mcp |
command | Per-server status row; model-readable and log-reconstructable |
/mcp <server> tools |
command | Model-visible mcp__* tool names + descriptions |
/mcp <server> health |
command | Derived self-heal suggestions from sanitized error text |
/mcp <server> disable / enable |
command | Toggle one server row in the profile patch |
/mcp <server> probe |
command | One Streamable HTTP connectivity probe (background job) |
/mcp <server> call <tool> [json] |
command | Trial-call through the official tool pipeline |
mcp_probe |
tool | Optional Streamable HTTP connectivity probe (background job) |
| Settings → Plugins → MCP tab | UI slot | Status cards, server CRUD, and the tool trial console |
mcpPanel Typert Remote |
service | Read-only snapshot channel (host → client) |
Examples
These are the plugin's real entry points; install once, then call one.
Detailed example — command /mcp github tools, output:
Tools of "github" (1, model-visible public names):
- mcp__github__create_issue — Create a new issue in a GitHub repository
Observed from plugins/dsh-mcp-panel/tests/command.spec.ts:99-110; renderer at src/command.ts:352-360
Failure branch — input:
/mcp nope tools
Output:
Unknown MCP server "nope" (configured: github)
Observed from plugins/dsh-mcp-panel/src/command.ts:104-105; plugins/dsh-mcp-panel/tests/command.spec.ts:152-157
Brief examples: /mcp <server> tools · /mcp <server> health
Architecture: official client = bridge, this plugin = console
@deepseek-ai/dsh-mcp-client is the only bridge: one plugin instance per MCP server, configured as a hand-written cordis.yml row, connecting the transport, syncing tools, and registering mcp__<server>__<tool> names. This plugin never replaces it — it is the experience layer on top:
┌────────────────────────────────────────────┐
profile │ cordis.yml / cordis.patch.yml │
composition │ - id: mcp-github │
(one row per │ name: '@deepseek-ai/dsh-mcp-client' │
server, hand- │ config: { serverName, transport, … } │
written) │ - id: mcp-panel │
│ name: dsh-mcp-panel ◄── this plugin │
└───────────────┬────────────────────────────┘
│
┌───────────────────────────┴───────────────────────────┐
│ │
┌────▼──────────────┐ ┌───────────────────────────┐ │
│ @deepseek-ai/dsh- │ │ dsh-mcp-panel (console) │ │
│ mcp-client │ │ │ │
│ • transport │ │ • /mcp command │ │
│ • tool sync │ │ • Settings → Plugins → │ │
│ • mcp__* tools │◄──────►│ MCP tab: CRUD, trial │ │
│ • mcp/status seam │ status │ • health diagnostics │ │
└───────────────────┘ │ • probes, capabilities │ │
└───────────────────────────┘ │
The console reads the client through its mcp/status observability seam (event + mcpStatus query service; not yet shipped upstream, feature-detected), the tool registry, and the loader; it writes only the profile's patch layer — append-only, approval-gated, always backed up. Transport, OAuth, and protocol stay untouched.
Console vs. hand-written cordis.yml
| Hand-written cordis.yml | dsh-mcp-panel console | |
|---|---|---|
| Add a server | Edit YAML, mind indent/quoting | Form → patch fragment → copy or write (approval + auto backup) |
| Edit a server | Edit YAML, restart/hot-reload | Form pre-filled from the live row; unchanged secrets keep their raw values host-side |
| Remove a server | Delete the row | - id: + disabled: true override (the patch vocabulary has no remove) — re-enableable anytime |
| See status | Read logs | Badges + reconnects + last error, live from the mcp/status seam |
| Try a tool | Ask the model to call it | Trial console → official ctx.tools.execute() pipeline (permission & approval stay in force) |
| Diagnose failures | Grep logs | /mcp <server> health with derived self-heal suggestions |
| Mistakes | Manual revert | Every write is append-only and leaves a timestamped backup |
The console's output IS cordis.patch.yml vocabulary — the same lines you would write by hand, generated, previewed, and applied safely.
Configuration
All tunables are Schemastery Config fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. cordis.patch.yml documents each key inline.
Most-used keys:
| Key | Default | Meaning |
|---|---|---|
probeEnabled |
true |
Register the mcp_probe background-job tool (panel-only results) |
probeTimeoutMs |
10000 |
Per-probe timeout in ms |
outputLanguage |
en |
/mcp output language: en | zh | es | pt | hi |
writeEnabled |
true |
Kill switch: false rejects every profile write (copy still works) |
writeVerifyEnabled |
true |
Re-verify each write against the loader's re-applied state before reporting success |
backupCount |
5 |
cordis.patch.yml backups retained per write |
| Key | Default | Meaning |
|---|---|---|
probeEnabled |
true |
Register the mcp_probe background-job tool (panel-only results) |
probeTimeoutMs |
10000 |
Per-probe timeout in ms |
maxProbes |
10 |
Probe records shown in the panel |
refreshIntervalMs |
0 |
Suggested panel refresh in ms; 0 = on demand |
outputLanguage |
en |
/mcp output language: en | zh | es | pt | hi |
passiveProbeEnabled |
false |
Periodically probe streamable-http servers |
passiveProbeIntervalMs |
60000 |
Passive probe interval in ms |
trialEnabled |
true |
Tool trial console (settings tab + /mcp call) |
trialTimeoutMs |
120000 |
Panel-side deadline per trial call in ms |
trialMaxResultChars |
60000 |
Cap on the trial result payload in chars |
writeEnabled |
true |
Kill switch: false rejects every profile write (copy still works) |
writeVerifyEnabled |
true |
Re-verify each write against the loader's re-applied state before reporting success |
writeVerifyTimeoutMs |
3000 |
Polling budget for write verification in ms |
backupCount |
5 |
cordis.patch.yml backups retained per write |
catalogEntries |
[] |
User overlay for the recommended server directory: entries append, an entry with the same id replaces the built-in one |
Example override in your profile patch:
- insert:
- id: mcp-panel
name: dsh-mcp-panel
config:
probeEnabled: false
outputLanguage: zh
writeVerifyTimeoutMs: 5000
backupCount: 10
FAQ
Status comes from the official client's mcp/status seam (not yet shipped upstream; feature-detected). Connection fields without upstream observations read unknown / — with statusSource: 'derived'; exit codes and stderr tails are labeled pending upstream support until the client exposes them. The console never fakes a connection state: unobservable fields read unknown / -1 / —.
It never rewrites the file. Writes are generated append-only fragments behind approval, keeping the newest backupCount backups, and each write is re-verified against the loader's re-applied state before success is reported. If the loader did not apply it (for example a row inserted by $DSH_HOME/cordis.patch.yml, which a profile-layer patch cannot reach), the console reports failure honestly. writeEnabled: false rejects every write while fragments stay copyable.
No. Panel content (status cards, CRUD, the trial console, the Resources browser) is shown in the settings page only and never enters model context; only /mcp output is model-readable and reconstructable from the session log. URL query credentials, userinfo passwords, header values, bearer tokens, and JWTs are redacted before rendering; configured headers never enter any snapshot, and env/header values never leave the host (the editor sees keys only).
It does not replace it. @deepseek-ai/dsh-mcp-client is the only bridge: one instance per MCP server, one cordis.yml / cordis.patch.yml row, owning transport, OAuth, and protocol. This plugin only reads the status seam, the tool registry, and the loader; its writes land only in the profile's patch layer, it registers no prompt sections, and transport, OAuth, and protocol stay untouched.
Security boundaries
- The bridge stays the bridge. No transport, OAuth, or protocol changes; one mcp-client row per server, exactly as hand-written.
- No fake status. Connection fields without upstream observations read
unknown/—withstatusSource: 'derived'; exit codes and stderr tails are never invented. - Writes are append-only, approval-gated, and backed up. The console never rewrites
cordis.patch.yml; it appends generated operations, keeps the newestbackupCountbackups, and re-verifies every write against the loader's re-applied state before reporting success (a skipped patch never reads as success). - No prompt injection. The panel registers no prompt sections; its only model-facing text is the two tool/command descriptions.
Permissions & data
- Permissions: the
dshWorkshopmanifest declaresnetwork:outboundandnative-code:none. - Data: the panel is read-only; it writes only append-only
cordis.patch.ymlfragments (approval-gated, backup-first). URL query credentials, userinfo passwords, header values, bearer tokens, and JWTs are redacted before rendering; configuredheadersnever enter any snapshot, and env/header values never leave the host (the editor sees keys only).
Known limitations
- Prompt templates & resource subscriptions are pending upstream support — the official client bridges tools and resources, but not prompts or subscriptions.
- Exit codes / stderr tails are labeled pending upstream support until the client exposes them.
- Read-only panel — the console never fakes a connection state; unobservable fields read
unknown/-1/—. - Writes are verified, not guaranteed — the console re-verifies each write against the loader's re-applied state and fails honestly when the loader did not apply it (e.g. a row inserted by
$DSH_HOME/cordis.patch.yml, which a profile-layer patch cannot reach).
Compatibility
| Surface | Status |
|---|---|
| Harness | DeepSeek Harness dsh-v0.2.1-rc.2 (verified 2026-10-18): engines.dsh >=0.2.1-0 <0.3.0; the P0 compatibility paths have regression tests. |
| Node | ^22.19.0 || >=24.9.0 |
| Platforms | Web GUI (dual-face: host + browser) |
| Model | Any (the panel is read-only; only /mcp output is model-readable) |
Resources & Prompts
Resources ARE bridged upstream: the base bundle mounts @deepseek-ai/dsh-mcp-resources, the official client registers each connection's resource provider into ctx.mcpResources, and that package owns the three shared tools (list_mcp_resources, list_mcp_resource_templates, read_mcp_resource). The console feature-detects the service and the registered tools, and offers a read-only Resources browser (list / templates / URI read) on every server card — each call runs through the OFFICIAL tool pipeline, and results never enter model context.
MCP prompt templates and resource subscriptions remain deferred upstream; the capabilities board marks Prompts pending upstream support.
Ecosystem & quality
- Gitee mirror (sync mirror; GitHub is canonical)
- dshfind plugin page (installs and ranking)
- OpenSSF Scorecard report (driven by .github/workflows/scorecard.yml)
- dsh-plugin-doctor verification report (driven by .github/workflows/plugin-doctor.yml)
- DSH Market (listed)
- 1024 store channel:
npm i -g dsh1024once, thendsh1024 plugin --profile web add dsh-mcp-panel(counts toward the deepseek1024.com install ranking) - Ecosystem knowledge base — measured data, not marketing: plugin development guide · plugin-selection data · maintenance criteria
Development
pnpm run typecheck && pnpm run typecheck:ci && pnpm test && pnpm run build && pnpm run verify:self-contained && pnpm run verify:artifacts && pnpm pack
pnpm run check:readmes
node scripts/verify-headless.mjs
pnpm run typecheck resolves the local harness checkout's fresh type faces through tsconfig paths, while typecheck:ci resolves the npm-published 0.1.7-rc.2 faces; both must stay green. scripts/verify-headless.mjs boots the real web profile and prints the exact /mcp output. Releases: node scripts/release.mjs <x.y.z> runs the full gate, commits, and tags v<x.y.z> locally (never pushes).
The README images are generated programmatically by scripts/gen-readme-assets.py (Pillow draws the hero, the SVG flow is hand-written): the hero writes docs/assets/dsh-mcp-panel-hero-{zh,en}-{light,dark}.webp, the structure figure writes docs/assets/dsh-mcp-panel-flow-v5-{light,dark}.svg, and it is safe to re-run.
Topics: dsh, dsh-plugin, deepseek-harness, deepseek, cordis, mcp, mcp-client, observability, panel
Family & thanks
This project is part of the DeepSeek Harness plugin family from PerryLink (all Apache-2.0). If it is useful, a star helps the next person find it — nothing is gated behind it.
- @PerryLink — creator and maintainer.
- @xiaoyuyu6420 — diagnosed the missing client devDependencies behind clean-checkout build failures (PR #5).
- @feiler0 — contributed the stdio MCP server probe (one MCP initialize handshake over stdin/stdout) (PR #7, merged as PR #15).
License
LICENSE (Apache License 2.0) © 2026 dsh-mcp-panel contributors
Links
More in this category
yjh051108/dsh-routing-suite★ 6994
One repository, three parts: a runtime injector for DSH plugin packages (inject, hot-reload, unload, promote a dev staging tool to the front, route self-heal, plus a settings-page plugin manager that lists, unloads and drags folders in to internalize), a task-aware reasoning-mode router agent preset (router-standard / router-spec / router-react), and a graded two-level task protocol whose six tools (commit_star, lock_stage, revise_do, edit_plan, mark_task, redteam_verdict) pin task state to disk. The injector implementation ships in-tree, so the install carries its own behaviour rather than a dependency list.
strukto-ai/mirage#dsh★ 3762
Swaps the filesystem and bash providers for a mirage virtual workspace: file tools and shell commands run over mounted resources (RAM, S3, Redis, Slack, Gmail, Notion, Postgres) instead of the host disk, with per-mount read/write/exec modes, per-command sandbox routing (monty, pyodide, quickjs in process; docker, e2b, daytona remote), and installed CLIs (git, gh, slack, linear, ntn, gws, or one you register) as head words in the virtual terminal.
first-fluke/oh-my-agent#dsh★ 1357
Runs project OMA checks before and after tool execution and when a turn tries to finish. Installs its OMA CLI dependency and initializes unconfigured projects on first use. Requires Node.js 22+; initial setup needs network access and project write access.
MichengAI/dsh-skills-manager★ 444
Manages local DeepSeek Harness skills in Settings and shows shared Agent skills as read-only.
hust-open-atom-club/oh-dsh★ 324
Community distribution: TUI, desktop, and Web UI as one bundle with layered installation.
Fishquito7/dsh-skill-mcp-panel★ 248
Manages DSH skills and MCP servers from the web settings: skill cards with hot enable/disable, workspace scopes, groups, batch migration and drag-and-drop import, plus stdio/HTTP MCP CRUD with connection tests, secret redaction and the unified dsh-panel CLI.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.