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:
co-authored by
Claude Opus 4.8
parent
e7c06c1905
commit
de6c54cd8a
@@ -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. |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user