Skip to main content
Glama

rh-agent-bridge

中文 | English


中文

rh-agent-bridge

License Node.js TypeScript MCP Tests

Agent-neutral 的 RunningHub / ComfyUI 工作流控制层 —— 让编程智能体用「工作流语义」而不是「鼠标坐标」操作 RunningHub。

rh-agent-bridge 是一个面向编程智能体(Codex、Zcode 或任何支持 MCP / CLI 的调用方)的本地工具。它向上提供稳定的结构化工具接口,向下对接 RunningHub 官方 OpenAPI 与 Native ComfyUI 接口,只在 API 确实无法表达时才返回结构化的浏览器兜底请求(由宿主智能体执行)。

当前状态:P0/MVP + P0.1 Hardening(v0.1.1)——P0.1 修复了 /models 契约、连接类型校验、baseline 快照语义、nodeInfoList 绕过、graph key/id invariant 等安全与正确性问题。

Related MCP server: comfyui-mcp

项目简介 / Overview

在节点式编辑器(如 ComfyUI)上使用通用浏览器 Agent 时,常见痛点是:节点坐标漂移、连线动作脆弱、页面改版后选择器失效、每次都要重新「看网页」——而其中绝大多数操作其实早已有官方 API。

本项目把 RunningHub 工作流抽象为结构化图(WorkflowGraph),提供 parse / inspect / diff / mutate / validate / serialize 全套纯函数能力,并按官方建议将修改分流:参数覆盖走 nodeInfoList,拓扑变化走完整 workflow JSON。节点目录在运行时从 ComfyUI /object_info 动态发现,找不到的节点就是 NODE_NOT_FOUND,绝不凭空编造。

项目功能 / Features

  • API-first:优先 RunningHub 官方 OpenAPI(任务创建、输出查询、素材上传、workflow 获取),其次 Native ComfyUI(/proxy/<key>),浏览器只是最后兜底

  • 结构化图引擎:API Format JSON ⇄ WorkflowGraph 双向转换;节点查询、不可变 patch(set_input / add_node / remove_node / connect / disconnect)、图 diff、拓扑环检测

  • 参数与拓扑分流:仅参数变化自动生成官方 nodeInfoList;拓扑/连接变化自动切换完整 workflow JSON 提交(官方明确不建议用 nodeInfoList 改连接)

  • 分层静态校验:Level 1 结构引用/环检测 → Level 2 基于 /object_info 的节点、输入与连接类型校验(outputIndex 越界、连接进入 primitive 字段、MODEL→IMAGE 类型不匹配)→ Level 3 模型名校验(优先级:object_info COMBO options → /models/{folder} → 字段名 fallback);服务端 promptTips 解析为结构化校验结果

  • Native 能力探测:运行时 feature-detect /features/object_info/models(folder 列表),模型文件按需 GET /models/{folder} 懒加载;探测失败自动降级,不影响 OpenAPI 主链路,逐端点明细(endpoint + status)对 Agent 可见

  • 安全兜底:浏览器 fallback 返回结构化目标(语义 goal + 域名 allowlist + 前置快照),由宿主智能体用自己的浏览器能力执行

  • 双出口同源:CLI(--json Agent 模式)与 MCP server 共用同一 service 层,13 个工具一一对应

  • 日志双层脱敏:API key 明文、/proxy/<key>、Bearer token、signed URL 全部 mask;create task / upload 默认禁止自动重试(防重复收费)

演示 / Demo

本项目是命令行 / 协议层工具,暂无图形界面截图。以下为两个可运行 demo 的流程概览(脚本见 examples/):

Demo A — 纯参数修改(全程无浏览器)

fetch workflow → 定位 prompt 节点 → set prompt → set seed
→ run by nodeInfoList → wait outputs

Demo B — 拓扑修改

fetch workflow → probe nodes(/object_info) → node search 确认节点存在
→ add node → connect → validate → run by full workflow JSON → wait outputs
(目标节点不存在时明确返回 NODE_NOT_FOUND,绝不编造节点名)

Demo C — 浏览器兜底(host 模式):对 control_after_generate 这类 API Format 中不存在的前端字段,patch 自动返回 requiresBrowser 结构化请求(含快照路径与回滚后置条件),见 examples/demo-c-browser-fallback.md

运行方式见 使用方法

环境要求 / Requirements

依赖

版本

说明

Node.js

≥ 20

