DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

@z-y-q/dsh-mcp-apps

Mcp Apps

DeepSeek Harness 的 MCP Apps 显示:通过独立源沙箱,在工具调用行中渲染 MCP App UI 资源(ui://)。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add @z-y-q/dsh-mcp-apps@0.3.0
README兼容性版本

兼容性与来源证明

Mcp Apps 以 @z-y-q/dsh-mcp-apps 发布,当前版本为 0.3.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/10/28

版本

0.3.0stable
2026/10/28

相关插件

正在加载相关插件…

最新版
0.3.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
1.6 MB
文件数
11
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 0
周下载
0
最近提交
2026/10/28
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 integrations-communication 分类下经过校验的插件。

Ds Botds-botDS Bot:DeepSeek Harness 的一组长期运行的 Bot,支持主 Bot、Bot 间消息和群聊Free Searchdsh-free-searchDeepSeek Harness 的免费网页搜索:27 个引擎(Bing/DuckDuckGo/AnySearch/SearXNG/Exa/Tavily/Keenable/Firecrawl/Parallel/You.com 无需密钥;通过 MCP 支持 Zhihu 全局/站内搜索,以及 Perplexity/SerpBase/DeepSeek(官方 + 原生工具/搜索)/Baidu/Kimi/Aliyun/Douba)Pocketdsh-pocket把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫码即同步访问电脑上的 DSH(局域网 + 公网,实时同屏)。Dafeiyudsh-dafeiyu由 DeepSeek Harness 会话事件驱动的原生桌面端 BigFish companion。

README

dsh-mcp-apps

Requires: dsh ≥ v0.1.7-rc.2 (compatible with 0.1.7 / 0.2.x, peer range >=0.1.7-rc.2 <0.3.0; dsh 0.2.1 gates plugin versions, so use a build from 2026-10-20 or later). This is a dsh plugin — install it into a dsh profile and let the dsh host load it; it is not a standalone npm library. Desktop app (DeepSeek Harness.app) is supported, including App cards: the sandbox now handshakes on a per-boot embed key because dsh-app:// pages send no Referer (architecture doc §7.3).

MCP Apps display for DeepSeek Harness: renders the ui:// App resources an MCP server attaches to its tools inside the tool-call rows of the dsh web GUI, using the official @modelcontextprotocol/ext-apps AppBridge and the double-iframe sandbox architecture from the MCP Apps specification.

The official @deepseek-ai/dsh-mcp-client package is never modified. This bundle reuses its loader-row server configuration (read-only) and opens its own MCP connections, because the official plugin discards tool _meta and exposes no resources/read.

Install

Add "@z-y-q/dsh-mcp-apps": "^0.2.0" to your profile (~/.dsh/profiles/web/package.json) dependencies, list "@z-y-q/dsh-mcp-apps" in dsh.profile.bundles, and run pnpm install inside the profile directory. The bundled cordis.patch.yml inserts the mcp-apps host row automatically.

Install dsh-mcp-auth (^0.2.0) alongside when you need OAuth login support — see its README for the mcp-client row configuration.

Config

- id: mcp-apps
  name: '@z-y-q/dsh-mcp-apps'
  config:
    servers: []          # allowlist of mcp-client serverName values; empty = all
    sandboxPort: 0       # loopback port for the sandbox origin; 0 = OS-assigned
    registerTools: false # live-credential tool bridge switch (see below); off by default

Security model

  • The sandbox proxy page is served from its own loopback-only listener, on a port distinct from the dsh web server. A separate PORT is required: the inner App iframe carries allow-same-origin, so sharing the dsh port would make untrusted App HTML same-origin with the dsh API. On a distinct port, a cross-origin fetch of the main /api fails the harness trust fence (origin.host !== host authority).
  • CSP is delivered as an HTTP response header derived from the resource's declared allowlists — never a meta tag. Domain entries containing ;, quotes, spaces, or newlines are rejected.
  • The sandbox proxy validates its embedder by referrer (loopback only) and refuses top-level loads; all relayed messages carry origin checks.
  • Tool/resource calls initiated by an App forward through this bundle's host half to its own MCP connection. As of 0.2.0 that forwarding rides the dsh Typert Gateway (the mcp-apps Remote namespace: list / resource / call-tool / read-resource / list-resources) — no separate loopback RPC endpoint, per-boot token, or settings-namespace bootstrap remains; the sandbox proxy page itself still lives on its own loopback origin (the security model is unchanged).

Reusing an mcp-client row's config (including !!js)

Server config is read only from the loader's @deepseek-ai/dsh-mcp-client rows, from the row fiber's already-interpolated config (entry.fiber.config), so:

  • credentials injected with headers: !!js ctx.mcpAuth.headers('x') reach this bundle's own connection too — otherwise a server that requires them shows no Apps at all, with only a warn as evidence.
  • when the row has no fiber yet, the serialized entry.options.config is used and any leftover {__jsExpr} node is evaluated on a best-effort basis; a node that cannot be evaluated is kept as-is and warned about, never silently sent as a credential-free request.

dsh-mcp-auth's headers() snapshots at bootstrap. That only matters when no authProvider is installed (see below): once one is, credentials come from the provider on every request and a login completed after boot takes effect immediately.

Debugging: with DSH_MCP_APPS_DEBUG=1 the discovery pass logs each row's URL and header names (never values) — the quickest way to see whether a connection carries credentials.

On-demand login (401 → consent → retry)

The MCP Apps reference host specifies that when an App calls a protected tool, the server answers 401 + WWW-Authenticate and the host runs the OAuth flow and retries. This bundle implements that half.

When dsh-mcp-auth is present (resolved through ctx.get('mcpAuth'), deliberately not via inject, so App support still applies in a profile that does not install it):

  1. Each connection asks it for a lazy-auth handle and passes provider to the StreamableHTTPClientTransport as authProvider.
  2. Authorization is stripped from the static headers (stripAuthorization). This is required: the SDK's _commonHeaders() spreads requestInit.headers after the bearer derived from the provider, so a leftover static header overrides the freshly obtained token.
  3. When a protected call fails with UnauthorizedError, authorize() runs and waits for the approval, then the call is retried once — the transport reads the token from the provider per request, so the retry carries it.

A FAILED outcome rethrows the original error and records why on the auth side (lastError() / oauthError in list): a silent failure would make "authorization is broken" indistinguishable from "the user cancelled".

Without dsh-mcp-auth the behaviour is exactly as before: a 401 is just an error.

Live-credential tool bridge (registerTools: true)

What it solves: the official dsh-mcp-client row's credentials are a !!js snapshot evaluated once at boot (loader semantics + the schema copy that severs object identity + the transport reusing one headers object — three gates, none of them bypassable), so a login or re-authorization completed after boot is invisible to model-side calls and requires restarting dsh.

How: this bundle registers every server's tools on the harness runtime via ctx.tools.register (public API — the same one the official mcp-client uses), with names and shapes aligned field-by-field with the official bridge — mcp__<server>__<tool> (64-char truncation + 12-hex sha256 suffix), exec.signal forwarding, isError → throw, the content/structuredContent output schema, and taskSupport: 'required' tools failing at call time with the official message. The dsh-mcp-security baseline fingerprint therefore does not change; its gate keeps applying.

Execution path: execute rides this bundle's own connection (the authProvider live credentials) — the token is read per request; a 401 or a rejected refresh triggers the consent flow, and after approval the very call is retried. A failed authorization rethrows the original error.

Taking over (choose one):

  1. Yield mode (recommended): set the official row to disabled: true. The row stays — discovery reads its url/serverName (falling back from the unavailable fiber.config snapshot to options.config plus best-effort !!js evaluation) — but the official client registers nothing and opens no connection; the bridge owns everything.
  2. Coexistence: keep the official row enabled. Name collisions are skipped with a warning, never hijacked (the registry's already registered semantics), so migration can be gradual; disable a row when you want that server fully on live credentials.

Off by default: with registerTools: false the tool registry is never touched, matching this bundle's earlier behaviour.

Known limitations

  • App display requires the GUI to be reached over loopback (127.0.0.1 / localhost); the sandbox proxy is not reachable from LAN browsers.
  • App discovery opens a second connection to each configured MCP server.
  • updateModelContext and ui/message notifications from Apps are accepted and ignored; only inline display mode is offered.
  • Tools registered by the bridge carry no _meta (the App resource marker) — same as the official registration path; App cards are handled separately by this bundle's discovery, so the two do not conflict.
  • Servers still on the official row (not yielded) keep the boot-time snapshot for model-side calls.
  • Each lazy-auth handle holds a loopback listener for its lifetime; they are disposed with the plugin (ctx.effect), and every tool registration is unregistered at the same time.

Model experience

With registerTools: false (default) nothing model-visible changes. With it on, the model sees tools identical in name and shape to the official registrations (the only difference is the live-credential execution path); no new prompt sections or session events, and KV-cache behavior is unchanged.

Development

pnpm install --ignore-workspace
pnpm run build   # tsdown twice: node half (@Remote decorator lowering) +
                 # client half; copies the hand-written Typert artifacts
                 # (typert.host / typert.remote-client) into lib/
pnpm test        # node --test --test-force-exit test/*.test.mjs test/*.test.ts

The Typert artifacts are hand-maintained (src/typert.host.manual.js / typert.remote-client.manual.js): the official generator's package mode only recognizes workspace-internal packages. When adding or changing an @Remote method, update both files (and set the implementation field whenever the wire name differs from the JS method name). For a minimal e2e check run node test/e2e-demo-server.mjs (a ui:// App demo on port 3927).