feat: COMFY_BRIDGE_MCP_HOST to bind 0.0.0.0 for Docker/remote access

Adds a host bind env var (mirrors the port var) plus a README section on
running ComfyUI in Docker: bind 0.0.0.0, publish the port, point the agent at
the server IP, and handle images via a shared folder with matching paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ethanfel
2026-06-28 14:51:25 +02:00
co-authored by Claude Opus 4.8
parent e7c06c1905
commit de6c54cd8a
3 changed files with 72 additions and 3 deletions
+37
View File
@@ -132,6 +132,42 @@ claude mcp add --transport http comfy http://127.0.0.1:9188/mcp
Then in Claude Code, `/mcp` should list the five tools.
## Running ComfyUI in Docker / on another host
The bridge binds `127.0.0.1` by default, reachable only from the same host (inside
the container). To reach it from an agent on another machine:
1. **Bind all interfaces** — set `COMFY_BRIDGE_MCP_HOST=0.0.0.0` in the container.
2. **Publish the port** — `-p 9188:9188` (or `ports: ["9188:9188"]` in compose).
3. **Point the agent at the server IP**, not 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
```
For the Codex *plugin*, edit `.codex-plugin/mcp.json`'s `url` to the server IP
(or just use `codex mcp add` above).
`COMFY_BASE_URL` stays `http://127.0.0.1:8188` — the bridge runs *inside* the
ComfyUI container and reaches ComfyUI over the container's own localhost.
**Images across hosts.** Images cross **by file path**, so the path `comfy_pull`
returns must point at the same file the agent can open. With a **shared folder**
between the container and your machine:
- Put the temp dir in the share, e.g. `COMFY_BRIDGE_TMP=/shared/comfy_tmp` (in the container).
- Mount that share at the **same absolute path** on your machine, so
`/shared/comfy_tmp/img_*.png` resolves on both sides — then `comfy_pull` /
`comfy_push` image paths work unchanged.
- If the mount paths **differ** between container and host, the raw path won't
resolve agent-side. Either make the paths identical, or switch to base64-inline
images (not yet implemented — open an issue if you need it).
Text needs none of this — it's inline.
> **Security:** binding `0.0.0.0` exposes the bridge — including `comfy_run_workflow`
> (runs saved workflows) and file-path reads — to your LAN with no authentication.
> Keep it on a trusted network or firewall the port.
## MCP tools
| Tool | Direction | Purpose |
@@ -165,6 +201,7 @@ prompt and an `Agent Emit(channel=render)` on the output, then from the agent:
| Variable | Default | Effect |
| --- | --- | --- |
| `COMFY_BRIDGE_MCP_HOST` | `127.0.0.1` | Interface the MCP bridge binds. Set `0.0.0.0` to reach it from another host (e.g. ComfyUI in Docker). See [Running ComfyUI in Docker](#running-comfyui-in-docker--on-another-host). |
| `COMFY_BRIDGE_MCP_PORT` | `9188` | Port the MCP bridge binds (use `0` for an ephemeral port, e.g. in tests). |
| `COMFY_BRIDGE_TMP` | `.comfy_bridge_tmp` | Temp dir where `Agent Emit` writes image PNGs. |
| `COMFY_BRIDGE_TMP_TTL` | `3600` | Age (seconds) after which `save_tensor_png` reaps old `img_*.png` temp files. |
+16 -3
View File
@@ -28,15 +28,28 @@ def registered_tool_names(mcp: FastMCP) -> list:
return [t.name for t in getattr(mcp, "list_tools", lambda: [])()]
def start_in_background(host: str = "127.0.0.1", port: int = None,
def _resolve_bind(host, port):
"""Resolve (host, port) from explicit args, else env, else defaults.
Set COMFY_BRIDGE_MCP_HOST=0.0.0.0 to reach the bridge from outside the host
(e.g. ComfyUI in Docker; also publish the port, and point the agent at the
server's LAN IP instead of 127.0.0.1).
"""
if host is None:
host = os.environ.get("COMFY_BRIDGE_MCP_HOST", "127.0.0.1")
if port is None:
port = int(os.environ.get("COMFY_BRIDGE_MCP_PORT", "9188"))
return host, port
def start_in_background(host: str = None, port: int = None,
_test_no_serve: bool = False) -> None:
global _started
with _lock:
if _started:
return
_started = True
port = port if port is not None else int(
os.environ.get("COMFY_BRIDGE_MCP_PORT", "9188"))
host, port = _resolve_bind(host, port)
mcp = build_server(host=host, port=port)
if _test_no_serve:
return
+19
View File
@@ -0,0 +1,19 @@
from src.bridge import mcp_server
def test_resolve_bind_defaults(monkeypatch):
monkeypatch.delenv("COMFY_BRIDGE_MCP_HOST", raising=False)
monkeypatch.delenv("COMFY_BRIDGE_MCP_PORT", raising=False)
assert mcp_server._resolve_bind(None, None) == ("127.0.0.1", 9188)
def test_resolve_bind_reads_env(monkeypatch):
monkeypatch.setenv("COMFY_BRIDGE_MCP_HOST", "0.0.0.0")
monkeypatch.setenv("COMFY_BRIDGE_MCP_PORT", "9999")
assert mcp_server._resolve_bind(None, None) == ("0.0.0.0", 9999)
def test_resolve_bind_explicit_args_override_env(monkeypatch):
monkeypatch.setenv("COMFY_BRIDGE_MCP_HOST", "0.0.0.0")
monkeypatch.setenv("COMFY_BRIDGE_MCP_PORT", "9999")
assert mcp_server._resolve_bind("127.0.0.1", 1234) == ("127.0.0.1", 1234)