需原生 fetch / FormData

npm

≥ 10

随 Node 20 附带

RunningHub 账号

需要有效 API key(官方文档获取);仅本地纯图操作不需要

安装与配置 / Installation

git clone https://github.com/yangxijia111/rh-agent-bridge.git
cd rh-agent-bridge
npm install
npm test        # 165 个测试全部基于 mock,无需真实 key

复制 .env.example.env 并填写(.env 已被 .gitignore 排除,严禁提交):

RUNNINGHUB_API_KEY=<必填,RunningHub API key>
RUNNINGHUB_BASE_URL=https://www.runninghub.ai     # 默认值
RUNNINGHUB_WORKFLOW_ID=<可选,默认 workflow id>
RUNNINGHUB_NATIVE_MODE=standard                    # standard(24GB) | plus(48GB)
RH_BROWSER_MODE=host                               # host | cdp(未实现,预留)
RH_CDP_URL=                                        # 仅 cdp 模式使用
RH_LOG_LEVEL=info

使用方法 / Usage

CLI(与 MCP 共用同一 service 层)

alias rh='npm run --silent dev --'

rh doctor                                          # 环境体检(key + native 能力探测)

rh workflow fetch <WORKFLOW_ID> --out workflow.api.json
rh workflow inspect workflow.api.json --query KSampler
rh workflow set-input workflow.api.json \
  --node 6 --field text --value "product photo" --out modified.json
rh workflow patch workflow.api.json \
  --ops '[{"type":"add_node","classType":"ImageUpscaleWithModel"},
          {"type":"connect","fromNode":"8","outputIndex":0,"toNode":"10","input":"image"}]' \
  --out modified.json
rh workflow validate modified.json --no-node-schema
rh workflow diff workflow.api.json modified.json

rh workflow run --workflow-id <ID> --file modified.json   # 自动 diff 选执行模式
rh workflow run --workflow-id <ID> --set 6.text="hi" --set 3.seed=42
rh task outputs <TASK_ID>
rh task wait <TASK_ID> --timeout-ms 600000

rh resource upload ./input.png       # 返回 fileName(相对路径,不是公共 URL)
rh nodes probe                       # /features /object_info /models 探测
rh nodes search "remove background"  # 节点目录搜索

rh browser fallback-request --workflow-id <ID> --goal "..."

workflow run --file 会先 fetch 远端原版并 diff:仅参数变化 → 转 nodeInfoList 提交;拓扑/连接变化 → 完整 workflow JSON 提交(并自动保存快照到 ~/.rh-agent/snapshots/)。

--json 为 Agent 模式:stdout 只输出 JSON(错误也结构化 {"error":{"code","message","retryable"}}),日志走 stderr。

MCP

{
  "mcpServers": {
    "rh-agent-bridge": {
      "command": "node",
      "args": ["dist/mcp/server.js"],
      "cwd": "/absolute/path/to/rh-agent-bridge",
      "env": { "RUNNINGHUB_API_KEY": "<your-key>" }
    }
  }
}

暴露 13 个工具(描述均为可决策式写法,便于 Agent 自动选路):

工具

用途

幂等

rh_doctor

配置与 native 能力体检

rh_workflow_fetch

获取 API Format → 结构化 graph

rh_workflow_inspect

节点列表 / 搜索

rh_workflow_diff

图 diff

rh_workflow_patch

set_input / add / remove / connect / disconnect

✅(不落远端)

rh_workflow_validate

分层静态校验

rh_workflow_run

