dsh-mcp-panel 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.es.md +48 -109
  3. package/README.hi.md +48 -109
  4. package/README.md +90 -79
  5. package/README.pt.md +48 -109
  6. package/README.zh.md +96 -86
  7. package/cordis.patch.yml +17 -4
  8. package/lib/client.js +1350 -48
  9. package/lib/client.js.map +1 -1
  10. package/lib/index.js +1191 -46
  11. package/lib/schemas-BhI7GrM5.js +4091 -0
  12. package/lib/typert.host.js +193 -4099
  13. package/lib/types/aggregate.d.ts +18 -1
  14. package/lib/types/aggregate.d.ts.map +1 -1
  15. package/lib/types/client/McpPanelTab.d.ts +12 -6
  16. package/lib/types/client/McpPanelTab.d.ts.map +1 -1
  17. package/lib/types/client/ServerEditor.d.ts +25 -0
  18. package/lib/types/client/ServerEditor.d.ts.map +1 -0
  19. package/lib/types/client/TrialConsole.d.ts +20 -0
  20. package/lib/types/client/TrialConsole.d.ts.map +1 -0
  21. package/lib/types/client/index.d.ts +7 -5
  22. package/lib/types/client/index.d.ts.map +1 -1
  23. package/lib/types/client/locales.d.ts +157 -1
  24. package/lib/types/client/locales.d.ts.map +1 -1
  25. package/lib/types/client/present.d.ts +6 -0
  26. package/lib/types/client/present.d.ts.map +1 -1
  27. package/lib/types/client/remote.d.ts +175 -2
  28. package/lib/types/client/remote.d.ts.map +1 -1
  29. package/lib/types/command.d.ts +32 -3
  30. package/lib/types/command.d.ts.map +1 -1
  31. package/lib/types/config.d.ts +41 -1
  32. package/lib/types/config.d.ts.map +1 -1
  33. package/lib/types/diagnostics.d.ts +55 -0
  34. package/lib/types/diagnostics.d.ts.map +1 -0
  35. package/lib/types/index.d.ts +32 -15
  36. package/lib/types/index.d.ts.map +1 -1
  37. package/lib/types/patch.d.ts +176 -0
  38. package/lib/types/patch.d.ts.map +1 -0
  39. package/lib/types/service.d.ts +73 -8
  40. package/lib/types/service.d.ts.map +1 -1
  41. package/lib/types/trial.d.ts +72 -0
  42. package/lib/types/trial.d.ts.map +1 -0
  43. package/lib/types/typert.host.d.ts +164 -0
  44. package/lib/types/typert.host.d.ts.map +1 -1
  45. package/lib/types/upstream.d.ts +44 -15
  46. package/lib/types/upstream.d.ts.map +1 -1
  47. package/lib/types/wire.d.ts +507 -10
  48. package/lib/types/wire.d.ts.map +1 -1
  49. package/lib/types/write.d.ts +30 -0
  50. package/lib/types/write.d.ts.map +1 -0
  51. package/package.json +44 -2
  52. package/src/aggregate.ts +79 -2
  53. package/src/client/McpPanelTab.tsx +138 -17
  54. package/src/client/ServerEditor.tsx +290 -0
  55. package/src/client/TrialConsole.tsx +145 -0
  56. package/src/client/index.ts +45 -18
  57. package/src/client/locales.ts +169 -5
  58. package/src/client/present.ts +9 -0
  59. package/src/client/remote.ts +17 -2
  60. package/src/client/styles.ts +201 -0
  61. package/src/command.ts +139 -18
  62. package/src/config.ts +88 -2
  63. package/src/diagnostics.ts +126 -0
  64. package/src/index.ts +49 -16
  65. package/src/patch.ts +493 -0
  66. package/src/probe.ts +1 -1
  67. package/src/service.ts +254 -9
  68. package/src/trial.ts +192 -0
  69. package/src/upstream.ts +45 -15
  70. package/src/wire.ts +292 -10
  71. package/src/write.ts +97 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # dsh-mcp-panel
2
2
 
3
- **Read-only runtime management panel for the official DeepSeek Harness MCP client — see every MCP server's status, tools, errors, and reconnect counts, without touching your config.**
3
+ **The MCP management console for the official DeepSeek Harness MCP client — add, edit, remove, and trial-call MCP servers from a settings page, with honest status, health diagnostics, and safe, reversible profile writes.**
4
4
 
