nodered-mcp
nodered-mcp
Un servidor MCP que lee, consulta y edita un flows.json de Node-RED.
Acerca de
Node-RED almacena cada flujo, nodo, cable y caja de grupo en un único archivo JSON grande.
Editarlo a mano — o con jq y sed — es como se termina con cables sueltos, grupos cuyas cajas ya no cubren sus propios nodos, y nodos nuevos apilados sobre los existentes.
Este servidor expone ese archivo a un cliente MCP como un pequeño conjunto de herramientas que entienden el formato. Sabe la diferencia entre un nodo de flujo y un nodo de configuración, puede trazar una ruta de cable y reproduce la geometría del propio editor de Node-RED, de modo que una caja de grupo que dibuja es la caja que el editor habría dibujado.
Es un puerto del par flows_util.py / layout_util.py utilizado para scriptear cambios de Node-RED en un repositorio de domótica, generalizado para que la ruta del archivo, el nombre del contenedor y el comando de reinicio sean configurables.
Related MCP server: nr-mcp
Características
Consultar — pestañas, grupos, nodos huérfanos, subflujos, entidades de Home Assistant referenciadas y trazados de cables a través de un flujo.
Editar — crear, actualizar, eliminar, renombrar y duplicar nodos; cablearlos y des-cablearlos; crear, poblar y reestilizar grupos; importar y exportar conjuntos de nodos.
Colocar — reclamar lienzo vacío antes de crear nodos en lugar de adivinar coordenadas, revisar el lienzo en busca de colisiones y reparar solapamientos.
Confirmar deliberadamente — las ediciones se acumulan en memoria y solo llegan al disco cuando lo pides, de modo que una compilación de varios nodos aterriza como una sola unidad.
Dos salvaguardas que los scripts subyacentes nunca necesitaron: una compuerta de diseño que rechaza escrituras que introduzcan nuevas colisiones, y una comprobación de obsolescencia que se niega a sobrescribir un
flows.jsonque alguien desplegó desde el navegador.
Requisitos
Python 3.11+
Un
flows.jsonen el sistema de archivos localDocker en
PATH— solo para la herramientadeploy, que copia el archivo a un contenedor y lo reinicia
Instalación
git clone https://github.com/ljmerza/nodered-mcp
cd nodered-mcp
uv syncUso
La ruta de flows.json es el único ajuste obligatorio. No hay un valor predeterminado razonable, por lo que el servidor se niega a arrancar sin uno.
uv run nodered-mcp --flows-path /path/to/nodered/data/flows.jsonRegistrarse con un cliente 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"
}
}
}
}Consulta .mcp.json.example para un ejemplo más completo.
Configuración
Cada ajuste se resuelve como bandera CLI > variable de entorno > valor predeterminado.
Banderas | Variable de entorno | Predeterminado | Propósito |
|
| (obligatorio) | Ruta a |
|
|
| Nombre del contenedor usado por |
|
|
| Ruta a |
|
|
| Comando de reinicio; se sustituye |
|
|
|
|
|
|
| Dirección de enlace para |
Si Node-RED se gestiona con algo distinto a Docker simple, apunta --restart-cmd a ello:
NODERED_RESTART_CMD="docker compose restart {container}"Herramientas
Siete herramientas, cada una despachando sobre un argumento op.
Herramienta | Ops |
|
|
| Búsqueda estructurada por pestaña, tipo o subcadena de nombre |
| El JSON sin procesar de un nodo más su contexto de cableado |
|
|
|
|
|
|
|
|
Una compilación típica
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")Nada de lo anterior toca flows.json hasta el save final.
Cómo protege el archivo
La compuerta de diseño
save y deploy revisan el lienzo antes y después de tu edición, y se niegan a escribir si la edición introduce un hallazgo nuevo de nivel de error:
Hallazgo | Severidad | Significado |
| error | Una caja de grupo aterrizó sobre otra caja de grupo |
| error | Una caja de grupo ya no cubre sus propios nodos |
| advertencia | Un nodo está dentro de una caja de grupo de la que no es miembro |
| advertencia | Dos nodos ocupan el mismo espacio |
Los problemas que ya existían en disco nunca bloquean, solo los que tu edición creó. Cuando la compuerta se dispara, la solución suele ser una de:
nodered_layout(op="free_region")para reclamar lienzo libre y luego colocar allínodered_group(op="refit", group_id=...)para redimensionar un grupo alrededor de sus nodosnodered_session(op="save", allow_overlap=true)si el solapamiento es deliberado
La geometría de los grupos es exacta: las reglas de dimensionado están portadas del editor de Node-RED, por lo que una caja calculada coincide con lo que dibuja el editor. La geometría de los nodos es exacta salvo por el ancho del texto de la etiqueta, que se aproxima a partir de las métricas de Helvetica; por eso los hallazgos a nivel de nodo solo son advertencias.
La comprobación de obsolescencia
Node-RED reescribe flows.json cada vez que alguien pulsa Deploy en el navegador. La sesión registra (mtime_ns, size) cuando carga el archivo y lo vuelve a comprobar antes de cada escritura. Si el archivo cambió sin que te des cuenta, se rechaza la confirmación en lugar de revertir silenciosamente ese trabajo. O bien haz reload y rehaz tus ediciones, o pasa force=true.
Nanosegundos en lugar de os.path.getmtime: una época flotante solo resuelve hasta aproximadamente un microsegundo, por lo que una escritura que aterriza en la misma marca de tiempo que la carga se compara como igual y se cuela por la comprobación.
Uso independiente
Ambos módulos de motor funcionan como bibliotecas y CLIs, independientes de 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,movefrom 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 boxessolo empeora las cosas: reajustar agranda algunas cajas para que engullan nodos vecinos que no son miembros. Ejecutaboxes,movejuntos y lee la ejecución en seco antes de pasar--apply.
Estructura del proyecto
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 editorFlows compone los mixins, por lo que la API pública permanece plana: f.summary(), f.create_node(), f.free_region(), f.save().
Desarrollo
uv sync --group dev
uv run pytest # 49 tests
uv run ruff check .
uv run ruff format --check .Las pruebas se ejecutan contra un fixture sintético en tests/fixtures/, nunca contra un archivo de flujos real. Cubren la precedencia de configuración, las herramientas de lectura, la semántica en memoria hasta guardar, la compuerta de diseño tanto bloqueando como anulada, la protección de obsolescencia, la secuencia de comandos de despliegue, y que ninguna herramienta escriba a stdout — un print suelto corrompería el marco stdio de MCP.
CI ejecuta las mismas comprobaciones a través de
ljmerza/misc-actions.
Contribuciones
Las incidencias y las pull requests son bienvenidas. Mantén ruff check, ruff format y pytest en verde.
Agradecimientos
Node-RED — la geometría del lienzo aquí está portada de su cliente editor, para que las cajas de grupo coincidan con lo que dibuja el editor.
FastMCP — el marco de servidor MCP.
Licencia
MIT. Consulta LICENSE.
This server cannot be installed
Maintenance
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
- AlicenseNot gradedqualityDmaintenanceEnables management of multiple N8N workflow automation instances through MCP. Supports listing, creating, updating, deleting, executing workflows and monitoring their executions across different N8N environments.63MIT
- AlicenseAqualityDmaintenanceLets AI assistants interact with Node-RED to read flows, search nodes, edit function code, deploy changes safely, and manage modules.131MIT
- AlicenseNot gradedqualityBmaintenanceExposes Node-RED flows as MCP tools for AI assistants, with OAuth protection and optional admin tools for flow management.2081ISC
- FlicenseNot gradedqualityBmaintenanceMinimal MCP server wrapping the Node-RED admin API, enabling flow management, node installation, and context retrieval via natural language.
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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