提交任务(不自动重试,产生费用

rh_task_outputs

查询输出 / 状态

rh_task_wait

轮询到终态(支持 MCP cancellation)

rh_resource_upload

上传素材(≤30MB)

rh_nodes_probe

native 能力探测 + 节点目录构建

rh_node_search

节点目录搜索

rh_browser_fallback_request

结构化浏览器兜底请求

Demo 脚本(真实账号,消耗算力配额)

RUNNINGHUB_API_KEY=<key> npm run demo:a -- <WORKFLOW_ID>   # 纯参数,全程无浏览器
RUNNINGHUB_API_KEY=<key> npm run demo:b -- <WORKFLOW_ID>   # 探测→加节点→连线→全量运行

项目目录结构 / Project Structure

rh-agent-bridge/
├── src/
│   ├── config/            环境配置 · 日志脱敏 · pino logger
│   ├── errors.ts          统一 RhError 错误模型(code + retryable + toJSON)
│   ├── clients/
│   │   ├── runninghub/    官方 OpenAPI client(zod 校验 / 超时 / 受控重试)
│   │   └── comfy/         Native ComfyUI client + capability probe
│   ├── graph/             纯函数图引擎(parse / serialize / inspect / mutate /
│   │                      diff / validate / topology / execution,零网络依赖)
│   ├── catalog/           object_info 适配器 + TTL 缓存 + 节点目录服务
│   ├── browser/           host 模式 BrowserAdapter(语义 goal + 域名 allowlist)
│   ├── services/          Workflow / Task / Resource / BrowserFallback 服务 + 快照存储
│   ├── tools/             13 个工具 + registry(zod 输入 schema)
│   ├── cli/               commander CLI(--json Agent 模式)
│   └── mcp/               MCP stdio server
├── tests/                 165 个测试 + workflow fixtures + API contract fixtures
├── examples/              Demo A/B 脚本 + Demo C 说明
├── .env.example           环境变量模板
└── package.json / tsconfig.json / vitest.config.ts / eslint.config.js

核心功能说明

1. 参数 vs 拓扑的执行分流

修改工作流后,工具计算图 diff 并按官方建议选择提交方式:

仅 primitive 输入变化(prompt / seed / steps / 图片文件名 …)
    → workflowId + nodeInfoList(模板 + 参数覆盖)

新增/删除节点、改连接、class_type 变化、连接值被常量替换
    → workflowId + workflow=<完整 JSON string>(执行前强制保存快照)

若 diff 含连接变化仍试图转 nodeInfoList,工具抛出 UNSUPPORTED 并明确说明原因——这是官方文档明确不建议的路径。

2. 分层校验

层级

内容

依赖

Level 1

引用存在性、自引用、outputIndex、环检测

Level 2

节点类存在性、required 输入、类型/枚举/范围,以及连接五要素校验(上游/下游存在、outputIndex 越界、连接进入 primitive 字段 CONNECTION_NOT_ALLOWED、类型不匹配 CONNECTION_TYPE_MISMATCH;未知 custom datatype 降级 warning 避免误报)

/object_info(缺失自动跳过)

Level 3

模型名校验,优先级:object_info 该字段 COMBO options → GET /models/{folder}(checkpoints/loras/vae/upscale_models)→ 字段名 fallback

上述任一(缺失自动跳过)

服务端

promptTips → 结构化 valid / nodeErrors / outputsToExecute

任务创建响应

3. 节点目录与反 hallucinate

节点目录在运行时从 Native ComfyUI /object_info 获取(TTL 缓存:object_info 10 分钟 / models folder 5 分钟 / features 30 分钟)。/models 按 ComfyUI Server 语义返回 folder 名称列表["checkpoints", "loras", ...]),具体模型文件按需 GET /models/{folder} 懒加载并独立 TTL 缓存;单个 folder 404 是合法降级,不影响其余能力。查找节点失败会强制刷新一次,仍不存在则返回 NODE_NOT_FOUND——工具不会编造任何节点类名。

4. 快照语义(baseline / candidate)

  • baseline snapshot = mutation / run 之前的远端当前状态(rollback 依据)。full workflow run 与浏览器兜底前必须保存,且必须来自远端 fetch——Agent 本地修改过的 graph 不可作为 rollback baseline;

  • candidate snapshot = 即将提交执行的候选状态(full workflow run 时一并保存,便于审计对比)。

5. 浏览器兜底(host 模式)

当操作目标属于 API Format 不存在的前端字段(如 control_after_generate、分组信息),工具不伪造 API 调用,而是:fetch 远端并保存 baseline 快照 → 返回结构化请求(语义 goal、DOM→CDP→vision 策略、RunningHub 域名 allowlist、fetch+diff 后置条件),由 Codex / Zcode 等宿主智能体用自己的浏览器能力执行。

