> ## Documentation Index
> Fetch the complete documentation index at: https://comfyui-mcp.artokun.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Authoring

> Build, modify, validate, and visualize ComfyUI workflows.

<Info>2 tools. Generated from the live MCP tool schemas — do not edit by hand; run `npm run docs:gen`.</Info>

<Tip>**You don't type these calls.** Ask your agent for what you want in ordinary English — it chooses the tool and fills in the arguments. The JSON on this page is what it sends. New here? Start with [Using the tools](/docs/using-tools).</Tip>

## create\_workflow

Author and check ComfyUI workflow JSON. Driven by the `action` parameter:

* action:"create" — Create a ready-to-run API-format workflow from a built-in template (txt2img, img2img, upscale, inpaint, controlnet, ip\_adapter, ace\_step\_15, stable\_audio\_3, remove\_background, ltx\_video). Pure local generation — does not contact ComfyUI and has no side effects. Returns the complete workflow JSON; pass it to action:"validate" or enqueue\_workflow. Unsupplied `params` fall back to template defaults, so the result may reference checkpoints/models that must exist on your ComfyUI server before it will execute.
* action:"modify" — Apply modification `operations` to an existing workflow. Supports: set\_input, add\_node, remove\_node, connect, insert\_between. Returns the modified workflow JSON and IDs of any newly added nodes.
* action:"validate" — Validate a workflow WITHOUT executing it. Checks for missing node types, broken connections, invalid output indices, missing models, and other issues. Returns a list of errors and warnings.
* action:"node\_info" — Query a running ComfyUI server's /object\_info endpoint for installed node type definitions. Requires a reachable ComfyUI instance; results reflect that server's installed custom nodes. Use the `node_type` filter to inspect a specific node before composing or modifying a workflow. Default response is a STRUCTURAL summary: input/output names and type tags, with enum (dropdown) inputs collapsed to a value count — safe for context even on Loader nodes whose model dropdowns embed the entire local model list (hundreds of KB raw). Pass verbose=true (20 or fewer matches) for the complete raw definitions including every dropdown value. When more than 20 node types match, returns only a name/category list and asks you to narrow the filter.

<Tip>**In plain terms:** Building a graph, and the schema lookup you make while building it — start one from a template, patch an existing one, check it before you queue it, or ask what a node's inputs are. Chosen with `action`.</Tip>

### Parameters

<ParamField path="action" type="enum" required>
  Which authoring operation to perform. "create" requires `template` (optional `params`); "modify" requires `workflow` + `operations`; "validate" requires `workflow` (optional `health`); "node\_info" takes no required parameters (optional `node_type`, `verbose`, `refresh`). Options: `action:"create"`, `action:"modify"`, `action:"validate"`, `action:"node_info"`.
</ParamField>

<ParamField path="template" type="enum">
  action:"create" (REQUIRED) — Template name: txt2img, img2img, upscale, or inpaint Options: `txt2img`, `img2img`, `upscale`, `inpaint`, `controlnet`, `ip_adapter`, `ace_step_15`, `stable_audio_3`, `remove_background`, `ltx_video`.
</ParamField>

<ParamField path="params" type="object" default="[object Object]">
  action:"create" — Template parameters; recognized keys depend on the template. txt2img: checkpoint, positive\_prompt, negative\_prompt, width, height, steps, cfg, seed, sampler\_name, scheduler. img2img/inpaint add image\_path (and mask\_path for inpaint) and denoise. upscale adds upscale\_model. Unknown keys are ignored; omitted keys use template defaults.
</ParamField>

<ParamField path="workflow" type="string | object">
  ComfyUI workflow JSON (as a JSON string or object). REQUIRED for action:"modify" and action:"validate" — API format for "validate".
</ParamField>

<ParamField path="operations" type="object[]">
  action:"modify" (REQUIRED) — Array of operations to apply in order. Each has an 'op' field: set\_input, add\_node, remove\_node, connect, or insert\_between
</ParamField>

<ParamField path="health" type="boolean" default="true">
  action:"validate" — Include graph-health heuristics (disconnected nodes, duplicate model loads, orphaned branches, muted/bypassed nodes) as info/warning issues plus a structured health section. Never affects `valid`.
</ParamField>

<ParamField path="node_type" type="string">
  action:"node\_info" — Filter by node class\_type name (case-insensitive substring match). Omit to list all available nodes.
</ParamField>

<ParamField path="verbose" type="boolean" default="false">
  action:"node\_info" — If true, return the full raw /object\_info definitions including enum dropdown values (model lists etc.) — can be hundreds of KB per Loader node, so only use it when you need the actual enum values (e.g. exact model filenames) and the filter matches few nodes. Default false: structural summary with enum value counts.
