Skip to main content
Glama

nodered-mcp

MCP-сервер, который читает, запрашивает и редактирует flows.json Node-RED.

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 и трассировка соединений по потоку.

  • Редактирование — создание, обновление, удаление, переименование и дублирование узлов; соединение и разъединение; создание, заполнение и изменение стилей групп; импорт и экспорт наборов узлов.

  • Размещение — занимайте пустое полотно перед созданием узлов вместо угадывания координат, проверяйте полотно на пересечения и исправляйте наложения.

  • Осознанная фиксация — правки накапливаются в памяти и попадают на диск только по вашей команде, так что многоузловая сборка сохраняется как единое целое.

  • Две защиты, которые базовым скриптам не требовались: проверка компоновки, отказывающая в записи при новых пересечениях, и проверка устаревания, отказывающая перезаписывать flows.json, развёрнутый кем-то из браузера.

Требования

  • Python 3.11+

  • flows.json в локальной файловой системе

  • Docker в PATH — только для инструмента 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 управляется не обычным 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")

Ничто из вышеперечисленного не касается flows.json до финального save.

Как сервер защищает файл

Проверка компоновки

save и deploy проверяют полотно до и после вашей правки и отказываются записывать, если правка вносит новую ошибку уровня error:

Находка

Уровень

Значение

group-overlap

error

Рамка группы попала на другую рамку группы

group-escape

error

Рамка группы больше не покрывает свои узлы

stray-in-group

warning

Узел находится внутри рамки группы, но не является её членом

node-overlap

warning

Два узла занимают одно и то же пространство

Проблемы, уже существовавшие на диске, никогда не блокируют — только те, что создала ваша правка. Когда проверка срабатывает, обычно помогает одно из:

  • nodered_layout(op="free_region") — занять свободное полотно, затем разместить там

  • nodered_group(op="refit", group_id=...) — изменить размер группы вокруг её узлов

  • nodered_session(op="save", allow_overlap=true) — если наложение намеренное

Геометрия групп точна: правила расчёта размеров перенесены из редактора Node-RED, поэтому вычисленная рамка совпадает с тем, что рисует редактор. Геометрия узлов точна, за исключением ширины текста метки, которая аппроксимируется по метрикам Helvetica — поэтому находки на уровне узлов всегда только предупреждения.

Проверка устаревания

Node-RED перезаписывает flows.json при каждом нажатии Deploy в браузере. Сессия записывает (mtime_ns, size) при загрузке файла и перепроверяет перед каждой записью. Если файл изменился под вами, фиксация отклоняется, а не молча откатывает вашу работу. Либо выполните reload и повторите правки, либо передайте force=true.

Наносекунды, а не os.path.getmtime: эпоха с плавающей точкой даёт точность примерно до микросекунды, поэтому запись, попавшая в тот же такт, что и загрузка, сравнивается как равная и проскальзывает мимо проверки.

Автономное использование

Оба модуля движка работают как библиотеки и CLI, независимо от 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 объединяет миксины, поэтому публичный 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/, никогда на реальном файле flows. Они покрывают приоритет конфигурации, инструменты чтения, семантику «в памяти до сохранения», проверку компоновки (и блокировку, и переопределение), защиту от устаревания, последовательность команд deploy и то, что ни один инструмент не пишет в stdout — случайный print нарушил бы фрейминг stdio MCP.

CI запускает те же проверки через ljmerza/misc-actions.

Вклад

Приветствуются issues и pull request. Пожалуйста, поддерживайте ruff check, ruff format и pytest зелёными.

Благодарности

  • Node-RED — геометрия полотна здесь перенесена из его клиента редактора, поэтому рамки групп совпадают с тем, что рисует редактор.

  • FastMCP — фреймворк MCP-сервера.

Лицензия

MIT. См. LICENSE.

A
license - permissive license
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
3Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    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.

View all related MCP servers

Related MCP Connectors

  • Create, browse, remix, collaborate on, and run durable AI workflow nodes from MCP hosts.

  • MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.

  • JSON tools MCP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ljmerza/nodered-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server