dsh-mcp-panel 0.2.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 (63) hide show
  1. package/LICENSE +201 -0
  2. package/README.es.md +129 -0
  3. package/README.hi.md +129 -0
  4. package/README.md +129 -0
  5. package/README.pt.md +129 -0
  6. package/README.zh.md +129 -0
  7. package/cordis.patch.yml +23 -0
  8. package/lib/client.js +5045 -0
  9. package/lib/client.js.map +1 -0
  10. package/lib/index.js +1079 -0
  11. package/lib/typert.host.js +4261 -0
  12. package/lib/types/aggregate.d.ts +92 -0
  13. package/lib/types/aggregate.d.ts.map +1 -0
  14. package/lib/types/client/McpPanelTab.d.ts +16 -0
  15. package/lib/types/client/McpPanelTab.d.ts.map +1 -0
  16. package/lib/types/client/index.d.ts +35 -0
  17. package/lib/types/client/index.d.ts.map +1 -0
  18. package/lib/types/client/locales.d.ts +90 -0
  19. package/lib/types/client/locales.d.ts.map +1 -0
  20. package/lib/types/client/present.d.ts +79 -0
  21. package/lib/types/client/present.d.ts.map +1 -0
  22. package/lib/types/client/remote.d.ts +119 -0
  23. package/lib/types/client/remote.d.ts.map +1 -0
  24. package/lib/types/client/styles.d.ts +12 -0
  25. package/lib/types/client/styles.d.ts.map +1 -0
  26. package/lib/types/command.d.ts +122 -0
  27. package/lib/types/command.d.ts.map +1 -0
  28. package/lib/types/config.d.ts +63 -0
  29. package/lib/types/config.d.ts.map +1 -0
  30. package/lib/types/grouping.d.ts +49 -0
  31. package/lib/types/grouping.d.ts.map +1 -0
  32. package/lib/types/index.d.ts +41 -0
  33. package/lib/types/index.d.ts.map +1 -0
  34. package/lib/types/probe.d.ts +67 -0
  35. package/lib/types/probe.d.ts.map +1 -0
  36. package/lib/types/sanitize.d.ts +42 -0
  37. package/lib/types/sanitize.d.ts.map +1 -0
  38. package/lib/types/service.d.ts +107 -0
  39. package/lib/types/service.d.ts.map +1 -0
  40. package/lib/types/typert.host.d.ts +110 -0
  41. package/lib/types/typert.host.d.ts.map +1 -0
  42. package/lib/types/upstream.d.ts +67 -0
  43. package/lib/types/upstream.d.ts.map +1 -0
  44. package/lib/types/wire.d.ts +342 -0
  45. package/lib/types/wire.d.ts.map +1 -0
  46. package/package.json +111 -0
  47. package/src/aggregate.ts +248 -0
  48. package/src/client/McpPanelTab.tsx +257 -0
  49. package/src/client/index.ts +87 -0
  50. package/src/client/locales.ts +92 -0
  51. package/src/client/present.ts +127 -0
  52. package/src/client/remote.ts +35 -0
  53. package/src/client/styles.ts +235 -0
  54. package/src/command.ts +387 -0
  55. package/src/config.ts +110 -0
  56. package/src/grouping.ts +109 -0
  57. package/src/index.ts +86 -0
  58. package/src/probe.ts +198 -0
  59. package/src/sanitize.ts +115 -0
  60. package/src/service.ts +279 -0
  61. package/src/typert.host.ts +25 -0
  62. package/src/upstream.ts +72 -0
  63. package/src/wire.ts +221 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Plugin configuration and its explicit resolve step. `resolveConfig` re-judges