</ParamField>

<ParamField path="refresh" type="boolean" default="false">
  action:"node\_info" — If true, discard the memoized /object\_info snapshot and refetch live from the connected server before answering. Use after the ComfyUI server was restarted EXTERNALLY (systemd/service manager) or new model files were added out-of-band — the cache is otherwise only invalidated by MCP-managed restarts, so loader dropdowns (model lists) would remain stale for the rest of the session (#499).
</ParamField>

### Examples

**You say:** Give me a basic text-to-image workflow to start from.

```json theme={null}
{
  "tool": "create_workflow",
  "arguments": {
    "action": "create",
    "template": "txt2img",
    "params": {
      "positive_prompt": "a snow leopard on a rooftop at dusk",
      "steps": 25
    }
  }
}
```

**You get back:** A complete, runnable API-format workflow. Anything you left out uses the template default, so check the checkpoint it picked actually exists on your server before running it.

**You say:** Turn the steps up to 40 on node 3.

```json theme={null}
{
  "tool": "create_workflow",
  "arguments": {
    "action": "modify",
    "workflow": {
      "4": {
        "class_type": "CheckpointLoaderSimple",
        "inputs": {
          "ckpt_name": "sd_xl_base_1.0.safetensors"
        }
      },
      "9": {
        "class_type": "SaveImage",
        "inputs": {
          "filename_prefix": "portrait",
          "images": [
            "8",
            0
          ]
        }
      }
    },
    "operations": [
      {
        "op": "set_input",
        "node_id": "3",
        "input_name": "steps",
        "value": 40
      }
    ]
  }
}
```

<Note>Shortened for readability — two nodes of a real API-format graph are shown. In practice the agent passes the whole thing: the graph it just loaded with get\_workflow, or the one it built for you.</Note>

**You get back:** The modified workflow plus the ids of any nodes the operations added. Nothing is written to disk and nothing is queued.

**You say:** Will this run?

```json theme={null}
{
  "tool": "create_workflow",
  "arguments": {
    "action": "validate",
    "workflow": {
      "4": {
        "class_type": "CheckpointLoaderSimple",
        "inputs": {
          "ckpt_name": "sd_xl_base_1.0.safetensors"
        }
      },
      "9": {
        "class_type": "SaveImage",
        "inputs": {
          "filename_prefix": "portrait",
          "images": [
            "8",
            0
          ]
        }
      }
    }
  }
}
```

<Note>Shortened for readability — two nodes of a real API-format graph are shown. In practice the agent passes the whole thing: the graph it just loaded with get\_workflow, or the one it built for you.</Note>

**You get back:** Either a clean bill of health or the specific problems, without queuing anything.

**You say:** What settings does the KSampler node have?

```json theme={null}
{
  "tool": "create_workflow",
  "arguments": {
    "action": "node_info",
    "node_type": "KSampler"
  }
}
```

**You get back:** That node's inputs and outputs with their types. Dropdown options are summarised as a count by default, because a model-loader dropdown can be hundreds of kilobytes on its own.

***

## visualize\_workflow

DRAW a diagram of, or convert, workflow JSON you PASS IN (a JSON string or object) — it does NOT read the user's live canvas, so for 'show me what's on the canvas' / the CURRENTLY-OPEN graph use panel\_graph\_outline instead. Driven by the `action` parameter:

* action:"render" — Mermaid flowchart of the whole graph: nodes grouped by category, connections labeled by data type.
* action:"render\_hierarchical" — the same graph SECTIONED rather than flat, which is what you want past \~20 nodes. `view` picks a compact overview, one section in detail, a text listing, or an AI-oriented structured summary.
* action:"mermaid" — the INVERSE of render: a Mermaid flowchart back into executable API-format workflow JSON, wired from /object\_info schemas.
* action:"to\_dsl" — API-format JSON into the compact, human/LLM-readable authoring DSL: `key &lt;- nodeId.outputIndex` for connections, `key = &lt;JSON&gt;` for literals. Round-trips losslessly. (Experimental.)
* action:"from\_dsl" — that DSL back into executable JSON, plus advisory wiring warnings when ComfyUI is reachable (the conversion succeeds either way). (Experimental.)

<Tip>**In plain terms:** Turn a workflow you PASS IN into something readable — a Mermaid diagram or the compact DSL — and back again. It never looks at the graph open on your canvas.</Tip>

### Parameters

<ParamField path="action" type="enum" required>
  Which rendering/conversion to perform. "render", "render\_hierarchical" and "to\_dsl" require `workflow`; "mermaid" requires `mermaid`; "from\_dsl" requires `dsl`. Options: `action:"render"`, `action:"render_hierarchical"`, `action:"mermaid"`, `action:"to_dsl"`, `action:"from_dsl"`.
</ParamField>

<ParamField path="workflow" type="string | object">
  ComfyUI workflow JSON (as a JSON string or object; API or UI format is auto-detected). REQUIRED for action:"render", action:"render\_hierarchical" and action:"to\_dsl" — "to\_dsl" expects API format (node ID -> \{class\_type, inputs}).
</ParamField>

<ParamField path="show_values" type="boolean" default="true">
  action:"render" / action:"render\_hierarchical" — Include widget values (seed, steps, cfg, etc.) in node labels (detail view only, for the hierarchical action).
</ParamField>

<ParamField path="direction" type="enum">
  action:"render" / action:"render\_hierarchical" — Flowchart direction: LR (left-to-right) or TB (top-to-bottom). Default LR for "render" and for the hierarchical detail view, TB for the hierarchical overview. Options: `LR`, `TB`.
</ParamField>

<ParamField path="view" type="enum" default="overview">
  action:"render\_hierarchical" — overview: compact diagram with sections as summary nodes; detail: full diagram for one section; list: text summary of all sections; summary: structured text optimized for AI ingestion with node IDs, key settings, virtual wires, and full connection graph Options: `overview`, `detail`, `list`, `summary`.
</ParamField>

<ParamField path="section" type="string">
  action:"render\_hierarchical" — Section name to show in detail view (required when view=detail). Use view=list to see available section names.
</ParamField>

<ParamField path="mermaid" type="string">
  action:"mermaid" (REQUIRED) — Mermaid flowchart text (with or without \`\`\`mermaid code fence). Nodes should use ComfyUI class\_type names as labels. Connections should be labeled with data types (e.g., -->|MODEL|).
</ParamField>

<ParamField path="dsl" type="string">
  action:"from\_dsl" (REQUIRED) — Workflow DSL text
</ParamField>

### Examples

**You say:** Draw me a diagram of this workflow.

```json theme={null}
{
  "tool": "visualize_workflow",
  "arguments": {
    "action": "render",
    "workflow": {
      "4": {
        "class_type": "CheckpointLoaderSimple",
        "inputs": {
          "ckpt_name": "sd_xl_base_1.0.safetensors"
        }
      },
      "9": {
        "class_type": "SaveImage",
        "inputs": {
          "filename_prefix": "portrait",
          "images": [
            "8",
            0
          ]
        }
      }
    }
  }
}
```

<Note>Shortened for readability — two nodes of a real API-format graph are shown. In practice the agent passes the whole thing: the graph it just loaded with get\_workflow, or the one it built for you.</Note>

**You get back:** Mermaid flowchart syntax, nodes grouped by role and every connection labelled with the data type flowing along it.

**You say:** That chart is unreadable, it's a 60-node graph.

```json theme={null}
{
  "tool": "visualize_workflow",
  "arguments": {
    "action": "render_hierarchical",
    "workflow": {
      "4": {
        "class_type": "CheckpointLoaderSimple",
        "inputs": {
          "ckpt_name": "sd_xl_base_1.0.safetensors"
        }
      },
      "9": {
        "class_type": "SaveImage",
        "inputs": {
          "filename_prefix": "portrait",
          "images": [
            "8",
            0
          ]
        }
      }
    },
    "view": "overview"
  }
}
```

<Note>Shortened for readability — two nodes of a real API-format graph are shown. In practice the agent passes the whole thing: the graph it just loaded with get\_workflow, or the one it built for you.</Note>

**You get back:** The same graph collapsed to one box per section with the data flow between them. `view: "list"` names the sections; `view: "detail"` with a `section` opens one of them up.

**You say:** Show me this workflow in a form I can actually edit by hand.

```json theme={null}
{
  "tool": "visualize_workflow",
  "arguments": {
    "action": "to_dsl",
    "workflow": {
      "4": {
        "class_type": "CheckpointLoaderSimple",
        "inputs": {
          "ckpt_name": "sd_xl_base_1.0.safetensors"
        }
      },
      "9": {
        "class_type": "SaveImage",
        "inputs": {
          "filename_prefix": "portrait",
          "images": [
            "8",
            0
          ]
        }
      }
    }
  }
}
```

<Note>Shortened for readability — two nodes of a real API-format graph are shown. In practice the agent passes the whole thing: the graph it just loaded with get\_workflow, or the one it built for you.</Note>

**You get back:** The compact DSL: one block per node, connections as `key &lt;- nodeId.outputIndex`. `action: "from_dsl"` converts it back to runnable JSON when you are done editing.

***
