Skip to main content
Glama

nodered-mcp

一个读取、查询并编辑 Node-RED flows.json 的 MCP 服务器。

License CI Python

关于

Node-RED 将所有的流程、节点、连线和分组框都保存在一个大型 JSON 文件中。手动编辑它——或使用 jq 和 sed——最终很容易落到悬空的连线、分组框不再覆盖属于自身的节点、以及新节点堆叠在已有节点之上的局面。

这个服务器会以一套了解该格式的小工具,把这个文件暴露给 MCP 客户端。它区分流程节点与配置节点,可以追踪连线路径,并能重现 Node-RED 编辑器自身的几何计算,因此它算出的分组框正是编辑器会绘制出的那个分组框。

它是从 flows_util.py / layout_util.py 这一对工具移植而来,最早用于在某一个家庭自动化仓库中以脚本方式修改 Node-RED;再经泛化,使文件路径、容器名称和重启命令都成为可配置项。

Related MCP server: nr-mcp

特性

  • 查询 — 标签页、分组、孤立节点、子流程、引用的 Home Assistant 实体,以及在流程中进行连线追踪。

  • 编辑 — 创建、更新、删除、重命名和复制节点;连接取消节点连线;创建、填充并重设分组样式;导入和导出节点集合。

  • 放置 — 在创建节点前先声明空白画布区域,而不是猜测坐标;对画布做碰撞检查,并修复重叠。

  • 审慎提交 — 编辑行为累积在内存里,必须由你主动触发才写盘,因此一次多节点构建可以作为一个整体落盘。

  • 底层脚本从未需要的两道防护 — 一道布局门会拒绝引入新碰撞的橡皮擦,一道陈旧性检查会拒绝覆盖从浏览器端 Deploy 出来的 flows.json。

环境要求

  • Python 3.11+

  • 本地文件系统上有一个 flows.json

  • PATH 里有 Docker —— 只有 deploy 工具需要,它会把文件复制到容器里并把容器重启

安装

git clone https://github.com/ljmerza/nodered-mcp
cd nodered-mcp
uv sync

使用

flows.json 路径是唯一必需的设置。没有合理默认值,所以不提供该参数时服务就拒绝启动。

uv run nodered-mcp --flows-path /path/to/nodered/data/flows.json

向 MCP 客户端注册

{
  "mcpServers": {
    "nodered": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--directory", "/path/to/nodered-mcp", "nodered-mcp"],
      "env": {
        "NODERED_FLOWS_PATH": "/path/to/nodered/data/flows.json"
      }
    }
  }
}

完整示例见 .mcp.json.example。

配置

每个配置项的解析优先级为 CLI 标志 > 环境变量 > 默认值。

标志

环境变量

默认值

用途

--flows-path

NODERED_FLOWS_PATH

(必需)

宿主机上 flows.json 的路径

--container

NODERED_CONTAINER

nodered

deploy 使用的容器名称

--container-flows-path

NODERED_CONTAINER_FLOWS_PATH

/data/flows.json

容器内部 flows.json 的路径

--restart-cmd

NODERED_RESTART_CMD

docker restart <container>

重启命令;{container} 会被替换

--transport

NODERED_MCP_TRANSPORT

stdio

取 stdio、http 或 sse

--host / --port

NODERED_MCP_HOST / NODERED_MCP_PORT

127.0.0.1 / 8080

http 与 sse 的绑定地址

如果 Node-RED 不是由 plain Docker 管理的,可以把 --restart-cmd 指向对应的管理方式:

NODERED_RESTART_CMD="docker compose restart {container}"

工具

共有七个工具,统一根据 op 参数分派。

工具

操作

nodered_query

summary, tabs, groups, tab, group, search, ungrouped, orphans, subflows, styles, entities, inspect, connections, trace

nodered_find_nodes

按标签、类型或中文片段的子串进行结构化搜索

nodered_get_node

单个节点的原始 JSON 以及其连线上下文

nodered_edit

create_node, update_node, delete_node, rename_node, duplicate_node, wire, unwire, import_nodes, export_group

nodered_group

create, add, move_node, rename, set_style, normalize_styles, refit, shift, bounds

nodered_layout

check, free_region, occupied, fix

nodered_session

status, save, deploy, reload

一次典型的构建

nodered_query(op="tabs")                                   -> tab ids
nodered_layout(op="free_region", tab_id=TAB, w=800, h=200) -> {"x": 100, "y": 3240}
nodered_edit(op="create_node", tab_id=TAB, node_type="inject",
             name="tick", x=100, y=3240)                   -> node id
nodered_edit(op="create_node", tab_id=TAB, node_type="switch",
             name="gate", x=300, y=3240)                   -> node id