3
+ * every default and bound so programmatic construction that bypasses
4
+ * Schemastery normalization still fails loud instead of running with hidden
5
+ * defaults (the explicit-resolve contract).
6
+ *
7
+ * @module dsh-mcp-panel/config
8
+ */
9
+ import z from '@deepseek-ai/schemastery';
10
+ /** Default per-probe timeout in milliseconds. */
11
+ export declare const DEFAULT_PROBE_TIMEOUT_MS = 10000;
12
+ /** Ceiling for a single probe timeout: a probe is a one-shot HTTP call. */
13
+ export declare const MAX_PROBE_TIMEOUT_MS = 300000;
14
+ /** Default cap on probe records shown in the panel. */
15
+ export declare const DEFAULT_MAX_PROBES = 10;
16
+ /** Ceiling on the suggested panel refresh interval (1 hour). */
17
+ export declare const MAX_REFRESH_INTERVAL_MS = 3600000;
18
+ /** Languages the `/mcp` command renders in (mirrors the five-language READMEs). */
19
+ export type OutputLanguage = 'en' | 'zh' | 'es' | 'pt' | 'hi';
20
+ /** Configuration for the MCP management panel. */
21
+ export interface Config {
22
+ /** Register the optional `mcp_probe` connectivity tool (default true). */
23
+ probeEnabled?: boolean;
24
+ /** Per-probe timeout in milliseconds (default 10000). */
25
+ probeTimeoutMs?: number;
26
+ /** Cap on probe records shown in the panel (default 10). */
27
+ maxProbes?: number;
28
+ /** Suggested panel refresh interval in ms; 0 = on demand only (default 0). */
29
+ refreshIntervalMs?: number;
30
+ /** Output language of the `/mcp` command (default en). */
31
+ outputLanguage?: OutputLanguage;
32
+ /** Periodically probe streamable-http servers in the background (default false). */
33
+ passiveProbeEnabled?: boolean;
34
+ /** Passive probe interval in milliseconds (default 60000). */
35
+ passiveProbeIntervalMs?: number;
36
+ }
37
+ /** Fully resolved configuration captured at plugin load. */
38
+ export interface ResolvedConfig {
39
+ /** Whether the `mcp_probe` tool is registered. */
40
+ probeEnabled: boolean;
41
+ /** Per-probe timeout in milliseconds. */
42
+ probeTimeoutMs: number;
43
+ /** Cap on probe records shown in the panel. */
44
+ maxProbes: number;
45
+ /** Suggested panel refresh interval in ms (0 = on demand). */
46
+ refreshIntervalMs: number;
47
+ /** Output language of the `/mcp` command. */
48
+ outputLanguage: OutputLanguage;
49
+ /** Whether the passive probe loop runs. */
50
+ passiveProbeEnabled: boolean;
51
+ /** Passive probe interval in milliseconds. */
52
+ passiveProbeIntervalMs: number;
53
+ }
54
+ /** Schemastery schema for loader-validated configuration. */
55
+ export declare const Config: z<Config>;
56
+ /**
57
+ * Resolve raw config to the runtime policy, re-validating defaults and bounds.
58
+ *
59
+ * @param config - raw loader config; `undefined` for a bare row.
60
+ * @returns the frozen resolved config.
61
+ */
62
+ export declare function resolveConfig(config: Config | undefined): ResolvedConfig;
63
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,iDAAiD;AACjD,eAAO,MAAM,wBAAwB,QAAS,CAAA;AAE9C,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,SAAU,CAAA;AAE3C,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,UAAY,CAAA;AAEhD,mFAAmF;AACnF,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAE7D,kDAAkD;AAClD,MAAM,WAAW,MAAM;IACrB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,oFAAoF;IACpF,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,8DAA8D;IAC9D,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,YAAY,EAAE,OAAO,CAAA;IACrB,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAA;IACzB,6CAA6C;IAC7C,cAAc,EAAE,cAAc,CAAA;IAC9B,2CAA2C;IAC3C,mBAAmB,EAAE,OAAO,CAAA;IAC5B,8CAA8C;IAC9C,sBAAsB,EAAE,MAAM,CAAA;CAC/B;AAED,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAQ3B,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CA8BxE"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Enumeration of model-facing MCP tools from the ToolRuntime schema list,
3
+ * grouped by server namespace. The official bridge registers every MCP tool
4
+ * under `mcp__<serverName>__<rawName>` (normalized deterministically), so a
5
+ * prefix match against the configured server names is exact; leftover
6
+ * `mcp__`-prefixed registrations from foreign plugins are preserved in
7
+ * separate unconfigured groups instead of being mis-attributed or dropped.
8
+ *
9
+ * Pure functions of the schema snapshot — no registry reads.
10
+ *
11
+ * @module dsh-mcp-panel/grouping
12
+ */
13
+ import type { McpToolView } from './wire.ts';
14
+ /** The `mcp__` namespace prefix every bridged MCP tool name starts with. */
15
+ export declare const MCP_TOOL_PREFIX = "mcp__";
16
+ /** One tool group: a server namespace with its model-visible tools. */
17
+ export interface McpToolGroup {
18
+ /** Server namespace (`mcp__<serverName>__…`); the best-effort segment for leftovers. */
19
+ serverName: string;
20
+ /** True when `serverName` is a configured mcp-client namespace. */
21
+ configured: boolean;
22
+ /** Model-visible tools under that namespace, sorted by public name. */
23
+ tools: readonly McpToolView[];
24
+ }
25
+ /** The schema face this module reads; the ToolRuntime snapshot satisfies it. */
26
+ export interface ToolSchemaFace {
27
+ /** Registered public tool name. */
28
+ readonly name: string;
29
+ /** One-line model-facing description; may be absent on hostile or partial input. */
30
+ readonly description?: string;
31
+ }
32
+ /**
33
+ * Split one registered tool schema list into per-server groups.
34
+ *
35
+ * @param schemas - the `ctx.tools.schemas()` snapshot (or any subset).
36
+ * @param configuredNames - server namespaces from the loader's mcp-client rows.
37
+ * @returns one group per configured namespace (even with zero tools) plus one
38
+ * group per unmatched `mcp__` namespace, sorted by server name.
39
+ */
40
+ export declare function groupMcpTools(schemas: readonly ToolSchemaFace[], configuredNames: readonly string[]): McpToolGroup[];
41
+ /**
42
+ * Count the tools registered under one configured server namespace.
43
+ *
44
+ * @param schemas - the `ctx.tools.schemas()` snapshot.
45
+ * @param serverName - the configured namespace.
46
+ * @returns the number of matching registrations.
47
+ */
48
+ export declare function countServerTools(schemas: readonly ToolSchemaFace[], serverName: string): number;
49
+ //# sourceMappingURL=grouping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../../src/grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,4EAA4E;AAC5E,eAAO,MAAM,eAAe,UAAU,CAAA;AAStC,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,wFAAwF;IACxF,UAAU,EAAE,MAAM,CAAA;IAClB,mEAAmE;IACnE,UAAU,EAAE,OAAO,CAAA;IACnB,uEAAuE;IACvE,KAAK,EAAE,SAAS,WAAW,EAAE,CAAA;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,eAAe,EAAE,SAAS,MAAM,EAAE,GACjC,YAAY,EAAE,CAwBhB;AAgBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAO/F"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `dsh-mcp-panel` — read-only runtime management panel for the official
3
+ * DeepSeek Harness MCP client (`@deepseek-ai/dsh-mcp-client`).
4
+ *
5
+ * Host half: mounts the `mcpPanel` Remote service (loader rows + tool
6
+ * registry + upstream `mcp/status` observations), registers the `/mcp`
7
+ * command where a command registry exists, and optionally registers the
8
+ * `mcp_probe` background-job tool where a job registry exists. The panel
9
+ * never edits configuration files and never fabricates connection state:
10
+ * without the proposed upstream status seam every connection field reads
11
+ * `unknown` with `statusSource: 'derived'`.
12
+ *
13
+ * Function plugin — no default export (the Loader unwraps
14
+ * `exports.default ?? exports`).
15
+ *
16
+ * @module dsh-mcp-panel
17
+ */
18
+ import type { Context } from '@deepseek-ai/cordis';
19
+ import { Config } from './config.ts';
20
+ export declare const name = "mcp-panel";
21
+ /** Hard services: the facts the panel reads. `commands`/`jobs` are optional children. */
22
+ export declare const inject: string[];
23
+ export { Config, resolveConfig } from './config.ts';
24
+ export { McpPanelService } from './service.ts';
25
+ export { mcpCommand, parseMcpArgs, renderList, renderPatchSuggestion, renderServer, renderTools } from './command.ts';
26
+ export { groupMcpTools, countServerTools } from './grouping.ts';
27
+ export { aggregateServerView, aggregateSnapshot, deriveTarget, serverNameOf } from './aggregate.ts';
28
+ export { sanitizeError, sanitizeText, sanitizeUrl } from './sanitize.ts';
29
+ export { probeEndpoint, probeJob, mcpProbeTool } from './probe.ts';
30
+ export { MCP_STATUS_EVENT, type McpStatusPayload, type McpStatusQuery, type McpServerStatus } from './upstream.ts';
31
+ export type * from './wire.ts';
32
+ /**
33
+ * Mount the panel: the snapshot service, the upstream status seam consumer,
34
+ * the `/mcp` command (when commands exist), and the probe tool (when enabled
35
+ * and a job registry exists).
36
+ *
37
+ * @param ctx - context carrying tools + loader.
38
+ * @param config - raw loader config; defaults applied through {@link resolveConfig}.
39
+ */
40
+ export declare function apply(ctx: Context, config: Config): Promise<void>;
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAA;AAMnD,eAAO,MAAM,IAAI,cAAc,CAAA;AAE/B,yFAAyF;AACzF,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,qBAAqB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACrH,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACnG,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAClH,mBAAmB,WAAW,CAAA;AAE9B;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCvE"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The optional `mcp_probe` tool: a one-shot connectivity probe of one
3
+ * configured Streamable HTTP endpoint, executed as an UNOWNED background job.
4
+ * Probe results are panel-only — the tool returns just the job id and a
5
+ * pointer to the settings tab, the job carries no owner (so no completion
6
+ * notice is injected into the model), and the panel reads the sanitized
7
+ * snapshot back through `mcpPanel/status`.
8
+ *
9
+ * @module dsh-mcp-panel/probe
10
+ */
11
+ import type { JobHooks, JobRegistry } from '@deepseek-ai/dsh-jobs';
12
+ import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
13
+ import type { McpPanelService } from './service.ts';
14
+ /** Producer kind; also the job-id prefix. */
15
+ export declare const PROBE_KIND = "mcp-probe";
16
+ declare module '@deepseek-ai/dsh-jobs' {
17
+ interface JobKindMap {
18
+ /** One-shot Streamable HTTP connectivity probe (panel-only results). */
19
+ 'mcp-probe': 'mcp-probe';
20
+ }
21
+ }
22
+ /** MCP clientInfo facts; protocol constants, not configuration. Exported so the
23
+ * version-consistency tripwire (`tests/version.spec.ts`) can assert the
24
+ * advertised version tracks the package version. */
25
+ export declare const PROBE_CLIENT_INFO: {
26
+ name: string;
27
+ version: string;
28
+ };
29
+ /** One settled probe: outcome status plus a sanitized one-line detail. */
30
+ export interface ProbeOutcome {
31
+ /** How the job ended. */
32
+ status: 'completed' | 'failed';
33
+ /** Sanitized one-line detail (HTTP status, latency, server info, or error). */
34
+ detail: string;
35
+ }
36
+ /**
37
+ * POST one MCP `initialize` request and describe the outcome in one sanitized
38
+ * line. Never sends or echoes credentials: the configured headers are used
39
+ * for the request itself (exactly as the bridge would) and never rendered.
40
+ *
41
+ * @param url - endpoint URL (already parsed by the caller).
42
+ * @param headers - the configured request headers; used, never displayed.
43
+ * @param timeoutMs - probe deadline.
44
+ * @param signal - caller-owned abort (job kill or timeout).
45
+ * @returns the settled probe outcome.
46
+ */
47
+ export declare function probeEndpoint(url: string, headers: Readonly<Record<string, string>>, timeoutMs: number, signal: AbortSignal): Promise<ProbeOutcome>;
48
+ /**
49
+ * Create the background-job hooks for one probe: cancel aborts the fetch, the
50
+ * outcome settles `done` with sanitized detail only.
51
+ *
52
+ * @param url - endpoint URL.
53
+ * @param headers - configured headers (used, never rendered).
54
+ * @param timeoutMs - probe deadline.
55
+ * @returns the registry hooks.
56
+ */
57
+ export declare function probeJob(url: string, headers: Readonly<Record<string, string>>, timeoutMs: number): JobHooks;
58
+ /**
59
+ * Build the `mcp_probe` tool definition.
60
+ *
61
+ * @param service - panel service (server lookup + snapshot for panel display).
62
+ * @param jobs - background-job registry the probe runs on.
63
+ * @param timeoutMs - per-probe deadline.
64
+ * @returns the registration-ready definition.
65
+ */
66
+ export declare function mcpProbeTool(service: McpPanelService, jobs: JobRegistry, timeoutMs: number): ToolDefinition;
67
+ //# sourceMappingURL=probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAc,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAG5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,6CAA6C;AAC7C,eAAO,MAAM,UAAU,cAAc,CAAA;AAErC,OAAO,QAAQ,uBAAuB,CAAC;IACrC,UAAU,UAAU;QAClB,wEAAwE;QACxE,WAAW,EAAE,WAAW,CAAA;KACzB;CACF;AAKD;;oDAEoD;AACpD,eAAO,MAAM,iBAAiB;;;CAA8C,CAAA;AAE5E,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAA;IAC9B,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAA;CACf;AAUD;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACzC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,CAW5G;AAUD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CA8C3G"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Display sanitization for MCP panel surfaces. Everything the panel shows —
3
+ * the `/mcp` command output, the web settings tab, probe job details — passes
4
+ * through these pure functions so URL query-string credentials, userinfo
5
+ * passwords, header values, and bearer tokens never reach a display.
6
+ *
7
+ * The panel never shows configured `headers` at all (they are dropped at
8
+ * snapshot assembly); this module redacts what can still leak through target
9
+ * URLs and error text.
10
+ *
11
+ * @module dsh-mcp-panel/sanitize
12
+ */
13
+ /** Replacement for every redacted credential value. */
14
+ export declare const REDACTED = "***";
15
+ /**
16
+ * Redact a URL for display: userinfo password, credential query values, and
17
+ * credential fragment pairs. Query keys are read through `URLSearchParams`,
18
+ * so percent-encoded key names are decoded before matching. Unparseable
19
+ * inputs fall back to pattern redaction (whole userinfo, credential query
20
+ * pairs, credential fragment pairs) instead of throwing.
21
+ *
22
+ * @param url - candidate URL text.
23
+ * @returns display-safe URL text.
24
+ */
25
+ export declare function sanitizeUrl(url: string): string;
26
+ /**
27
+ * Redact credential-shaped fragments from free text: header lines, bearer
28
+ * tokens, raw JWTs, embedded query pairs, and quoted token values.
29
+ *
30
+ * @param text - candidate display text.
31
+ * @returns display-safe text.
32
+ */
33
+ export declare function sanitizeText(text: string): string;
34
+ /**
35
+ * Stringify an arbitrary thrown value safely and redact it for display.
36
+ * Never throws: unrenderable values degrade to a fixed marker.
37
+ *
38
+ * @param error - thrown value from a connection attempt, probe, or sync.
39
+ * @returns display-safe error text.
40
+ */
41
+ export declare function sanitizeError(error: unknown): string;
42
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uDAAuD;AACvD,eAAO,MAAM,QAAQ,QAAQ,CAAA;AAmC7B;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgB/C;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAajD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQpD"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * The panel's host service: assembles the read-only MCP snapshot and serves
3
+ * it under the `mcpPanel` Typert Remote namespace (`mcpPanel/status`).
4
+ *
5
+ * Data sources, all read-only:
6
+ * - `ctx.loader` — mcp-client rows (raw config, effective disabled, fiber phase).
7
+ * - `ctx.tools.schemas()` — registered `mcp__<server>__` tool names + descriptions.
8
+ * - the proposed upstream `mcp/status` seam — observed via {@link observe}.
9
+ * - `ctx.jobs` — unowned `mcp-probe` background jobs (panel-only results).
10
+ *
11
+ * Connection status is reported honestly: without upstream observations the
12
+ * view reads `unknown` with `statusSource: 'derived'`; the panel never infers
13
+ * a connection state from tool-registry presence.
14
+ *
15
+ * @module dsh-mcp-panel/service
16
+ */
17
+ import type { Context } from '@deepseek-ai/cordis';
18
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
19
+ import type { McpServerStatus } from './upstream.ts';
20
+ import type { McpPanelSnapshot, ProbeStarted } from './wire.ts';
21
+ declare module '@deepseek-ai/cordis' {
22
+ interface Context {
23
+ /** Read-only MCP management snapshot service (this package). */
24
+ mcpPanel: McpPanelService;
25
+ }
26
+ }
27
+ /** Service-level runtime settings; the plugin passes its resolved config in. */
28
+ export interface McpPanelServiceConfig {
29
+ /** Per-probe timeout in milliseconds. */
30
+ probeTimeoutMs: number;
31
+ /** Cap on probe records shown in the panel. */
32
+ maxProbes: number;
33
+ /** Suggested panel refresh interval in ms (0 = on demand). */
34
+ refreshIntervalMs: number;
35
+ /** Whether the passive probe loop runs. */
36
+ passiveProbeEnabled: boolean;
37
+ /** Passive probe interval in milliseconds. */
38
+ passiveProbeIntervalMs: number;
39
+ }
40
+ /** Read-only MCP management snapshot service, exported over the `mcpPanel` Remote namespace. */
41
+ export declare class McpPanelService extends TypertRemoteService {
42
+ private readonly config;
43
+ static inject: string[];
44
+ /** Latest upstream payload per server namespace. */
45
+ private readonly statuses;
46
+ /** Cumulative reconnect attempts observed per server namespace. */
47
+ private readonly reconnects;
48
+ /** Epoch ms of the latest upstream event receipt per server namespace. */
49
+ private readonly observedAt;
50
+ /** Latest passive-probe reachability per server namespace. */
51
+ private readonly probeStates;
52
+ /** Passive-probe loop guard: one sweep at a time. */
53
+ private passiveRunning;
54
+ /**
55
+ * @param ctx - context carrying the loader and tool registry.
56
+ * @param config - resolved runtime settings; defaults apply for direct construction.
57
+ */
58
+ constructor(ctx: Context, config?: McpPanelServiceConfig);
59
+ /**
60
+ * Record one upstream `mcp/status` payload (event or query-seed). A
61
+ * `connecting` payload with a positive attempt counts one reconnect.
62
+ *
63
+ * @param payload - post-transition status facts.
64
+ */
65
+ observe(payload: McpServerStatus): void;
66
+ /**
67
+ * Assemble the current snapshot. Read-only: touches no configuration file
68
+ * and mutates no registry. Exported on the wire by the `mcpPanel/status`
69
+ * invocation descriptor in `./wire.ts` (registered through the package's
70
+ * `./typert` manifest) — no method decorator, so the built bundle stays
71
+ * plain ESM.
72
+ *
73
+ * @returns the wire snapshot (validated by the strict Typert codec on both faces).
74
+ */
75
+ status(): McpPanelSnapshot;
76
+ /**
77
+ * Start a one-shot connectivity probe of one configured streamable-http
78
+ * server as an UNOWNED background job — panel-only, like the `mcp_probe`
79
+ * tool, but callable from the settings tab. Exported on the wire by the
80
+ * `mcpPanel/probe` invocation descriptor.
81
+ *
82
+ * @param serverName - configured namespace.
83
+ * @returns the started job id and where the result lands.
84
+ */
85
+ probe(serverName: string): ProbeStarted;
86
+ /** One passive-probe sweep over every configured streamable-http server. */
87
+ private runPassiveProbes;
88
+ /**
89
+ * Resolve one server's raw endpoint for the probe tool. Credentials stay
90
+ * inside this return value and are used for the request only — they never
91
+ * reach a snapshot, a log, or a display.
92
+ *
93
+ * @param serverName - configured namespace.
94
+ * @returns the raw URL + configured headers, or `undefined` when the server
95
+ * is not a configured streamable-http row.
96
+ */
97
+ rawEndpoint(serverName: string): {
98
+ url: string;
99
+ headers: Record<string, string>;
100
+ } | undefined;
101
+ /** Unowned `mcp-probe` background jobs, newest first, sanitized for display. */
102
+ private probeViews;
103
+ /** Absolute path of the profile patch layer the suggestions name, or null. */
104
+ private patchFile;
105
+ }
106
+ export default McpPanelService;
107
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AAetE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACpD,OAAO,KAAK,EAAiB,gBAAgB,EAAgB,YAAY,EAAE,MAAM,WAAW,CAAA;AAE5F,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,gEAAgE;QAChE,QAAQ,EAAE,eAAe,CAAA;KAC1B;CACF;AAqBD,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAA;IACjB,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAA;IACzB,2CAA2C;IAC3C,mBAAmB,EAAE,OAAO,CAAA;IAC5B,8CAA8C;IAC9C,sBAAsB,EAAE,MAAM,CAAA;CAC/B;AAWD,gGAAgG;AAChG,qBAAa,eAAgB,SAAQ,mBAAmB;IAkB5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAjBjD,MAAM,CAAC,MAAM,WAAsB;IAEnC,oDAAoD;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,8DAA8D;IAC9D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+E;IAC3G,qDAAqD;IACrD,OAAO,CAAC,cAAc,CAAQ;IAE9B;;;OAGG;gBACS,GAAG,EAAE,OAAO,EAAmB,MAAM,GAAE,qBAA8C;IAUjG;;;;;OAKG;IACH,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IASvC;;;;;;;;OAQG;IACH,MAAM,IAAI,gBAAgB;IA+B1B;;;;;;;;OAQG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY;IAqBvC,4EAA4E;YAC9D,gBAAgB;IAiB9B;;;;;;;;OAQG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,SAAS;IAsB7F,gFAAgF;IAChF,OAAO,CAAC,UAAU;IAkBlB,8EAA8E;IAC9E,OAAO,CAAC,SAAS;CAMlB;AAED,eAAe,eAAe,CAAA"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * The hand-written Typert HOST manifest for `dsh-mcp-panel`, exported as
3
+ * `./typert` so the harness's typert-loader registers the `mcpPanel` status
4
+ * and probe invocations automatically when this plugin mounts. Same shape as
5
+ * a generator output (validated by the loader): package face, empty model and
6
+ * schemas, and the canonical invocation list shared with the client Remote
7
+ * contribution (`src/wire.ts`).
8
+ *
9
+ * @module dsh-mcp-panel/typert
10
+ */
11
+ /** Host Typert manifest (validated by `@deepseek-ai/dsh-typert-loader`). */
12
+ export declare const TYPERT: Readonly<{
13
+ package: "dsh-mcp-panel";
14
+ face: "host";
15
+ schemas: readonly never[];
16
+ invocations: readonly (Readonly<{
17
+ readonly id: "dsh-mcp-panel#mcpPanel/status";
18
+ readonly service: "mcpPanel";
19
+ readonly namespace: "mcpPanel";
20
+ readonly method: "status";
21
+ readonly invocation: Readonly<{
22
+ kind: "direct";
23
+ }>;
24
+ readonly parameters: readonly never[];
25
+ readonly result: Readonly<{
26
+ mode: "strict";
27
+ typeSymbol: "dsh-mcp-panel/types#McpPanelSnapshot";
28
+ schema: import("zod").ZodObject<{
29
+ observed: import("zod").ZodBoolean;
30
+ patchFile: import("zod").ZodNullable<import("zod").ZodString>;
31
+ refreshIntervalMs: import("zod").ZodNumber;
32
+ servers: import("zod").ZodArray<import("zod").ZodObject<{
33
+ serverName: import("zod").ZodString;
34
+ entryId: import("zod").ZodString;
35
+ transport: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"stdio">, import("zod").ZodLiteral<"streamable-http">, import("zod").ZodLiteral<"unknown">]>;
36
+ target: import("zod").ZodString;
37
+ enabled: import("zod").ZodBoolean;
38
+ fiberPhase: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"pending">, import("zod").ZodLiteral<"loading">, import("zod").ZodLiteral<"active">, import("zod").ZodLiteral<"failed">, import("zod").ZodLiteral<"unloading">, import("zod").ZodNull]>;
39
+ configuredNote: import("zod").ZodNullable<import("zod").ZodString>;
40
+ toolCount: import("zod").ZodNumber;
41
+ tools: import("zod").ZodArray<import("zod").ZodObject<{
42
+ name: import("zod").ZodString;
43
+ description: import("zod").ZodString;
44
+ }, import("zod/v4/core").$strip>>;
45
+ phase: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"connecting">, import("zod").ZodLiteral<"connected">, import("zod").ZodLiteral<"waiting">, import("zod").ZodLiteral<"exhausted">, import("zod").ZodLiteral<"disposed">, import("zod").ZodLiteral<"unknown">]>;
46
+ attempt: import("zod").ZodNumber;
47
+ maxAttempts: import("zod").ZodNumber;
48
+ delayMs: import("zod").ZodNullable<import("zod").ZodNumber>;
49
+ reconnectCount: import("zod").ZodNumber;
50
+ lastError: import("zod").ZodNullable<import("zod").ZodString>;
51
+ connectedAt: import("zod").ZodNullable<import("zod").ZodNumber>;
52
+ observedAt: import("zod").ZodNullable<import("zod").ZodNumber>;
53
+ probeState: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"reachable">, import("zod").ZodLiteral<"unreachable">, import("zod").ZodNull]>;
54
+ probeCheckedAt: import("zod").ZodNullable<import("zod").ZodNumber>;
55
+ statusSource: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"upstream-event">, import("zod").ZodLiteral<"derived">]>;
56
+ }, import("zod/v4/core").$strip>>;
57
+ probes: import("zod").ZodArray<import("zod").ZodObject<{
58
+ id: import("zod").ZodString;
59
+ serverName: import("zod").ZodString;
60
+ status: import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"running">, import("zod").ZodLiteral<"stopping">, import("zod").ZodLiteral<"completed">, import("zod").ZodLiteral<"killed">, import("zod").ZodLiteral<"failed">]>;
61
+ startedAt: import("zod").ZodNumber;
62
+ finishedAt: import("zod").ZodNullable<import("zod").ZodNumber>;
63
+ detail: import("zod").ZodNullable<import("zod").ZodString>;
64
+ }, import("zod/v4/core").$strip>>;
65
+ }, import("zod/v4/core").$strip>;
66
+ }>;
67
+ readonly sourceLocation: Readonly<{
68
+ file: "src/wire.ts";
69
+ line: 1;
70
+ column: 1;
71
+ }>;
72
+ }> | Readonly<{
73
+ readonly id: "dsh-mcp-panel#mcpPanel/probe";
74
+ readonly service: "mcpPanel";
75
+ readonly namespace: "mcpPanel";
76
+ readonly method: "probe";
77
+ readonly invocation: Readonly<{
78
+ kind: "direct";
79
+ }>;
80
+ readonly parameters: readonly Readonly<{
81
+ name: string;
82
+ wire: string;
83
+ source: "json";
84
+ codec: Readonly<{
85
+ mode: "strict";
86
+ typeSymbol: "dsh-mcp-panel/types#ProbeRequestServerName";
87
+ schema: import("zod").ZodString;
88
+ }>;
89
+ }>[];
90
+ readonly result: Readonly<{
91
+ mode: "strict";
92
+ typeSymbol: "dsh-mcp-panel/types#ProbeStarted";
93
+ schema: import("zod").ZodObject<{
94
+ jobId: import("zod").ZodString;
95
+ note: import("zod").ZodString;
96
+ }, import("zod/v4/core").$strip>;
97
+ }>;
98
+ readonly sourceLocation: Readonly<{
99
+ file: "src/wire.ts";
100
+ line: 1;
101
+ column: 1;
102
+ }>;
103
+ }>)[];
104
+ model: Readonly<{
105
+ services: readonly never[];
106
+ events: readonly never[];
107
+ objects: readonly never[];
108
+ }>;
109
+ }>;
110
+ //# sourceMappingURL=typert.host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typert.host.d.ts","sourceRoot":"","sources":["../../src/typert.host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,4EAA4E;AAC5E,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUjB,CAAA"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The proposed upstream observability seam of `@deepseek-ai/dsh-mcp-client`
3
+ * (see `docs/upstream-proposal.md` in the deepseek-harness repository),
4
+ * consumed here before it ships: the typed `mcp/status` Cordis event and the
5
+ * `mcpStatus` query service face.
6
+ *
7
+ * Declarations merge into `@deepseek-ai/cordis`. If upstream later ships the
8
+ * same seam, its identical declarations merge cleanly; a conflicting
9
+ * signature fails this package's compile, which is the intended tripwire.
10
+ * At runtime the seam is feature-detected: with no upstream implementation
11
+ * mounted, no events arrive and `ctx.mcpStatus` is absent, so the panel falls
12
+ * back to derived facts and reports `statusSource: 'derived'`.
13
+ *
14
+ * @module dsh-mcp-panel/upstream
15
+ */
16
+ /** Supervisor phase after one `mcp/status` transition (mirrors the proposal). */
17
+ export type McpStatusPhase = 'connecting' | 'connected' | 'waiting' | 'exhausted' | 'disposed';
18
+ /**
19
+ * App-level connection-status payload emitted on every mcp-client state
20
+ * transition. `error` carries raw same-process text; DISPLAY consumers must
21
+ * sanitize (this package's `sanitize.ts`) before rendering.
22
+ */
23
+ export interface McpStatusPayload {
24
+ /** Stable local namespace from plugin config. */
25
+ serverName: string;
26
+ /** Supervisor phase after the transition. */
27
+ phase: McpStatusPhase;
28
+ /** Consecutive failed attempts in the current outage (0 while connected). */
29
+ attempt: number;
30
+ /** Resolved reconnect budget (`reconnect.maxAttempts`). */
31
+ maxAttempts: number;
32
+ /** Scheduled backoff delay while `waiting`. */
33
+ delayMs?: number;
34
+ /** Raw error text of the failed attempt or re-sync. */
35
+ error?: string;
36
+ /** Tools registered after the last successful sync. */
37
+ toolCount: number;
38
+ /** Epoch ms of the last successful connect; absent while down. */
39
+ connectedAt?: number;
40
+ }
41
+ /** Current per-server status snapshot; the query face of `mcp/status`. */
42
+ export type McpServerStatus = McpStatusPayload;
43
+ /** Structural query face of the proposed `mcpStatus` service (feature-detected). */
44
+ export interface McpStatusQuery {
45
+ /** Current status of every server this process knows. */
46
+ list(): readonly McpServerStatus[];
47
+ /** Current status of one server namespace, or `undefined`. */
48
+ get(serverName: string): McpServerStatus | undefined;
49
+ }
50
+ declare module '@deepseek-ai/cordis' {
51
+ interface Events {
52
+ /**
53
+ * One MCP client supervisor state transition (the proposed upstream
54
+ * observability seam). App-level: no agent or session scope.
55
+ * @param payload - post-transition status facts.
56
+ * @mode emit
57
+ */
58
+ 'mcp/status'(payload: McpStatusPayload): void;
59
+ }
60
+ interface Context {
61
+ /** The proposed upstream status query service; absent until upstream ships it. */
62
+ mcpStatus?: McpStatusQuery;
63
+ }
64
+ }
65
+ /** Exact event name, exported so consumers never hardcode the literal twice. */
66
+ export declare const MCP_STATUS_EVENT = "mcp/status";
67
+ //# sourceMappingURL=upstream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upstream.d.ts","sourceRoot":"","sources":["../../src/upstream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,iFAAiF;AACjF,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAA;AAE9F;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAA;IAClB,6CAA6C;IAC7C,KAAK,EAAE,cAAc,CAAA;IACrB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAA;IACf,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAA;IACjB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAE9C,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,IAAI,IAAI,SAAS,eAAe,EAAE,CAAA;IAClC,8DAA8D;IAC9D,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAA;CACrD;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd;;;;;WAKG;QACH,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAA;KAC9C;IACD,UAAU,OAAO;QACf,kFAAkF;QAClF,SAAS,CAAC,EAAE,cAAc,CAAA;KAC3B;CACF;AAED,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,eAAe,CAAA"}