6. 安全设计

  • API key 只从环境变量读取,.env 不入库;日志双层脱敏(字段名规则 + 字符串规则,覆盖 key 明文、/proxy/<key>、Bearer、signed URL)

  • create taskupload 默认禁止自动重试(防重复收费 / 重复上传);仅幂等读操作自动重试(≤3 次,408/429/5xx/网络层)

  • nodeInfoList 护栏下沉到 Service boundary:任何入口(工具 / CLI --set / MCP 直接 overrides)携带连接形态值(["nodeId", index])→ UNSUPPORTED(要求走 full workflow JSON);前端-only 字段 → REQUIRES_BROWSER

  • graph key/id invariantgraph.nodes[key].id === key 在所有边界(parse / wire / serialize)强校验,不一致直接 INVALID_WORKFLOW,绝不静默纠正或覆盖

  • doctor 语义诚实:configured=true 仅表示 key 已配置,authenticationChecked=false 表示未做(也未伪称)服务端验证

  • 任务轮询遇到未确认业务码时最多连续容忍 2 次,超过即 TASK_FAILED(UNKNOWN_API_STATE),不会无限轮询到 timeout

  • 上传返回的 fileName 是加载节点相对路径,绝不拼接为公共 URL(官方明确上传接口不是图床)

  • baseline 快照强制先于 full workflow run 与浏览器兜底,保存失败即中止

构建、运行与部署

npm run build     # tsc 编译到 dist/(dist/cli/main.js 为 bin 入口)
npm test          # vitest 全量测试(165 个,全部 mock,无需真实 key)
npm run dev       # 开发模式 CLI(tsx 直跑 TS 源码)
npm run mcp       # 启动 MCP stdio server(可直接被 MCP 客户端挂载)
npm run lint      # eslint
npm run demo:a    # Demo A 脚本(需真实 key)
npm run demo:b    # Demo B 脚本(需真实 key)

本项目是本地工具 / MCP server,无需服务端部署;作为 npm 依赖或直接 clone 使用均可。

开源协议 / License

MIT © yangxijia111

贡献说明 / Contributing

欢迎 Issue 与 PR。提交前请确保:

npm run lint && npm test && npm run build   # 三项全部通过

约定:

  • Graph domain 层(src/graph/)保持纯函数、零网络依赖,禁止 import fetch / process.env / MCP SDK

  • CLI 与 MCP 不允许各写一套业务逻辑,新工具先进 src/tools/registry.ts,两个出口自动获得

  • 涉及 RunningHub 接口的改动,以最新官方文档为准并同步更新测试

更新计划 / Roadmap

  • P1remove_node cascade、rh_model_search(复用 /models)、LoRA 上传执行段(signed URL 消费)

  • M9:Playwright / CDP 浏览器模式(RH_BROWSER_MODE=cdp,带域名 allowlist)

  • M10:Recorder —— UI 操作前后 snapshot diff,沉淀可复用 operation recipe

  • 真实账号端到端验证的 CI job(手动触发,需 self-hosted runner 与配额)

  • 发布 npm 包(npx rh-agent-bridge 直接可用)

致谢 / Acknowledgements


English

rh-agent-bridge

License Node.js TypeScript MCP Tests

An agent-neutral control layer for RunningHub / ComfyUI workflows — lets coding agents operate RunningHub with workflow semantics instead of mouse coordinates.

rh-agent-bridge is a local tool for coding agents (Codex, Zcode, or any MCP / CLI caller). It exposes a stable set of structured tools on top of the RunningHub official OpenAPI and Native ComfyUI endpoints, and only returns a structured browser-fallback request (executed by the host agent) when an operation genuinely cannot be expressed via API.

Current status: P0/MVP + P0.1 Hardening (v0.1.1) — P0.1 fixed the /models contract, connection-type validation, baseline-snapshot semantics, nodeInfoList bypass, graph key/id invariant and other safety/correctness issues.

Overview

Generic browser agents struggle with node editors like ComfyUI: node coordinates drift, wire-drawing actions are fragile, selectors break on UI updates, and the agent has to "look at the page" again every time — even though the vast majority of those operations already have official APIs.

This project models a RunningHub workflow as a structured graph (WorkflowGraph) with a full pure-function toolkit: parse / inspect / diff / mutate / validate / serialize. Modifications are routed per official guidance: parameter overrides go through nodeInfoList; topology changes go through the full workflow JSON. The node catalog is discovered at runtime from ComfyUI /object_info; a missing node class is a NODE_NOT_FOUND — the tool never invents one.

