Skip to main content
Glama

comfy-draftsman

The MCP server that drafts ComfyUI workflows a human can actually read.

A local-first Model Context Protocol server that lets coding agents (Claude Code, Claude Desktop, Cursor, ...) build, repair, port, validate, and run ComfyUI workflows against your own ComfyUI instance — and deliver them as clean, organized, fully-labeled workflows: computed layout, colored stage groups, titled nodes, green-highlighted "knobs you may touch", and markdown guidance notes explaining which tuned settings to leave alone and why.

A draftsman-organized workflow in the ComfyUI editor

Every agent tool for ComfyUI can emit raw API-format JSON — a working but unreadable pile of unpositioned nodes. Draftsman's reason to exist is the finished drawing:

Model-aware guidance notes and tuned settings

The note above was generated automatically: draftsman detected the checkpoint was a DMD-distilled SDXL merge and tuned CFG to 1.0, 4 steps, lcm/sgm_uniform — then wrote down why, so the person opening the workflow doesn't "fix" it back to CFG 7.

What it does

  • Draft — seed from ComfyUI's bundled templates (always current with the latest models) or build from scratch with semantic graph operations (add_node, connect, set_widget — validated against the live instance's schemas; set_widget by index reaches a pack's JS-only widgets).

  • Organize - the differentiator: pipeline-stage auto-layout, colored groups, human titles (Positive Prompt, Base Pass), green highlights on user-editable knobs, and generated notes in two registers: "type your prompt here" vs "turbo model - CFG stays at 1.0". Everything you'd tweak (source images, canvas size, models/LoRAs, prompts) reads left-to-right first, and preview/Show Text nodes sit right beside the node they display - no tracing wires across the canvas to figure out which sampler made which image.

  • Diagnose & modernize — hand it an old broken workflow: it reports every incompatibility against your live instance (renamed nodes, changed widget layouts, missing model files with closest-installed suggestions) and resolves missing custom nodes to installable packs via the official Comfy Registry.

  • Port — retarget across model families (sdxl → flux, ...): swaps loader topology (checkpoint ⇄ separate UNET/CLIP/VAE loaders) and rewires consumers, retunes CFG/steps/samplers and technique nodes (FaceDetailer settings are family-specific — there is no universal detailer config), swaps latent node classes, picks installed model files, and flags everything needing human judgment.

  • Validate & prove — structural + live validation, then an actual render with an inline preview, before the workflow is ever delivered.

  • V3 dynamic combos — modern nodes whose choices reveal conditional sub-widgets (COMFY_DYNAMICCOMBO_V3 — e.g. SaveImageAdvanced's format, Depth-Anything-3's mode/output) are first-class: their values are set, round-tripped, validated, and serialized to the API's dotted-key form (output.normalization), so a graph containing them runs end-to-end through the draftsman alone. The rest of the V3 io system is handled alongside them: autogrow inputs (COMFY_AUTOGROW_V3 — a growing socket list like BatchImagesNode's images) expand to their real, connectable slot names with the dotted API keys the backend actually matches on, match types wire freely the way ComfyUI's own executor treats them, and inputs ComfyUI flags as widget-rendered (socketless/widgetType) are set as widgets rather than mistaken for required sockets.

  • Run & watch — run any workflow (one you just built, or one already saved in your ComfyUI) and see the output right in the conversation: previews come back as downscaled thumbnails to keep the chat light, with view_output fetching full resolution on demand. Long renders can queue in the background (wait=False) with live step progress via get_run_status. If the instance already has a long queue, draftsman says so instead of silently waiting — and can queue your test run to go next (front=True) without touching the jobs already in line. Upload source images for img2img/inpaint, and manage the queue when something needs interrupting. (wait=False + get_run_status polling for long/paid renders — see run_workflow's docstring)

  • Compare - run_workflow(sweep=...) renders variants x seeds into one contact sheet, with 1:1 crop sheets for detail, per-run sampling time that ignores model loads (detailer passes included) plus the slowest nodes per run, freeze=<node id> to hold an upstream stage (a random or LLM prompt) fixed across every cell, and a banding score to rank runs on stripe artifacts.

  • Learn - a two-layer knowledge system: a curated per-family floor (SD1.5/SDXL/SD3.5/FLUX/FLUX 3 Klein/Krea-2/Chroma/Qwen-Image/MOSS-Image/FIBO 2.0/Anima/Wan/LTX/MiniMax H3, variant-aware for turbo/lightning/DMD/distills) plus a persistent learned overlay: when the agent researches better settings for a new model, record_learning saves them so every future session starts smarter. A learned entry can carry its own detect block, so a brand-new model researched once becomes self-detecting next session instead of being mistaken for a lookalike family.

  • Stay current — ground truth is your running ComfyUI (/object_info, live templates, live model lists), never a bundled snapshot.

Related MCP server: ComfyPilot

Requirements

  • Python ≥ 3.11 with uv (or pip)

  • A running ComfyUI instance (default http://127.0.0.1:8188)

Install

Claude Code:

claude mcp add comfy-draftsman \
  -e COMFYUI_URL=http://127.0.0.1:8188 \
  -e COMFYUI_MOUNT_DIR=/path/your/agent/can/reach \
  -- uvx --from git+https://github.com/EnragedAntelope/comfy-draftsman comfy-draftsman

Claude Desktop / other MCP clients (mcpServers config):

{
  "mcpServers": {
    "comfy-draftsman": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/EnragedAntelope/comfy-draftsman", "comfy-draftsman"],
      "env": {
        "COMFYUI_URL": "http://127.0.0.1:8188",
        "COMFYUI_MOUNT_DIR": "/path/your/agent/can/reach"
      }
    }
  }
}

Prefer the published package? uv tool install comfy-draftsman (or pip install comfy-draftsman) puts the server on PATH, and both configs above shorten to plain uvx comfy-draftsman / "args": ["comfy-draftsman"]. The git+https form above tracks unreleased commits.

COMFYUI_MOUNT_DIR is optional but recommended: it's a folder your agent (or a sandboxed client like Claude Desktop / Cowork) can actually read, and save_output / run_workflow relocate finished renders there — otherwise renders stay inside ComfyUI's output/ tree and every save needs an explicit dest_dir. On Windows use a native path, e.g. C:\\Users\\you\\comfy-renders. See Configuration for all environment variables.

Then just ask your agent things like:

"Build me a Krea workflow with LoRA support and a face detailer, labeled so my friend can use it."

"Here's an old SD1.5 workflow JSON that doesn't load anymore — fix it and port it to SDXL."

"Take this workflow I downloaded and make it neat and organized."

It checks your hardware before you spend forty minutes on a download: ask for guidance on a model family your GPU can't comfortably hold and the answer comes back with a fit verdict — what's needed, what you have, and what to do about it. When it fits, it says nothing.

Updating

uvx caches, and it will not tell you. uv keys a git+https:// dependency on the resolved commit hash, and uvx reuses a cached environment rather than re-resolving — so a config pointing at the git URL keeps running whatever commit it first installed, indefinitely, with no warning. A plain uvx comfy-draftsman behaves the same way once published.

Pick whichever shape you prefer:

Config

Updates

Trade-off

uvx comfy-draftsman@latest

Every time the server starts

Needs PyPI reachable at start-up — uv errors rather than falling back to its cache on a network failure

uv tool install comfy-draftsman

When you run uv tool upgrade comfy-draftsman

Starts offline, but you have to remember

uvx --from git+https://…

Only after uv cache clean comfy-draftsman

Tracks unreleased commits; silently stale otherwise

@latest is the right default for most people. If you work offline often, take the uv tool install row and run uv tool upgrade comfy-draftsman (or uv tool upgrade --all) when you want a new version.

To find out what you're running, ask your agent to call check_setup — the first line of its report is the running comfy-draftsman version. The draftsman://capabilities resource carries it too.

To hear about new versions, watch the repo on GitHub: Watch → Custom → Releases. Every tagged release publishes to PyPI and creates a GitHub Release whose notes are that version's CHANGELOG.md section. The server itself never phones home — it talks only to your ComfyUI and (read-only) the Comfy Registry, and checking for updates is deliberately your call, not a background poll.

Migrating an existing install costs nothing but a config edit. Session state and learned knowledge live in ~/.comfy-draftsman/ and saved workflows live in ComfyUI's own browser, so neither depends on how the server was installed — change the args line, restart your client, and optionally uv cache clean comfy-draftsman to reclaim the old checkout.

Configuration

Env var

Default

Purpose

COMFYUI_URL

http://127.0.0.1:8188

The ComfyUI instance to drive

DRAFTSMAN_SESSION_DIR

~/.comfy-draftsman/sessions

Where in-progress workflows persist

DRAFTSMAN_LEARNED_DIR

~/.comfy-draftsman/learned

Persistent learned model knowledge

COMFYUI_MOUNT_DIR

(unset)

Folder a sandboxed client can reach; save_output (and run_workflow's auto-relocate) copy finished renders — images, video, audio — here out of ComfyUI's output/ tree

DRAFTSMAN_TIMEOUT

30

HTTP timeout (seconds)

DRAFTSMAN_ELICITATION

on

off never opens a confirmation dialog and always takes the ask-in-chat fallback — for a client whose dialog never renders

COMFY_API_KEY

(unset)

Comfy Org API key for partner/* nodes (Luma, Seedance, Kling, Runway); injected into the prompt payload's extra_data so headless queues authenticate

Using with Claude Cowork / Code

ComfyUI's save nodes only ever write inside ComfyUI's own output/ tree, so a finished render has to be copied out before a sandboxed agent can open, edit, or show it to you. That copy lands in COMFYUI_MOUNT_DIR — and the one rule that makes it work is:

COMFYUI_MOUNT_DIR must be a folder that both the draftsman server (next to ComfyUI) and your agent's sandbox can see — typically your Cowork/Code workspace directory, or a subfolder of it.

  • Set it to an absolute path. The server runs with its own working directory (MCP hosts often launch it from a system directory like System32), so a relative dest_dir/save_dir would resolve somewhere invisible — draftsman now refuses a relative path with a clear error rather than misplacing your render.

  • Same machine (typical): point it at your project folder, e.g. COMFYUI_MOUNT_DIR=I:\source\repos\my-project\renders (Windows) or /home/you/project/renders. run_workflow auto-relocates the finished output files there — images, video and audio alike — and returns their saved_paths; the agent opens those paths directly. (Relocation needs finished files, so it applies to a blocking run; a background wait=False run relocates afterwards with save_output(prompt_id=...), and says so rather than ignoring save_dir.)

  • Check readiness first. get_instance_info (call it first anyway) returns a relocation block — {"configured": true, "writable": true, "path": ...} when you're good to go, or a hint telling you to set COMFYUI_MOUNT_DIR when you're not. check_setup is the dedicated doctor — it also confirms ComfyUI itself is reachable and never raises — and the draftsman://capabilities resource reports the same relocation status. If it's unset, the agent can ask you to configure it before spending a render instead of after.

Without COMFYUI_MOUNT_DIR, everything except handing you the finished file still works — you'd just pass an explicit absolute save_dir= per run, or fetch previews inline with view_output.

Reducing permission prompts

Building a workflow makes many tool calls (schema lookups, validation, layout), so your agent may ask to approve each one. Draftsman marks its read-only tools with MCP readOnlyHint annotations and batches schema lookups (get_node_info takes a list), but the actual prompting is your client's policy. To "approve once", add the read-only tools to your client's allowlist — see docs/PERMISSIONS.md for a copy-paste Claude Code permissions.allow block (and the tradeoffs of allowing the mutating tools like run_workflow / save_workflow).

Troubleshooting

  • Draftsman's tools don't appear in Claude Code. The server can be silently disabled per project (~/.claude.json → your project → disabledMcpServers). check_setup can't report that, because a disabled server never runs — re-enable it from /mcp.

Tools

Discovery — get_instance_info (version, VRAM in raw bytes and GB, queue — and a relocation block reporting whether renders can be handed to a sandboxed client; call first), check_setup (one-shot doctor: ComfyUI reachable? renders relocatable? — never raises, so it's the first call when something's off), search_nodes, get_node_info (long combo lists — fonts, model files — are capped for chat-friendliness; choices_filter='substring' / max_choices=N browse the full list), list_models (per-folder, with search substring filtering; long lists are capped for chat-friendliness — the true count and a search= hint always come back — and metadata_for='file.safetensors' returns a LoRA's embedded training metadata: base model and top trigger tags, so trigger words come from ground truth, not guesses), list_templates (~450 bundled templates — the response carries the true match count and a search= hint, never a silent truncation), list_workflows (what's already in ComfyUI's workflow browser, by name), find_workflow (describe a goal — "flux portrait at 1024 with a face detailer" — and get a few ranked, compact matches from your saved workflows: family, base model, resolution, feature tags, and why each matched; profiled from the saved JSON so hand-built ones count too. Reuse-before-rebuild without importing every candidate — the fetch/parse happens server-side, only the top summaries come back)

Authoring - create_workflow (blank or template-seeded), import_workflow (paste UI/API-format JSON, or name=... to load one straight from ComfyUI's workflow browser - no pasting), inspect_workflow (for subgraph-packaged workflows - how newer bundled templates ship - it lists each subgraph's inner nodes and wiring, marking which boundary inputs the instance actually exposes as sockets), edit_workflow (batched ops with strict per-op schemas, all or nothing - a failing op changes nothing, so the fixed batch is resent whole; copy_nodes clones nodes and their links from another session workflow; widget values are checked against the live schema at write time, so a made-up sampler or model filename fails immediately with closest-match suggestions instead of at run time; supports Note/MarkdownNote annotation nodes via their single text widget; connect reports when it replaces an existing link; returns a compact delta - summary=true for the full graph), organize_workflow (never overwrites human-authored node titles; nodes no output depends on go to an "Unconnected" band, and layout="panel" groups what you edit into one Controls band), lint_workflow (readability checks, including no-prompt-preview: a wildcard-generated positive prompt should reach a Show Text node - inline before the encoder or tapped off the generator - so the user sees the final text; hidden-troubleshooting flags an LLM prompt generator whose troubleshooting output is shown nowhere)

Correctness — validate_workflow (live checks + closest-match suggestions), diagnose_workflow (validation + registry resolution of missing nodes), port_workflow (cross-family model ports like SDXL→Flux — missing-node repair is diagnose_workflow/resolve_missing_nodes, not this)

Execution & delivery — run_workflow (validates, renders, returns an inline preview thumbnail; wait=False queues in the background; allow_invalid=True submits past the local validator when you're sure a graph is fine; save_dir=... — or a configured COMFYUI_MOUNT_DIR — auto-relocates the finished renders and returns their saved_paths, so one call gets you a presentable file), get_run_status (queue position, live step progress, outputs when done), view_output (fetch any rendered image so the agent — and you — can see it; downscaled by default, max_dim=None for full resolution), save_output (copy a finished render — image, video or audio — out of ComfyUI's output/ tree into a folder the caller can reach; needed because ComfyUI's save nodes only write inside output/ and reject absolute paths; takes a prompt_id or an explicit filename), upload_image (put a source image/mask into ComfyUI's input folder for img2img / inpaint / ControlNet), manage_queue (status / interrupt / clear / delete / free memory), save_workflow (validates first — refuses to save a broken workflow unless allow_invalid=True; errors that only stop a headless run, like a pack's JS widgets, don't block saving — then lands in ComfyUI's workflow browser; never overwrites an existing workflow file unless overwrite=True — a taken name saves as <name> (draftsman) so your original is preserved), export_workflow_json

Ecosystem & knowledge — resolve_missing_nodes, search_node_packs, get_model_guidance (tuned per-family settings, plus a fit verdict when your GPU can't comfortably hold the model — silent when it can), record_learning

Prompts — build_workflow, modernize_workflow (guided flows) · Resources — draftsman://workflow-format, draftsman://knowledge/{family}, draftsman://capabilities (relocation readiness, background runs, partner-node key)

Run it and see the result

Whether the agent just built a workflow or imported one you already had, running it puts the picture in the conversation. A real session looks like this:

You: Run my "ZITx Zimage Turbo" workflow and show me what it makes.

Agent: One of its model files was moved since it was saved — I've repointed the checkpoint loader to the installed file. Rendering now… done in 9 seconds. Here's the result:

A render delivered straight into the conversation

The full-resolution file is ZIT_00042_.png in ComfyUI's output folder — want me to copy it somewhere, tweak the prompt, or queue a batch of variations?

The agent sees the same image you do, so "make it warmer and less cluttered" works as a follow-up. Long renders queue in the background with live step progress; inline previews are size-optimized thumbnails (the files on disk are untouched originals), and view_output fetches full resolution on demand. With COMFYUI_MOUNT_DIR set, finished renders are also copied to a folder your agent can reach, so sandboxed clients can hand you the actual file.

How it stays correct

  • The graph model round-trips ComfyUI's UI workflow format (schema 0.4, including subgraph definitions) faithfully and serializes to API format with the fiddly bits handled: positional widget arrays (including control_after_generate slots — even the ones the frontend adds by name to legacy seed widgets with no schema flag), V3 dynamic-combo and autogrow dotted keys, converted-widget connections, PrimitiveNode baking, Reroute tracing, mute/bypass semantics.

  • Headless runs match the browser. Behaviors ComfyUI implements in frontend JS — which the raw /prompt API never performs — are replayed at submit time: custom pack-specific widget inputs (e.g. a LoRA autocomplete box) are serialized instead of dropped, %date:…% filename tokens are substituted, and seeds on randomize/increment/decrement re-roll per run (run_workflow(roll_seeds=False) to opt out). Combo-value validation blocks on missing model files and core-node enums but only warns on custom nodes that repopulate their pickers client-side, so it doesn't flood.

  • Subgraph-packaged workflows run. Instances are flattened to API format the way the frontend does it at queue time (boundary rewiring, promoted proxyWidgets values, nested definitions), and validate checks the inner nodes too. Each inner finding is tagged with its subgraph provenance and the definition_id/inner_node_id that edit_workflow's definition-scoped ops take — so a wrong model path inside a bundled template is a one-call fix, not a rebuild.

  • Everything is validated against the live /object_info — combo checks double as "is this model actually installed" checks, refreshed right before every run/save.

  • The test suite includes protocol-level end-to-end tests that build, validate, organize, render, and save real workflows on a real ComfyUI instance — including a subgraph-packaged one.

  • Module map, data flow, and design gotchas: docs/ARCHITECTURE.md.

Security notes

  • Runs over stdio only; the server opens no listening port.

  • Talks only to the ComfyUI URL you configure and (read-only) the official Comfy Registry at api.comfy.org.

  • It never installs custom nodes. resolve_missing_nodes tells you which pack provides a missing node and how to install it yourself — custom node packs execute arbitrary code, so that decision stays with you.

  • Partner/API nodes never run without your say-so. Luma, Kling, Runway, Seedance and friends execute on the provider's hardware and bill your Comfy Org account per submit, so run_workflow asks before queueing one (and tells the agent how to ask you, on clients that can't prompt). A graph needing them without COMFY_API_KEY set fails immediately by name instead of as a confusing queue-time Unauthorized.

  • Other people's renders are not draftsman's to discard. manage_queue's interrupt/clear/delete confirm first when the affected jobs weren't queued by this session — and stay quiet when it's just cleaning up after itself.

Development

git clone https://github.com/EnragedAntelope/comfy-draftsman
cd comfy-draftsman
uv sync --group dev
uv run pytest                 # unit tests (no ComfyUI needed)
uv run pytest -m integration  # needs a live instance: COMFYUI_TEST_URL=http://127.0.0.1:8288
uv run ruff check .

The repo's .comfyui-test/ convention (gitignored) holds a disposable ComfyUI clone for integration testing — see tests/test_integration_live.py.

Publishing a release

.github/workflows/release.yml publishes to PyPI via Trusted Publishing — no API token is stored in this repo. One-time setup: create the pypi and testpypi GitHub environments, then register a pending publisher on pypi.org and test.pypi.org (owner EnragedAntelope, repo comfy-draftsman, workflow release.yml, matching environment name).

Then: Actions → Release → Run workflow → testpypi for a dry run, and git tag vX.Y.Z && git push origin vX.Y.Z for the real thing. The workflow refuses to publish when the tag disagrees with comfy_draftsman.__version__, and re-runs CI's wheel-data assertion before uploading. A PyPI version number can never be reused — do the TestPyPI run first.

A tag push also creates a GitHub Release, with that version's CHANGELOG.md section as its notes and the built artifacts attached — that Release is what notifies anyone watching the repo, so write the changelog entry before tagging. tests/test_packaging.py fails the build if the current __version__ has no matching section.

Acknowledgments

The execution-side tools — view_output, upload_image, background runs with get_run_status progress, and manage_queue — were inspired by KerbalTheGathering/ComfyUI_MCP, whose author suggested merging those capabilities into draftsman. They were re-implemented independently for this codebase; the ideas (return-refs-by-default with a dedicated view tool, thumbnail downscaling, websocket progress tracking) are credited to KerbalTheGathering.

License

MIT

Available Tools

29 tools
check_setupA
Read-onlyIdempotent

One-shot setup diagnostic for a fresh install or a sandboxed client (Cowork/ Desktop/Code): can I reach ComfyUI, can I hand finished renders back to the user (COMFYUI_MOUNT_DIR), is the partner-node key present. Unlike get_instance_info it never raises - a down instance is a failed check, not an error - so run it first when a render can't be delivered or the instance seems unreachable. Returns {ok, checks:[{name, ok, detail}], hint?}; ok gates on ComfyUI being reachable, relocation is a soft check surfaced via hint.

Inputs: no named parameters. Returns: object

create_workflowA

Start a workflow: blank, or seeded from a bundled template (recommended for current model families - see list_templates). Returns workflow_id + node summary.

Inputs: title (required), template. Returns: object

diagnose_workflowA
Read-onlyIdempotent

Deep-check an old/broken workflow and propose fixes: everything from validate_workflow PLUS Comfy Registry resolution for missing custom-node classes (which pack provides them, how to install). Apply fixes via edit_workflow, or port_workflow for model-family moves.

Inputs: workflow_id (required). Returns: object

edit_workflowA

Apply batched edits. Each op is a dict with 'op' plus:

  • {"op": "add_node", "class_type": str, "title"?: str, "ref"?: str, "widgets"?: {name: value}} # later ops may use a ref as a node id

  • {"op": "remove_node", "node_id": int}

  • {"op": "connect", "from_node": int, "from_output": str|int, "to_node": int, "to_input": str} # replaces a link

  • {"op": "disconnect", "node_id": int, "input": str}

  • {"op": "set_widget", "node_id": int, "input": str | "index": int, "value": any}

  • {"op": "replace_in_widget", "node_id": int, "input": str, "old": str, "new": str} # 'old' must match once

  • {"op": "set_title", "node_id": int, "title": str}

  • {"op": "set_mode", "node_id": int, "mode": int} # 0 normal, 2 mute, 4 bypass

  • {"op": "set_resolution", "width": int, "height": int} # all latents + size patches

  • {"op": "copy_nodes", "from_workflow": id, "node_ids": [int], "ref"?: str} # + links among them

Subgraph twins add "definition_id": add_node_to_definition, remove_node_from_definition, connect/set_widget/set_title/set_mode_in_definition.

Layout ops (no twin): set_pos {node_id, pos:[x,y], size?:[w,h]}; set_color {node_id, color, bgcolor?}; add_group {title, node_ids, color?}; set_group {group_id, title?, node_ids?, color?, bounding?:[x,y,w,h]}; remove_group {group_id} ('#N' in inspect_workflow). organize_workflow redoes all layout.

Slot/widget names come from get_node_info. Virtual classes: Note/MarkdownNote take one widget 'text'; Reroute/PrimitiveNode take none at add - connect a PrimitiveNode to a widget input to mirror its type, then set_widget 'value' (+ 'control_after_generate' for number/combo, to advance each run).

Ops apply in order, all or nothing (a failing op changes nothing). Widget values and link types are checked live - "force": true on set_widget/add_node/connect overrides; on connect it also creates a frontend-only input (rgthree switches, dynamic collectors).

Result is a delta; summary=true gives the full graph.

Inputs: operations (required), workflow_id (required), summary. Returns: object

export_workflow_jsonA
Read-onlyIdempotent

The workflow as JSON: 'ui' (shareable, opens in the editor, keeps layout & notes) or 'api' (for POST /prompt automation).

Pass path to also write the JSON to a file; the dict then reports saved_to instead of embedding the graph.

Inputs: workflow_id (required), path, format. Returns: object

find_workflowA
Read-onlyIdempotent

Find saved workflows that already DO what you're about to build (reuse beats rebuilding). Describe the goal in words, e.g. "flux portrait at 1024 with a face detailer"; get a few RANKED summaries (family, base model, resolution, feature tags, why it matched) from the saved JSON, hand-built ones included. Never full graphs - load one with import_workflow(name=...). Prefer this over importing each result of list_workflows.

Inputs: intent (required), limit. Returns: object

get_instance_infoA
Read-onlyIdempotent

ComfyUI version, OS, VRAM, queue length, and render-relocation readiness of the connected instance. Call first. The relocation block reports whether COMFYUI_MOUNT_DIR is set and writable - if it isn't, renders can't be handed to the user automatically, so surface that to them before spending a render.

Inputs: no named parameters. Returns: object

get_model_guidanceA
Read-onlyIdempotent

Tuned settings for a model family: sampling (CFG/steps/samplers), native resolutions, technique blocks (face_detailer, hires_fix...), prompt style notes. Variant-aware: pass model_filename (alone, it detects the family) so turbo/lightning/distill overrides apply. Includes any learned overlay from past research plus a research directive - for brand-new models, verify online and record_learning what you find. A fit block appears only when this GPU can't comfortably hold the model.

Inputs: family, model_filename. Returns: object

get_node_infoA
Read-onlyIdempotent

Full input/output schema for node classes: slot names, types, widget defaults/ranges, combo choices, tooltips.

BATCH your lookups: pass class_types=["A", "B", "C"] to fetch many in ONE call (returns {class_type: schema}) instead of one call per node. A single class_type=... still returns that one node's schema directly.

Long combo lists (fonts, model files...) are capped at 24 choices by default; to browse the rest, pass choices_filter='substring' (case-insensitive; every combo, or 'input:substring' for one) and/or max_choices=N to raise the cap.

Inputs: class_type, class_types, max_choices, choices_filter. Returns: object

get_run_statusA
Read-onlyIdempotent

Polling tool for runs queued with run_workflow(wait=False). For long/paid renders, see run_workflow's long-render pattern. Status of a run queued with run_workflow(wait=False): queue position, live step progress while sampling, and outputs (+ error details, elapsed_s) once finished. full_output=<node_id> returns that node's text unclipped.

Inputs: prompt_id (required), full_output. Returns: object

import_workflowA

Import an existing workflow into the session. Provide exactly ONE source:

  • workflow_json: paste the JSON inline (UI format with nodes/links, or API format {id: {class_type, inputs}})

  • name: load straight from ComfyUI's workflow browser (see list_workflows) - preferred for large files, no pasting needed

  • file_path: read a local .json file Use for beautifying/diagnosing/porting outside work.

Inputs: name, title, file_path, workflow_json. Returns: object

inspect_workflowA
Read-onlyIdempotent

Compact view of a session workflow: nodes (id/class/title/widgets), links, groups - plus full inner node/wiring detail for any subgraph definitions (newer bundled templates package their graph as a subgraph).

Inputs: workflow_id (required). Returns: object

lint_workflowA
Read-onlyIdempotent

Readability/wiring lint: unlabeled prompts, missing groups/notes, orphan nodes, unconnected required inputs, overlapping nodes, misaligned resolution (when a family with a known alignment requirement is detected). Empty list = clean.

Inputs: workflow_id (required). Returns: result

list_modelsA
Read-onlyIdempotent

Model files installed on the instance. folder picks the model type: checkpoints, loras, vae, diffusion_models, text_encoders, upscale_models, controlnet, embeddings, ... (unknown folder -> the full available list). search filters filenames (case-insensitive substring). metadata_for (a .safetensors filename from this folder) returns its embedded training metadata instead - base model + top trigger tags, key for using a LoRA.

Inputs: folder, search, metadata_for. Returns: object

list_templatesA
Read-onlyIdempotent

ComfyUI's bundled workflow templates - the best starting points for current models (they ship with every release). Seed one via create_workflow(template=...). Narrow with search= (matched against title/description/models); the catalog is ~450 templates, far more than one response should carry.

Inputs: search. Returns: object

list_workflowsA
Read-onlyIdempotent

Workflows already saved in ComfyUI's workflow browser (userdata). Use a returned name with import_workflow(name=...) to load one WITHOUT pasting its JSON. search filters names (case-insensitive substring).

Inputs: search. Returns: object

manage_queueA
Destructive

Inspect or manage the instance's run queue: status (queued prompt ids; draftsman_submitted maps the ones THIS session queued to their workflow_id - the rest are someone else's job), interrupt (stop the running prompt), clear (drop ALL pending), delete (drop given pending prompt_ids), free (release cached VRAM/RAM; unload_models=True also unloads models). clear/delete/ interrupt are gated when they'd discard prompts this session didn't queue; confirm=True once the user agrees.

Inputs: action (required), confirm, prompt_ids, unload_models. Returns: object

organize_workflowA

THE finishing step: auto-layout into pipeline stage bands, colored groups, human titles, green highlights on user-editable knobs, and markdown guidance notes (model-family aware, two registers: 'touch this' vs 'leave alone'). Run after wiring, before save_workflow; replaces a hand-made layout. Idempotent. layout="panel" groups Controls (what you edit) | Pipeline | Unconnected. MUTATES the session workflow in place; applied summarizes the changes.

Inputs: workflow_id (required), layout. Returns: object

port_workflowA

CROSS-FAMILY MODEL PORT ONLY (e.g. 'sdxl' -> 'flux'): swaps loader topology when needed, retunes CFG/steps/sampler/scheduler and technique nodes (FaceDetailer etc.) from family knowledge, swaps latent node class, picks installed model files. NOT for fixing missing/uninstalled nodes - that's diagnose_workflow + resolve_missing_nodes. Returns changes + flags for anything that needs your judgment. Families: get_model_guidance / get_instance_info.

Inputs: workflow_id (required), target_family (required). Returns: object

record_learningA

Persist researched settings so FUTURE sessions start smarter. updates uses the guidance shape, e.g. {"sampling": {"cfg": {"default": 3.5}}} or {"techniques": {"face_detailer": {"denoise": 0.4}}}. source = URL/model page. Any family name works; for a NEW family also include a "detect" block so it's auto-recognized next session: {"detect": {"checkpoint_patterns": ["mymodel"]}, "loader": "unet_clip_vae"}.

A "sources" list teaches organize_workflow's Models note where to download each file - it never invents a URL, so this is the only way one appears: {"sources": [{"match": ["mymodel_v1.safetensors"], "what": "checkpoint", "url": "https://..."}]}. Verify the URL resolves first.

Inputs: family (required), source, updates. Returns: object

resolve_missing_nodesA
Read-onlyIdempotent

Find which installable node packs provide these node class names (official Comfy Registry). THIS is the tool for missing/uninstalled nodes (port_workflow is for model-family moves, not missing nodes). Returns pack ids, repos, and install hints. Installing custom nodes runs third-party code - surface the choice to the user.

Inputs: class_types (required). Returns: object

run_workflowA

Queue the workflow and (by default) wait for completion. Returns status, node errors on failure, output file refs, any non-file return values (data_outputs: generated text, paths a save node wrote), and an inline preview thumbnail so you can SEE the result (view_output fetches full size). wait=False returns {status: queued, prompt_id} - poll get_run_status. Prove a workflow works before saving.

return_preview=False (text-only caller): no inline images, sweeps included; a file path comes back if save_dir/COMFYUI_MOUNT_DIR is set.

roll_seeds=True (default) mirrors the browser: randomize/increment/decrement seeds and PrimitiveNodes re-roll and persist before submit. False re-runs the stored values.

allow_invalid=True submits despite local validation errors (ComfyUI is the final judge). save_dir (or COMFYUI_MOUNT_DIR) relocates finished outputs into a folder the caller can reach (saved_paths); needs wait=True - a background run relocates later via save_output(prompt_id=...).

front: None (default) refuses to queue when >=2 prompts are pending and returns {status: queue_busy} so the USER can choose; True runs next; False waits at the back of the line.

confirm_spend: partner/API nodes charge per submit, so a graph containing one is gated - pass True only after they agree.

sweep={variants:[{label,ops}],seeds:[int],crops:[[x0,y0,x1,y1]],reference?: "file [input]",freeze?:node_id}: each variant (ops on a copy) x seed; returns a contact sheet (reference = first cell), 1:1 crop sheets, per-run elapsed_s/files. <=24 runs, wait=True; crops <=512px or 0-1 floats.

LONG RENDERS: a timeout cancels your wait, not the job. wait=False, front=False, poll get_run_status(prompt_id) to success/error/partial, then save_output; manage_queue(status).draftsman_submitted keeps prompt_ids.

Inputs: workflow_id (required), wait, front, sweep, +6 more.

save_outputA

Copy a finished render out of ComfyUI's output tree into a folder the caller (e.g. a Cowork sandbox) can reach - save nodes only write inside output/.

Pass prompt_id (relocates every output FILE of that finished job - images, video, audio) OR an explicit filename (+subfolder/type, as reported in a run's outputs). dest_dir defaults to COMFYUI_MOUNT_DIR; dest_filename renames a single file. Returns {saved_paths, dest_dir}.

Inputs: type, dest_dir, filename, overwrite, +3 more. Returns: object

save_workflowA

Save the workflow (UI format, with layout/groups/notes) into ComfyUI's workflow browser + the session dir. Organize a graph you built first (not a hand-arranged one). REFUSES to save with validation errors unless allow_invalid=True. Never overwrites by default: a taken name saves as ' (draftsman)' (result.renamed_from says so); overwrite=True replaces deliberately.

Inputs: name (required), workflow_id (required), overwrite, allow_invalid. Returns: object

search_node_packsA
Read-onlyIdempotent

Search the Comfy Registry for node packs by capability (e.g. 'face detailer', 'wildcards', 'video interpolation').

Inputs: query (required). Returns: result

search_nodesA
Read-onlyIdempotent

Search node classes installed on the instance (name/display-name/description).

Use category to narrow (e.g. 'loaders', 'conditioning', 'sampling', 'ImpactPack'). Set detail=True to fold each hit's full input/output schema in-line (use a specific query + small limit) so you can skip the follow-up get_node_info.

Inputs: query (required), limit, detail, category. Returns: result

upload_imageA

Upload a source image into ComfyUI's input folder so LoadImage can use it (img2img / inpaint / ControlNet). Exactly one of image_path (local file) or image_base64. mask_for={filename, subfolder?, type?} uploads this as a MASK for that already-uploaded image instead.

Inputs: name, mask_for, overwrite, subfolder, +2 more. Returns: object

validate_workflowA
Read-onlyIdempotent

Validate against the LIVE instance: node classes installed, widget values in range, combo/model-file values actually present (with closest-match suggestions), required inputs connected. Fix errors before run_workflow.

Inputs: workflow_id (required). Returns: object

view_outputA
Read-onlyIdempotent

Fetch a rendered image so you (and the user) can SEE it - refs come from run_workflow/get_run_status outputs. Downscaled to max_dim px to keep the conversation light; max_dim=None for full resolution.

Inputs: filename (required), type, max_dim, subfolder.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 29 tools

    Disambiguation4/5

    Descriptions go out of their way to fence off look-alike tools (validate_workflow vs diagnose_workflow vs lint_workflow; resolve_missing_nodes vs port_workflow; check_setup vs get_instance_info), which makes most selections unambiguous. Still, several clusters genuinely overlap — three validation/checking tools, two saved-workflow listings (list_workflows vs find_workflow), and two setup diagnostics — so an agent must read carefully before picking.

    Naming Consistency5/5

    Every tool is snake_case with a leading verb (inspect_, create_, save_, validate_, list_, search_, get_, run_, manage_, record_), forming a predictable verb_noun convention throughout. Action families are readable at a glance (search_*, list_*, *_workflow).

    Tool Count2/5

    At 29 tools this is well past the heavy threshold, and a few groupings could be consolidated (three validators, two workflow-listings, two setup checks, search_nodes vs search_node_packs). The domain is broad — authoring, discovery, execution, queueing, assets, learning — so the size is defensible, but it still burdens tool selection.

    Completeness4/5

    Coverage is unusually deep: full authoring lifecycle (create/import/edit/organize/validate/export/save), node and model discovery, execution with polling, queue management, image upload, and output viewing/relocation. Minor gaps remain, notably no tool to delete or rename workflows already in the browser (save_workflow only renames on collision).

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers