> ## 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 Library

> Save, load, strip/slice, analyze, and extract 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>

## get\_workflow

Return, list, summarize or query a SAVED workflow FILE — files on disk, named from the library or given as a path/JSON — NOT the graph open on the user's canvas (that is panel\_graph\_outline). Every action here is READ-ONLY; saving and locking are save\_workflow. Driven by the `action` parameter:

* action:"get" — the full JSON of one saved workflow FILE named from the library. Defaults to converted API format; pass format:'ui' for the raw on-disk UI JSON. Use action:"analyze" instead if you just need to UNDERSTAND the workflow — it returns a structured summary without flooding context with JSON. Use action:"get" only when you need the actual JSON for enqueue\_workflow, create\_workflow (action:"modify"), or save\_workflow.
* action:"list" — the workflows saved in the connected ComfyUI server's user library (the same ones visible in the ComfyUI web UI), INCLUDING the ones filed in subfolders. Requires a running ComfyUI server. Takes no other parameters. Returns a numbered list of library names, each relative to the library root — a workflow in a folder appears as 'VIDEO/MiniMaxH3/clip.json', and that whole string is what `filename` takes. It never reports an absence it did not establish: a listing it could not read says so, and an EMPTY listing says the library could not be CONFIRMED empty (an answer with no names in it cannot show whether it covered subfolders) and tells you to check the ComfyUI sidebar rather than recreate anything.
* action:"strip" — strip a workflow to a clean, flat API graph, resolving Get/Set buses, Reroutes, subgraph definitions, and bypassed/muted nodes into real connections (the 'de-getter-setter' pass). Unlike action:"get" this reads from ANY server-side file path on disk (not just the workflow library), so it loads ad-hoc / expert workflow files that action:"list" and panel\_open\_workflow can't resolve. Provide exactly one of: path, filename, or graph. Returns conversion warnings, a node-type summary, and the stripped graph (much smaller than the raw UI JSON).
* action:"slice" — slice ONE pipeline out of a toggle-template workflow, the kind built with rgthree 'Fast Groups Bypasser/Muter' where one graph holds many pipelines and only one is active at a time. Seeds from the output/SaveImage nodes in the named `groups`, takes their backward dependency closure (through real links AND virtual Set/Get buses), un-bypasses the kept nodes (and the internals of any subgraph defs they use), and returns a STANDALONE, activated UI graph carrying only the subgraph defs it uses. Pair with action:"strip" afterward to flatten the Set/Get buses into real connections.
* action:"from\_image" — extract embedded ComfyUI workflow metadata from a PNG file. ComfyUI stores the full workflow (API format) and prompt data in PNG tEXt chunks. Use this to reverse-engineer how any ComfyUI image was generated.
* action:"analyze" — SUMMARIZE a saved workflow file named from the library: sections, node settings, connections, and data flow. Returns a concise text summary (not raw JSON) optimized for AI reasoning. Prefer this over action:"get" unless you need the raw JSON for enqueue\_workflow or create\_workflow (action:"modify").
* action:"query" — filter, traverse, project, and aggregate over a saved workflow's nodes WITHOUT dumping the whole JSON (the missing middle between action:"analyze"'s fixed summary and action:"get"'s full dump; on 100+-node graphs this is the ONLY context-safe way to answer questions like 'which KSamplers run cfg>7', 'what feeds node 42', 'count nodes by type'). Provide exactly one of path/filename/graph, then combine: `types`, `title`, `where` widget predicates ANDed ('cfg>7', 'steps\<=20', 'sampler\_name=euler', 'text\~sunset' — ops = != >= \<= > \< \~contains), `ids`, `upstream_of`/`downstream_of` + `depth`, `fields`, `group_by`, `limit`, `max_chars`. Output is TOKEN-BOUNDED and, when it truncates, the tail names WHICH of the two caps fired and the exact parameter to raise — read it and retry rather than concluding the graph can't be read. For the LIVE canvas this is panel\_query\_graph instead.
* action:"prompt\_director" — read Prompt Director's latest sanitized RUNTIME state after its nodes execute: each node id, node kind, resolved Model Explorer model/LoRA context, structured edit plan, source analysis, exact final prompt, warnings, or Result Critic verdict. Secrets and image tensors are redacted. Pair it with a live panel graph audit: graph inspection explains wiring and widget state, while this explains what the nodes actually resolved and compiled. Pass `node_id` to inspect one executed Prompt Director node.