nodered_edit(op="wire", source_id=..., target_id=...)
nodered_group(op="create", name="My Flow", tab_id=TAB, node_ids=[...])
nodered_session(op="save")

以上的操作在最终 save 之前都不会触碰 flows.json。

它是如何保护文件的

布局门

save 和 deploy 会在编辑前后各对画布做一次 layout 风检,如果编辑引入了新的 error 级发现,write 会被拒绝:

发现

严重级别

含义

group-overlap

错误

一个分组框叠到了其他分组框上

group-escape

错误

分组框不再覆盖它自己的节点

stray-in-group

警告

某个节点位于分组框内,但它并不属于该分组

node-overlap

警告

两个节点占了同一个坐标区

换句话说,在打开文件时已经存在磁盘上已存在的问题不会阻挡写入——只有本次编辑关系列的问题会被拦下。当布局门被触发时,通常的修复方式有:

  • nodeRedLayout(op="free_region") 先声明空白画布,然后把节点放进去

  • nodered_group(op="refit", group_id=...) 按节点把分组框的大小重新围合

  • nodered_session(op="save", allow_overlap=true) 若重叠是刻意为之

分组框的几何结构是精确的:计算规则从 Node-RED 编辑器里移植而来,因此得出的结果就是编辑器会绘制的那个形状。节点的几何除了标签文字的宽度以外也是精确的;标签宽度按 Helvetica 的字量估算——这正是节点级检查永远只作为 warning 警告。

陈旧性检查

Node-RED 每当有人点击浏览器面板里的 Deploy 会重写 flows.json 。会话在加载时记录 (mtime_ns, size),之后每次写入都会重新校验。如果底层的文件已经变化,那提交会被拒绝,而不会无声无息覆盖别人工作。你可以执行 reload 重新加载并再编辑一次,或改用 force=true。

之所以使用纳秒级时间戳而不是 os.path.getmtime,是因为浮点秒的时间够只在微秒(约)精度上,所以若同一 tick 内写入,比较时相等就把校验蒙混过去了。

独立使用

两个引擎模块也可作为库或命令行工具存在,不依赖 MCP。

uv run python -m nodered_mcp.flows summary --flows-path /path/to/flows.json
uv run python -m nodered_mcp.layout --path /path/to/flows.json --fix boxes,move
from nodered_mcp.flows import Flows

f = Flows("/path/to/flows.json")
ox, oy = f.free_region(tab_id, w=1600, h=300)
f.create_node(tab_id, "inject", "tick", x=ox, y=oy)
f.save()

记住,--fix boxes 单独用会让结果更糟:有些方框会被拉伸然后吞掉相邻不是成员节点,所以请把 boxes,move 一起使用,并在传递 --apply 之前先仔细读试运行输出。

工程结构

src/nodered_mcp/
├── server.py       FastMCP server: the seven tools
├── session.py      in-memory session, stdout capture, staleness guard
├── config.py       CLI flags and environment resolution
├── flows.py        the Flows class, composed from the mixins below
├── constants.py    defaults, the group style, LayoutError
├── reports.py      ReadMixin      — summary, tab, group, search, trace
├── nodes.py        NodeEditMixin  — create/update/delete/wire nodes
├── groups.py       GroupMixin     — create and populate group boxes
├── placement.py    LayoutMixin    — claim free canvas, measure and refit boxes
├── transfer.py     TransferMixin  — import and export node sets
├── persist.py      PersistMixin   — save, deploy, and the layout gate
└── layout.py       canvas geometry and linter, ported from the NR editor

Flows 聚合了这些 mixin,因此公开的 API 保持为扁平的:f.summary()、f.create_node()、f.free_region()、f.save()。

开发

uv sync --group dev
uv run pytest                    # 49 tests
uv run ruff check .
uv run ruff format --check .

测试运行阶段使用 tests/fixtures/ 中合成的 fixture ,而不是从真实的真实文件来测试。测试用例覆盖:配置优先级、查询工具、内存驻留直到 save 的语义、布局门在 go/no-go 两个方向上的行为、陈旧性守卫、deploy 完整的命令序列,以及没有任何工具会向 stdout 输出——一个多余的 print 就会毁掉 MCP 的 stdio 间包规则。

同时,CI 使用 ljmerza/misc-actions 执行同样这些检查。

开发互动

欢迎提交 Issues 和 Pull Requests。请让 ruff check、ruff format 和 pytest 保持通过。

致谢

  • Node-RED —— 这里出现在画布的几何规则移植自其编辑器客户端,所以分组框与编辑器呈现出的一致。

  • FastMCP —— 用来构建该 MCP 服务器的框架。

许可证

MIT。见 LICENSE。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Minimal MCP server wrapping the Node-RED admin API, enabling flow management, node installation, and context retrieval via natural language.
    265 npm
    MIT