Skip to main content
Glama

duddy-comfyui

GitHub License: MIT

让 AI 在你的 ComfyUI 画布上干活,但每一笔都要你点头。

不是「AI 生成一份 workflow JSON 然后 POST 过去」,而是:AI 先提交一份分步计划,你在 ComfyUI 界面右下角的弹窗里看清楚每一步要建什么节点、连哪根线,点「同意」之后,它才一步一个节点地在你的画布上长出来。你全程看得见,随时能喊停。

你在聊天里说「搭个文生图链路」
   ↓
AI 在聊天里讲计划:建哪些节点、怎么连、大概几步   ← 此时画布纹丝不动
   ↓
你说「做」
   ↓
duddy_plan_workflow   →  后端自动逐步执行到底
   ↓
画布上节点一个接一个长出来,右下角播报「第 3/12 步」+ 一个停止按钮

确认发生在聊天里,不发生在弹窗里。 弹窗只是播报牌,不需要你点任何东西。

两种模式

模式

怎么开

行为

auto(默认)

什么都不用做

计划一提交就自动跑完,画布实时可见,随时可停

manual

DUDDY_REQUIRE_APPROVAL=1

恢复审批闸门:必须等前端点「同意」,token 才有效

auto 模式下 duddy_plan_workflow 就是执行动作,不是提案。 所以"先问后做"全靠技能层约束(skills/duddy-comfyui/SKILL.md 里写死了),而不是代码闸门。 manual 模式下才有代码级强制——这是用 0 和 1 换来的自由度。


Related MCP server: ComfyUI MCP Server

为什么要有这东西

现有的 ComfyUI MCP 方案(mcp-comfy-ui-builder、comfyui-mcp、comfymcp 等)几乎都是同一个模式:

LLM 生成完整 API-format JSON  →  POST /prompt  →  直接开跑

问题在于:你的画布上什么都没发生。出图了,但你不知道它建了什么、连了什么线、参数对不对。想改?只能重来。这对学习、调试、复用都是灾难。

duddy 换个路子:不碰 /prompt,只碰画布。所有操作都通过 litegraph 在前端执行,等价于「有人替你拖节点、拉线」,你能看见过程。


核心机制:为什么 AI 绕不过去

这是本项目的设计核心,也是它和别的 MCP 最大的区别。

三根钉子

钉子一:token 只走 WebSocket,不进 HTTP 响应

POST /duddy/plan          → 返回 plan_id,**不含 token**
   ↓
后端 send_sync("duddy.plan.proposed", {plan, token}, sid=<浏览器>)
   ↓
只有那个浏览器标签页收到 token

AI 客户端用的是 stdio + HTTP,不持有浏览器那条 WebSocket。它拿不到 token,就调不动 POST /duddy/plan/{id}/approve。

钉子二:MCP 层刻意不提供 approve 工具

你去 mcp_server/server.py 里翻,只有 duddy_apply_step,没有 duddy_approve_plan。不是忘了写——是不给 AI 这个能力。

钉子三:状态机在服务端强制

core/plan.py 里,begin_step() 第一件事就是检查:

if plan.state not in ("approved", "applying"):
    raise PlanError("必须先获得人类批准才能执行", 403, "not_approved")

跳步(expected_index 不符)、重放(重复回报同一 index)、非法跃迁,全部 403/409。没有「尽力而为」。

诚实说明边界

这三根钉子防的是**「AI 偷懒跳过审批流程」**——这是真实且高频的问题,实测有效。

它不防「AI 恶意攻击你自己的电脑」。本机上任何 Python 进程本来就是完全权限,可以 rm 你的硬盘、改你的 ComfyUI 源码。任何声称能防住这点的设计都是骗人。要看代码,别只看承诺。


安装

一键装

python install.py

它会:

  1. 从运行中的 ComfyUI 的 /system_stats 读 argv,精确定位安装路径(比你猜路径靠谱)

  2. 在 custom_nodes/ 下建一个目录联接/软链(Windows 用 Junction,不用管理员权限,改代码即时生效)

  3. 往 ~/.workbuddy/mcp.json / Claude Desktop 配置里登记 MCP

  4. 告诉你下一步

参数:

python install.py --dry-run              # 只看不动
python install.py --comfy "D:/AI/ComfyUI_windows_portable"
python install.py --no-mcp               # 只装 ComfyUI 侧
python install.py --force                # 覆盖旧链接