Features

  • API-first: RunningHub official OpenAPI first (task creation, output polling, resource upload, workflow fetch), then Native ComfyUI (/proxy/<key>); the browser is only a last resort

  • Structured graph engine: bidirectional API Format JSON ⇄ WorkflowGraph; node query, immutable patch (set_input / add_node / remove_node / connect / disconnect), graph diff, cycle detection

  • Parameter vs topology routing: value-only changes auto-generate an official nodeInfoList; topology/connection changes automatically switch to full-workflow JSON submission (official docs advise against changing connections via nodeInfoList)

  • Layered static validation: Level 1 structural references/cycles → Level 2 node, input and connection-type checks against /object_info (output-index overflow, connections into primitive fields, MODEL→IMAGE mismatches) → Level 3 model-name checks (priority: object_info COMBO options → /models/{folder} → field-name fallback); server-side promptTips parsed into a structured result

  • Native capability probe: runtime feature-detection of /features, /object_info, /models (folder list); model files lazily fetched via GET /models/{folder}; graceful degradation never breaks the OpenAPI path, and per-endpoint details (endpoint + status) are exposed to the agent

  • Safe fallback: browser fallback returns a structured request (semantic goal + domain allowlist + mandatory pre-snapshot) for the host agent to execute with its own browser capabilities

  • One source, two surfaces: the CLI (--json agent mode) and the MCP server share the same service layer with 13 mirrored tools

  • Redacted logging: API key literals, /proxy/<key>, Bearer tokens and signed URLs are always masked; create task and upload never auto-retry (no double billing)

Demo

This is a CLI / protocol-layer tool with no GUI screenshots yet. Below is an overview of the two runnable demos (scripts in examples/):

Demo A — parameter-only (no browser at any point)

fetch workflow → find prompt node → set prompt → set seed
→ run by nodeInfoList → wait outputs

Demo B — topology change

fetch workflow → probe nodes (/object_info) → node search confirms existence
→ add node → connect → validate → run by full workflow JSON → wait outputs
(if the target node does not exist, a clear NODE_NOT_FOUND is returned — never an invented class name)

Demo C — browser fallback (host mode): for frontend-only fields absent from API Format (e.g. control_after_generate), patch automatically returns a requiresBrowser structured request (with snapshot path and rollback postconditions) — see examples/demo-c-browser-fallback.md.

See Usage for how to run them.

Requirements

Dependency

Version

Notes

Node.js

≥ 20

requires native fetch / FormData

npm

≥ 10

bundled with Node 20

RunningHub account

a valid API key (official docs); not needed for local graph-only operations

Installation

git clone https://github.com/yangxijia111/rh-agent-bridge.git
cd rh-agent-bridge
npm install
npm test        # 165 mock-based tests, no real key required

Copy .env.example to .env and fill it in (.env is git-ignored — never commit it):

RUNNINGHUB_API_KEY=<required, RunningHub API key>
RUNNINGHUB_BASE_URL=https://www.runninghub.ai     # default
RUNNINGHUB_WORKFLOW_ID=<optional, default workflow id>
RUNNINGHUB_NATIVE_MODE=standard                    # standard(24GB) | plus(48GB)
RH_BROWSER_MODE=host                               # host | cdp(reserved, not implemented)
RH_CDP_URL=                                        # cdp mode only
RH_LOG_LEVEL=info

Usage

CLI (shares the same service layer with MCP)

alias rh='npm run --silent dev --'

rh doctor                                          # config & native capability check

rh workflow fetch <WORKFLOW_ID> --out workflow.api.json
rh workflow inspect workflow.api.json --query KSampler
rh workflow set-input workflow.api.json \
  --node 6 --field text --value "product photo" --out modified.json
rh workflow patch workflow.api.json \
  --ops '[{"type":"add_node","classType":"ImageUpscaleWithModel"},
          {"type":"connect","fromNode":"8","outputIndex":0,"toNode":"10","input":"image"}]' \
  --out modified.json
rh workflow validate modified.json --no-node-schema
rh workflow diff workflow.api.json modified.json

rh workflow run --workflow-id <ID> --file modified.json   # auto-selects execution mode via diff
rh workflow run --workflow-id <ID> --set 6.text="hi" --set 3.seed=42
rh task outputs <TASK_ID>
rh task wait <TASK_ID> --timeout-ms 600000

rh resource upload ./input.png       # returns fileName (relative path, not a public URL)
rh nodes probe                       # /features /object_info /models probe
rh nodes search "remove background"  # node catalog search

rh browser fallback-request --workflow-id <ID> --goal "..."

workflow run --file first fetches the remote original and diffs: value-only changes → submitted as nodeInfoList; topology/connection changes → submitted as full workflow JSON (with an automatic snapshot to ~/.rh-agent/snapshots/).