<Tip>**In plain terms:** Everything you can READ about a saved workflow FILE, chosen with `action` — the library listing, the raw JSON, a plain-English summary, a targeted query. Never the graph currently open on your canvas. If you only want to know what a workflow does, `action: "analyze"` is a far shorter answer than the full JSON.</Tip>

### Parameters

<ParamField path="action" type="enum" required>
  Which read to perform. "list" and "prompt\_director" take no required parameters; "get" and "analyze" require `filename`; "strip", "slice" and "query" require exactly one of `path`/`filename`/`graph` (and "slice" also requires `groups`); "from\_image" requires `image_path`. Options: `action:"get"`, `action:"list"`, `action:"strip"`, `action:"slice"`, `action:"from_image"`, `action:"analyze"`, `action:"query"`, `action:"prompt_director"`.
</ParamField>

<ParamField path="filename" type="string">
  Workflow library name, exactly as action:"list" reports it. A workflow filed in a folder keeps its folder in the name ('VIDEO/MiniMaxH3/clip.json') and that whole string goes here. REQUIRED for action:"get" and action:"analyze"; one of the three sources for "strip", "slice" and "query".
</ParamField>

<ParamField path="format" type="enum" default="api">
  action:"get" — 'api' (default, recommended) converts to compact API format with named inputs, connection references, and \_meta.mode flags for muted/bypassed nodes; 'ui' returns the raw UI format with layout positions and links arrays. action:"strip" — 'api' (default) strips to the flat resolved graph; 'raw' returns the file/graph unchanged. Each action accepts only its own two values (this field is the union of what the two tools it replaces accepted) and refuses the third rather than guessing at an alias. Options: `ui`, `api`, `raw`.
</ParamField>

<ParamField path="path" type="string">
  action:"strip" / "slice" / "query" — Absolute server-side path to a workflow .json on disk (e.g. C:\Users\you\ComfyUI\user\default\workflows\pusa\_extend.json). Read directly from disk — no library lookup.
</ParamField>

<ParamField path="graph" type="object">
  action:"strip" / "slice" / "query" — Inline workflow JSON (UI format for "strip"/"slice"; UI or API for "query"), as an alternative to path/filename.
</ParamField>

<ParamField path="groups" type="string | string[]">
  action:"slice" (REQUIRED) — Group-title substrings (case-insensitive) whose output nodes seed the slice — CSV string or array, e.g. 'TEXT TO IMAGE,TXT' or \['extend','sampler']. Shared post-proc is pulled in via the closure.
</ParamField>

<ParamField path="image_path" type="string">
  action:"from\_image" (REQUIRED) — Absolute path to a ComfyUI-generated PNG file
</ParamField>

<ParamField path="view" type="enum" default="summary">
  action:"analyze" — summary (default): structured text with sections, node IDs, key settings, virtual wires, and full connection graph — best for AI understanding. overview: mermaid diagram showing sections as summary nodes with cross-section data flow. detail: mermaid diagram for one section (requires section parameter). list: text listing of all sections with data flow summary. flat: single mermaid flowchart of the entire workflow (best for small workflows). health: graph-health heuristics (disconnected nodes, duplicate model loads, orphaned branches, muted/bypassed). Options: `summary`, `overview`, `detail`, `list`, `flat`, `health`.
</ParamField>

<ParamField path="section" type="string">
  action:"analyze" — Section name for detail view. Use view='list' first to see available section names.
</ParamField>

<ParamField path="node_id" type="string">
  action:"prompt\_director" — Optional ComfyUI node id; omit to list all recent Prompt Director runtime states.
</ParamField>

<ParamField path="types" type="string[]">
  action:"query" — Keep nodes whose class\_type contains ANY of these (case-insensitive).
</ParamField>

<ParamField path="title" type="string">
  action:"query" — Keep nodes whose title contains this.
