大家好,我是小木头。上一期,我们介绍了 DeepSeek Harness 是什么以及怎么在本地把它运行起来。这一期咱们继续这个话题,介绍一下 DeepSeek Harness 当中我觉得最有意思的概念——插件(Plugin)。

插件是什么呢?DeepSeek Harness 基于 Cordis,插件本质上是一个接收 Context 的函数。它声明自己依赖哪些服务,在 Context 上注册新的能力,并在卸载时让框架统一清理。模型、会话工具和 Web 界面都可以沿着这条扩展边界接进 Harness。

我们先从最小的 Hello World 开始。一个简单的插件只需要三个核心元素:第一,一个可以被加载的模块入口;第二,一个 apply 函数,它接收 Context;第三,在 apply 里注册能力。比如注册一个 hello 工具,输入名字,返回 Hello 加上这个名字。

如果插件需要配置,再导出 Config 类型和对应的 Schema。Harness 会用它校验配置,并在管理界面里展示正确的字段。这里第一次出现两个概念:Host 和 Client。

Host 就是运行 DeepSeek Harness 的后端进程,负责模型、工具网络连接和密钥。Client 则是我们在浏览器看到的 Harness Web UI,负责组件和交互界面。同一个插件可以只扩展 Host,也可以同时提供 Host 和 Client 两个入口。

比如 Hello World 插件只需要在 Host 注册一个 hello 工具,Web UI 使用原有的消息界面显示结果。而本期的 MCP Apps 插件会在 Host 连接到比如 VibeFun 这类 MCP Server,注册远端工具;同时呢,在客户端(也就是 Client)增加一个界面渲染器,把游戏比如 2048 显示在对话中。

两个入口会在各自的运行环境里执行 apply,卸载时再由 Context 统一清理注册项和资源。接下来我们直接看一个已经提交也已经运行验证过的插件项目根目录,包含源码、示例、测试、文档和包配置。

src 下面再把 config、connection、protocol、RPC、tools 和 client 分开。观众不需要逐行读代码,只要先认出入口配置和浏览器端这三块,就能找到插件开发的主干。

打开 src/index.ts,最重要的是几行公开契约(contract):name 是插件的名字;inject 声明依赖 Config,交给 Harness 做配置校验;apply 接收 Context 和配置。需要长期存在的连接、RPC 和工具注册都放进 ctx.effect,这样插件卸载时,Harness 能统一释放它们。

这几行就是 Host 插件必须和框架对接的地方。再打开 config.ts,这里用 Schema 描述 stdio 和 Streamable HTTP 两种配置分支,明确哪些字段必须、哪些字段有默认值。

然后看看 Client 那一端的 client/index.tsx,这个代码文件是浏览器入口。同样声明了 inject 和 apply,但它注册的是工具结果视图。一个包可以构建 Host 与 Client 两个入口,各自在自己的运行环境使用 Context。

最后来看 examples 里的 Cordis 配置。使用者提供插件的包名、serverName、transport 和 URL,就能够创建一个插件实例。开发者负责实现接口和 Schema,使用者只负责填配置。这就是插件的价值:把复杂的实现封装成一个配置清楚、可以重复使用的扩展能力。

这次演示我选择给 DeepSeek Harness 增加 MCP Apps 的支持,原因很简单:它不只是注册一个模型工具,同时还需要扩展 Host 和 Web Client。正好可以展示一个相对完整的 Harness 插件是什么样。

这里简单介绍一下 MCP Apps。传统 MCP 工具通常返回文字、图片资源或结构化的数据,而 MCP Apps 让工具在描述信息中引用一个 UI 资源。Host 可以把它预加载到受限的 iframe 中,这样工具就能够在对话里提供表单、图表、游戏或其他交互的界面。

它的流程并不复杂:Host 从工具描述里的 meta.ui.resourceUri 得知界面的地址,并从 Server 获取 UI 资源。模型调用工具后,结果被推送给已经加载的界面。界面还可以通过安全的 postMessage 通道请求资源、调用工具、发送消息或者更新模型上下文。

回到我们的插件:Host 使用成熟的 MCP SDK 连接 stdio 或者 Streamable HTTP Server,把远端工具注册成 Harness 模型工具,并提供受限的资源与调用桥接。Client(也就是 Web)在工具结果区域创建沙箱 iframe,再用 App Bridge 把界面请求交回给 Host。

连接和密钥留在 Host,允许展示的资源和调用结果才会流向浏览器。最后,我们把插件真正配置到本地 Harness:先通过 DSH Home 来指定运行目录;再把插件安装到 Web Profile。

然后呢,在 Cordis patch 里声明插件的名称。在我们这个例子当中,填入 VibeFun MCP Server 的连接方式和地址。这样 Harness 启动时就会自动的加载这个插件。

接下来,用同一个 DSH Home 启动 Harness Web。在对话中我让它通过 VibeFun 打开 2048 游戏:模型调用远端的 MCP 工具,插件读取对应的 UI 资源,再把一个可以直接交互的 2048 游戏加载到对话里。

到这里,我们就完成了插件从安装、配置到实际运行的完整流程。最后回顾一下吧:写 DeepSeek Harness 插件,可以先从最小结构开始——模块入口、apply 函数、Context 注册以及需要时的 Config Schema。

能力变复杂以后,再增加服务的依赖、生命周期的清理和 Client 入口。MCP Apps 是这期的演示案例,真正希望分享给大家的,是怎么把一种新的能力做成插件再配置到 Harness。

如果这期内容对你有帮助,欢迎点赞投币收藏,来个一键三连吧!也别忘了关注我哟。项目代码和配置示例都放在了视频描述中,那我们就下期再见吧!