--json is agent mode: stdout carries JSON only (errors are structured too: {"error":{"code","message","retryable"}}), logs go to stderr.

MCP

{
  "mcpServers": {
    "rh-agent-bridge": {
      "command": "node",
      "args": ["dist/mcp/server.js"],
      "cwd": "/absolute/path/to/rh-agent-bridge",
      "env": { "RUNNINGHUB_API_KEY": "<your-key>" }
    }
  }
}

13 tools are exposed (all with decision-friendly descriptions so agents can self-route):

Tool

Purpose

Idempotent

rh_doctor

config & native capability check

rh_workflow_fetch

fetch API Format → structured graph

rh_workflow_inspect

node listing / search

rh_workflow_diff

graph diff

rh_workflow_patch

set_input / add / remove / connect / disconnect

✅ (no remote writes)

rh_workflow_validate

layered static validation

rh_workflow_run

submit task (never auto-retried, costs credits)

rh_task_outputs

query outputs / state

rh_task_wait

poll to terminal state (supports MCP cancellation)

rh_resource_upload

upload assets (≤30MB)

rh_nodes_probe

native probe + node catalog build

rh_node_search

node catalog search

rh_browser_fallback_request

structured browser fallback request

Demo scripts (real account, consumes GPU credits)

RUNNINGHUB_API_KEY=<key> npm run demo:a -- <WORKFLOW_ID>   # parameter-only, no browser
RUNNINGHUB_API_KEY=<key> npm run demo:b -- <WORKFLOW_ID>   # probe → add node → connect → full run

Project Structure

rh-agent-bridge/
├── src/
│   ├── config/            env config · log redaction · pino logger
│   ├── errors.ts          unified RhError model (code + retryable + toJSON)
│   ├── clients/
│   │   ├── runninghub/    official OpenAPI client (zod / timeout / controlled retry)
│   │   └── comfy/         Native ComfyUI client + capability probe
│   ├── graph/             pure-function graph engine (parse / serialize / inspect /
│   │                      mutate / diff / validate / topology / execution; no network)
│   ├── catalog/           object_info adapter + TTL cache + node catalog service
│   ├── browser/           host-mode BrowserAdapter (semantic goal + domain allowlist)
│   ├── services/          Workflow / Task / Resource / BrowserFallback services + snapshots
│   ├── tools/             13 tools + registry (zod input schemas)
│   ├── cli/               commander CLI (--json agent mode)
│   └── mcp/               MCP stdio server
├── tests/                 165 tests + workflow fixtures + API contract fixtures
├── examples/              Demo A/B scripts + Demo C guide
├── .env.example           environment template
└── package.json / tsconfig.json / vitest.config.ts / eslint.config.js

Core Design Notes

1. Parameter vs topology execution routing

After a modification, the tool computes a graph diff and picks the submission path per official guidance:

only primitive inputs changed (prompt / seed / steps / image filename …)
    → workflowId + nodeInfoList (template + overrides)

nodes added/removed, connections changed, class_type changed, a connection replaced by a constant
    → workflowId + workflow=<full JSON string> (snapshot forced before submission)

If a connection change is ever routed to nodeInfoList, the tool throws UNSUPPORTED with an explicit reason — a path the official docs advise against.

2. Layered validation

Level

Checks

Depends on

Level 1

reference existence, self-reference, outputIndex, cycles

none

Level 2

node-class existence, required inputs, type/enum/range, plus five-point connection validation (source/target existence, output-index overflow, connections into primitive fields CONNECTION_NOT_ALLOWED, type mismatches CONNECTION_TYPE_MISMATCH; unknown custom datatypes degrade to warnings to avoid false positives)

/object_info (skipped if unavailable)

Level 3

model names, priority: object_info COMBO options for the field → GET /models/{folder} (checkpoints/loras/vae/upscale_models) → field-name fallback

any of the above (skipped if unavailable)

Server-side

promptTips → structured valid / nodeErrors / outputsToExecute

task-creation response

3. Node catalog & anti-hallucination

The node catalog is fetched at runtime from Native ComfyUI /object_info (TTL cache: object_info 10 min / models folders 5 min / features 30 min). /models follows ComfyUI Server semantics and returns a list of folder names (["checkpoints", "loras", ...]); actual model files are lazily fetched per folder via GET /models/{folder} with independent TTL caching — a missing folder is a legal degradation. A failed node lookup forces one refresh; if the class still does not exist the tool returns NODE_NOT_FOUND — it never invents a class name.