5
5
  [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
6
6
 
@@ -11,52 +11,83 @@
11
11
  [![dsh-plugin](https://img.shields.io/badge/ecosystem-dsh--plugin-8b5cf6)](https://github.com/topics/dsh-plugin)
12
12
  [![deepseek-harness](https://img.shields.io/badge/runtime-deepseek--harness-4f46e5)](https://github.com/deepseek-ai/deepseek-harness)
13
13
 
14
- > 🔭 **Observability-first.** [`@deepseek-ai/dsh-mcp-client`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/mcp/mcp-client) keeps its connection state private — logs only. This plugin shows everything it *can* observe (config, tool registry, loader state) and says **"unknown"** for what it cannot, instead of guessing. It also proposes the minimal upstream seam that would make status real: see the [upstream proposal](docs/upstream-proposal.md).
14
+ ## Architecture: official client = bridge, this plugin = console
15
15
 
16
- ## Compatibility
16
+ [`@deepseek-ai/dsh-mcp-client`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/mcp/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**:
17
17
 
18
- - **Runtime**: DeepSeek Harness ≥ `0.1.0-rc.5` (peer dependencies pin the `0.1.0-rc.6` package line).
19
- - **Latest release**: v0.3.0 (2026-08-15) — full gate green on the TypeScript 7 / Vitest 4 / jsdom 30 toolchain, 109 tests.
20
- - **Last verified**: 2026-08-14 against a source checkout of deepseek-harness (workspace packages at `0.1.0-rc.5`, mainline `7b9644f`) — headless `/mcp` end-to-end plus a live web profile; evidence in [docs/research-notes.zh.md](docs/research-notes.zh.md). Re-verified the same day against mainline `47f9438` with the `mcp/status` seam branch (`feat/mcp-client-status-observability-seam`): a real `server-everything` row renders `status: connected (source: upstream-event)` through the packed plugin, plus the launcher-faithful compat flow; record in [docs/optimization-plan-v2.zh.md](docs/optimization-plan-v2.zh.md).
18
+ ```
19
+ ┌────────────────────────────────────────────┐
20
+ profile │ cordis.yml / cordis.patch.yml │
21
+ composition │ - id: mcp-github │
22
+ (one row per │ name: '@deepseek-ai/dsh-mcp-client' │
23
+ server, hand- │ config: { serverName, transport, … } │
24
+ written) │ - id: mcp-panel │
25
+ │ name: dsh-mcp-panel ◄── this plugin │
26
+ └───────────────┬────────────────────────────┘
27
+ │
28
+ ┌───────────────────────────┴───────────────────────────┐
29
+ │ │
30
+ ┌────▼──────────────┐ ┌───────────────────────────┐ │
31
+ │ @deepseek-ai/dsh- │ │ dsh-mcp-panel (console) │ │
32
+ │ mcp-client │ │ │ │
33
+ │ • transport │ │ • /mcp command │ │
34
+ │ • tool sync │ │ • Settings → Plugins → │ │
35
+ │ • mcp__* tools │◄──────►│ MCP tab: CRUD, trial │ │
36
+ │ • mcp/status seam │ status │ • health diagnostics │ │
37
+ └───────────────────┘ │ • probes, capabilities │ │
38
+ └───────────────────────────┘ │
39
+ ```
40
+
41
+ The console **reads** the client through its shipped `mcp/status` observability seam (event + `mcpStatus` query service), 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.
42
+
43
+ ## Console vs. hand-written cordis.yml
44
+
45
+ | | Hand-written cordis.yml | dsh-mcp-panel console |
46
+ |---|---|---|
47
+ | Add a server | Edit YAML, mind indent/quoting | Form → patch fragment → **copy** or **write** (approval + auto backup) |
48
+ | Edit a server | Edit YAML, restart/hot-reload | Form pre-filled from the live row; unchanged secrets keep their raw values host-side |
49
+ | Remove a server | Delete the row | `set disabled: true` operation (the patch vocabulary has no remove) — re-enableable anytime |
50
+ | See status | Read logs | Badges + reconnects + last error, live from the `mcp/status` seam |
51
+ | Try a tool | Ask the model to call it | Trial console → official `ctx.tools.execute()` pipeline (permission & approval stay in force) |
52
+ | Diagnose failures | Grep logs | `/mcp <server> health` with derived self-heal suggestions |
53
+ | Mistakes | Manual revert | Every write is append-only and leaves a timestamped backup |
54
+
55
+ The console's output IS `cordis.patch.yml` vocabulary — the same lines you would write by hand, generated, previewed, and applied safely.
21
56
 
22
57
  ## What you get
23
58
 
24
- | Surface | What it shows |
59
+ | Surface | What it does |
25
60
  |---|---|
26
- | **`/mcp` command** | transport, target, tool count, connection status, last error, reconnect count — model-readable, session-log reconstructable, five output languages (`outputLanguage: en\|zh\|es\|pt\|hi`) |
27
- | **Settings → Plugins → MCP tab** | the same snapshot read-only, with status badges, expandable tool lists, sanitized errors, probe results |
28
- | **At a glance** | summary counts above the cards, a server search box, and expand-all / collapse-all buttons |
29
- | **Panel probe button** | one-click connectivity probe of one streamable-http server from the tab; results stay panel-only |
30
- | **Passive probes** | optional background reachability badges per server, kept separate from connection status |
31
- | **Auto refresh** | the host suggests a refresh interval (`refreshIntervalMs`); the tab polls and pauses while hidden |
32
- | **`/mcp <server> disable\|enable`** | the exact `cordis.patch.yml` line to apply — a *suggestion*, never a write |
33
- | **`mcp_probe` tool** | one-shot Streamable HTTP connectivity probe as a background job; results are **panel-only** |
61
+ | **`/mcp` command** | one row per server: transport, target, tool count, connection status (from the upstream seam; `unknown` when unobserved), last error, reconnect count — model-readable, session-log reconstructable, five output languages |
62
+ | **`/mcp <server> tools`** | model-visible `mcp__*` tool names + descriptions |
63
+ | **`/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 |
64
+ | **`/mcp <server> call <tool> [json]`** | trial-call through the **official tool pipeline** — pre-execute permission policy, approval (routed through the command's agent), guards, post-execute all apply |
65
+ | **`/mcp <server> disable\|enable`** | the exact `set` patch line, as before |
66
+ | **Settings → Plugins → MCP tab** | status cards with badges, diagnostics, probes, plus the three consoles below |
67
+ | **Server CRUD** | add/edit/remove forms → `insert`/`set`/`set disabled` fragments → clipboard copy or approval-gated write with automatic backups (`cordis.patch.yml.bak-<ts>`, newest `backupCount` kept) |
68
+ | **Tool trial console** | server → `mcp__*` tool → JSON args → canonical JSON result + rendered content; capped by `trialMaxResultChars`; panel-only, never model context |
69
+ | **Capabilities board** | Resources / Prompts availability, feature-detected; both read *pending upstream support* today (the official client bridges tools only) |
70
+ | **Probes** | one-click / passive Streamable HTTP connectivity probes (panel-only results) |
34
71
 
35
72
  ## Quick start
36
73
 
37
74
  ```sh
38
75
  # git channel (builds via the package's prepare script)
39
- dsh plugin --profile web add github:PerryLink/dsh-mcp-panel#v0.3.0
76
+ dsh plugin --profile web add github:PerryLink/dsh-mcp-panel#v0.4.0
40
77
  # npm channel (published tarball, no build approval needed)
41
- dsh plugin --profile web add dsh-mcp-panel@0.3.0
78
+ dsh plugin --profile web add dsh-mcp-panel@0.4.0
42
79
  ```
43
80
 
44
- Then restart (or let the web surface hot-reload its `cordis.patch.yml`) and:
81
+ Then restart (or let the web surface hot-reload `cordis.patch.yml`) and open **Settings → Plugins → MCP**, or run:
45
82
 
46
83
  ```text
47
84
  /mcp
48
85
  /mcp everything tools
49
- /mcp everything disable
50
- ```
51
-
52
- ```text
53
- MCP servers (1):
54
- - everything [mcp-everything] stdio node …/server-everything/dist/index.js
55
- | 13 tools | enabled | status: unknown (source: derived) | reconnects: — | last error: —
86
+ /mcp everything health
87
+ /mcp everything call echo '{"message": "hi"}'
56
88
  ```
57
89
 
58
- Manual install: put `dsh-mcp-panel` into the profile's `node_modules` (or the shared
59
- `$DSH_HOME/profiles/node_modules` fallback) and add the row to `cordis.patch.yml`:
90
+ Manual install: put `dsh-mcp-panel` into the profile's `node_modules` (or the shared `$DSH_HOME/profiles/node_modules` fallback) and add the row to `cordis.patch.yml`:
60
91
 
61
92
  ```yaml
62
93
  - insert:
@@ -64,7 +95,6 @@ Manual install: put `dsh-mcp-panel` into the profile's `node_modules` (or the sh
64
95
  name: dsh-mcp-panel
65
96
  config:
66
97
  probeEnabled: true
67
- probeTimeoutMs: 10000
68
98
  ```
69
99
 
70
100
  ### Uninstall
@@ -75,67 +105,48 @@ Manual install: put `dsh-mcp-panel` into the profile's `node_modules` (or the sh
75
105
 
76
106
  ## Honest by contract
77
107
 
78
- - **Read-only.** No configuration file is ever written. `disable`/`enable` prints a suggestion you apply yourself.
79
- - **No fake status.** Connection fields without upstream data read `unknown` / `—`, with `statusSource: derived`.
80
- - **Sanitized display.** URL query credentials, userinfo passwords, header values, bearer tokens, and JWTs are redacted before rendering; configured `headers` never enter any snapshot.
81
- - **Panel-only results.** Probe details live in the settings tab, never in model context; `/mcp` output is the model-readable surface and is fully reconstructable from the session log.
82
- - **No mcp-client changes.** Transport, OAuth, and protocol stay untouched — the observability gap is covered by the [upstream proposal](docs/upstream-proposal.md), which this plugin already consumes (typed `mcp/status` event + `mcpStatus` query service, feature-detected at runtime).
108
+ - **The bridge stays the bridge.** No transport, OAuth, or protocol changes; one mcp-client row per server, exactly as hand-written.
109
+ - **No fake status.** Connection fields without upstream observations read `unknown` / `—` with `statusSource: 'derived'`; exit codes / stderr tails are never invented.
110
+ - **Sanitized display.** URL query credentials, userinfo passwords, header values, bearer tokens, and JWTs are redacted before rendering; configured `headers` never enter any snapshot; env/header **values** never leave the host (the editor sees keys only).
111
+ - **Writes are append-only, approval-gated, and backed up.** The console never rewrites `cordis.patch.yml`: it appends generated operations. When an approval service exists and the caller's session has a live agent inside an open turn, the write asks `ctx.approval` (only `allowed-once` proceeds); otherwise the explicit interactive confirmation is the approval channel. `writeEnabled: false` is a hard kill switch.
112
+ - **No prompt injection.** The panel registers **no prompt sections**; its only model-facing text is the two tool/command descriptions, in the official client's minimal style.
83
113
 
84
- ## Configuration
114
+ ## Config
85
115
 
86
- | Field | Default | Description |
116
+ | Key | Default | Description |
87
117
  |---|---|---|
88
- | `probeEnabled` | `true` | Register the `mcp_probe` tool (needs `ctx.jobs` in the composition) |
89
- | `probeTimeoutMs` | `10000` | Per-probe timeout |
90
- | `maxProbes` | `10` | Cap on probe records shown in the panel |
91
- | `refreshIntervalMs` | `0` | Suggested panel refresh interval in ms (`0` = on demand only) |
92
- | `outputLanguage` | `en` | Output language of the `/mcp` command (`en` \| `zh` \| `es` \| `pt` \| `hi`) |
93
- | `passiveProbeEnabled` | `false` | Periodically probe streamable-http servers in the background |
94
- | `passiveProbeIntervalMs` | `60000` | Passive probe interval in milliseconds |
95
-
96
- ## Permissions & data
97
-
98
- - **Reads**: loader entries, the tool registry (`mcp__<server>__` names), and — when upstream ships it — `mcp/status` events.
99
- - **Writes**: none. No configuration file is ever modified.
100
- - **Network**: only the one-shot `mcp_probe` (and the optional passive probe) POSTs one MCP `initialize` request to endpoints you configured; configured headers are used for the request and are never displayed or logged.
101
- - No telemetry, no external services, no background work beyond the optional probe timers.
102
-
103
- ## Troubleshooting
104
-
105
- - Row not visible? Run `dsh web --dump-config` and check that the `mcp-panel` insert landed with a unique id.
106
- - Panel shows `status: unknown (source: derived)` — expected until the upstream seam lands; see [docs/upstream-proposal.md](docs/upstream-proposal.md).
107
- - Panel looks stale? Set `refreshIntervalMs` to a positive value (e.g. `5000`) in the `mcp-panel` config row to poll automatically.
108
- - Boot log shows a FAILED `mcp-panel` fiber — the package must resolve from the profile (bare `name: dsh-mcp-panel` resolves via the profile's `node_modules` or the shared fallback).
109
- - Rollback: remove the row (see Uninstall).
110
-
111
- ## Security
112
-
113
- Found a security issue? Open a GitHub issue **without** pasting secrets, keys, or tokens — redact everything first. This plugin holds the credentials of your configured MCP servers only in memory for probe requests; they never reach logs or snapshots.
114
-
115
- ## How it works
116
-
117
- - **Host half** — a `mcpPanel` Typert Remote service assembles the snapshot from three read-only sources: loader rows (`@deepseek-ai/dsh-mcp-client` entries), `ctx.tools.schemas()` grouped by the `mcp__<server>__` namespace, and upstream `mcp/status` observations. The hand-written `./typert` manifest registers `mcpPanel/status` with the gateway; `zod` is bundled, so the host bundle is self-contained.
118
- - **Browser half** — a `dsh.client` bundle (served at `/plugins/dsh-mcp-panel/client.js`) mounts the same descriptor via `ctx.remote.$mount` and registers a read-only `settings.plugins.tab` entry (`id: mcp`). The presenter is a pure function; styles are scoped and token-driven.
119
- - **The `/mcp` command** goes through the standard command registry — every line lands in `command/run` + `command/done` session events.
118
+ | `probeEnabled` | `true` | register the `mcp_probe` background-job tool (panel-only results) |
119
+ | `probeTimeoutMs` | `10000` | per-probe timeout in ms |
120
+ | `maxProbes` | `10` | probe records shown in the panel |
121
+ | `refreshIntervalMs` | `0` | suggested panel refresh in ms; `0` = on demand |
122
+ | `outputLanguage` | `en` | `/mcp` output language: `en\|zh\|es\|pt\|hi` |
123
+ | `passiveProbeEnabled` | `false` | periodically probe streamable-http servers |
124
+ | `passiveProbeIntervalMs` | `60000` | passive probe interval in ms |
125
+ | `trialEnabled` | `true` | tool trial console (settings tab + `/mcp call`) |
126
+ | `trialTimeoutMs` | `120000` | panel-side deadline per trial call |
127
+ | `trialMaxResultChars` | `60000` | cap on the trial result payload |
128
+ | `writeEnabled` | `true` | kill switch: `false` rejects every profile write (copy still works) |
129
+ | `backupCount` | `5` | `cordis.patch.yml` backups retained per write |
130
+
131
+ ## Resources & Prompts
132
+
133
+ The official client documents *"Tools are the only bridged MCP capability"* — Resources and Prompts are deferred. The console feature-detects a proposed upstream catalog seam and will show read-only lists the day it ships; until then the capabilities board marks both **pending upstream support** (see the harness `docs/upstream-proposal.md` addendum for the follow-up proposals).
120
134
 
121
135
  ## Development
122
136
 
123
137
  ```sh
124
- pnpm install
125
- pnpm run typecheck # local gate: resolves the harness checkout's fresh type faces via tsconfig paths
126
- pnpm run typecheck:ci # npm gate: resolves the published 0.1.0-rc.6 type faces (what CI runs)
127
- pnpm test # 109 tests: sanitizer extremes, grouping, aggregation tolerance, command output (5 languages), probe gating, client wiring, presenter (badges, summary, filter)
128
- pnpm run build # tsc declarations → lib/types; tsdown → lib/index.js + lib/typert.host.js + lib/client.js
129
- pnpm run verify:self-contained
130
- pnpm run verify:artifacts
131
- pnpm pack
138
+ pnpm run typecheck && pnpm run typecheck:ci && pnpm test && pnpm run build && pnpm run verify:self-contained && pnpm run verify:artifacts && pnpm pack
132
139
  ```
133
140
 
134
- Release: `node scripts/release.mjs <x.y.z>` bumps the version, stamps the changelog, re-runs the gate, commits and tags; pushing the tag publishes npm + the GitHub Release automatically (see [CONTRIBUTING.md](CONTRIBUTING.md)).
141
+ - `src/patch.ts` — validation, keep-semantics merge, YAML fragment rendering (pure).
142
+ - `src/write.ts` — backup + append + retention (the only file-write module).
143
+ - `src/trial.ts` — official-pipeline trial calls via `ctx.tools.execute()`.
144
+ - `src/diagnostics.ts` — error-pattern → suggestion mapping (pure).
145
+ - `src/client/` — the settings console (server editor, trial console, diagnostics).
146
+ - `scripts/verify-headless.mjs` boots the real web profile and prints exact `/mcp` output.
135
147
 
136
- Verification against a real harness checkout:
137
- `node --import tsx/esm scripts/verify-headless.mjs` boots the full web profile in process (ephemeral port) and prints the exact `/mcp`, `/mcp <server> tools`, and `/mcp <server> disable` output.
148
+ Releases: `node scripts/release.mjs <x.y.z>` runs the full gate, commits, and tags `v<x.y.z>` locally (never pushes).
138
149
 
139
150
  ## License
140
151
 
141
- [Apache License 2.0](LICENSE) © 2026 dsh-mcp-panel contributors
152
+ Apache-2.0 — see [LICENSE](LICENSE).
package/README.pt.md CHANGED
@@ -1,141 +1,80 @@
1
1
  # dsh-mcp-panel
2
2
 
3
- **Painel de gerenciamento em tempo de execução, somente leitura, para o cliente MCP oficial do DeepSeek Harness: veja status, ferramentas, erros e contadores de reconexão de cada servidor MCP sem tocar na sua configuração.**
3
+ **Console de gerenciamento MCP para o cliente MCP oficial do DeepSeek Harness: adicione, edite, remova e teste servidores MCP numa página de configurações, com status honesto, diagnósticos de saúde e gravações de perfil seguras e reversíveis.**
4
4
 
5
5
  [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
6
6
 
7
7
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
8
8
  [![npm](https://img.shields.io/npm/v/dsh-mcp-panel)](https://www.npmjs.com/package/dsh-mcp-panel)
9
- [![downloads](https://img.shields.io/npm/dm/dsh-mcp-panel)](https://www.npmjs.com/package/dsh-mcp-panel)
10
9
  [![CI](https://github.com/PerryLink/dsh-mcp-panel/actions/workflows/ci.yml/badge.svg)](https://github.com/PerryLink/dsh-mcp-panel/actions/workflows/ci.yml)
11
10
  [![dsh-plugin](https://img.shields.io/badge/ecosystem-dsh--plugin-8b5cf6)](https://github.com/topics/dsh-plugin)
12
- [![deepseek-harness](https://img.shields.io/badge/runtime-deepseek--harness-4f46e5)](https://github.com/deepseek-ai/deepseek-harness)
13
11
 
14
- > 🔭 **Observabilidade em primeiro lugar.** [`@deepseek-ai/dsh-mcp-client`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/mcp/mcp-client) mantém seu estado de conexão privado — apenas logs. Este plugin mostra tudo o que *consegue* observar (configuração, registro de ferramentas, estado do Loader) e diz **"unknown"** para o que não consegue, em vez de adivinhar. Ele também propõe a costura mínima que tornaria o status real: veja a [proposta upstream](docs/upstream-proposal.md).
12
+ ## Arquitetura: o cliente oficial é a ponte; este plugin é o console
15
13
 
16
- ## Compatibilidade
14
+ [`@deepseek-ai/dsh-mcp-client`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/mcp/mcp-client) é a **única ponte**: uma instância por servidor MCP, configurada como linha escrita à mão no `cordis.yml`, que conecta o transporte, sincroniza ferramentas e registra os nomes `mcp__<servidor>__<ferramenta>`. Este plugin nunca a substitui: é a **camada de experiência** por cima:
17
15
 
18
- - **Runtime**: DeepSeek Harness ≥ `0.1.0-rc.5` (as peerDependencies fixam a linha `0.1.0-rc.6`).
19
- - **Última versão**: v0.3.0 (2026-08-15) — porta completa em verde com a cadeia TypeScript 7 / Vitest 4 / jsdom 30, 109 testes.
20
- - **Última verificação**: 2026-08-14 contra um checkout do código-fonte do deepseek-harness (pacotes do workspace em `0.1.0-rc.5`, mainline `7b9644f`) — `/mcp` headless de ponta a ponta mais um perfil web ao vivo; evidências em [docs/research-notes.zh.md](docs/research-notes.zh.md). Reverificado no mesmo dia contra mainline `47f9438` com o ramo da costura `mcp/status` (`feat/mcp-client-status-observability-seam`): uma linha real de `server-everything` mostra `status: connected (source: upstream-event)` através do plugin empacotado, além do fluxo de compatibilidade fiel ao lançador; registro em [docs/optimization-plan-v2.zh.md](docs/optimization-plan-v2.zh.md).
21
-
22
- ## O que você ganha
23
-
24
- | Superfície | O que mostra |
25
- |---|---|
26
- | **Comando `/mcp`** | transporte, alvo, contagem de ferramentas, status de conexão, último erro, contador de reconexões — legível pelo modelo e reconstruível pelo log, cinco idiomas de saída (`outputLanguage: en\|zh\|es\|pt\|hi`) |
27
- | **Configurações → Plugins → aba MCP** | o mesmo snapshot somente leitura, com selos de status, listas expansíveis de ferramentas, erros sanitizados e resultados de sondas |
28
- | **De relance** | contagens de resumo acima dos cartões, um campo de busca de servidores e botões de expandir/recolher tudo |
29
- | **Botão de sonda do painel** | sonda de conectividade em um clique para um servidor streamable-http a partir da aba; os resultados continuam somente do painel |
30
- | **Sondas passivas** | selos de alcançabilidade opcionais em segundo plano por servidor, separados do status de conexão |
31
- | **Atualização automática** | o host sugere um intervalo de atualização (`refreshIntervalMs`); a aba consulta e pausa enquanto oculta |
32
- | **`/mcp <server> disable\|enable`** | a linha exata de `cordis.patch.yml` a aplicar — uma *sugestão*, nunca uma escrita |
33
- | **Ferramenta `mcp_probe`** | sonda de conectividade de uso único para Streamable HTTP como tarefa em segundo plano; resultados são **somente do painel** |
34
-
35
- ## Início rápido
36
-
37
- ```sh
38
- # canal git (compila pelo script prepare do pacote)
39
- dsh plugin --profile web add github:PerryLink/dsh-mcp-panel#v0.3.0
40
- # canal npm (tarball publicado, sem aprovação de compilação)
41
- dsh plugin --profile web add dsh-mcp-panel@0.3.0
42
16
  ```
43
-
44
- Reinicie (ou deixe a superfície web recarregar seu `cordis.patch.yml`) e execute:
45
-
46
- ```text
47
- /mcp
48
- /mcp everything tools
49
- /mcp everything disable
50
- ```
51
-
52
- ```text
53
- MCP servers (1):
54
- - everything [mcp-everything] stdio node …/server-everything/dist/index.js
55
- | 13 tools | enabled | status: unknown (source: derived) | reconnects: — | last error: —
17
+ profile/composição dsh-mcp-client (ponte) dsh-mcp-panel (console)
18
+ - id: mcp-github • transporte • comando /mcp
19
+ name: '@deepseek-ai/…' • sincronização de tools • Configurações → Plugins →
20
+ config: { serverName, … } • ferramentas mcp__* MCP: CRUD, banco de testes,
21
+ - id: mcp-panel • seam mcp/status ◄─status─► diagnósticos, sondas
22
+ name: dsh-mcp-panel
56
23
  ```
57
24
 
58
- Instalação manual: coloque `dsh-mcp-panel` no `node_modules` do perfil (ou no
59
- respaldo compartilhado `$DSH_HOME/profiles/node_modules`) e adicione a linha a `cordis.patch.yml`:
60
-
61
- ```yaml
62
- - insert:
63
- - id: mcp-panel
64
- name: dsh-mcp-panel
65
- config:
66
- probeEnabled: true
67
- probeTimeoutMs: 10000
68
- ```
25
+ O console **lê** pelo seam `mcp/status` (evento + serviço `mcpStatus`), pelo registro de ferramentas e pelo loader; **escreve** apenas na camada de patches do perfil: somente anexa, com aprovação e backup automático. Transporte, OAuth e protocolo permanecem intocados.
69
26
 
70
- ### Desinstalação
27
+ ## Console vs. cordis.yml escrito à mão
71
28
 
72
- 1. Remova a linha `mcp-panel` de `cordis.patch.yml` (a superfície web a recarrega em quente; outras superfícies reiniciam).
73
- 2. Apague o pacote do `node_modules` do perfil (ou do respaldo compartilhado `profiles/node_modules`).
74
- 3. Confirme com `dsh web --dump-config` que nenhuma linha `mcp-panel` restou.
75
-
76
- ## Honestidade por contrato
77
-
78
- - **Somente leitura.** Nenhum arquivo de configuração é gravado. `disable`/`enable` imprime uma sugestão que você aplica.
79
- - **Sem status falso.** Campos de conexão sem dados upstream mostram `unknown` / `—`, com `statusSource: derived`.
80
- - **Exibição sanitizada.** Credenciais em query strings, senhas userinfo, valores de cabeçalhos, tokens bearer e JWTs são removidos antes da renderização; os `headers` configurados nunca entram em nenhum snapshot.
81
- - **Resultados somente do painel.** Os detalhes das sondas ficam na aba de configurações, nunca no contexto do modelo; `/mcp` é a superfície legível pelo modelo e é totalmente reconstruível a partir do log da sessão.
82
- - **Sem mudanças no mcp-client.** Transporte, OAuth e protocolo permanecem intactos — a lacuna de observabilidade é coberta pela [proposta upstream](docs/upstream-proposal.md), que este plugin já consome (evento tipado `mcp/status` + serviço de consulta `mcpStatus`, detectados em tempo de execução).
83
-
84
- ## Configuração
85
-
86
- | Campo | Padrão | Descrição |
29
+ | | cordis.yml à mão | Console dsh-mcp-panel |
87
30
  |---|---|---|
88
- | `probeEnabled` | `true` | Registra a ferramenta `mcp_probe` (requer `ctx.jobs` na composição) |
89
- | `probeTimeoutMs` | `10000` | Tempo limite por sonda |
90
- | `maxProbes` | `10` | Limite de registros de sonda exibidos no painel |
91
- | `refreshIntervalMs` | `0` | Intervalo de atualização sugerido para o painel em ms (`0` = somente sob demanda) |
92
- | `outputLanguage` | `en` | Idioma de saída do comando `/mcp` (`en` \| `zh` \| `es` \| `pt` \| `hi`) |
93
- | `passiveProbeEnabled` | `false` | Sondear periodicamente servidores streamable-http em segundo plano |
94
- | `passiveProbeIntervalMs` | `60000` | Intervalo da sonda passiva em milissegundos |
95
-
96
- ## Permissões e dados
31
+ | Adicionar servidor | Editar YAML | Formulário → fragmento de patch → **copiar** ou **gravar** (aprovação + backup) |
32
+ | Editar servidor | Editar YAML e reiniciar | Formulário pré-preenchido; segredos inalterados preservam o valor no host |
33
+ | Remover servidor | Apagar a linha | Operação `set disabled: true` (o vocabulário de patches não tem remove); re-habilitável |
34
+ | Ver status | Ler logs | Selos + reconexões + último erro, ao vivo do `mcp/status` |
35
+ | Testar uma ferramenta | Pedir ao modelo | Banco de testes → pipeline oficial `ctx.tools.execute()` (permissões e aprovação em vigor) |
36
+ | Diagnosticar | grep de logs | `/mcp <servidor> health` com sugestões derivadas |
97
37
 
98
- - **Lê**: linhas do Loader, o registro de ferramentas (nomes `mcp__<server>__`) e, quando o upstream implementar, eventos `mcp/status`.
99
- - **Escreve**: nada. Nenhum arquivo de configuração é modificado.
100
- - **Rede**: apenas a sonda de uso único `mcp_probe` (e a sonda passiva opcional) envia uma requisição MCP `initialize` para os endpoints que você configurou; os cabeçalhos configurados são usados na requisição e nunca são exibidos nem registrados.
101
- - Sem telemetria, sem serviços externos, sem trabalho em segundo plano além dos temporizadores de sonda opcionais.
38
+ ## O que você ganha
102
39
 
103
- ## Solução de problemas
40
+ - **`/mcp`**: uma linha por servidor — transporte, destino, contagem de ferramentas, status de conexão (honesto: `unknown` sem dados upstream), último erro, reconexões; legível pelo modelo, reconstruível do log da sessão, cinco idiomas de saída.
41
+ - **`/mcp <servidor> tools | health | call <tool> [json] | disable | enable`**: lista de ferramentas; diagnósticos derivados (ENOENT → dependência ausente, ECONNREFUSED, timeouts, 401/403/404, DNS, rate limit, reconexão esgotada); chamada de teste pelo **pipeline oficial** (permissões + aprovação em vigor); sugestões de patch exatas.
42
+ - **Configurações → Plugins → MCP**: cartões de status com selos e diagnósticos, **CRUD de servidores** (fragmentos `insert`/`set`/`set disabled`, cópia para a área de transferência ou gravação com aprovação e backup `cordis.patch.yml.bak-<ts>`), **banco de testes de ferramentas** (JSON canônico + conteúdo renderizado, limitado por `trialMaxResultChars`, somente painel) e o **painel de capacidades**: Resources e Prompts marcados como *aguardando suporte upstream* (hoje o cliente oficial só pontua ferramentas).
43
+ - **Sondas**: conectividade Streamable HTTP com um clique ou passiva (resultados somente do painel).
104
44
 
105
- - A linha não aparece? Rode `dsh web --dump-config` e confira se o insert `mcp-panel` foi aplicado com um id único.
106
- - O painel mostra `status: unknown (source: derived)` — esperado até a costura upstream aterrissar; veja [docs/upstream-proposal.md](docs/upstream-proposal.md).
107
- - O painel parece desatualizado? Defina `refreshIntervalMs` com um valor positivo (ex.: `5000`) na linha de configuração `mcp-panel` para consultar automaticamente.
108
- - O log de boot mostra um fiber `mcp-panel` FAILED — o pacote precisa resolver a partir do perfil (o `name: dsh-mcp-panel` simples resolve via o `node_modules` do perfil ou o respaldo compartilhado).
109
- - Rollback: remova a linha (ver Desinstalação).
45
+ ## Início rápido
110
46
 
111
- ## Segurança
47
+ ```sh
48
+ dsh plugin --profile web add github:PerryLink/dsh-mcp-panel#v0.4.0
49
+ # ou pelo canal npm:
50
+ dsh plugin --profile web add dsh-mcp-panel@0.4.0
51
+ ```
112
52
 
113
- Encontrou um problema de segurança? Abra uma issue no GitHub **sem** colar segredos, chaves ou tokens — redija tudo antes. Este plugin mantém as credenciais dos seus servidores MCP configurados apenas em memória para as requisições de sonda; elas nunca chegam a logs ou snapshots.
53
+ Reinicie (ou deixe a superfície web recarregar o `cordis.patch.yml`) e abra **Configurações → Plugins → MCP**, ou execute `/mcp`.
114
54
 
115
- ## Como funciona
55
+ ## Honesto por contrato
116
56
 
117
- - **Metade host** — um serviço Typert Remote `mcpPanel` monta o snapshot a partir de três fontes somente leitura: linhas do Loader (entradas `@deepseek-ai/dsh-mcp-client`), `ctx.tools.schemas()` agrupadas pelo namespace `mcp__<server>__`, e observações upstream `mcp/status`. O manifesto `./typert` escrito à mão registra `mcpPanel/status` no gateway; o `zod` é empacotado, então a metade host é autocontida.
118
- - **Metade navegador** — um bundle `dsh.client` (servido em `/plugins/dsh-mcp-panel/client.js`) monta o mesmo descritor via `ctx.remote.$mount` e registra uma entrada `settings.plugins.tab` somente leitura (`id: mcp`). O apresentador é uma função pura; os estilos têm escopo e usam tokens de tema.
119
- - **O comando `/mcp`** passa pelo registro de comandos padrão — cada linha cai nos eventos de sessão `command/run` + `command/done`.
57
+ - **A ponte continua sendo a ponte**: nenhuma mudança de transporte/OAuth/protocolo.
58
+ - **Sem status falso**: `unknown` / `—` com `statusSource: 'derived'` sem dados upstream; códigos de saída e stderr nunca inventados (marcados *aguardando suporte upstream*).
59
+ - **Exibição saneada**: credenciais em URLs, userinfo, valores de headers, tokens bearer e JWTs redigidos; os **valores** de env/headers nunca saem do host (o editor vê apenas chaves).
60
+ - **Gravações somente-anexar, com aprovação e backup**: o console nunca reescreve o `cordis.patch.yml`; havendo serviço de aprovação e um agente em turno aberto, pergunta ao `ctx.approval` (apenas `allowed-once` prossegue); caso contrário, a confirmação interativa é o canal de aprovação. `writeEnabled: false` é o interruptor de segurança.
61
+ - **Sem injeção de prompts**: o console não registra seções de prompt; apenas as descrições de suas duas ferramentas/comandos, no estilo minimalista do cliente oficial.
120
62
 
121
- ## Desenvolvimento
63
+ ## Config
122
64
 
123
- ```sh
124
- pnpm install
125
- pnpm run typecheck # porta local: resolve as faces de tipo frescas do checkout do harness via caminhos tsconfig
126
- pnpm run typecheck:ci # porta npm: resolve as faces de tipo publicadas 0.1.0-rc.6 (o que o CI executa)
127
- pnpm test # 109 testes: extremos do sanitizador, agrupamento, tolerância de agregação, saída do comando (5 idiomas), controle de sondas, fiação do cliente, apresentador (selos/resumo/filtro)
128
- pnpm run build # declarações tsc → lib/types; tsdown → lib/index.js + lib/typert.host.js + lib/client.js
129
- pnpm run verify:self-contained
130
- pnpm run verify:artifacts
131
- pnpm pack
132
- ```
65
+ | Chave | Valor | Descrição |
66
+ |---|---|---|
67
+ | `probeEnabled` / `probeTimeoutMs` / `maxProbes` | `true` / `10000` / `10` | ferramenta de sonda, prazo, registros exibidos |
68
+ | `refreshIntervalMs` | `0` | atualização sugerida do painel (`0` = sob demanda) |
69
+ | `outputLanguage` | `en` | idioma do `/mcp`: `en\|zh\|es\|pt\|hi` |
70
+ | `passiveProbeEnabled` / `passiveProbeIntervalMs` | `false` / `60000` | sondas passivas e seu intervalo |
71
+ | `trialEnabled` / `trialTimeoutMs` / `trialMaxResultChars` | `true` / `120000` / `60000` | banco de testes e seus limites |
72
+ | `writeEnabled` / `backupCount` | `true` / `5` | interruptor de gravações; backups retidos |
133
73
 
134
- Publicação: `node scripts/release.mjs <x.y.z>` sobe a versão, sela o CHANGELOG, reexecuta a porta, faz commit e cria a tag; ao empurrar a tag, npm e GitHub Release são publicados automaticamente (ver [CONTRIBUTING.md](CONTRIBUTING.md)).
74
+ ## Resources e Prompts
135
75
 
136
- Verificação contra um checkout real do harness:
137
- `node --import tsx/esm scripts/verify-headless.mjs` inicializa o perfil web completo em processo (porta efêmera) e imprime a saída exata de `/mcp`, `/mcp <server> tools` e `/mcp <server> disable`.
76
+ O cliente oficial documenta "Tools are the only bridged MCP capability": ambos estão adiados. O console detecta um seam de catálogo proposto e exibirá listas somente-leitura quando chegar; até lá o painel marca *aguardando suporte upstream* (adendo em `docs/upstream-proposal.md` do harness).
138
77
 
139
78
  ## Licença
140
79
 
141
- [Apache License 2.0](LICENSE) © 2026 colaboradores do dsh-mcp-panel
80
+ Apache-2.0 — veja [LICENSE](LICENSE).