DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-mcp-mcp-status

M

dsh-mcp-mcp-status

Discovered

MCP server inventory for the DSH Web Settings dialog: status, transport, target, tools, and enable/disable for every configured MCP server

dsh-mcp-mcp-status

An installable DeepSeek Harness plugin that adds an MCP section to the Web Settings dialog, listing every MCP server the active profile configures with its derived status, transport, target, registered tools, and an enable/disable switch.

The package replaces the MCP inventory earlier DSH releases shipped in-tree (@deepseek-ai/dsh-host-mcp-inventory and @deepseek-ai/dsh-client-ui-settings-mcp) as one dual-face package: the package root is the Host side (mcpInventory service) and the ./client export is the browser side (the Settings section). It reads only published surfaces — the Loader and the tool registry — so no DSH release has to carry an inventory-publication seam for it to work.

What it does

The Settings section lists one row per configured MCP server: the server name from the entry's config (falling back to the Loader entry id), a status tag, the transport and connection target from that stored config, the tools registered under the server's namespace, and a switch. Its navigation row draws the package's own glyph — a server node above two tool nodes — through the shell's settings.section.icon slot instead of the shell's fallback icon.

The status is derived from the Loader entry and the tool registry: disabled for a row the profile has switched off, which is still listed because the configured set comes from the Loader rather than from a connection; failed when the entry's Loader fiber is in its failed phase; connected once the server has registered at least one tool under its mcp__<serverName>__ namespace; and starting in every remaining case.

Two situations are indistinguishable in that derivation: a server that is negotiating or retrying reports starting, exactly like one that has not started yet, and a connected server that registers no tool reports starting as well. The text of the last connection failure is not exposed by any of these surfaces, so the section no longer renders it.

The switch persists one server's enablement in the current profile through the profile manager and returns the re-read inventory; when the Host has no profile manager composed, managementAvailable is false and the section renders the switches inert rather than pretending the write would work.

Nothing here is model-visible: the Host service reads the Loader configuration and the tool registry, and the section reads that service. No prompt, tool schema, or session log entry is involved.

Install from a git checkout

Substitute your GitHub owner for <user>; the repository must be named dsh-mcp-mcp-status so the installed package name matches the profile's dependency key (rename the repository and pnpm derives a different key, which then needs an alias such as dsh-mcp-mcp-status@github:<user>/other-name).

dsh plugin --profile demo add github:<user>/dsh-mcp-mcp-status

The first run fails: pnpm ≥ 10 refuses to run the prepare script that builds the git checkout, and dsh prints the exact blocked key and the file to edit.

Add that key to the profile's pnpm-workspace.yaml — ~/.dsh/profiles/demo/pnpm-workspace.yaml by default — then run the same command again:

allowBuilds:
  dsh-mcp-mcp-status: true

pnpm-workspace.yaml is where pnpm ≥ 10 reads its settings, not .npmrc, and the key must match the blocked package exactly; a version-qualified key that a different pnpm release prints is equally valid. A prebuilt tarball or a local checkout installed by path needs no allowance, because neither runs the prepare script.

The profile must also list the package as a bundle, which is what applies its patch layer. dsh plugin add writes the dependency; dsh.profile.bundles in the profile's package.json is the ordered layer list, and this package is listed after the bundles that supply the profile's base rows:

{
  "dsh": {
    "profile": {
      "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-mcp-mcp-status"]
    }
  }
}

Restart the server after a bundle-list edit; client bundles are served from lib/, so a browser refresh alone does not pick up a rebuilt plugin.

One Remote per Web app

The patch inserts one row and disables nothing, so this package registers both the mcpInventory Host service and the Settings section on its own. Current DSH releases ship no in-tree MCP inventory, so no other row provides that service or renders that section.

A composition may still provide the namespace — an older @deepseek-ai/dsh-host-mcp-inventory mounted by the Web app's own Client assembly (@deepseek-ai/dsh-api-remotes), or another plugin. The Gateway rejects a second contribution for one namespace, so the browser half reads it first — a non-strict ctx.get('remote.mcpInventory') — and mounts its own generated contribution only when nothing provides it. The descriptors address the namespace by method name, so an existing contribution dispatches to this package's Host service either way, and the plugin withdraws only what it added.

