Skip to main content
Glama

IRSofka ComfyUI MCP

A stdio Model Context Protocol server for the ComfyUI you run yourself. It is a takeover, not a rewrite: the base is ComfyUI-MCP-Server by Joe Norton (Apache-2.0), vendored verbatim, and this repository adds the station's gate and consent policy on top of its 17 tools. No cloud, no account, no telemetry — and nothing that reaches outside the machine unless you say so.

Its central behaviour is one line: a submit that the machine cannot pay for is refused before it is sent, and the refusal names who is holding the VRAM. The refusal is installed in code, not asked of the caller: guard_submits() replaces ComfyUIClient.run_custom_workflow on the client instance before the base's tools are registered, and every submit tool in the vendored tree calls that attribute (tools/generation.py:105, tools/generation.py:415, tools/workflow.py:75), so nothing reaches POST /prompt without a verdict. A blocked submit returns VRAM_GATE_REFUSED as data — with the state, the reason and the opt-in — rather than raising, and the base cannot silently grow a new submit path that bypasses it. Whether other ComfyUI MCPs do this was not measured, so no claim is made about them — only about this tree. On the workstation this was built on, that is not a hypothetical. A 3D job once asked for 9.73 GiB on a card with 6.38 GiB free, and the only thing standing in the way was a sentence in a documentation file that the engine making the request was not reading.

$ python3 server.py --status | head -20          # read-only, safe
$ python3 server.py --selftest                   # 22 checks, no ComfyUI needed, no request ever sent

The gate

tools/gpu_gate.py in Irsofka AI Workstation owns the decision: which class of work needs how much, measured from the machine's own meter, and which processes are holding it. This server calls it and adds no policy of its own. Three states, priced differently:

state

meaning

what the server does

ALLOW

free ≥ needed

submits, and reports the rule, the free figure and the headroom

DENY

free < needed

refuses, names the top holders and the shortfall in MiB, sends nothing

UNKNOWN

the meter could not be read

refuses. Absence of a measurement is not evidence of free VRAM

If the workstation is not on this machine, there is no meter, so vram.decide() answers UNKNOWN: a missing guard is not evidence that the work is safe, and the server refuses rather than issuing a permit it cannot sign. IRSOFKA_COMFY_GATE=off is the explicit override for a machine with no workstation and an operator who accepts OOM risk; it appears in every answer it touches as state: "BYPASSED".

Related MCP server: Universe Imagine MCP

Tools

The base contributes 17 tools and the station layer adds two. Names come from the running server (--surface-policy), not from a document:

group

tools

generation and workflow (base)

generate_image, generate_song, run_workflow, regenerate, view_image

jobs and queue (base)

get_job, cancel_job, get_queue_status

models, assets, workflows (base)

list_models, list_assets, list_workflows, get_asset_metadata, get_defaults, set_defaults, get_publish_info, set_comfyui_output_root, publish_asset

station layer (ours)

irsofka_gpu_gate, irsofka_surface_policy

view_image is the one tool that can make the machine fetch a URL someone supplied, so it is not registered until IRSOFKA_COMFY_ALLOW_NETWORK consents; irsofka_surface_policy says whether it is live. publish_asset despite its name writes to a session-scoped local registry — checked, not assumed — so it is not gated as network.

Measured on this machine, 2026-10-15 — the layer before the takeover

These numbers were produced by the seven-tool clean-room server that this repository contained until 2026-10-16, and the tool names below (comfy_status, comfy_fetch, comfy_free) belong to that build. They are kept because they are measurements that happened, not documentation to imitate; the VRAM-gate behaviour they describe is what the station layer still does, now over the base's tools. Nothing here is quoted from documentation. RTX 3060 12 GB, ComfyUI Desktop standalone:

fact

value

comfyui_version from /system_stats

0.39.2 (a tool on this machine reported 0.40.0 the same day — the endpoint is the one that is true)

VRAM free, GET /system_stats

7149 MiB of 11889 MiB

VRAM free, whole-card meter

7498 MiB of 12288 MiB

top holders

UnrealEditor 2118 MiB, ComfyUI's own python 1624 MiB

GET /object_info/<one node>

891 bytes

GET /object_info (whole catalog)

1 951 939 bytes across 976 node classes — never returned to a caller; action=names gives the list only

POST /prompt with an unknown class

400 {"type":"missing_node_type"} and nothing queued — verified by re-reading /queue

GET /object_info/<unknown node>

200 with {}. The status code is not the verdict; an empty body is

gate decision on a 3D submit, live

DENY, rule 3d-trellis, need 9966 MiB, free 7498 MiB, shortfall 2468 MiB, holders named

a submit the gate allowed, live

prompt_id 166cbff0…, rule image-diffusion, need 5919 MiB against 7241 MiB free, finished in 21.0 s

its output, fetched by comfy_fetch

