Skip to content

Getting started

doorcommandwhen
npxnpx @mcptoolshop/comfy-preflight check graph.jsonyou want to look at a graph and have no Python
pippip install comfy-preflightyou are going to call it from Python — which is the production path
MCPpip install "comfy-preflight[mcp]"an agent session is hand-driving a graph

The npx door downloads a PyInstaller binary from the GitHub Release and verifies its SHA256 against the checksums published in that same release before running it. No Python is needed on the machine.

Supported: Python ≥ 3.11; binaries for linux-x64 and win-x64. macOS binaries are not built — the org drops macOS runners at roughly ten times Linux cost — so macOS users install via pip, which works everywhere.

Terminal window
npx @mcptoolshop/comfy-preflight check graph.json

On any of the 70 recorded graphs this repo tests against, that prints:

verdict: NOT_APPLICABLE

That is the correct answer, and it is worth understanding before anything else. Two checks could not be asked: check 4 has no saved sidecar to compare against, and check 5 has no frame to look at, because every recorded graph is img2img and the frame lives in the uploaded image rather than in the graph. Reporting PASS there would claim work that was never done.

Give it the missing operands and the run becomes answerable:

Terminal window
npx @mcptoolshop/comfy-preflight check graph.json \
--input-dims 1072x1024 \
--saved saved-sidecar.json \
--register subject.json \
--consumer 6.model

Every optional flag is an askability parameter: supplying it makes a clause askable, and omitting it makes a check decline and name what it could not see. None of them turns a check off, and there is no flag that does.

flagunlocks
--input-dims WxHcheck 5. The operand is the input image’s dimensions — this package never decodes an image, so you supply them
--saved PATHcheck 4’s saved-vs-submitted comparison
--register PATHcheck 2. The gate’s reference must come from the subject, not from the graph it gates
--consumer NODE.INPUTcheck 2’s consumer-link clause, e.g. 6.model
--schema PATHcheck 1’s third clause, as {class_type: [input names]}
--jsonthe structured result, which is what the MCP tool returns too
--debugre-raise an internal error with its traceback instead of reporting it structurally
{
"declared": false,
"known_cards": [
"house_style_v2.safetensors",
"other-namespace__house_style_v2.safetensors"
]
}

declared: false is the no-adapter condition, and the claim it makes is not “the weight is 0.0” — it is that no loader node and no card reference exist anywhere in the graph.

For a subject that does use an adapter:

{
"declared": true,
"card": "house_style_v2.safetensors",
"weight": 0.75,
"card_aliases": ["other-namespace__house_style_v2.safetensors"]
}

card_aliases exists because the recorded corpus carries two names for one adapter — the same weights re-imported under a different cloud-side namespace, differing in the whole basename. Equivalence is declared, never inferred: a prefix-stripping heuristic would also accept a genuinely wrong card whose name happened to share a tail.

Unknown keys are rejected rather than ignored. A misspelled known_card silently dropped would empty the vocabulary, and check 2 would then decline the very clause the misspelling was meant to enable — a typo turning a gate off quietly.

Terminal window
python verify.py

Runs the suite in all three interpreter modes, builds sdist and wheel, then installs the wheel into a clean venv and runs a real verb from outside the checkout. --version is kept in that script as a labelled floor, not the gate: it touches no graph, so it stays green through exactly the packaging defects that break a user.