手动装

# 1. 把 comfyui_duddy 放进 custom_nodes
#    Windows: mklink /J "ComfyUI\custom_nodes\duddy-comfyui" "本仓库\comfyui_duddy"
#    Linux/mac: ln -s "$PWD/comfyui_duddy" "ComfyUI/custom_nodes/duddy-comfyui"

# 2. 重启 ComfyUI,刷新浏览器

# 3. 验证
curl http://127.0.0.1:8188/duddy/ping

返回 {"ok": true, ...} 就通了。

接 MCP 客户端

WorkBuddy / Claude Desktop(install.py 自动写,手动的话):

{
  "mcpServers": {
    "duddy": {
      "command": "D:/AI/ComfyUI_windows_portable/python_embeded/python.exe",
      "args": ["D:/github/wuddy/duddy-comfyui/mcp_server/server.py"],
      "env": { "COMFY_URL": "http://127.0.0.1:8188" }
    }
  }
}

Hermes(~/.hermes/config.yaml):

mcp_servers:
  duddy:
    command: 'D:/AI/ComfyUI_windows_portable/python_embeded/python.exe'
    args: ['D:/github/wuddy/duddy-comfyui/mcp_server/server.py']
    env:
      COMFY_URL: 'http://127.0.0.1:8188'

MCP server 是零依赖的(只用标准库手写 JSON-RPC),所以直接用 ComfyUI 自带的嵌入式 Python 就行,不用另外配环境。


工具清单

工具

干什么

谁能调

duddy_ping

检查扩展在不在线

AI

duddy_plan_workflow

提交计划(只规划,不动手)

AI

duddy_plan_status

查状态、进度、下一步

AI

duddy_apply_step

执行下一步(必须已获批)

AI

duddy_list_plans

最近计划列表

AI

duddy_abort_plan

中止

AI

duddy_canvas_state

读当前画布快照

AI

duddy_events

事件流(排障)

AI

POST /duddy/plan/{id}/approve

审批

只有浏览器前端


计划怎么写

steps 里每一项是一个操作。别贪,一个节点一步、一条线一步——这样你在画布上才能看见它一个个长出来。

{
  "title": "最小文生图链路",
  "summary": "从零搭一条能出图的最短路径",
  "steps": [
    {
      "kind": "create_node",
      "title": "建 Checkpoint 加载器",
      "why": "整条链的起点",
      "args": { "type": "CheckpointLoaderSimple", "ref": "ckpt", "pos": [100, 200] }
    },
    {
      "kind": "create_node",
      "title": "建正向提示词",
      "why": "描述要画什么",
      "args": { "type": "CLIPTextEncode", "ref": "pos", "pos": [450, 120] }
    },
    {
      "kind": "connect",
      "title": "CLIP → 正向提示词",
      "why": "文本编码需要 CLIP",
      "args": { "from_ref": "ckpt", "from_slot": 1, "to_ref": "pos", "to_slot": 0 }
    }
  ]
}

关键:用别名(ref)而不是 node_id

规划时节点还不存在,AI 不可能知道 ComfyUI 会分配什么 id。所以:

  • create_node 必须给 ref(自己起名,如 ckpt)

  • connect / set_widget / move_node 用 from_ref / to_ref / ref 引用

  • 前端执行时维护 ref → 真实 node 的映射

这样 AI 只描述「谁连谁」,不会猜错 id,也不会因为顺序变化而全盘崩。

支持的 kind

kind

必填参数

说明

create_node

type

可选 ref pos widgets title color

connect

from_ref/from_slot/to_ref/to_slot

槽位从 0 开始

set_widget

ref widget value

改参数

move_node

ref pos

摆位置

delete_node

ref

删掉

note

—

纯注释,跳过


HTTP API

所有路由在 /duddy 前缀下。

方法

路径

说明

GET

/duddy/ping

存活检查

GET

/duddy/health

详细状态(客户端、画布、事件总线)

GET

/duddy/capabilities

能力表

POST

/duddy/client/hello

前端报到

POST

/duddy/plan

创建计划

GET

/duddy/plan/{id}

计划详情

POST

/duddy/plan/{id}/approve

审批(需 token)

POST

/duddy/plan/{id}/reject

拒绝

POST

/duddy/plan/{id}/step

执行下一步

POST

/duddy/plan/{id}/abort

中止

POST