1 290 126 bytes, PNG 832 x 1216 8-bit RGB, sha256 2ea33e87…e4e5

The submit above needed no hand-written node wiring: GET /history hands back the graph that produced each past run inside prompt[2], which is a valid API-format graph on the machine that ran it. Read a finished job, change the seed and the prompt, submit that.

Two numbers for "free VRAM" are on purpose. ComfyUI reports what it can allocate inside its own torch pool; the whole-card meter reports what the card has left, including what other processes hold. The gate decides on the whole-card number, because an OOM does not respect the boundary between "my process" and "someone else's".

Basis Open-Source dan Provenansi

Repositori ini telah mengambil alih basis terbuka joenorton/comfyui-mcp-server (Apache-2.0, tag v1.1.1, commit e0101b2312f30501664dabe4a74c1283c4268eb8, 49 berkas, 6.846 LOC Python) yang disimpan verbatim di upstream/. Klaim clean-room / independen sebelumnya ("nothing was copied, translated or adapted") telah ditarik dan digantikan oleh dokumen UPSTREAM.

Lisensi Apache-2.0 upstream mengizinkan pembuatan karya turunan berlisensi Business Source License 1.1 (dengan Change License MIT) dengan tetap menyertakan hak cipta dan NOTICE asli di upstream/NOTICE. Lapisan stasiun di server.py menambahkan penegakan gerbang VRAM (vram.py) dan pembatasan izin akses jaringan eksternal (IRSOFKA_COMFY_ALLOW_NETWORK).

License

Business Source License 1.1, LICENSE in this directory. Licensor PT IRSofka Data Teknologi, Additional Use Grant None, Change Date four years after each version is first made publicly available (each version carries its own date), Change License Apache-2.0.

In practice:

  • you may read it, run it, copy it, modify it, build on it, and use it for anything that is not production;

  • production use — running it as part of something you operate for users or for revenue — needs a paid commercial licence from the Licensor;

  • every version of this code becomes Apache-2.0 four years after it is published, so nothing here is locked forever; the newer versions simply cost a licence until they age;

  • the name and logo are not licensed. Fork the code freely, do not call your fork IRSofka.

Licensor is PT IRSofka Data Teknologi, registered in Indonesia under NIB 1258 0003 4132 6 (OSS) and DUNS 5645 3618 4. Commercial licence and showcase enquiries: admin@irsofka.co.id — https://irsofka.co.id

Registering it

Run it from a checkout: python3 server.py, with mcp and requests installed. pip install . installs the station layer only — the base is loaded from upstream/ beside server.py, and its internal imports use bare top-level names (tools, models, managers) that must not be installed into site-packages. There is therefore deliberately no console script: an entry point that cannot work is worse than none, which is the same lesson the packaging audit produced today. The AST scan in the selftest confirms the top-level imports of our two files are only the standard library plus mcp — the third-party imports live in the vendored base, which is exactly why the dependency list above is not empty. The station's gate is imported lazily and only when a workstation is present, so it is a bridge, not a dependency.

pyproject.toml is committed for packaging, but it has not been built here: this machine's system Python has no setuptools and python3 -m venv cannot seed one offline, so python -m build was never run. Treat the wheel as unverified until someone builds it. Registration, not installation, is the supported path.

Registration is a statement about the machine, so it is not in this repository. Pick the one for your client; both CLIs read their own file.

{
  "mcpServers": {
    "irsofka-comfyui": {
      "command": "python3",
      "args": ["/ABSOLUTE/PATH/TO/irsofka-comfyui-mcp/server.py"],
      "env": { "COMFYUI_URL": "http://127.0.0.1:8188" }
    }
  }
}

variable

default

effect

COMFYUI_URL

http://127.0.0.1:8188

which ComfyUI to talk to

AI_STATION_HOME

$HOME/.ai-station

where the station gate lives. If set and it holds no gate, the answer is no gate — this server does not quietly look somewhere else

IRSOFKA_COMFY_GATE

unset

off disables the gate by operator order; every affected answer then says BYPASSED

IRSOFKA_COMFY_ALLOW_NETWORK

unset (refuse)

registers view_image, the one tool that can fetch a caller-supplied URL

COMFYUI_OUTPUT_ROOT

auto-detected

where ComfyUI writes its images, for view_image

COMFY_MCP_ASSET_TTL_HOURS

24

how long a fetched asset stays in the local registry

What this server will not do

  • It will not run a paid partner node. There is no API key surface here at all.

  • It will not hand over the whole node catalog, because doing so once would cost more context than most agents have.

  • It will not fabricate a measurement. If nvidia-smi cannot be read, the answer is UNKNOWN and the submit is refused, not approved on hope.

  • It cannot unload VRAM belonging to another process. Unreal Editor holding 2 GiB is Unreal Editor's business; comfy_free does not reach it and no MCP call should pretend otherwise.

Related MCP Connectors

Related MCP Servers