这正是移动端 App 建在上面的那一面。只要你能打开 WebSocket 并发送 JSON,就能构建主机。
工作原理
1
桌面已经在听
智能体面板打开时,编排器会在局域网上跑一个令牌把门的配对监听器(见
端点)。每个打开的面板标签页都是一个带稳定
tab_id 和实时智能体会话的
桌面标签页。2
你的主机带着配对令牌连接
用查询字符串里的令牌打开到配对 URL 的 WebSocket。没有有效令牌,连接会被拒绝 ——
配对就是整条安全边界。
3
列出并附着到一个标签页
发送
list_tabs 发现打开的桌面标签页,再发 attach_tab 镜像其中一个。你的主机现在
接收那个标签页的活动(流式),并且可以驱动它。4
驱动共享会话
发送
user_message 帧。附着期间,服务器把它们路由到被镜像的标签页 —— 于是你的
消息进入桌面智能体所在的同一段对话。这才是「一个智能体、共享上下文」,而不是第二个
会话。端点
配对监听器从桥接端口派生(COMFYUI_MCP_BRIDGE_PORT,默认 9180):
配对 URL:
- 令牌要么由用户通过
COMFYUI_MCP_PAIR_TOKEN钉死(始终开启配对),要么按会话 铸造并通过面板的二维码 / 配对流程发出。你的主机拿到它的方式和移动端 App 一样: 用户配对一次。 - 默认绑在局域网上,但用户要求时也内置了公网暴露:面板的配对对话框提供
Internet 模式,打开一条加密的 cloudflared 快速隧道;企业也可以把它走自建中继
(
COMFYUI_MCP_TUNNEL_BACKEND=relay)。无论哪种,令牌都把门。
消息形状
所有帧都是带type 的 JSON 对象。请求 / 响应帧携带一个你自己选的 cid(关联 id),
在对应回复上原样回显。
入站 —— 主机 → 编排器
附着期间你发送的任何其他面板事件,同样会路由到被镜像的标签页。
出站 —— 编排器 → 主机
再加上被镜像标签页的实时智能体活动(流式回复、状态、卡片),由你的主机来渲染。
安全不变量 —— 主机必须守住这些
这些保证让配对是安全的。构建一个尊重它们的主机就是整份合约;试图绕过它们的主机,正是 监听器设计来拒绝的东西。守住这些不是对你主机的约束 —— 它就是功能本身。它们阻止客户端劫持它从未配对过的
会话。
- 令牌门。 监听器拒绝任何没有有效配对令牌的连接(
verifyClient)。永远不要做 自动下发或内嵌令牌的流程 —— 用户配对,一次,故意的。 - 权威的
attach_tab盖戳。 决定你的帧打向哪个标签页的是服务器,不是客户端。 不要依赖客户端提供的tab_id做路由;先附着,再发送。 - 只允许非无头目标。 你可以附着到真实桌面标签页,永远不能附着到另一个无头客户端 (你不能镜像另一部手机 / 主机)。
- 一次一个标签页。 附着到 B 会丢掉你对 A 的订阅。按每个连接一个活动镜像来建模。
- 钉死的套接字种类。 连接的种类(无头 vs 桌面)在第一次
hello时固定;不要试图 翻转它来逃过接管护栏。
最小参考客户端
教 LLM 构建你的适配器
把下面的提示粘进 Claude、ChatGPT 或你的编码智能体,让它为你的平台搭一份主机适配器 脚手架。它带着完整的协议合约,模型不用猜。Copy this into your LLM
登记你的集成
做出了什么?登记它,这样它可以被列出,我们也能在协议变更发货前通知你:登记第三方主机
在 GitHub 上打开登记模板 —— 名称、平台、仓库,以及你对照构建的协议版本。
稳定性: 上面的帧是移动端 App 发货时用的,但这还不是一份冻结、带版本的合约 ——
以源码(
src/services/ui-bridge.ts)
为准,并登记你的主机,形状变动时你会收到通知。