/duddy/canvas/state

前端上报画布

POST

/duddy/canvas/applied

前端回报执行结果

GET

/duddy/events

事件流

WebSocket 事件(ComfyUI 原生 /ws):

事件

方向

携带

duddy.plan.proposed

后端 → 前端

plan + token

duddy.plan.approved

后端 → 前端

plan_id

duddy.canvas.op

后端 → 前端

一步操作

duddy.canvas.applied

后端 → 前端

执行结果

duddy.plan.done / failed

后端 → 前端

plan_id


已知陷阱:执行进度需要 client_id

ComfyUI 的 execution.py 里是这样发执行事件的:

if server.client_id is not None:
    server.send_sync("executing", {...}, server.client_id)

没有 client_id 时它什么都不发。 这意味着:

  • 浏览器点 Queue → api.queuePrompt 自动带 clientId → 进度正常

  • 脚本直接 POST /prompt → 必须自己带 "client_id": "xxx",否则 duddy_run_status 永远是 idle

不是 bug,是 ComfyUI 的设计(避免无谓广播)。写在这里免得下次又怀疑进度模块坏了。

排障

/duddy/ping 连不上

  1. ComfyUI 重启过吗?(自定义节点只在启动时扫描)

  2. custom_nodes/duddy-comfyui 存在吗?

  3. 控制台有没有 [duddy] v0.1.0 ready?

弹窗不出来

  • F12 控制台看有没有 [duddy] extension setup

  • 没有 → 前端扩展没加载,硬刷新(Ctrl+Shift+R)

  • 有但没有弹窗 → duddy_events 看 duddy.plan.proposed 发出去了没

apply 一直 403

  • 这是正常拦截。说明你还没点「同意」。

  • 去 ComfyUI 页面右下角找弹窗。

节点建不出来

  • 前端回报 unknown_node_type 说明缺插件,去 ComfyUI-Manager 装

  • connect_rejected 说明类型不匹配,看回报里的 from.type / to.type


能力矩阵

能力

状态

说明

画布建节点 / 连线 / 改参数 / 移动 / 删除

已实现

litegraph 原生操作,实时可见

节点知识库

已实现

从运行时注册表同步,本机 1301 个类型

计划预检

已实现

类型 / 参数名 / 模型文件三重校验,动手前拦截

执行进度

已实现

hook send_sync,节点级 + 步数 + ETA

实时日志

已实现

logging Handler + stdout 劫持

文件变更监控

已实现

零依赖轮询,2s 间隔

失败回滚

已实现

撤销已建的节点和连线

代跑图

已实现

execute kind,graphToPrompt + queuePrompt

subgraph / group

未实现

返回 skipped

路线图

  • M0 骨架 + WebSocket 事件总线 + 安装器

  • M1 plan / approve / apply 强制闸门 + 节点逐条长出

  • M2 画布能力补全(delete/batch/group)+ 位置自动排布

  • M3 执行进度追踪(跑到第几步、哪个节点、ETA)

  • M4 实时日志流(侧栏滚动、按级别过滤)

  • M5 文件监控(custom_nodes / models 增删改即时感知)

  • M6 节点知识库(从 /object_info 自动同步,规划不瞎编)

  • M7 技能包 + 跨客户端一键接入

  • M8 文档 + 发布


协议版本

duddy/1。事件里都带 v、seq、ts、type、data。

License

MIT。拿去改,改成你自己的也行。

Available Tools

16 tools
duddy_abort_planB

中止一个尚未完成或已失败的流程。用户说「停」时立刻调。

Inputs: plan_id (required), reason.

duddy_apply_stepA

【第二步·逐个动手】执行计划的下一步,一次只走一步。

前置条件:用户已经在 ComfyUI 弹窗里点了「同意」,plan.state == approved/applying。 如果返回 403 not_approved,说明用户还没批准。此时你必须停下来,告诉用户「请在弹出的窗口里点同意」,然后等待。 严禁尝试其它方式绕过(直接 POST /prompt、写 workflow 文件、批量推送都不行)。

返回里会告诉你这一步建了/连了什么、真实 node_id、剩余步数。把结果用一句话回报给用户,再决定要不要继续下一步。

Inputs: plan_id (required), expected_index.

duddy_canvas_stateA

读取用户当前画布的快照(节点数、连线数、完整 graph)。规划前先看一眼现有画布,避免重复建节点或位置重叠。

