Passer au contenu principal
X

dsh-capability-gateway

xiaomao361/dsh-capability-gateway

Hides opted-in third-party skills and MCP servers from the model-facing catalogs and serves them through one capability tool: search by intent, read the schema or the skill instructions, then call. A local journal records metadata only, never query text or arguments.

Installer

dsh plugin --profile web add github:xiaomao361/dsh-capability-gateway

README

dsh-capability-gateway

English | 中文

One on-demand gateway for opted-in third-party skills and MCP tools in DeepSeek Harness.

Install enough MCP servers or skills and two things happen: the model's tool catalog grows until it crowds out the actual task, and the model starts choosing worse because every capability is equally visible. This plugin hides the ones you opt in and serves them through a single capability tool: search by intent, read the schema or instructions, then call.

It is a DeepSeek Harness host + client plugin. It does not proxy remote traffic, does not add a server, and does not send anything anywhere.

What it changes

  • Managed skills leave the model-facing skill catalog. They stay user-invocable and are loaded through capability.
  • Managed MCP servers keep their native execution path but their tool schemas are removed from the prompt. Calls go through the same native permission and guard chain.
  • PTC mode keeps run_code and the capability SDK binding, while managed MCP declarations are omitted. Search/describe on demand, then call through tools.capability. Unsupported host presentation APIs retain the original SDK and report that limitation in status and inventory.
  • One tool (capability) replaces what would otherwise be dozens of tool definitions.
  • A bounded name index is added to the system prompt so the model knows which capabilities exist even when lexical search would miss them. Names only — no descriptions, no schemas.
  • A local journal records metadata about searches and calls (never query text, arguments or results), and can be exported as a weekly report.

Install

# from your DSH profile directory
pnpm add link:/path/to/dsh-capability-gateway   # or: pnpm add dsh-capability-gateway

Register the bundle in ~/.dsh/profiles/<profile>/package.json so the plugin layer is applied:

{
  "dependencies": { "dsh-capability-gateway": "link:/path/to/dsh-capability-gateway" },
  "dsh": { "profile": { "bundles": [
    "@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-capability-gateway"
  ] } }
}

Then declare what it manages:

# ~/.dsh/profiles/<profile>/cordis.patch.yml
- id: capability-gateway
  config:
    skillRoots:
      - '~/.agents/skills'
    mcpServers:
      - my-mcp-server

The package default manages nothing on purpose: what to wrap is install data, not package data. An id patch replaces the whole config object, so repeat every key you need.

Reload the plugin (or restart DSH). The settings page is at Settings → Built-in plugins → Capability gateway.

Configuration

KeyDefaultMeaning
enabledtruefalse makes the plugin inert and restores native exposure.
skillRoots[]Directories whose skills are served by the gateway.
mcpServers[]MCP server names whose mcp__<server>__* tools are managed.
wrapSkills / wrapMcptrueTurn either half on or off.
mcpKeywords{}{ "server": ["alias", ...] } for MCP entries.
skillKeywords{}{ "skill": ["alias", ...] }.
keywordPacks[]JSON files merged in order; aliases are additive.
promptHinttrueAdd the "capabilities are behind capability" pointer.
promptIndextrueAdd the bounded capability name index.
promptIndexChars2000Cap for the index (200–6000).
maxResults5Search candidates returned (1–10).
logDir$DSH_HOME/data/capability-gatewayJournal directory.

Aliases

A Chinese question rarely shares a token with an English skill description, and no lexical search can guess a vocabulary it has never seen. Aliases are how that gap gets closed, and they are always data:

skillKeywords:
  release-notes: [发布说明, 变更记录]

or a shareable pack, referenced from keywordPacks:

{ "release-notes": ["发布说明", "变更记录"] }

Missing or broken packs do not block startup; valid packs and entries remain usable. Status, inventory and the prompt mark alias coverage as incomplete. Settings identify each affected pack by its configuration index and list invalid entry positions. Correct the file and reload the plugin. Explicit skillKeywords must map names to arrays of up to 50 nonempty strings, each at most 80 Unicode characters; invalid values raise invalid_config before normalization. A skill can also declare its own aliases in SKILL.md with keywords:, which travels with the skill.

The capability tool

ActionPurpose
searchFind candidates by goal, short keywords or a name.
loadReturn a skill's instructions and base directory.
describeReturn one MCP tool's exact JSON Schema.
callInvoke an MCP tool; arguments are validated against that schema first.
statusWhether the gateway is active and how much it manages.
inventoryCompact counts, roots, coverage and bounded anomalies.
history / statsThis session's recent routing metadata and window statistics.
reportExport a weekly summary as Markdown.

Search is deliberately conservative. Unmatched queries return not_found with a pointer to the native path rather than a fake match, and the gateway never calls an upstream tool on its own.

Privacy

Unreleased reports follow the settings page's all-session or selected-session record scope and label it explicitly. An expired selection fails instead of widening the report. Model action=report uses the calling session. Exact-name search remains scoped; partial Skill/MCP discovery is marked in text and structured metadata rather than counted as a miss.

Recorded per event: action, target name, route, outcome, error code, duration, candidate names and ranks, plugin version. Not recorded: query text, tool arguments, results, error bodies, credentials, file paths.

Everything is local. Nothing is uploaded. A report is produced only when you export it, and it contains counts and names only. Alias packs and the local retrieval snapshot are per-install data and are not part of the published package.

Limitations

  • Search is lexical, not semantic. Cross-language retrieval depends on aliases being present.
  • Retrieval quality is measured on a fixed task set (tests/retrieval.test.js); it is not a guarantee for every phrasing.
  • The journal covers the last 7 days / 10,000 events and is a sample, not an audit.
  • Capability names in the prompt are bounded; very large installs will show a truncated index.

Development

npm run check   # syntax
npm test        # unit, component, client-boot and retrieval tests
npm pack --dry-run

Design notes and the behaviour contract live in docs/DESIGN.md.

License

MIT

Plugins associés