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),
89 lines (79 loc) • 2.72 kB
JavaScript
/**
* PostToolUse hook (unused — kept for reference).
* Finds and opens the most recently generated image from ComfyUI's output directory.
*
* Environment: Receives tool result JSON on stdin.
* Exit 0 = success (no blocking).
*/
import { readdirSync, statSync } from "node:fs";
import { join } from "node:path";
import { homedir, platform } from "node:os";
import { spawnSync } from "node:child_process";
// Read stdin (tool result JSON) — but we only care if it succeeded
let input = "";
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (chunk) => {
input += chunk;
});
process.stdin.on("end", () => {
try {
const data = JSON.parse(input);
// If tool returned an error, don't try to open anything
if (data.isError) process.exit(0);
} catch {
// Can't parse — proceed anyway
}
// Find ComfyUI output directory
const home = homedir();
const candidates = [
join(home, "Documents", "ComfyUI", "output"),
join(home, "My Documents", "ComfyUI", "output"),
join(home, "ComfyUI", "output"),
join(home, "AppData", "Local", "Programs", "ComfyUI", "resources", "ComfyUI", "output"),
];
let outputDir;
for (const dir of candidates) {
try {
statSync(dir);
outputDir = dir;
break;
} catch {
continue;
}
}
if (!outputDir) {
process.exit(0);
}
// Find newest image
try {
const files = readdirSync(outputDir)
.filter((f) => /\.(png|jpg|jpeg|webp)$/i.test(f))
.map((f) => {
const p = join(outputDir, f);
return { path: p, mtime: statSync(p).mtimeMs };
})
.sort((a, b) => b.mtime - a.mtime);
if (files.length === 0) process.exit(0);
const newest = files[0];
// Only open if it was modified in the last 30 seconds (likely from this generation)
if (Date.now() - newest.mtime > 30000) process.exit(0);
const os = platform();
if (os === "win32") {
// Keep the filename out of command syntax, including cmd.exe's parser.
const powershell = join(process.env.SystemRoot || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
spawnSync(powershell, ["-NoProfile", "-NonInteractive", "-Command", "Start-Process -FilePath $env:COMFYUI_MCP_OPEN_IMAGE"], {
stdio: "ignore",
shell: false,
env: { ...process.env, COMFYUI_MCP_OPEN_IMAGE: newest.path },
});
} else if (os === "darwin") {
spawnSync("open", [newest.path], { shell: false, stdio: "ignore" });
} else {
spawnSync("xdg-open", [newest.path], { shell: false, stdio: "ignore" });
}
} catch {
// Silent failure — don't interrupt the user's workflow
}
process.exit(0);
});