mcp-node-red 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +107 -232
  3. package/dist/client.d.ts +14 -1
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +181 -4
  6. package/dist/client.js.map +1 -1
  7. package/dist/env.d.ts +2 -0
  8. package/dist/env.d.ts.map +1 -0
  9. package/dist/env.js +13 -0
  10. package/dist/env.js.map +1 -0
  11. package/dist/index.js +2 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/schemas.d.ts +286 -0
  14. package/dist/schemas.d.ts.map +1 -1
  15. package/dist/schemas.js +47 -0
  16. package/dist/schemas.js.map +1 -1
  17. package/dist/server.d.ts.map +1 -1
  18. package/dist/server.js +232 -0
  19. package/dist/server.js.map +1 -1
  20. package/dist/tools/delete-context.d.ts +8 -0
  21. package/dist/tools/delete-context.d.ts.map +1 -0
  22. package/dist/tools/delete-context.js +26 -0
  23. package/dist/tools/delete-context.js.map +1 -0
  24. package/dist/tools/delete-flow.d.ts +8 -0
  25. package/dist/tools/delete-flow.d.ts.map +1 -0
  26. package/dist/tools/delete-flow.js +17 -0
  27. package/dist/tools/delete-flow.js.map +1 -0
  28. package/dist/tools/get-context.d.ts +8 -0
  29. package/dist/tools/get-context.d.ts.map +1 -0
  30. package/dist/tools/get-context.js +23 -0
  31. package/dist/tools/get-context.js.map +1 -0
  32. package/dist/tools/get-diagnostics.d.ts +8 -0
  33. package/dist/tools/get-diagnostics.d.ts.map +1 -0
  34. package/dist/tools/get-diagnostics.js +12 -0
  35. package/dist/tools/get-diagnostics.js.map +1 -0
  36. package/dist/tools/get-flow-state.d.ts +8 -0
  37. package/dist/tools/get-flow-state.d.ts.map +1 -0
  38. package/dist/tools/get-flow-state.js +12 -0
  39. package/dist/tools/get-flow-state.js.map +1 -0
  40. package/dist/tools/get-nodes.d.ts +8 -0
  41. package/dist/tools/get-nodes.d.ts.map +1 -0
  42. package/dist/tools/get-nodes.js +12 -0
  43. package/dist/tools/get-nodes.js.map +1 -0
  44. package/dist/tools/get-settings.d.ts +8 -0
  45. package/dist/tools/get-settings.d.ts.map +1 -0
  46. package/dist/tools/get-settings.js +12 -0
  47. package/dist/tools/get-settings.js.map +1 -0
  48. package/dist/tools/install-node.d.ts +8 -0
  49. package/dist/tools/install-node.d.ts.map +1 -0
  50. package/dist/tools/install-node.js +17 -0
  51. package/dist/tools/install-node.js.map +1 -0
  52. package/dist/tools/remove-node-module.d.ts +8 -0
  53. package/dist/tools/remove-node-module.d.ts.map +1 -0
  54. package/dist/tools/remove-node-module.js +17 -0
  55. package/dist/tools/remove-node-module.js.map +1 -0
  56. package/dist/tools/set-debug-state.d.ts +8 -0
  57. package/dist/tools/set-debug-state.d.ts.map +1 -0
  58. package/dist/tools/set-debug-state.js +18 -0
  59. package/dist/tools/set-debug-state.js.map +1 -0
  60. package/dist/tools/set-flow-state.d.ts +8 -0
  61. package/dist/tools/set-flow-state.d.ts.map +1 -0
  62. package/dist/tools/set-flow-state.js +17 -0
  63. package/dist/tools/set-flow-state.js.map +1 -0
  64. package/dist/tools/set-node-module-state.d.ts +8 -0
  65. package/dist/tools/set-node-module-state.d.ts.map +1 -0
  66. package/dist/tools/set-node-module-state.js +18 -0
  67. package/dist/tools/set-node-module-state.js.map +1 -0
  68. package/dist/tools/trigger-inject.d.ts +8 -0
  69. package/dist/tools/trigger-inject.d.ts.map +1 -0
  70. package/dist/tools/trigger-inject.js +17 -0
  71. package/dist/tools/trigger-inject.js.map +1 -0
  72. package/package.json +22 -5
  73. package/.github/workflows/ci.yml +0 -37
  74. package/.github/workflows/release.yml +0 -30
  75. package/.mcp.json.example +0 -11
  76. package/.releaserc.json +0 -17
  77. package/CLAUDE.md +0 -147
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-debug-state.js","sourceRoot":"","sources":["../../src/tools/set-debug-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAqB,EAAE,IAAa;IACtE,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEnD,MAAM,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAE9D,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;aAClF;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { NodeRedClient } from '../client.js';
2
+ export declare function setFlowState(client: NodeRedClient, args: unknown): Promise<{
3
+ content: {
4
+ type: "text";
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=set-flow-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-flow-state.d.ts","sourceRoot":"","sources":["../../src/tools/set-flow-state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO;;;;;GAWtE"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ const SetFlowStateArgsSchema = z.object({
3
+ state: z.enum(['start', 'stop']),
4
+ });
5
+ export async function setFlowState(client, args) {
6
+ const parsed = SetFlowStateArgsSchema.parse(args);
7
+ const result = await client.setFlowState(parsed.state);
8
+ return {
9
+ content: [
10
+ {
11
+ type: 'text',
12
+ text: JSON.stringify(result, null, 2),
13
+ },
14
+ ],
15
+ };
16
+ }
17
+ //# sourceMappingURL=set-flow-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-flow-state.js","sourceRoot":"","sources":["../../src/tools/set-flow-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAqB,EAAE,IAAa;IACrE,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvD,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { NodeRedClient } from '../client.js';
2
+ export declare function setNodeModuleState(client: NodeRedClient, args: unknown): Promise<{
3
+ content: {
4
+ type: "text";
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=set-node-module-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-node-module-state.d.ts","sourceRoot":"","sources":["../../src/tools/set-node-module-state.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAOlD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO;;;;;GAW5E"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ const SetNodeModuleStateArgsSchema = z.object({
3
+ module: z.string(),
4
+ enabled: z.boolean(),
5
+ });
6
+ export async function setNodeModuleState(client, args) {
7
+ const parsed = SetNodeModuleStateArgsSchema.parse(args);
8
+ const result = await client.setNodeModuleState(parsed.module, parsed.enabled);
9
+ return {
10
+ content: [
11
+ {
12
+ type: 'text',
13
+ text: JSON.stringify(result, null, 2),
14
+ },
15
+ ],
16
+ };
17
+ }
18
+ //# sourceMappingURL=set-node-module-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-node-module-state.js","sourceRoot":"","sources":["../../src/tools/set-node-module-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAqB,EAAE,IAAa;IAC3E,MAAM,MAAM,GAAG,4BAA4B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { NodeRedClient } from '../client.js';
2
+ export declare function triggerInject(client: NodeRedClient, args: unknown): Promise<{
3
+ content: {
4
+ type: "text";
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=trigger-inject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-inject.d.ts","sourceRoot":"","sources":["../../src/tools/trigger-inject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO;;;;;GAavE"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ const TriggerInjectArgsSchema = z.object({
3
+ nodeId: z.string(),
4
+ });
5
+ export async function triggerInject(client, args) {
6
+ const parsed = TriggerInjectArgsSchema.parse(args);
7
+ await client.triggerInject(parsed.nodeId);
8
+ return {
9
+ content: [
10
+ {
11
+ type: 'text',
12
+ text: JSON.stringify({ nodeId: parsed.nodeId, triggered: true }, null, 2),
13
+ },
14
+ ],
15
+ };
16
+ }
17
+ //# sourceMappingURL=trigger-inject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-inject.js","sourceRoot":"","sources":["../../src/tools/trigger-inject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAqB,EAAE,IAAa;IACtE,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEnD,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAE1C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;aAC1E;SACF;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-node-red",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "MCP server for Node-RED workflow management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,8 @@
14
14
  "test:coverage": "vitest run --coverage",
