mcp-node-red 1.0.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 (41) hide show
  1. package/.github/workflows/ci.yml +37 -0
  2. package/.github/workflows/release.yml +30 -0
  3. package/.mcp.json.example +11 -0
  4. package/.releaserc.json +17 -0
  5. package/CHANGELOG.md +8 -0
  6. package/CLAUDE.md +147 -0
  7. package/LICENSE +21 -0
  8. package/README.md +330 -0
  9. package/dist/client.d.ts +20 -0
  10. package/dist/client.d.ts.map +1 -0
  11. package/dist/client.js +110 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +7 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/schemas.d.ts +252 -0
  18. package/dist/schemas.d.ts.map +1 -0
  19. package/dist/schemas.js +44 -0
  20. package/dist/schemas.js.map +1 -0
  21. package/dist/server.d.ts +26 -0
  22. package/dist/server.d.ts.map +1 -0
  23. package/dist/server.js +121 -0
  24. package/dist/server.js.map +1 -0
  25. package/dist/tools/create-flow.d.ts +8 -0
  26. package/dist/tools/create-flow.d.ts.map +1 -0
  27. package/dist/tools/create-flow.js +26 -0
  28. package/dist/tools/create-flow.js.map +1 -0
  29. package/dist/tools/get-flows.d.ts +8 -0
  30. package/dist/tools/get-flows.d.ts.map +1 -0
  31. package/dist/tools/get-flows.js +12 -0
  32. package/dist/tools/get-flows.js.map +1 -0
  33. package/dist/tools/update-flow.d.ts +8 -0
  34. package/dist/tools/update-flow.d.ts.map +1 -0
  35. package/dist/tools/update-flow.js +32 -0
  36. package/dist/tools/update-flow.js.map +1 -0
  37. package/dist/tools/validate-flow.d.ts +8 -0
  38. package/dist/tools/validate-flow.d.ts.map +1 -0
  39. package/dist/tools/validate-flow.js +36 -0
  40. package/dist/tools/validate-flow.js.map +1 -0
  41. package/package.json +46 -0