The bundle list above is what makes the patch layer apply: with dsh-mcp-mcp-status absent from dsh.profile.bundles, the plugin's row is never inserted, and removing the package from the list removes the section again.

The mcpInventory service

The Host side is a Cordis service registered under the key mcpInventory (readable as ctx.mcpInventory) and projected to the browser as the Remote namespace remote.mcpInventory.

Remote methodSignatureBehavior
list() => Promise<McpInventorySnapshot>Every Loader entry naming @deepseek-ai/dsh-mcp-client, in Loader order, each with the status and tools derived from that entry and the registry.
setEnabled(entryId: PluginEntryId, enabled: boolean) => Promise<McpInventorySnapshot>Persists one entry's enablement through the profile manager and returns the re-read inventory. Rejects when no profile manager is composed, when the manager refuses the target as read-only, or when the value was already in the requested state.

McpServerInfo carries entryId, serverName, transport (stdio, streamable-http, or unknown), an optional target, enabled, status, tools, and an optional readOnlyReason. McpInventorySnapshot adds managementAvailable.

A row's identity, transport, and target come from the entry's stored config, and its tools are the model-facing names the tool registry holds in the mcp__<serverName>__ namespace, so a tool the server registers later appears on the next read with no publication step in between.

How this package is built

prepare runs the same four steps that build runs, in this order: tsc -b tsconfig.host.json emits the Host types and JavaScript into packages/status/lib/types, tsdown --config tsdown.config.ts bundles the Host half into packages/status/lib/index.js and lets the Typert generator emit the face artifacts beside it, tsc -b tsconfig.client.json emits the browser half, and tsdown --config tsdown.client.config.ts bundles it into the closure-factory artifact packages/status/lib/client.js.

The Typert generator's real input contract is the reason for the file layout at the repository root. Its tsdown plugin resolves the workspace anchor by walking up from the build's output directory until it finds a tsconfig.host.json, so the root must own that file and packages/status must not contain one — a file of that name inside the package directory would move the anchor and silently stop artifact generation. From the anchor it reads the aggregate's project references, and it accepts only packages physically under <anchor>/packages, which is why the build project lives at packages/status rather than beside the root manifest. Each accepted registration must declare a ./typert export, and the emitted artifacts are written into that package's own lib/. Only those registrations are emitted for, but they are not the only packages the analysis recognizes: a declaration resolved from node_modules belongs to the installed package named by its nearest ancestor package.json, so the protocol's @Remote and TypertRemoteService decorators and the Remote boundary types this package imports from published dependencies count as published surfaces rather than as unowned declarations.

The browser artifact calls window.__ModuleLoader__.load({ id: 'dsh-mcp-mcp-status', factory }) and resolves externals through the require the loader hands to the factory. The id equals the package name, which is exactly the key the client module registry uses for the row, and only the shell's static module table stays external — zod and the generated Remote contribution are inlined, because a require the module table cannot answer throws when the factory materializes.

tsdown.client.ts is a standalone replacement for the monorepo's repository-internal packages/client/tsdown.client.ts. It keeps the artifact rules — closure-factory wrapper, baseline externals, lightningcss-compiled CSS Modules injecting one tagged style per stylesheet, and source maps chained back through the .tsx sources — and drops the monorepo's repository-level gates: the bundle-input isolation check, the client bundle purity allowlist (it names other monorepo packages), the async-chunk require.async rewrite (this package has no dynamic chunks), and the ?inline/global stylesheet loaders (this package ships only a .module.css).

Compatibility

The Host half imports only published surfaces: @deepseek-ai/cordis-plugin-loader for the Loader entries, @deepseek-ai/dsh-tools for the tool registry, and @deepseek-ai/dsh-typert-protocol for the Remote decorators. No DSH release has to export a publication seam for it, and tsc -b tsconfig.host.json compiles the half against the published 0.2.0-rc.2.