</ParamField>

<ParamField path="where" type="string[]">
  action:"query" — Widget predicates, ANDed: 'cfg>7', 'sampler\_name=euler', 'text\~sunset'.
</ParamField>

<ParamField path="ids" type="string | number[]">
  action:"query" — Keep exactly these node ids.
</ParamField>

<ParamField path="upstream_of" type="string | number">
  action:"query" — Scope to the dependency closure FEEDING this node id.
</ParamField>

<ParamField path="downstream_of" type="string | number">
  action:"query" — Scope to the nodes CONSUMING this node id's outputs.
</ParamField>

<ParamField path="depth" type="integer">
  action:"query" — Max hops from the traversal seed (seed=0). Absent = full closure.
</ParamField>

<ParamField path="fields" type="enum">
  action:"query" — Projection: compact one-liners (default), bare ids, or detail JSON rows. Options: `ids`, `compact`, `detail`.
</ParamField>

<ParamField path="group_by" type="enum">
  action:"query" — Aggregate: counts per class\_type instead of listing. Options: `type`.
</ParamField>

<ParamField path="limit" type="integer">
  action:"query" — Max nodes listed (default 40, max 200).
</ParamField>

<ParamField path="max_chars" type="integer">
  action:"query" — Output character bound (default 12000, max 60000). Raise this — not `limit` — when the truncation tail says the char budget cut the result.
</ParamField>

### Examples

**You say:** What workflows have I got saved?

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "list"
  }
}
```

**You get back:** A numbered list of names, each relative to the library root — one filed in a folder shows as VIDEO/MiniMaxH3/clip.json. Pick one and hand the whole name back as `filename`.

**You say:** Open my portrait workflow so we can change the prompt.

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "get",
    "filename": "portrait-flux.json"
  }
}
```

**You get back:** The full workflow as runnable API-format JSON. This is a big response — it is meant for the agent to work on, not for you to read.

**You say:** Give me the raw file exactly as ComfyUI saved it.

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "get",
    "filename": "portrait-flux.json",
    "format": "ui"
  }
}
```

**You get back:** The on-disk UI format, including node positions and colours — what you want if the file is going to be loaded back into the canvas rather than executed.

**You say:** What does my portrait workflow actually do?

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "analyze",
    "filename": "portrait-flux.json"
  }
}
```

**You get back:** A short summary: the model it loads, the prompts, the sampler settings, and what it saves.

**You say:** Is that workflow going to run, or is something missing?

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "analyze",
    "filename": "portrait-flux.json",
    "view": "health"
  }
}
```

**You get back:** Problems only — missing models, unconnected inputs, nodes whose packs are not installed.

**You say:** Which samplers in that graph are running above cfg 7?

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "query",
    "filename": "portrait-flux.json",
    "types": [
      "KSampler"
    ],
    "where": [
      "cfg>7"
    ]
  }
}
```

**You get back:** One line per matching node instead of the whole file — the only context-safe way to ask a question of a 100-node graph.