package/dist/client.js ADDED
@@ -0,0 +1,110 @@
1
+ import { request } from 'undici';
2
+ import { NodeRedFlowsResponseSchema } from './schemas.js';
3
+ export class NodeRedClient {
4
+ baseUrl;
5
+ token;
6
+ basicAuth;
7
+ constructor(config) {
8
+ const url = new URL(config.nodeRedUrl);
9
+ // Extract basic auth from URL if present
10
+ if (url.username || url.password) {
11
+ this.basicAuth = Buffer.from(`${url.username}:${url.password}`).toString('base64');
12
+ url.username = '';
13
+ url.password = '';
14
+ }
15
+ this.baseUrl = url.toString().replace(/\/$/, '');
16
+ this.token = config.nodeRedToken;
17
+ }
18
+ getHeaders() {
19
+ const headers = {
20
+ 'Content-Type': 'application/json',
21
+ 'Node-RED-API-Version': 'v2',
22
+ };
23
+ if (this.token) {
24
+ headers.Authorization = `Bearer ${this.token}`;
25
+ }
26
+ else if (this.basicAuth) {
27
+ headers.Authorization = `Basic ${this.basicAuth}`;
28
+ }
29
+ return headers;
30
+ }
31
+ async getFlows() {
32
+ const response = await request(`${this.baseUrl}/flows`, {
33
+ method: 'GET',
34
+ headers: this.getHeaders(),
35
+ });
36
+ if (response.statusCode !== 200) {
37
+ const body = await response.body.text();
38
+ throw new Error(`Failed to get flows: ${response.statusCode}\n${body}`);
39
+ }
40
+ const data = await response.body.json();
41
+ return NodeRedFlowsResponseSchema.parse(data);
42
+ }
43
+ async createFlow(flowData) {
44
+ const response = await request(`${this.baseUrl}/flow`, {
45
+ method: 'POST',
46
+ headers: this.getHeaders(),
47
+ body: JSON.stringify(flowData),
48
+ });
49
+ if (response.statusCode !== 200 && response.statusCode !== 204) {
50
+ const body = await response.body.text();
51
+ throw new Error(`Failed to create flow: ${response.statusCode}\n${body}`);
52
+ }
53
+ // POST /flow returns 200 or 204 with JSON body containing {id}
54
+ const data = await response.body.json();
55
+ return data;
56
+ }
57
+ async updateFlow(flowId, flowData) {
58
+ const response = await request(`${this.baseUrl}/flow/${flowId}`, {
59
+ method: 'PUT',
60
+ headers: this.getHeaders(),
61
+ body: JSON.stringify(flowData),
62
+ });
63
+ if (response.statusCode !== 204) {
64
+ const body = await response.body.text();
65
+ throw new Error(`Failed to update flow: ${response.statusCode}\n${body}`);
66
+ }
67
+ // PUT /flow/:id returns 204 with JSON body containing {id}
68
+ const data = await response.body.json();
69
+ return data;
70
+ }
71
+ async validateFlow(flowData) {
72
+ try {
73
+ const errors = [];
74
+ if (!flowData.id) {
75
+ errors.push('Flow missing required id field');
76
+ }
77
+ if (flowData.nodes) {
78
+ for (const node of flowData.nodes) {
79
+ if (!node.id) {
80
+ errors.push('Node missing required id field');
81
+ }
82
+ if (!node.type) {
83
+ errors.push(`Node ${node.id} missing required type field`);
84
+ }
85
+ }
86
+ }
87
+ if (flowData.configs) {
88
+ for (const config of flowData.configs) {
89
+ if (!config.id) {
90
+ errors.push('Config node missing required id field');
91
+ }
92
+ if (!config.type) {
93
+ errors.push(`Config node ${config.id} missing required type field`);
94
+ }
95
+ }
96
+ }
97
+ return {
98
+ valid: errors.length === 0,
99
+ errors: errors.length > 0 ? errors : undefined,
100
+ };
101
+ }
102
+ catch (error) {
103
+ return {
104
+ valid: false,
105
+ errors: [error instanceof Error ? error.message : String(error)],
106
+ };
107
+ }
108
+ }
109
+ }
110
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { runServer } from './server.js';
3
+ runServer().catch((error) => {
4
+ console.error('Fatal error:', error);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,252 @@
1
+ import { z } from 'zod';
2
+ export declare const NodeRedNodeSchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ type: z.ZodString;
5
+ z: z.ZodOptional<z.ZodString>;
6
+ name: z.ZodOptional<z.ZodString>;
7
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
8
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
9
+ id: z.ZodString;
10
+ type: z.ZodString;
11
+ z: z.ZodOptional<z.ZodString>;
12
+ name: z.ZodOptional<z.ZodString>;
13
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
14
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
15
+ id: z.ZodString;
16
+ type: z.ZodString;
17
+ z: z.ZodOptional<z.ZodString>;
18
+ name: z.ZodOptional<z.ZodString>;
19
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
20
+ }, z.ZodTypeAny, "passthrough">>;
21
+ export declare const NodeRedFlowSchema: z.ZodObject<{
22
+ id: z.ZodString;
23
+ type: z.ZodLiteral<"tab">;
24
+ label: z.ZodString;
25
+ disabled: z.ZodOptional<z.ZodBoolean>;
26
+ info: z.ZodOptional<z.ZodString>;
27
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
28
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
29
+ id: z.ZodString;
30
+ type: z.ZodLiteral<"tab">;
31
+ label: z.ZodString;
32
+ disabled: z.ZodOptional<z.ZodBoolean>;
33
+ info: z.ZodOptional<z.ZodString>;
34
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
35
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
36
+ id: z.ZodString;
37
+ type: z.ZodLiteral<"tab">;
38
+ label: z.ZodString;
39
+ disabled: z.ZodOptional<z.ZodBoolean>;
40
+ info: z.ZodOptional<z.ZodString>;
41
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
42
+ }, z.ZodTypeAny, "passthrough">>;
43
+ export declare const NodeRedConfigSchema: z.ZodObject<{
44
+ id: z.ZodString;
45
+ type: z.ZodString;
46
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
47
+ id: z.ZodString;
48
+ type: z.ZodString;
49
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
50
+ id: z.ZodString;
51
+ type: z.ZodString;
52
+ }, z.ZodTypeAny, "passthrough">>;
53
+ export declare const NodeRedItemSchema: z.ZodUnion<[z.ZodObject<{
54
+ id: z.ZodString;
55
+ type: z.ZodLiteral<"tab">;
56
+ label: z.ZodString;
57
+ disabled: z.ZodOptional<z.ZodBoolean>;
58
+ info: z.ZodOptional<z.ZodString>;
59
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
60
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
61
+ id: z.ZodString;
62
+ type: z.ZodLiteral<"tab">;
63
+ label: z.ZodString;
64
+ disabled: z.ZodOptional<z.ZodBoolean>;
65
+ info: z.ZodOptional<z.ZodString>;
66
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
67
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
68
+ id: z.ZodString;
69
+ type: z.ZodLiteral<"tab">;
70
+ label: z.ZodString;
71
+ disabled: z.ZodOptional<z.ZodBoolean>;
72
+ info: z.ZodOptional<z.ZodString>;
73
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
74
+ }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{
75
+ id: z.ZodString;
76
+ type: z.ZodString;
77
+ z: z.ZodOptional<z.ZodString>;
78
+ name: z.ZodOptional<z.ZodString>;
79
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
80
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
81
+ id: z.ZodString;
82
+ type: z.ZodString;
83
+ z: z.ZodOptional<z.ZodString>;
84
+ name: z.ZodOptional<z.ZodString>;
85
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
86
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
87
+ id: z.ZodString;
88
+ type: z.ZodString;
89
+ z: z.ZodOptional<z.ZodString>;
90
+ name: z.ZodOptional<z.ZodString>;
91
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
92
+ }, z.ZodTypeAny, "passthrough">>]>;
93
+ export declare const NodeRedFlowsResponseSchema: z.ZodObject<{
94
+ rev: z.ZodString;
95
+ flows: z.ZodArray<z.ZodUnion<[z.ZodObject<{
96
+ id: z.ZodString;
97
+ type: z.ZodLiteral<"tab">;
98
+ label: z.ZodString;
99
+ disabled: z.ZodOptional<z.ZodBoolean>;
100
+ info: z.ZodOptional<z.ZodString>;
101
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
102
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
103
+ id: z.ZodString;
104
+ type: z.ZodLiteral<"tab">;
105
+ label: z.ZodString;
106
+ disabled: z.ZodOptional<z.ZodBoolean>;
107
+ info: z.ZodOptional<z.ZodString>;
108
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
109
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
110
+ id: z.ZodString;
111
+ type: z.ZodLiteral<"tab">;
112
+ label: z.ZodString;
113
+ disabled: z.ZodOptional<z.ZodBoolean>;
114
+ info: z.ZodOptional<z.ZodString>;
115
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
116
+ }, z.ZodTypeAny, "passthrough">>, z.ZodObject<{
117
+ id: z.ZodString;
118
+ type: z.ZodString;
119
+ z: z.ZodOptional<z.ZodString>;
120
+ name: z.ZodOptional<z.ZodString>;
121
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
122
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
123
+ id: z.ZodString;
124
+ type: z.ZodString;
125
+ z: z.ZodOptional<z.ZodString>;
126
+ name: z.ZodOptional<z.ZodString>;
127
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
128
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
129
+ id: z.ZodString;
130
+ type: z.ZodString;
131
+ z: z.ZodOptional<z.ZodString>;
132
+ name: z.ZodOptional<z.ZodString>;
133
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
134
+ }, z.ZodTypeAny, "passthrough">>]>, "many">;
135
+ }, "strip", z.ZodTypeAny, {
136
+ rev: string;
137
+ flows: (z.objectOutputType<{
138
+ id: z.ZodString;
139
+ type: z.ZodString;
140
+ z: z.ZodOptional<z.ZodString>;
141
+ name: z.ZodOptional<z.ZodString>;
142
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
143
+ }, z.ZodTypeAny, "passthrough"> | z.objectOutputType<{
144
+ id: z.ZodString;
145
+ type: z.ZodLiteral<"tab">;
146
+ label: z.ZodString;
147
+ disabled: z.ZodOptional<z.ZodBoolean>;
148
+ info: z.ZodOptional<z.ZodString>;
149
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
150
+ }, z.ZodTypeAny, "passthrough">)[];
151
+ }, {
152
+ rev: string;
153
+ flows: (z.objectInputType<{
154
+ id: z.ZodString;
155
+ type: z.ZodString;
156
+ z: z.ZodOptional<z.ZodString>;
157
+ name: z.ZodOptional<z.ZodString>;
158
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
159
+ }, z.ZodTypeAny, "passthrough"> | z.objectInputType<{
160
+ id: z.ZodString;
161
+ type: z.ZodLiteral<"tab">;
162
+ label: z.ZodString;
163
+ disabled: z.ZodOptional<z.ZodBoolean>;
164
+ info: z.ZodOptional<z.ZodString>;
165
+ env: z.ZodOptional<z.ZodArray<z.ZodUnknown, "many">>;
166
+ }, z.ZodTypeAny, "passthrough">)[];
167
+ }>;
168
+ export declare const UpdateFlowRequestSchema: z.ZodObject<{
169
+ id: z.ZodString;
170
+ label: z.ZodOptional<z.ZodString>;
171
+ disabled: z.ZodOptional<z.ZodBoolean>;
172
+ info: z.ZodOptional<z.ZodString>;
173
+ nodes: z.ZodOptional<z.ZodArray<z.ZodObject<{
174
+ id: z.ZodString;
175
+ type: z.ZodString;
176
+ z: z.ZodOptional<z.ZodString>;
177
+ name: z.ZodOptional<z.ZodString>;
178
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
179
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
180
+ id: z.ZodString;
181
+ type: z.ZodString;
182
+ z: z.ZodOptional<z.ZodString>;
183
+ name: z.ZodOptional<z.ZodString>;
184
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
185
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
186
+ id: z.ZodString;
187
+ type: z.ZodString;
188
+ z: z.ZodOptional<z.ZodString>;
189
+ name: z.ZodOptional<z.ZodString>;
190
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
191
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
192
+ configs: z.ZodOptional<z.ZodArray<z.ZodObject<{
193
+ id: z.ZodString;
194
+ type: z.ZodString;
195
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
196
+ id: z.ZodString;
197
+ type: z.ZodString;
198
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
199
+ id: z.ZodString;
200
+ type: z.ZodString;
201
+ }, z.ZodTypeAny, "passthrough">>, "many">>;
202
+ }, "strip", z.ZodTypeAny, {
203
+ id: string;
204
+ label?: string | undefined;
205
+ disabled?: boolean | undefined;
206
+ info?: string | undefined;
207
+ nodes?: z.objectOutputType<{
208
+ id: z.ZodString;
209
+ type: z.ZodString;
210
+ z: z.ZodOptional<z.ZodString>;
211
+ name: z.ZodOptional<z.ZodString>;
212
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
213
+ }, z.ZodTypeAny, "passthrough">[] | undefined;
214
+ configs?: z.objectOutputType<{
215
+ id: z.ZodString;
216
+ type: z.ZodString;
217
+ }, z.ZodTypeAny, "passthrough">[] | undefined;
218
+ }, {
219
+ id: string;
220
+ label?: string | undefined;
221
+ disabled?: boolean | undefined;
222
+ info?: string | undefined;
223
+ nodes?: z.objectInputType<{
224
+ id: z.ZodString;
225
+ type: z.ZodString;
226
+ z: z.ZodOptional<z.ZodString>;
227
+ name: z.ZodOptional<z.ZodString>;
228
+ wires: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString, "many">, "many">>;
229
+ }, z.ZodTypeAny, "passthrough">[] | undefined;
230
+ configs?: z.objectInputType<{
231
+ id: z.ZodString;
232
+ type: z.ZodString;
233
+ }, z.ZodTypeAny, "passthrough">[] | undefined;
234
+ }>;
235
+ export declare const ConfigSchema: z.ZodObject<{
236
+ nodeRedUrl: z.ZodString;
237
+ nodeRedToken: z.ZodOptional<z.ZodString>;
238
+ }, "strip", z.ZodTypeAny, {
239
+ nodeRedUrl: string;
240
+ nodeRedToken?: string | undefined;
241
+ }, {
242
+ nodeRedUrl: string;
243
+ nodeRedToken?: string | undefined;
244
+ }>;
245
+ export type NodeRedNode = z.infer<typeof NodeRedNodeSchema>;
246
+ export type NodeRedFlow = z.infer<typeof NodeRedFlowSchema>;
247
+ export type NodeRedConfig = z.infer<typeof NodeRedConfigSchema>;
248
+ export type NodeRedItem = z.infer<typeof NodeRedItemSchema>;
249
+ export type NodeRedFlowsResponse = z.infer<typeof NodeRedFlowsResponseSchema>;
250
+ export type UpdateFlowRequest = z.infer<typeof UpdateFlowRequestSchema>;
251
+ export type Config = z.infer<typeof ConfigSchema>;
252
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;gCAQd,CAAC;AAEjB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;gCASd,CAAC;AAEjB,eAAO,MAAM,mBAAmB;;;;;;;;;gCAKhB,CAAC;AAEjB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCAAkD,CAAC;AAEjF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGrC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOlC,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;EAGvB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod';
2
+ export const NodeRedNodeSchema = z
3
+ .object({
4
+ id: z.string(),
5
+ type: z.string(),
6
+ z: z.string().optional(),
7
+ name: z.string().optional(),
8
+ wires: z.array(z.array(z.string())).optional(),
9
+ })
10
+ .passthrough();
11
+ export const NodeRedFlowSchema = z
12
+ .object({
13
+ id: z.string(),
14
+ type: z.literal('tab'),
15
+ label: z.string(),
16
+ disabled: z.boolean().optional(),
17
+ info: z.string().optional(),
18
+ env: z.array(z.unknown()).optional(),
19
+ })
20
+ .passthrough();
21
+ export const NodeRedConfigSchema = z
22
+ .object({
23
+ id: z.string(),
24
+ type: z.string(),
25
+ })
26
+ .passthrough();
27
+ export const NodeRedItemSchema = z.union([NodeRedFlowSchema, NodeRedNodeSchema]);
28
+ export const NodeRedFlowsResponseSchema = z.object({
29
+ rev: z.string(),
30
+ flows: z.array(NodeRedItemSchema),
31
+ });
32
+ export const UpdateFlowRequestSchema = z.object({
33
+ id: z.string(),
34
+ label: z.string().optional(),
35
+ disabled: z.boolean().optional(),
36
+ info: z.string().optional(),
37
+ nodes: z.array(NodeRedNodeSchema).optional(),
38
+ configs: z.array(NodeRedConfigSchema).optional(),
39
+ });
40
+ export const ConfigSchema = z.object({
41
+ nodeRedUrl: z.string().url(),
42
+ nodeRedToken: z.string().optional(),
43
+ });
44
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,MAAM,CAAC;IACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACxB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC/C,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,MAAM,CAAC;IACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACtB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC;KACjC,MAAM,CAAC;IACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC;KACD,WAAW,EAAE,CAAC;AAEjB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAEjF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;CAClC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE;IAC5C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,QAAQ,EAAE;CACjD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC5B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ export declare function createServer(): Server<{
3
+ method: string;
4
+ params?: {
5
+ [x: string]: unknown;
6
+ _meta?: {
7
+ [x: string]: unknown;
8
+ progressToken?: string | number | undefined;
9
+ } | undefined;
10
+ } | undefined;
11
+ }, {
12
+ method: string;
13
+ params?: {
14
+ [x: string]: unknown;
15
+ _meta?: {
16
+ [x: string]: unknown;
17
+ } | undefined;
18
+ } | undefined;
19
+ }, {
20
+ [x: string]: unknown;
21
+ _meta?: {
22
+ [x: string]: unknown;
23
+ } | undefined;
24
+ }>;
25
+ export declare function runServer(): Promise<void>;
26
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAUnE,wBAAgB,YAAY;;;;;;;;;;;;;;;;;;;;;;GAyH3B;AAED,wBAAsB,SAAS,kBAI9B"}
package/dist/server.js ADDED
@@ -0,0 +1,121 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
+ import { NodeRedClient } from './client.js';
5
+ import { ConfigSchema } from './schemas.js';
6
+ import { createFlow } from './tools/create-flow.js';
7
+ import { getFlows } from './tools/get-flows.js';
8
+ import { updateFlow } from './tools/update-flow.js';
9
+ import { validateFlow } from './tools/validate-flow.js';
10
+ export function createServer() {
11
+ const nodeRedUrl = process.env.NODE_RED_URL;
12
+ const nodeRedToken = process.env.NODE_RED_TOKEN;
13
+ if (!nodeRedUrl) {
14
+ throw new Error('NODE_RED_URL environment variable is required');
15
+ }
16
+ const config = ConfigSchema.parse({
17
+ nodeRedUrl,
18
+ nodeRedToken,
19
+ });
20
+ const client = new NodeRedClient(config);
21
+ const server = new Server({
22
+ name: 'node-red-mcp-server',
23
+ version: '1.0.0',
24
+ }, {
25
+ capabilities: {
26
+ tools: {},
27
+ },
28
+ });
29
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
30
+ tools: [
31
+ {
32
+ name: 'get_flows',
33
+ description: 'Get all flows from Node-RED instance. Returns current flows configuration including revision number.',
34
+ inputSchema: {
35
+ type: 'object',
36
+ properties: {},
37
+ },
38
+ },
39
+ {
40
+ name: 'create_flow',
41
+ description: 'Create a new flow using POST /flow. Adds a new flow to Node-RED. Flow ID can be provided or will be auto-generated.',
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {
45
+ flow: {
46
+ type: 'string',
47
+ description: 'JSON string containing flow data with format: {id, label, nodes: [], configs: []}',
48
+ },
49
+ },
50
+ required: ['flow'],
51
+ },
52
+ },
53
+ {
54
+ name: 'update_flow',
55
+ description: 'Update a specific flow by ID using PUT /flow/:id. Only affects the specified flow, leaving all other flows untouched. Requires flow object with id, label, nodes array, and optional configs array.',
56
+ inputSchema: {
57
+ type: 'object',
58
+ properties: {
59
+ flowId: {
60
+ type: 'string',
61
+ description: 'ID of the flow to update',
62
+ },
63
+ updates: {
64
+ type: 'string',
65
+ description: 'JSON string containing flow update with format: {id, label, nodes: [], configs: []}',
66
+ },
67
+ },
68
+ required: ['flowId', 'updates'],
69
+ },
70
+ },
71
+ {
72
+ name: 'validate_flow',
73
+ description: 'Validate flow configuration without deploying. Checks for required fields and structural integrity.',
74
+ inputSchema: {
75
+ type: 'object',
76
+ properties: {
77
+ flow: {
78
+ type: 'string',
79
+ description: 'JSON string containing flow data with format: {id, label, nodes: [], configs: []}',
80
+ },
81
+ },
82
+ required: ['flow'],
83
+ },
84
+ },
85
+ ],
86
+ }));
87
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
88
+ try {
89
+ switch (request.params.name) {
90
+ case 'get_flows':
91
+ return await getFlows(client);
92
+ case 'create_flow':
93
+ return await createFlow(client, request.params.arguments);
94
+ case 'update_flow':
95
+ return await updateFlow(client, request.params.arguments);
96
+ case 'validate_flow':
97
+ return await validateFlow(client, request.params.arguments);
98
+ default:
99
+ throw new Error(`Unknown tool: ${request.params.name}`);
100
+ }
101
+ }
102
+ catch (error) {
103
+ return {
104
+ content: [
105
+ {
106
+ type: 'text',
107
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
108
+ },
109
+ ],
110
+ isError: true,
111
+ };
112
+ }
113
+ });
114
+ return server;
115
+ }
116
+ export async function runServer() {
117
+ const server = createServer();
118
+ const transport = new StdioServerTransport();
119
+ await server.connect(transport);
120
+ }
121
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { NodeRedClient } from '../client.js';
2
+ export declare function createFlow(client: NodeRedClient, args: unknown): Promise<{
3
+ content: {
4
+ type: "text";
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=create-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-flow.d.ts","sourceRoot":"","sources":["../../src/tools/create-flow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAOlD,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO;;;;;GAwBpE"}
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import { UpdateFlowRequestSchema } from '../schemas.js';
3
+ const CreateFlowArgsSchema = z.object({
4
+ flow: z.string(),
5
+ });
6
+ export async function createFlow(client, args) {
7
+ const parsed = CreateFlowArgsSchema.parse(args);
8
+ let flowData;
9
+ try {
10
+ flowData = JSON.parse(parsed.flow);
11
+ }
12
+ catch (error) {
13
+ throw new Error(`Invalid JSON in flow parameter: ${error instanceof Error ? error.message : String(error)}`);
14
+ }
15
+ const validated = UpdateFlowRequestSchema.parse(flowData);
16
+ const result = await client.createFlow(validated);
17
+ return {
18
+ content: [
19
+ {
20
+ type: 'text',
21
+ text: JSON.stringify(result, null, 2),
22
+ },
23
+ ],
24
+ };
25
+ }
26
+ //# sourceMappingURL=create-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-flow.js","sourceRoot":"","sources":["../../src/tools/create-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAqB,EAAE,IAAa;IACnE,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEhD,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,mCAAmC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC5F,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,uBAAuB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAElD,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 getFlows(client: NodeRedClient): Promise<{
3
+ content: {
4
+ type: "text";
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=get-flows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-flows.d.ts","sourceRoot":"","sources":["../../src/tools/get-flows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAsB,QAAQ,CAAC,MAAM,EAAE,aAAa;;;;;GAUnD"}