The consequence is concrete: with the seam gone, nothing in the build or at runtime waits for a release that carries one, and the published 0.2.0-rc.2 packages satisfy every import this package makes — the Loader's entry list and fiber state and the registry's schemas() are public members of the published surfaces.

Every @deepseek-ai/dsh-* dependency and peer is ^0.2.0-rc.2; @deepseek-ai/cordis is ~4.0.4 and @deepseek-ai/cordis-plugin-loader is ~1.0.5, both being published on their own version lines rather than the DSH line.

Known limitations

The ported unit tests are not included. They were written against @deepseek-ai/dsh-client-test-runtime, which is not published, so the browser suites cannot resolve their runtime; vitest and @testing-library/react would add a test-only dependency tree to a package whose whole job is a build-time prepare.

The browser baseline in tsdown.client.ts is a copy of the shell's static module table (PLATFORM_MODULES plus the empty PRELOADED_CLIENT_EXTERNALS). A row added to the shell's table after this file was written is not requested by this package, so it would be inlined here instead of shared; that is a duplicated module identity, not a load failure, and it is fixed by adding the specifier to the copy.

No run against a live profile was possible in the port environment: no dsh web observation covers the row, the patch layering, the namespace reuse, or the Settings rendering, so those are documented from the source they were ported from. The build does complete with a Typert generator that recognizes installed package owners: the Host bundle emits packages/status/lib/typert.host.* and packages/status/lib/typert.remote-client.*, and both tsc -b tsconfig.host.json and tsc -b tsconfig.client.json exit 0. Without that recognition the generator fails the Host bundle step with typert(host): dsh-mcp-mcp-status publishes Remote artifacts but has no Remote methods, and the browser half then cannot resolve the dsh-mcp-mcp-status/remote artifact that step emits. Building this package from npm alone therefore waits on a @deepseek-ai/dsh-typert-generator release carrying that recognition.

README.i18n.yaml is intentionally absent. The bilingual pairing record next to a translated README is generated by the harness repository's own verify-translation-pairing --write step, which does not exist in this standalone repository; hand-writing its per-heading digests would record values nothing verified.

License

MIT.

Comments

Loading…

Similar plugins

dsh-mcp-admin

by kairoz9

dsh plugin for MCP status inspection and server management | dsh 的 MCP状态查看与服务管理插件

Manifest valid

★ 4

MIT

TypeScript

Aug 15, 2026

dsh plugin --profile web add dsh-mcp-admin

by xxxyz

DSH durable MCP server manager plugin — Settings UI + HTTP API + mcp_manager_* model tools, cross-platform installers

Tools & CapabilitiesManifest valid

★ 22

↓ 214/wk

MIT

JavaScript

Oct 20, 2026

dsh plugin --profile web add @xxxyz/dsh-mcp-manager

by lyufeng000

DSH MCP 服务器管理器:在「设置 → MCP 服务器」里添加、编辑、启停、重连、移除 MCP 客户端条目。

Manifest valid

★ 0

MIT

JavaScript

Oct 17, 2026

dsh plugin --profile web add dsh-mcp-manager

by Zenjibad

Enables or disables MCP servers from Settings → MCP Servers: stops or starts each @deepseek-ai/dsh-mcp-client connection immediately and persists the change across restarts.

UI & ExperienceModels & ProvidersManifest valid

★ 1

MIT

TypeScript

Aug 28, 2026

dsh plugin --profile web add dsh-mcp-toggle

by Js2Hou

用于 DeepSeek Harness 的 MCP 可视化管理插件:在「设置 → MCP」中查看已安装/启用的 MCP 服务器,支持增删、启用/停用,并实时查看连接状态。

UI & ExperienceManifest valid

★ 25

↓ 337/wk

MIT

TypeScript

Oct 27, 2026

dsh plugin --profile web add @js2hou/dsh-mcp-manager

by whiteS18

MCP server management panel in Settings: add, edit, enable/disable and delete servers across user and workspace scopes with form or JSON editing, and auto-register discovered MCP tools as native conve

UI & ExperienceManifest valid

★ 0

MIT

JavaScript

Oct 8, 2026

dsh plugin --profile web add dsh-mcp-servers-panel