15
15
  "lint": "biome check .",
16
16
  "lint:fix": "biome check --write .",
17
- "format": "biome format --write ."
17
+ "format": "biome format --write .",
18
+ "prepare": "husky"
18
19
  },
19
20
  "keywords": [
20
21
  "mcp",
@@ -25,22 +26,38 @@
25
26
  ],
26
27
  "author": "",
27
28
  "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/fx/mcp-node-red"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "LICENSE",
37
+ "CHANGELOG.md"
38
+ ],
28
39
  "dependencies": {
29
40
  "@modelcontextprotocol/sdk": "^1.0.4",
41
+ "dotenv": "^17.3.1",
30
42
  "undici": "^7.3.0",
31
43
  "zod": "^3.24.1"
32
44
  },
33
45
  "devDependencies": {
34
46
  "@biomejs/biome": "^1.9.4",
35
- "@semantic-release/changelog": "^6.0.3",
36
- "@semantic-release/git": "^10.0.1",
37
47
  "@types/node": "^22.10.5",
38
48
  "@vitest/coverage-v8": "^2.1.8",
39
- "semantic-release": "^24.2.9",
49
+ "husky": "^9.1.7",
50
+ "lint-staged": "^16.2.3",
40
51
  "typescript": "^5.7.2",
41
52
  "vitest": "^2.1.8"
42
53
  },
43
54
  "engines": {
44
55
  "node": ">=20"
56
+ },
57
+ "lint-staged": {
58
+ "*.{js,ts}": [
59
+ "biome format --write --files-ignore-unknown=true",
60
+ "biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
61
+ ]
45
62
  }
46
63
  }
@@ -1,37 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- pull_request:
7
- branches: [main]
8
-
9
- jobs:
10
- test:
11
- runs-on: ubuntu-latest
12
- strategy:
13
- matrix:
14
- node-version: [20, 22]
15
- steps:
16
- - uses: actions/checkout@v4
17
- - name: Use Node.js ${{ matrix.node-version }}
18
- uses: actions/setup-node@v4
19
- with:
20
- node-version: ${{ matrix.node-version }}
21
- cache: 'npm'
22
- - run: npm ci
23
- - run: npm run build
24
- - run: npm test
25
- - run: npm run lint
26
-
27
- coverage:
28
- runs-on: ubuntu-latest
29
- steps:
30
- - uses: actions/checkout@v4
31
- - uses: actions/setup-node@v4
32
- with:
33
- node-version: 22
34
- cache: 'npm'
35
- - run: npm ci
36
- - run: npm run build
37
- - run: npm run test:coverage
@@ -1,30 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- push:
5
- branches: [main]
6
-
7
- permissions:
8
- contents: write
9
- issues: write
10
- pull-requests: write
11
- id-token: write
12
-
13
- jobs:
14
- release:
15
- runs-on: ubuntu-latest
16
- steps:
17
- - uses: actions/checkout@v4
18
- with:
19
- fetch-depth: 0
20
- - uses: actions/setup-node@v4
21
- with:
22
- node-version: 22
23
- - run: npm ci
24
- - run: npm run build
25
- - run: npm test
26
- - run: npm run lint
27
- - run: npx semantic-release
28
- env:
29
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
package/.mcp.json.example DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "node-red": {
4
- "command": "node",
5
- "args": ["/absolute/path/to/mcp-node-red/dist/index.js"],
6
- "env": {
7
- "NODE_RED_URL": "http://localhost:1880"
8
- }
9
- }
10
- }
11
- }
package/.releaserc.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "branches": ["main"],
3
- "plugins": [
4
- "@semantic-release/commit-analyzer",
5
- "@semantic-release/release-notes-generator",
6
- "@semantic-release/changelog",
7
- "@semantic-release/npm",
8
- "@semantic-release/github",
9
- [
10
- "@semantic-release/git",
11
- {
12
- "assets": ["package.json", "package-lock.json", "CHANGELOG.md"],
13
- "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
14
- }
15
- ]
16
- ]
17
- }
package/CLAUDE.md DELETED
@@ -1,147 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- MCP (Model Context Protocol) server that provides Node-RED workflow management capabilities via stdio transport. Exposes 4 tools for AI agents to interact with Node-RED Admin API v2: get flows, create flow, update flow, and validate flow.
8
-
9
- ## Commands
10
-
11
- ```bash
12
- # Build (required after any code changes)
13
- npm run build
14
-
15
- # Development with auto-rebuild
16
- npm run dev
17
-
18
- # Run all tests
19
- npm test
20
-
21
- # Run tests with coverage
22
- npm run test:coverage
23
-
24
- # Run single test file
25
- npx vitest tests/client.test.ts
26
-
27
- # Lint
28
- npm run lint
29
-
30
- # Fix lint issues
31
- npm run lint:fix
32
-
33
- # Format code
34
- npm run format
35
- ```
36
-
37
- ## Architecture
38
-
39
- ### Core Components
40
-
41
- **Server Layer** (`src/server.ts`):
42
- - Creates MCP server using `@modelcontextprotocol/sdk`
43
- - Reads config from env vars: `NODE_RED_URL` (required), `NODE_RED_TOKEN` (optional)
44
- - Registers 4 MCP tools with schemas (get_flows, create_flow, update_flow, validate_flow)
45
- - Routes tool calls to individual tool handlers
46
- - Catches errors and returns MCP-formatted error responses
47
-
48
- **HTTP Client** (`src/client.ts`):
49
- - `NodeRedClient` class wraps Node-RED Admin API v2
50
- - Handles two auth modes:
51
- - Bearer token via `NODE_RED_TOKEN` env var
52
- - Basic auth extracted from URL credentials (e.g., `http://user:pass@host:1880`)
53
- - Always sets `Node-RED-API-Version: v2` header
54
- - Uses `undici` for HTTP requests
55
-
56
- **Tools** (`src/tools/*.ts`):
57
- - Each tool is a standalone async function
58
- - Takes `NodeRedClient` instance and tool arguments
59
- - Returns MCP tool response format: `{ content: [{ type: 'text', text: '...' }] }`
60
- - `create-flow.ts` uses POST /flow to create new flows
61
- - `update-flow.ts` uses PUT /flow/:id to update individual flows safely
62
-
63
- **Schemas** (`src/schemas.ts`):
64
- - Zod schemas for validation
65
- - `NodeRedItemSchema` is a union of flows (type: "tab") and nodes (other types)
66
- - All items have `id` and `type`, flows also require `label`
67
- - Node references to parent flows via `z` property
68
- - `UpdateFlowRequestSchema` defines structure for PUT /flow/:id requests
69
-
70
- ### Key Design Decisions
71
-
72
- **Stdio Transport**: Uses stdin/stdout for MCP communication, not HTTP. Server runs as child process.
73
-
74
- **API v2 with Optimistic Locking**: Uses `rev` field in responses to prevent conflicts.
75
-
76
- **Authentication Flexibility**: Supports both Bearer tokens (standalone Node-RED) and Basic auth (Home Assistant add-on).
77
-
78
- **JSON String Parameters**: MCP tool parameters receive flows as JSON strings, not objects. Tools parse and validate them.
79
-
80
- **Individual Flow Updates**: Uses PUT /flow/:id to update one flow at a time, preventing accidental destruction of other flows.
81
-
82
- ## Node-RED Admin API v2
83
-
84
- **GET /flows**:
85
- - Returns all flows: `{rev: "...", flows: [...]}`
86
-
87
- **POST /flow**:
88
- - Creates a new flow
89
- - Request: `{id, label, nodes: [], configs: []}`
90
- - Response: 200 or 204 with `{id: "..."}` in body
91
- - Flow ID is optional - auto-generated if not provided
92
-
93
- **PUT /flow/:id**:
94
- - Updates a single flow by ID
95
- - Request: `{id, label, nodes: [], configs: []}`
96
- - Response: 204 with `{id: "..."}` in body
97
- - Only affects the specified flow, all other flows remain untouched
98
-
99
- ## Testing
100
-
101
- Tests use vitest with mocked `undici` requests. Each component has dedicated test file:
102
- - `tests/client.test.ts` - HTTP client + auth modes
103
- - `tests/tools.test.ts` - Tool handlers
104
- - `tests/server.test.ts` - MCP server setup
105
-
106
- ## CRITICAL: Flow Update Safety
107
-
108
- **Always use PUT /flow/:id for individual flow updates**
109
-
110
- The MCP server uses `PUT /flow/:id` which:
111
- - Updates ONLY the specified flow
112
- - Leaves all other flows completely untouched
113
- - No risk of destroying unrelated workflows
114
- - Simpler and safer than POST /flows
115
-
116
- **Flow update format**:
117
- ```json
118
- {
119
- "id": "flow-id",
120
- "label": "Flow Name",
121
- "nodes": [...],
122
- "configs": [...]
123
- }
124
- ```
125
-
126
- ## CRITICAL: ALWAYS Use MCP Tools
127
-
128
- **NEVER bypass MCP tools to interact with Node-RED directly**
129
-
130
- - NEVER use `curl` to call Node-RED API directly
131
- - NEVER use Bash to make HTTP requests to Node-RED
132
- - ALWAYS use the MCP tools: `get_flows`, `create_flow`, `update_flow`, `validate_flow`
133
-
134
- The entire purpose of this MCP server is to provide safe, validated access to Node-RED through MCP tools. Bypassing them defeats the purpose and removes safety checks.
135
-
136
- If MCP tools appear to fail:
137
- 1. Debug the MCP tool issue
138
- 2. Fix the tool implementation
139
- 3. Test the fix
140
- 4. NEVER work around it with direct API calls
141
-
142
- ## Configuration
143
-
144
- Required env var: `NODE_RED_URL`
145
- Optional env var: `NODE_RED_TOKEN`
146
-
147
- For Home Assistant add-on deployments, embed credentials in URL: `http://username:password@host:1880`