Inputs: include_graph.

duddy_eventsB

最近的事件流,排查「为什么没反应」时用(弹窗没弹、前端没回报等)。

Inputs: limit, prefix.

duddy_fs_changesA

最近哪些文件变了:新增/修改/删除了哪些模型、插件、工作流。用户说「我刚装了个节点」或者怀疑文件被改时用。

Inputs: limit.

duddy_get_logsA

读 ComfyUI 的运行日志(包含节点里的 print)。出图报错、加载失败、卡住不动时,先看日志再猜原因。

Inputs: level, limit, contains.

duddy_list_modelsA

列出模型文件。不带 folder 时返回所有模型目录名;带 folder 返回该目录下的文件名。写死模型名之前查一下,避免文件不存在。

Inputs: folder.

duddy_list_plansB

列出最近的计划及其状态。用户问「刚才那个计划呢」时用。

Inputs: limit.

duddy_node_infoA

查某个节点类型的完整定义:需要哪些输入、有哪些 widget、可选值是什么、输出什么。写 widgets 之前必须查,否则参数名写错会直接失败。

Inputs: node_type (required).

duddy_pingA

检查 duddy 扩展是否在线。第一次接触 ComfyUI 时先调这个,能立刻区分「ComfyUI 没开」和「扩展没装」两种故障。

Inputs: no named parameters.

duddy_plan_statusA

查某个计划的状态与进度。执行每一步之前都应该先看一眼,确认 state 是 approved 或 applying,以及 cursor 指向第几步。

Inputs: plan_id (required).

duddy_plan_workflowA

【第一步·只规划,绝不动手】把你想在画布上做的事写成一个分步计划,推送给用户的 ComfyUI 界面,等待用户点击「同意」。

硬性要求: · 每个 step 只做一件事,粒度要细(一个节点一步、一条连线一步) · create_node 必须给 ref 别名,后续 connect/set_widget 用别名引用,不要猜 node_id · connect 用 from_ref/from_slot → to_ref/to_slot · 每步给 title(人类可读)和 why(为什么需要这一步)

调用后你会拿到 plan_id 和 state=proposed。此时什么都不会发生,直到用户在弹窗里点同意。 直接把 narration 字段念给用户听,然后停下来等。

Inputs: steps (required), title (required), summary (required), notes.

duddy_precheck_planA

只检查不执行:把计划丢进来,看它在这台机器上跑不跑得通(节点在不在、参数名对不对、模型文件有没有)。不确定的活儿先 precheck 一下,比失败后再回滚便宜。

Inputs: steps (required).

duddy_rollback_planA

把某个计划已经做过的建节点/连线动作撤销掉。执行到一半失败、或者用户说「撤了重来」时用。注意:删除节点和改参数无法撤销,只有新建的能撤。

Inputs: plan_id (required).

duddy_run_statusA

当前跑到哪一步了:哪个节点、第几步/共几步、已完成哪些、预计还要多久、有没有报错。用户问「跑到哪了」或你想确认任务是否结束时调。

Inputs: no named parameters.

duddy_search_nodesA

搜索这台机器上真实存在的节点类型。【规划前必查】不要凭记忆写节点名,先搜一下确认它真的装了。

Inputs: q (required), limit.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 16 tools

    Disambiguation4/5

    Most tools have clearly distinct purposes across discovery, planning, execution, and diagnostics. There is minor overlap between duddy_plan_status and duddy_run_status, and among duddy_events, duddy_get_logs, and duddy_fs_changes for troubleshooting, but the descriptions provide enough context to distinguish them.

    Naming Consistency4/5

    All tools share the duddy_ prefix and snake_case formatting, making the set predictable. Most names follow a verb_noun pattern, though a few are noun phrases such as duddy_events, duddy_node_info, duddy_canvas_state, duddy_run_status, and duddy_fs_changes.

    Tool Count4/5

    At 16 tools, the set is slightly above the typical 3-15 range but remains well-scoped for a workflow planning and execution server. Each tool maps to a distinct phase such as discovery, planning, approval, execution, rollback, or diagnostics, so the count does not feel bloated.

    Completeness5/5

    The surface covers the full lifecycle: node/model discovery, plan creation, prechecking, approval status, step execution, run status, abort, rollback, and diagnostic logs/events. The documented rollback limitation is a known constraint rather than an obvious missing operation.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers