如何创建 DeepSeek Harness 插件

十二步截图实证:从最小 Context 函数到双运行时工具插件,再注册为持久化 bundle、跑完 HTTP 验收。

最近更新: 2026-09-25

DeepSeek Harness 里的所有能力——从单个 hello 工具到完整的交互界面——都以插件形式存在,而自己写一个插件的门槛比看起来低:一个接收 Context 的函数、几个导出、一个 Schema。这篇图文跟着一次真实的开发过程,从空文件夹走到一个能在对话里跑起来的 MCP Apps 插件。

九步覆盖完整路径:插件是什么、最小契约、Host 与 Client 两个运行时、load–run–dispose 生命周期、真实仓库的目录结构、宿主入口与 Config Schema,以及在你自己的 profile 里安装、声明、验证插件的确切命令。

九步创建一个 DeepSeek Harness 插件

  1. 1

    先看清插件插在哪里

    DeepSeek Harness 基于 Cordis,插件就是一个接收 Context 的函数:它声明自己依赖哪些服务,向 Context 注册新能力,卸载时的清理则交给框架。模型会话工具和网页界面都从这个边界接入——视频里的示意图标出了代码可以扩展的几个面:模型、工具、MCP 和 Web Client。

    DeepSeek Harness 架构示意图:MODEL、TOOLS、MCP、WEB CLIENT 四个模块接入 DSH 可配置核心
    四个扩展面汇入 harness 核心——插件就是你给任何一面加能力的方式。在 0:13 观看
    DSH 插件教程里的 Cordis Context 示意图,标注声明依赖、注册工具与界面、Config + Schema 和卸载清理
    插件就是接收这个 Context 的函数:声明、注册,剩下的交给框架清理。在 0:25 观看
  2. 2

    从最小的可用插件开始

    教程里的 hello 例子只需要三样东西:可加载的模块入口(export const name = 'hello')、接收 Context 的 apply(ctx) 函数并在其中注册能力——这里用 ctx.tools.add 添加一个回显名字的 hello 工具——以及只有插件需要配置时才导出的、用 Schema.object 构建的 Config。Harness 会校验这个 Schema,并在管理界面里渲染对应的字段。其余都是可选的。

    最小的 DeepSeek Harness 插件源码:export const name、apply(ctx) 调用 ctx.tools.add,旁边是 Schema.object 的 Config 和三条清单
    整个文件就是一个能跑的插件:入口、apply 函数、可选的 Config Schema。在 1:00 观看
  3. 3

    选 Host、Client 还是两者都要——生命周期是同一套

    有两个运行时需要分清。Host 是运行 DeepSeek Harness 的后端进程,掌握网络连接和工具要用的密钥;浏览器里的 Harness Web UI 是 Client,负责组件和交互界面。hello 插件只有 Host 入口——注册一个工具,让对话展示结果;带界面的插件则额外提供 Client 入口,声明自己的 inject 和 apply。无论哪种,每个入口都在自己的运行时里执行 apply,卸载时 Context 会统一销毁它注册的一切。

    DSH 插件生命周期示意图,LOAD、RUN、DISPOSE 三个阶段下方标注 HOST ENTRY 和 CLIENT ENTRY · OPTIONAL
    Host 入口必备,Client 入口可选——两者走同一个三阶段生命周期。在 1:45 观看
    DSH 插件生命周期示意图里高亮为绿色的 RUN 阶段:apply(ctx) 在这里执行并注册插件的能力
    RUN 就是你的 apply 函数干活的时刻——把能力注册到两个运行时都能看到的地方。在 1:20 观看
  4. 4

    研究一个已上线插件的目录结构

    写代码之前,先看一个已发布插件是怎么组织的。sugarforever/dsh-mcp-apps 仓库把源码、examples、tests、docs 和包配置放在根目录,src/ 下再分成 config、connection、protocol、rpc、tools、client。你不必逐行读完——认准三个锚点(src/index.ts、src/config.ts、src/client/)就足以看懂任何 DSH 插件。

    GitHub 上的 dsh 插件目录结构:sugarforever/dsh-mcp-apps 的 src 文件夹列出 client、config.ts、connection.ts、index.ts、protocol.ts、rpc.ts、tools.ts
    已上线插件把契约放在 index.ts、校验放在 config.ts、浏览器端放在 client/。在 2:05 观看
  5. 5

    写宿主入口:name、inject、Config、apply

    打开 src/index.ts,声明公开契约。export const name 标识插件;export const inject 列出依赖的服务——MCP Apps 插件声明了 ['tools', 'connection'];export const Config 把校验交给 Harness。apply(ctx, config) 接收 Context 和校验后的配置,而长连接、工具注册这类持久资源都包进 ctx.effect,卸载时 Harness 会统一释放。这几行就是宿主插件与框架之间必须遵守的接口。

    VS Code 中打开的 DeepSeek Harness 插件 src/index.ts:宿主端 import 和高亮的 name、inject、Config 契约导出
    宿主文件先 import @deepseek-ai/cordis,再写三个契约导出,最后是 apply。在 2:34 观看
    DSH 插件代码上方的 PLUGIN CONTRACT 标注卡:name 是插件标识、inject 是声明依赖、apply 负责注册与清理
    四个导出就是全部公开契约——name、inject、Config、apply。在 2:55 观看
  6. 6

    给用户一个能填的 Config Schema

    在 src/config.ts 里,教程插件用一个 Schema union 描述两种传输分支:stdio(command、args、env)和 streamable-http(必填 url、可选 headers),外加共享字段 serverName(必填)、toolCallTimeoutMs(默认 60000)和 failOnStartupError(默认 false)。开发者实现接口和 Schema,用户只需要填值——仓库里的 examples/streamable-http.cordis.yml 就是那份填空实例。

    DSH MCP 插件的 config.ts:Schema union 分 stdio 和 streamable-http 两个分支,url 必填,超时字段带默认值
    一个 Schema union 覆盖两种传输;必填与默认字段直接驱动管理界面。在 3:05 观看
    dsh-mcp-apps 仓库的 streamable-http.cordis.yml 示例:insert 条目把插件指向 MCP 服务器 url 并带 failOnStartupError
    照这样附一个 examples 文件——它就是用户照抄的填空实例。在 3:35 观看
  7. 7

    把插件装进 web profile

    克隆插件仓库,把 DSH_HOME 指向要扩展的 Harness 主目录,再把包加进 web profile。演示执行的是 npx @deepseek-ai/dsh plugin --profile web add <路径>,它把本地文件夹链接进 profile,并输出 added 1 package 确认。装到别的 profile 了?对同一个 profile 再跑一遍 add 即可。

    $git clone https://github.com/sugarforever/dsh-mcp-apps.git
    $cd dsh-mcp-apps
    $export DSH_HOME=/tmp/dsh-video-home
    $npx @deepseek-ai/dsh plugin --profile web add /path/to/dsh-mcp-apps
    终端里执行 git clone https://github.com/sugarforever/dsh-mcp-apps.git,DeepSeek Harness 插件安装演示的第一步
    从参考仓库起步——先克隆,再装依赖。在 5:37 观看
    zsh 会话在 export DSH_HOME 后执行 npx @deepseek-ai/dsh plugin --profile web add 注册 DSH 插件
    add 命令把插件链接进 web profile——此时还不需要别的配置。在 5:40 观看
  8. 8

    在 cordis.patch.yaml 里声明实例

    只装包还不够——还需要一条 patch 条目告诉 Harness 去实例化它。在 profile 的 cordis.patch.yaml(本例是 $DSH_HOME/profiles/web/cordis.patch.yaml)里插入一条:唯一的 id、插件的包名('@sugarforever/dsh-mcp-apps')和它的 config:serverName、transport: streamable-http、MCP 服务器 url 和 failOnStartupError。Harness 启动时读取这份 patch,自动加载插件。

    vi 里编辑 DSH web profile 的 cordis.patch.yaml:插入 @sugarforever/dsh-mcp-apps,含 serverName、streamable-http 传输和 failOnStartupError
    这条 patch 条目才是让 Harness 在启动时实例化插件的关键。在 5:49 观看
  9. 9

    启动 Harness Web,看工具真的跑起来

    用同一个 DSH_HOME 启动 Harness Web,打开 127.0.0.1:3080。让 agent 玩一局 2048:模型看到插件暴露的远程工具并调用它,Host 把结果推送到插件预加载的沙箱界面,一个可以玩的 2048 棋盘直接出现在对话里。安装、配置、验证,全流程走通。

    DeepSeek Harness 网页端(127.0.0.1:3080)处理“玩一局2048”请求:dsh-system-prompt 上下文注入与 MCP app 工具调用
    模型自己看到插件暴露的远程工具并决定调用——无需手动接线。在 6:10 观看
    模型调用远程 MCP 工具后,DeepSeek Harness 对话里渲染出带 New Game 按钮的可玩 2048 棋盘
    插件的 Client 入口把工具结果变成了对话框里的交互界面。在 6:15 观看

注册与验收:从 plugin add 到 HTTP 200

上面九步止于一个能跑的工具。这一章交给博学谷的《插件定制-注册插件》接棒:把做好的插件注册成 DSH 持久化 bundle——写入 bundles 列表、两侧校验,再用 HTTP 验收。步骤 10-12 全部来自这一课。

还缺可注册的插件?找插件的两条路线(内置市场、社区目录站)都写在这篇图文教程里:dsh 怎么找插件(实拍图文)

  1. 10

    用 dsh plugin add 注册插件

    在 Harness 网页端,智能体用官方 dsh plugin add 命令从源码目录安装做好的插件——课程示例是 dsh-what-to-eat。这条命令会 pnpm 装包、把插件追加进 profile 的 bundles 列表,然后自己动手验证两件事:bundles 里有它、包确实落到了 node_modules。都过了,才开始规划 --dump-config 的 compose 校验。

    dsh plugin add ~/.dsh/plugins/dsh-what-to-eat
    DeepSeek Harness 网页端用官方 dsh plugin add 安装 dsh-what-to-eat:Bash 块先核对 bundles 列表与 node_modules 安装到位,再规划 --dump-config compose 校验
    一条命令完成装包、写 bundles 和前两项检查。在 1:44 观看
    DSH 对话里 --dump-config 校验通过:what-to-eat 入口出现在合成配置树末尾,随后检查 web 服务是否已能正常返回 client bundle
    host 侧 compose 校验:新入口恰好出现在配置树收尾的位置。在 2:20 观看
  2. 11

    读落盘报告,然后重启 dsh

    智能体收尾时给出一张步骤-结果表:源码落在 ~/.dsh/plugins/dsh-what-to-eat/(package.json、cordis.patch.yml 和 host/client 入口),dsh plugin add 已写入 bundles 列表与依赖,--dump-config 里能看到 what-to-eat 入口。但有个关键点——新加的 bundle 只在启动时加载,所以必须重启 dsh(Ctrl-C 停掉再启动);临时的会话内插件会消失,由正式 bundle 接管。

    DeepSeek Harness 的正式安装汇总表:插件源码落盘 ~/.dsh/plugins/dsh-what-to-eat、自动写入 bundles 与依赖、--dump-config 的 host 入口三项全部打勾
    注册动过的每一处,一张表说清:磁盘、profile、配置树。在 3:10 观看
    DeepSeek Harness 的交接说明:请用户用 Ctrl-C 重启 dsh 以加载新 bundle,并提示会话会断开、临时插件 wte-1 将被替代
    bundle 只在启动时加载——最后一步得你自己来。在 3:17 观看
  3. 12

    用 HTTP 验收插件

    重启之后,课程让智能体证明插件真的活了。验收表全绿:客户端路由 GET /plugins/dsh-what-to-eat/client.js 从改动前的 404 变成 200,返回内容与 lib/client.js 逐字节一致,合成配置树里也有 what-to-eat 入口。注册、加载、可被访问——整个闭环走完。

    DeepSeek Harness 的插件验收清单全绿:源码落盘、bundles 列表、dsh 进程重启、client.js 从 404 变 200、内容逐字节一致、host compose 入口
    一纸回执:六项检查证明 bundle 已注册、已加载、能正常访问。在 5:09 观看

创建 DeepSeek Harness 插件:常见问题

开发者写第一个插件时真正会问的问题。

一句话说明白:DeepSeek Harness 插件是什么?

插件就是一个接收 Cordis Context 的函数:它声明自己依赖哪些服务,向 Context 注册新能力——模型工具、服务或界面——并依靠框架在插件卸载时统一释放它注册的一切。

一个 DSH 插件最少需要什么?

三样:可加载的模块入口、接收 Context 的 apply(ctx) 函数,以及 apply 里注册的至少一种能力——教程的 hello 插件用 ctx.tools.add 添加了一个工具。只有插件需要配置时才导出 Config Schema,其余都是可选的。

创建 DeepSeek Harness 插件必须用 TypeScript 吗?

教程的参考插件是 TypeScript 写的——export const name = 'mcp-apps'、inject 数组、Schema.object(...) 都是 TypeScript 惯用法,直接克隆那个仓库起步最快。契约本身只是一组模块导出,概念可以迁移,但本页所有示例都是 TypeScript。

Harness 启动时是怎么加载我的插件的?

三步:把 DSH_HOME 指向你的 Harness 主目录;用 npx @deepseek-ai/dsh plugin --profile web add <路径> 把包装进某个 profile;在该 profile 的 cordis.patch.yaml 里写一条 insert 条目,填插件名和配置。Harness 启动时读取 patch 并自动加载插件——Harness 侧不用改任何代码。

DSH 插件可以包装远程 MCP 服务器吗?

可以——案例就是这么做的。宿主入口连接 stdio 或 Streamable HTTP 的 MCP 服务器,然后在 ctx.effect 里把远程工具注册成 Harness 模型工具。Config Schema 暴露两种传输分支,用户只需在 cordis.patch.yaml 里填 serverName、transport 和 url。

插件被移除时,连接由谁清理?

框架来清理——前提是你通过 Context 注册。把持久连接和工具注册包进 ctx.effect,DISPOSE 阶段会在卸载时统一释放。这也是教程从不用模块级全局变量存连接的原因。

相关指南

插件生态的其余部分,从概念到在线目录。

来源与署名

截图均来自下方署名的公开录屏,每张图都深链回各自源视频的对应时间点;上文分步文字是我们的自行整理。

DSH Plugins 是独立的 DeepSeek Harness 插件市场,与 DeepSeek 官方无关,也不代表官方背书。第三方插件未经安全审计,安装前请审查源码。

每周获取最新的 DeepSeek Harness 插件,绝不滥发。