**You say:** How was this picture made?

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "from_image",
    "image_path": "C:/ComfyUI/output/ComfyUI_00042_.png"
  }
}
```

**You get back:** The workflow ComfyUI embedded in the PNG when it saved it, in both API and UI form — the way to reverse-engineer someone else's image.

**You say:** This graph is a mess of Get/Set nodes. What is actually wired to what?

```json theme={null}
{
  "tool": "get_workflow",
  "arguments": {
    "action": "strip",
    "path": "C:/ComfyUI/user/default/workflows/expert.json"
  }
}
```

**You get back:** The same graph with the virtual wiring resolved into real connections, plus a note wherever the stripped form DIFFERS from the source. Read those notes before running it.

***

## save\_workflow

WRITE to the ComfyUI user library: persist a workflow, or capture/verify its provenance lock. This is the only tool here that writes — reading is get\_workflow. Driven by the `action` parameter:

* action:"save" — Save a workflow JSON to the connected ComfyUI server's user library so it appears in the ComfyUI web UI. Requires a running ComfyUI server; this writes to that server's userdata and OVERWRITES any existing file with the same filename without confirmation. Web-UI-format JSON (\{ nodes: \[], links: \[] }) is saved as-is and is the preferred input — when re-saving an existing workflow, load it with get\_workflow (action:"get", format='ui') and modify THAT. API-format graphs (\{ '1': \{ class\_type, inputs } }) are AUTO-CONVERTED to Web UI format with a generated layout so the saved file always opens in the ComfyUI canvas (the canvas cannot open raw API format). Returns a confirmation message (noting the conversion and any warnings), or the HTTP status and error text on failure.
* action:"lock" — Capture a provenance lock for a saved workflow so it can be exactly reproduced later. Walks the workflow's model loaders (CheckpointLoaderSimple, UNETLoader, VAELoader, LoraLoader, ControlNetLoader, etc.), SHA-256s every referenced model file, records the git commit currently checked out for every custom node pack the workflow's class\_types come from, and captures ComfyUI's reported version. WRITES `&lt;filename&gt;.lock.json` next to the workflow in ComfyUI's user library. Requires a local install (COMFYUI\_PATH) — SHA-256 needs raw file bytes and pack commits come from `custom_nodes/*/.git/HEAD`. Pair with action:"verify\_lock" later to detect drift.
* action:"verify\_lock" — Compare a saved workflow's lock file against the current state of the local install and report drift. Loads `&lt;filename&gt;.lock.json`, re-computes a current lock from the same workflow, and diffs: which models have a different SHA-256, which custom node packs are on a different commit, whether ComfyUI's version changed. Use before re-running an important workflow days or weeks later to confirm it'll behave the same. Requires a local install (COMFYUI\_PATH). Read-only; returns a structured drift report (empty arrays everywhere mean perfect parity).

<Tip>**In plain terms:** The WRITE half of the library: store a workflow, or record/check the exact models and node-pack commits it ran against so it can be reproduced later.</Tip>

### Parameters

<ParamField path="action" type="enum" required>
  Which write/provenance operation to perform. All three require `filename`; "save" also requires `workflow`. Options: `action:"save"`, `action:"lock"`, `action:"verify_lock"`.
</ParamField>

<ParamField path="filename" type="string">
  Workflow filename in the ComfyUI user library (e.g. 'my\_workflow\.json'). REQUIRED for every action. For action:"save" this OVERWRITES an existing file of the same name; for "lock"/"verify\_lock" the lock is read/written as '\<filename>.lock.json' alongside it.
</ParamField>

<ParamField path="workflow" type="object">
  action:"save" (REQUIRED) — Workflow JSON to save. Web UI format (\{ nodes: \[], links: \[] }) is stored verbatim; API format (\{ '1': \{ class\_type, inputs } }) is auto-converted to Web UI format (generated layout) so it stays openable in ComfyUI's canvas. Not validated against the server before saving.
</ParamField>

### Examples

**You say:** Save that as a new file so I don't lose the original.

```json theme={null}
{
  "tool": "save_workflow",
  "arguments": {
    "action": "save",
    "filename": "portrait-flux-v2.json",
    "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:** Confirmation and the path it was written to.

<Warning>Writing to a filename that already exists replaces that file. Ask for a new name — as above — when you want to keep the original.</Warning>

**You say:** Pin this one down so it renders the same in six months.

```json theme={null}
{
  "tool": "save_workflow",
  "arguments": {
    "action": "lock",
    "filename": "portrait-flux-v2.json"
  }
}
```

**You get back:** A lock file written alongside the workflow, recording a SHA-256 for every model it loads and the git commit of every custom node pack it uses. Needs a local install — hashing reads the model files.

<Warning>This writes a second file (\<filename>.lock.json) and hashes every referenced model, which on a large install is minutes of disk work.</Warning>

**You say:** Has anything changed since I locked that workflow?

```json theme={null}
{
  "tool": "save_workflow",
  "arguments": {
    "action": "verify_lock",
    "filename": "portrait-flux-v2.json"
  }
}
```

**You get back:** A drift report: which models now hash differently, which node packs moved to a new commit, whether ComfyUI itself was updated. Empty everywhere means it will behave exactly as it did. Read-only.

***