4. Snapshot semantics (baseline / candidate)

  • baseline snapshot = the remote current state before a mutation/run (the rollback source). Mandatory before full-workflow runs and browser fallbacks, and must come from a remote fetch — a locally modified agent graph is never a valid rollback baseline;

  • candidate snapshot = the state intended for execution (saved alongside full-workflow runs for audit/diff).

5. Browser fallback (host mode)

When an operation targets a frontend-only field absent from API Format (e.g. control_after_generate, grouping), the tool does not fake an API call. Instead it fetches the remote workflow, saves the baseline snapshot, then returns a structured request (semantic goal, DOM→CDP→vision strategy, RunningHub domain allowlist, fetch+diff postconditions) for the host agent (Codex / Zcode / …) to execute with its own browser capabilities.

6. Security design

  • The API key is read only from environment variables; .env never enters git; logging is double-layer redacted (field-name rules + string rules covering key literals, /proxy/<key>, Bearer tokens, signed URLs)

  • create task and upload never auto-retry (no double billing / duplicate uploads); only idempotent reads retry automatically (≤3 times, 408/429/5xx/network)

  • nodeInfoList guardrails enforced at the Service boundary: any entry point (tool / CLI --set / direct MCP overrides) carrying a connection-like value (["nodeId", index]) → UNSUPPORTED (full workflow JSON required); frontend-only fields → REQUIRES_BROWSER

  • graph key/id invariant: graph.nodes[key].id === key is strictly enforced at every boundary (parse / wire / serialize) — mismatches raise INVALID_WORKFLOW, never silently corrected or overwritten

  • honest doctor semantics: configured=true only means the key is present; authenticationChecked=false means no server-side verification was (or is claimed to have been) performed

  • task polling tolerates at most 2 consecutive unrecognized business codes, then fails with TASK_FAILED(UNKNOWN_API_STATE) instead of polling until timeout

  • The uploaded fileName is a relative path for load nodes and is never concatenated into a public URL (the official docs state the upload endpoint is not an image host)

  • baseline snapshots are mandatory before full-workflow runs and browser fallbacks; failure aborts the operation

Build & Run

npm run build     # tsc → dist/ (dist/cli/main.js is the bin entry)
npm test          # full vitest suite (165 mock-based tests, no real key needed)
npm run dev       # dev-mode CLI (tsx runs TS directly)
npm run mcp       # start the MCP stdio server (mountable by any MCP client)
npm run lint      # eslint
npm run demo:a    # Demo A script (real key required)
npm run demo:b    # Demo B script (real key required)

This is a local tool / MCP server — no server deployment needed; use it via clone or as an npm dependency.

License

MIT © yangxijia111

Contributing

Issues and PRs are welcome. Before submitting, make sure:

npm run lint && npm test && npm run build   # all three pass

Conventions:

  • The graph domain layer (src/graph/) stays pure and network-free: no fetch, no process.env, no MCP SDK imports

  • The CLI and MCP must not duplicate business logic — new tools go into src/tools/registry.ts and both surfaces pick them up automatically

  • RunningHub API changes must follow the latest official docs and update the tests accordingly

Roadmap

  • P1: remove_node cascade, rh_model_search (reusing /models), LoRA upload execution step (signed URL consumption)

  • M9: Playwright / CDP browser mode (RH_BROWSER_MODE=cdp, with domain allowlist)

  • M10: Recorder — snapshot diff around UI operations, distilled into reusable operation recipes

  • Opt-in end-to-end CI job with a real account (manual trigger, self-hosted runner with credits)

  • Publish as an npm package (npx rh-agent-bridge)

Acknowledgements

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Dynamically loads ComfyUI workflows as MCP tools, enabling AI assistants to generate images, videos, and audio by executing workflows across categories like text-to-image, image-to-video, and text-to-audio with automatic parameter mapping and progress monitoring.
    43,607 npm
    3
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    The MCP server that drafts ComfyUI workflows a human can actually read. It lets coding agents build, repair, port, validate, and run ComfyUI workflows against your own ComfyUI instance, delivering clean, organized, fully-labeled workflows.
    29
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI coding agents to visually build and run AI generation pipelines on a canvas by adding, wiring, and executing nodes via MCP tools.
    Apache 2.0