内容
# ComfyUI-节点-代理
图形中的 **代理发出** / **代理接收** 节点在命名通道上,以及进程内的 **MCP 服务器**,允许外部运行的编码代理(Claude Code / Codex)可以在管道中间与ComfyUI工作流交换文本和图像,并触发运行。
## 工作原理
线程安全的单例 `通道存储` 持有每个命名通道的两个 **FIFO 队列**:一个 **收件箱**(图形 -> 代理)和一个 **发件箱**(代理 -> 图形)。每个发出/推送都会被保存并按顺序递送 — 不会覆盖或丢弃。ComfyUI节点直接访问存储(在同一进程中)。`快速MCP` 流式HTTP服务器在副端口的守护线程中运行;其工具访问同一个单例。文本/种子交叉内联;图像通过临时目录通过文件路径交叉。
- **收件箱** = 图形 -> 代理:`代理发出` 入队,`comfy_pull` 出队(按顺序)。
- **发件箱** = 代理 -> 图形:`comfy_push` 入队,`代理接收` 出队(按顺序)。
- 每个消息仅传递一次;当队列排空时,读取返回为空。
## 安装
将此仓库克隆(或符号链接)到您的ComfyUI `custom_nodes` 目录中,并安装依赖项,然后重启ComfyUI:
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/ethanfel/ComfyUI-Agent-Bridge
pip install -r ComfyUI-Agent-Bridge/requirements.txt # mcp>=1.2.0 (validated on 1.28.1)
```
(`custom_nodes` 子目录名称是任意的 — ComfyUI无论如何都加载该包。)
启动时,ComfyUI加载包,桥接器记录其URL:
```
[comfyui-nodes-agents] MCP bridge on http://127.0.0.1:9188/mcp (claude mcp add --transport http comfy http://127.0.0.1:9188/mcp)
```
桥接器从 `__init__.py` 自动启动,并被包装在try/except中,因此桥接器故障不会阻止ComfyUI加载节点。
## 两个节点(类别 `agents/bridge`)
**代理发出(-> 代理)** — 从图形发送到代理。
- 输入:`通道`(字符串,默认 `main`);可选 `文本`(多行字符串),`图像`(图像),`种子`(整数,套接字输入 — 例如连接KSampler种子)。
- 将文本/图像/种子加入通道收件箱(图像保存在临时目录中的PNG文件中,存储路径)。直接传递 `(文本, 图像, 种子)` 作为输出,以便可以内联连接。多个发出队列(FIFO)。
**代理接收(<- 代理)** — 从代理接收到图形。
- 输入:`通道`(字符串,默认 `main`);`等待秒数`(浮点数,默认 `30.0`,最大 `86400`);`保留最后`(布尔值,默认 `true`);`超时后停止`(布尔值,默认 `true`)。
- 输出 `(文本, 图像, 种子)` — `种子`(整数)是代理传递给 `comfy_push(种子=...)` 的值,或如果没有则为 `0`。连接它到KSampler等。
- 按顺序出队通道中最老的未读 `comfy_push`(FIFO),最多阻塞 `等待秒数` 以等待一个到达。每个推送仅传递一次,按顺序传递,因此在自动队列中,连续运行按消息顺序排空队列(推送 A、B、C -> 接收 A,然后 B,然后 C)。无丢弃,无重放。
- **`保留最后`** — 在超时(无新消息)时,再次输出最后一条消息,而不是清空。对于自动队列,此功能非常有用,以便在评估之间显示保持稳定。关闭时 -> 返回 `""` + 64x64 黑色占位图像超时。
- **`超时后停止`** — 在超时时,向ComfyUI前端发送信号以关闭 **自动队列**,因此当消息流静默时循环停止(由捆绑的 `web/agent_bridge.js` 处理;尽力而为跨ComfyUI前端版本)。
> 每个通道一个消费者:每个排队的消息仅由一个读取器接收,因此两个通道上的 `代理接收` 节点将队列分开。除非您故意需要这种分发,否则请使用不同的通道名称。
> `等待秒数` 阻塞ComfyUI执行工作线程整个持续时间。非交互式使用时,请保持其适中(秒级,而不是小时级),以免占用工作线程等待代理。
## 连接代理
桥接器通过 `http://127.0.0.1:9188/mcp` 上的 **MCP流式HTTP** 进行通信。
### Codex(插件 — 推荐)
此仓库作为 **Codex插件** 交付。将Codex指向仓库作为市场,然后安装插件;Codex自动注册 `comfy` MCP服务器(HTTP,无身份验证)和 `comfyui-bridge` 技能。在Codex CLI 0.142.3上验证:
```bash
# from GitHub:
codex plugin marketplace add ethanfel/ComfyUI-Agent-Bridge
# ...or from a local clone:
codex plugin marketplace add /path/to/ComfyUI-Agent-Bridge
codex plugin add comfyui-agents@comfyui-agents
```
确认注册:
```bash
codex mcp get comfy
# transport: streamable_http
# url: http://127.0.0.1:9188/mcp
```
插件仅*声明* HTTP服务器URL,因此ComfyUI(和桥接器)必须运行以便工具连接。
### Codex(单个MCP服务器,无插件)
如果您不想安装插件,请添加单个MCP服务器:
```bash
codex mcp add comfy --url http://127.0.0.1:9188/mcp
```
这会写入一个流式HTTP条目,等效于:
```toml
[mcp_servers.comfy]
url = "http://127.0.0.1:9188/mcp"
```
**Codex(仅stdio)**:如果您的Codex版本*仅*支持stdio MCP,请指向 `scripts/codex_stdio_shim.py` — 一个真正的stdio <-> HTTP MCP代理,它连接到同一个桥接器URL并转发工具调用。等效于 `codex mcp add comfy --env COMFY_BRIDGE_URL=http://127.0.0.1:9188/mcp -- python /abs/path/scripts/codex_stdio_shim.py`:
```toml
[mcp_servers.comfy]
command = "python"
args = ["/abs/path/ComfyUI-Nodes-Agents/scripts/codex_stdio_shim.py"]
env = { COMFY_BRIDGE_URL = "http://127.0.0.1:9188/mcp" }
```
代理需要ComfyUI(和桥接器)运行;如果它无法访问HTTP桥接器,它会退出并显示清晰的stderr消息,以便Codex显示错误。请使用绝对路径到shim。
### Claude Code(HTTP)
```bash
claude mcp add --transport http comfy http://127.0.0.1:9188/mcp
```
然后在Claude Code中,`/mcp` 应该列出五个工具。
## 在Docker中运行ComfyUI / 在另一台主机上
桥接器默认绑定 `127.0.0.1`,仅可从同一主机(容器内)访问。要从另一台机器上的代理访问它:
1. **绑定所有接口** — 在容器中设置 `COMFY_BRIDGE_MCP_HOST=0.0.0.0`。
2. **发布端口** — `-p 9188:9188`(或docker-compose中的 `ports: ["9188:9188"]`)。
3. **让代理指向服务器IP**,而不是localhost:
```bash
claude mcp add --transport http comfy http://192.168.1.12:9188/mcp
codex mcp add comfy --url http://192.168.1.12:9188/mcp
```
对于Codex *插件*,请编辑 `.codex-plugin/mcp.json` 的 `url` 为服务器IP(或仅使用上面的 `codex mcp add`)。
`COMFY_BASE_URL` 保持为 `http://127.0.0.1:8188` — 桥接器在ComfyUI容器内运行,并通过容器自己的localhost访问ComfyUI。
**跨主机图像**。图像通过 **文件路径** 交叉。默认情况下,桥接器将它们写入ComfyUI的 **输出目录** (`output/agent_bridge/`),在典型设置中,这是一个共享的挂载,在 **相同路径** 上对ComfyUI和代理都可见 — 因此路径在双方解析,无需配置。
如果您的容器将该文件夹挂载到与代理看到的 **不同内部路径**,请设置两者:
- `COMFY_BRIDGE_TMP` — 桥接器写入的目录,容器端(例如 `/ComfyUI/output/agent_bridge`)
- `COMFY_BRIDGE_TMP_PUBLIC` — 代理看到的路径前缀(例如 `/media/unraid/comfyui/output/agent_bridge`)
然后 `comfy_pull` 广告代理可见的路径,`comfy_push` 将其转换回容器路径,然后 `代理接收` 加载它。文本不需要这些 — 它是内联的。
> **安全:** 绑定 `0.0.0.0` 将桥接器暴露给您的LAN,包括 `comfy_run_workflow`(运行保存的工作流)和文件路径读取 — 无身份验证。请将其放在受信任的网络中或防火墙端口。
## MCP工具
| 工具 | 方向 | 目的 |
| --- | --- | --- |
| `comfy_pull(channel="main")` | 图形 -> 代理 | 出队最老的发出消息(FIFO;返回 `{turn, text, image_path, seed}`,排空时为空)。 |
| `comfy_push(channel="main", text=None, image_path=None, seed=None)` | 代理 -> 图形 | 向通道的 `代理接收` 节点发送文本/图像/种子。 |
| `comfy_list_channels()` | — | 列出活动通道及其转数。 |
| `comfy_run_workflow(name, inputs=None, wait=True)` | — | 从 `workflows/` 加载保存的工作流,可选地注入输入,通过ComfyUI API排队,可选地轮询结果。 |
| `comfy_get_result(prompt_id)` | — | 获取队列提示ID的生成图像/输出。 |
`comfy_run_workflow` 读取 `workflows/<name>.json`(API格式导出)。`inputs` 重写节点字段键为 `"<node_id>.<field>"`,例如 `{"6.text": "a red fox"}`。使用 `wait=True` 时,它轮询ComfyUI `/history` 端点(有界 ~60s)直到输出出现。
## 核心循环
1. 图形:`加载图像 -> 代理发出(通道=in)`。排队提示。
2. 代理:`comfy_pull("in")` -> 获取图像路径;检查/编辑它。
3. 代理:`comfy_push("out", text="...", image_path="<edited>.png")`。
4. 图形:`代理接收(通道=out, wait_seconds=30)-> 预览/保存`。排队;文本 + 图像到达。
对于完整的渲染往返:保存API格式的工作流到 `workflows/txt2img.json`,其中包含一个 `代理接收(通道=提示)` 馈送提示和一个 `代理发出(通道=渲染)` 在输出上,然后从代理:`comfy_push("prompt", "a red fox")` -> `comfy_run_workflow("txt2img", wait=true)` -> `comfy_pull("render")`。
## 环境变量
| 变量 | 默认值 | 效果 |
| --- | --- | --- |
| `COMFY_BRIDGE_MCP_HOST` | `127.0.0.1` | MCP桥接器绑定的接口。设置为 `0.0.0.0` 以从另一个主机访问(例如Docker中的ComfyUI)。请参阅 [在Docker中运行ComfyUI](#在docker中运行comfyui--在另一个主机上)。 |
| `COMFY_BRIDGE_MCP_PORT` | `9188` | MCP桥接器绑定的端口(使用 `0` 获取临时端口,例如在测试中)。 |
| `COMFY_BRIDGE_TMP` | ComfyUI `output/agent_bridge` | `代理发出` 编写图像PNG的目录。默认为ComfyUI的输出目录(典型设置中共享的相同路径挂载);如果不在ComfyUI外部,则回退到 `.comfy_bridge_tmp`。 |
| `COMFY_BRIDGE_TMP_PUBLIC` | _(未设置)_ | 如果容器将临时目录挂载到与代理看到的路径不同,则代理应看到的前缀。`comfy_pull` 广告它;`comfy_push` 翻译回来。请参阅 [Docker](#在docker中运行comfyui--在另一个主机上)。 |
| `COMFY_BRIDGE_TMP_TTL` | `3600` | `save_tensor_png` 删除旧 `img_*.png` 临时文件的年龄(秒)。 |
| `COMFY_BRIDGE_WORKFLOWS` | `workflows` | `comfy_run_workflow` 从中加载 `<name>.json` 的目录。 |
| `COMFY_BASE_URL` | `http://127.0.0.1:8188` | `comfy_run_workflow` / `comfy_get_result` 使用的ComfyUI HTTP API基准URL。 |
## 开发
```bash
COMFY_BRIDGE_MCP_PORT=0 python -m pytest tests/ -v
```
`COMFY_BRIDGE_MCP_PORT=0` 使入口点导入(自动启动桥接器)绑定临时端口而不是固定的 `9188`。测试套件包括一个真正的MCP往返测试(`tests/bridge/test_mcp_roundtrip.py`),它启动流式HTTP服务器在一个空闲端口上,并使用真正的MCP客户端驱动它。