comfyui-mcp
Version:
Local-first, agent-native control plane for ComfyUI — MCP server + autonomous sidebar agent that drives your live graph in natural language on ANY LLM: Claude/ChatGPT/Gemini on your subscription (no API key), free local models via Ollama (fully offline),
96 lines • 3.81 kB
JavaScript
import { createWorkflow } from "./workflow-composer.js";
import { DefaultsManager } from "./defaults-manager.js";
import { ValidationError } from "../utils/errors.js";
const DEFAULTABLE_KEYS = [
"negative_prompt",
"width",
"height",
"steps",
"cfg",
"sampler",
"scheduler",
"seed",
"checkpoint",
];
function withDefaults(args) {
const seed = {};
for (const key of DEFAULTABLE_KEYS) {
const v = args[key];
if (v !== undefined)
seed[key] = v;
}
return DefaultsManager.apply(seed);
}
async function resolveCheckpointOrThrow(explicit, resolved, resolveCheckpoint) {
let checkpoint = explicit ?? resolved.checkpoint;
if (!checkpoint)
checkpoint = await resolveCheckpoint();
if (!checkpoint) {
throw new ValidationError("No checkpoint specified, defaulted, or found locally. " +
"Pass `checkpoint`, set a default via get_defaults (action:\"set\"), or download one with download_model.");
}
return checkpoint;
}
function commonTemplateParams(args, resolved, checkpoint) {
return {
checkpoint,
positive_prompt: args.prompt,
negative_prompt: resolved.negative_prompt,
width: resolved.width,
height: resolved.height,
steps: resolved.steps,
cfg: resolved.cfg,
seed: resolved.seed,
sampler_name: resolved.sampler,
scheduler: resolved.scheduler,
};
}
/**
* Build + enqueue a ControlNet-conditioned txt2img workflow. `control_image`
* must already exist in ComfyUI's input dir (use upload_image (action:"image") first).
*/
export async function generateWithControlNet(args, deps) {
if (!args.control_image) {
throw new ValidationError("control_image is required (upload it first with upload_image (action:\"image\"))");
}
const resolved = withDefaults(args);
const checkpoint = await resolveCheckpointOrThrow(args.checkpoint, resolved, deps.resolveCheckpoint);
let controlnetModel = args.controlnet_model;
if (!controlnetModel && deps.resolveControlNetModel) {
controlnetModel = await deps.resolveControlNetModel();
}
if (!controlnetModel) {
throw new ValidationError("No controlnet_model specified and none found locally. Pass `controlnet_model` " +
"(a file in models/controlnet/) or download one with download_model.");
}
const workflow = createWorkflow("controlnet", {
...commonTemplateParams(args, resolved, checkpoint),
control_image: args.control_image,
controlnet_model: controlnetModel,
strength: args.strength,
});
const { prompt_id, queue_remaining } = await deps.enqueue(workflow);
return { prompt_id, queue_remaining, checkpoint };
}
/**
* Build + enqueue an IP-Adapter-conditioned txt2img workflow. Requires the
* ComfyUI_IPAdapter_plus custom nodes. `reference_image` must already exist in
* ComfyUI's input dir (use upload_image (action:"image") first).
*/
export async function generateWithIpAdapter(args, deps) {
if (!args.reference_image) {
throw new ValidationError("reference_image is required (upload it first with upload_image (action:\"image\"))");
}
const resolved = withDefaults(args);
const checkpoint = await resolveCheckpointOrThrow(args.checkpoint, resolved, deps.resolveCheckpoint);
const workflow = createWorkflow("ip_adapter", {
...commonTemplateParams(args, resolved, checkpoint),
reference_image: args.reference_image,
weight: args.weight,
preset: args.preset,
weight_type: args.weight_type,
});
const { prompt_id, queue_remaining } = await deps.enqueue(workflow);
return { prompt_id, queue_remaining, checkpoint };
}
//# sourceMappingURL=generate-conditioned.js.map