save_workflow_template
Save a ComfyUI workflow as a named template for later use. Prevent accidental overwrites with an optional overwrite flag.
Instructions
Save a ComfyUI workflow JSON to the server's template registry under a named slot. Overwrites are disabled by default.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Template name. Letters, digits, '-', '_'; max 64 chars. Must start alphanumeric. | |
| workflow | Yes | Complete ComfyUI workflow JSON (from ComfyUI's 'Save (API Format)'). | |
| description | No | ||
| overwrite | No | Allow overwriting an existing template with the same name. |
Implementation Reference
- src/tools/templates.ts:75-124 (handler)The handler function for the 'save_workflow_template' tool. It validates the name, checks if template exists, optionally overwrites, creates/updates a StoredTemplate record, and writes to disk as JSON.
server.tool( "save_workflow_template", "Save a ComfyUI workflow JSON to the server's template registry under a named slot. Overwrites are disabled by default.", saveSchema, async (args) => { validateName(args.name); const file = templatePath(store.dir, args.name); let existed = false; try { await fs.access(file); existed = true; } catch { existed = false; } if (existed && !args.overwrite) { throw new Error( `Template "${args.name}" already exists. Pass overwrite=true to replace it.`, ); } const now = new Date().toISOString(); let createdAt = now; if (existed) { try { const prior = JSON.parse( await fs.readFile(file, "utf-8"), ) as StoredTemplate; createdAt = prior.createdAt ?? now; } catch { // ignore parse failure, treat as fresh create } } const record: StoredTemplate = { name: args.name, description: args.description, createdAt, updatedAt: now, workflow: args.workflow as Workflow, }; await fs.writeFile(file, JSON.stringify(record, null, 2)); return { content: [ { type: "text" as const, text: existed ? `Updated template "${args.name}" at ${file}` : `Saved template "${args.name}" at ${file}`, }, ], }; }, - src/tools/templates.ts:38-54 (schema)Zod schema for the 'save_workflow_template' tool inputs: name (string), workflow (record), description (optional string), overwrite (boolean, default false).
const saveSchema = { name: z .string() .describe( "Template name. Letters, digits, '-', '_'; max 64 chars. Must start alphanumeric.", ), workflow: z .record(z.string(), z.any()) .describe( "Complete ComfyUI workflow JSON (from ComfyUI's 'Save (API Format)').", ), description: z.string().optional(), overwrite: z .boolean() .default(false) .describe("Allow overwriting an existing template with the same name."), }; - src/server.ts:48-48 (registration)Registration call: registerTemplateTools(s, client, templateStore) wire up the tool in the MCP server.
registerTemplateTools(s, client, templateStore); - src/tools/templates.ts:70-125 (registration)The registerTemplateTools function that calls server.tool('save_workflow_template', ...) to register the tool with the MCP server.
export function registerTemplateTools( server: McpServer, client: ComfyUIClient, store: TemplateStore, ): void { server.tool( "save_workflow_template", "Save a ComfyUI workflow JSON to the server's template registry under a named slot. Overwrites are disabled by default.", saveSchema, async (args) => { validateName(args.name); const file = templatePath(store.dir, args.name); let existed = false; try { await fs.access(file); existed = true; } catch { existed = false; } if (existed && !args.overwrite) { throw new Error( `Template "${args.name}" already exists. Pass overwrite=true to replace it.`, ); } const now = new Date().toISOString(); let createdAt = now; if (existed) { try { const prior = JSON.parse( await fs.readFile(file, "utf-8"), ) as StoredTemplate; createdAt = prior.createdAt ?? now; } catch { // ignore parse failure, treat as fresh create } } const record: StoredTemplate = { name: args.name, description: args.description, createdAt, updatedAt: now, workflow: args.workflow as Workflow, }; await fs.writeFile(file, JSON.stringify(record, null, 2)); return { content: [ { type: "text" as const, text: existed ? `Updated template "${args.name}" at ${file}` : `Saved template "${args.name}" at ${file}`, }, ], }; }, ); - src/tools/templates.ts:30-36 (helper)StoredTemplate interface defining the shape of saved template data (name, description, createdAt, updatedAt, workflow).
interface StoredTemplate { name: string; description?: string; createdAt: string; updatedAt: string; workflow: Workflow; }