@iflow-mcp/jimmy974-n8n-workflow-builder 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.
@@ -0,0 +1,4 @@
1
+ [2026-01-12 13:21:25] [SUCCESS] 步骤1:获取项目完成 - Fork并克隆项目成功
2
+ [2026-01-12 13:21:45] [SUCCESS] 步骤2:阅读代码完成 - Node.js项目,MCP服务端项目,使用@modelcontextprotocol/sdk,支持stdio协议
3
+ [2026-01-12 13:22:23] [SUCCESS] 步骤3:本地测试完成 - 修改配置、构建、本地测试通过,发现1个工具:create_workflow
4
+ [2026-01-12 13:22:40] [SUCCESS] 步骤4:创建并推送iflow分支完成 - 已推送到https://github.com/iflow-mcp/jimmy974-n8n-workflow-builder
package/Dockerfile ADDED
@@ -0,0 +1,36 @@
1
+ # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
2
+ # Use Node.js as the base image
3
+ FROM node:20-alpine AS builder
4
+
5
+ # Set the working directory in the container
6
+ WORKDIR /app
7
+
8
+ # Copy the package files and install dependencies
9
+ COPY package.json package-lock.json ./
10
+ RUN npm install
11
+
12
+ # Copy the source code
13
+ COPY src ./src
14
+ COPY tsconfig.json ./
15
+
16
+ # Compile the TypeScript code
17
+ RUN npx tsc
18
+
19
+ # Use a slim Node.js image for the final build
20
+ FROM node:20-slim
21
+
22
+ # Set the working directory in the container
23
+ WORKDIR /app
24
+
25
+ # Copy compiled code from the builder stage
26
+ COPY --from=builder /app/dist ./dist
27
+
28
+ # Install only production dependencies
29
+ COPY package.json package-lock.json ./
30
+ RUN npm install --omit=dev
31
+
32
+ # Expose any necessary ports (assuming 3000 as an example)
33
+ EXPOSE 3000
34
+
35
+ # Command to run the application
36
+ CMD ["node", "dist/index.js"]
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Makafeli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # n8n Workflow Builder MCP Server
2
+ [![smithery badge](https://smithery.ai/badge/n8n-workflow-builder)](https://smithery.ai/server/n8n-workflow-builder)
3
+
4
+ A Model Context Protocol (MCP) server for programmatically creating and managing n8n workflows.
5
+
6
+ <a href="https://glama.ai/mcp/servers/fhoynrlnpp"><img width="380" height="200" src="https://glama.ai/mcp/servers/fhoynrlnpp/badge" alt="n8n Workflow Builder Server MCP server" /></a>
7
+
8
+ ## Features
9
+ - Create workflows with nodes and connections
10
+ - Validate workflow specifications
11
+ - Export complete workflow configurations
12
+ - REST API interface through MCP
13
+
14
+ ## Installation
15
+
16
+ ### Installing via Smithery
17
+
18
+ To install n8n Workflow Builder for Claude Desktop automatically via [Smithery](https://smithery.ai/server/n8n-workflow-builder):
19
+
20
+ ```bash
21
+ npx -y @smithery/cli install n8n-workflow-builder --client claude
22
+ ```
23
+
24
+ ### Manual Installation
25
+ 1. Clone the repository:
26
+ ```bash
27
+ git clone https://github.com/[your-username]/n8n-workflow-builder.git
28
+ cd n8n-workflow-builder
29
+ ```
30
+
31
+ 2. Install dependencies:
32
+ ```bash
33
+ npm install
34
+ ```
35
+
36
+ 3. Compile TypeScript:
37
+ ```bash
38
+ npx tsc
39
+ ```
40
+
41
+ 4. Start the server:
42
+ ```bash
43
+ npm start
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ The server provides a `create_workflow` tool that accepts a workflow specification:
49
+
50
+ ```json
51
+ {
52
+ "nodes": [
53
+ {
54
+ "type": "n8n-nodes-base.httpRequest",
55
+ "name": "HTTP Request",
56
+ "parameters": {
57
+ "url": "https://example.com",
58
+ "method": "GET"
59
+ }
60
+ }
61
+ ],
62
+ "connections": []
63
+ }
64
+ ```
65
+
66
+ ## Configuration
67
+
68
+ Add the server to your MCP configuration:
69
+
70
+ ```json
71
+ {
72
+ "n8n-workflow-builder": {
73
+ "command": "node",
74
+ "args": ["/path/to/n8n-workflow-builder/dist/index.js"]
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## License
80
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
+ import { CallToolRequestSchema, ListToolsRequestSchema, McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
14
+ class N8NWorkflowBuilder {
15
+ constructor() {
16
+ this.nodes = [];
17
+ this.connections = [];
18
+ this.nextPosition = { x: 100, y: 100 };
19
+ }
20
+ addNode(nodeType, name, parameters) {
21
+ const node = {
22
+ type: nodeType,
23
+ name: name,
24
+ parameters: parameters,
25
+ position: Object.assign({}, this.nextPosition)
26
+ };
27
+ this.nodes.push(node);
28
+ this.nextPosition.x += 200;
29
+ return name;
30
+ }
31
+ connectNodes(source, target, sourceOutput = 0, targetInput = 0) {
32
+ this.connections.push({
33
+ source_node: source,
34
+ target_node: target,
35
+ source_output: sourceOutput,
36
+ target_input: targetInput
37
+ });
38
+ }
39
+ exportWorkflow() {
40
+ const workflow = {
41
+ nodes: this.nodes,
42
+ connections: { main: [] }
43
+ };
44
+ for (const conn of this.connections) {
45
+ const connection = {
46
+ node: conn.target_node,
47
+ type: 'main',
48
+ index: conn.target_input,
49
+ sourceNode: conn.source_node,
50
+ sourceIndex: conn.source_output
51
+ };
52
+ workflow.connections.main.push(connection);
53
+ }
54
+ return workflow;
55
+ }
56
+ }
57
+ class N8NWorkflowServer {
58
+ constructor() {
59
+ this.server = new Server({
60
+ name: 'n8n-workflow-builder',
61
+ version: '0.1.0'
62
+ }, {
63
+ capabilities: {
64
+ resources: {},
65
+ tools: {}
66
+ }
67
+ });
68
+ this.setupToolHandlers();
69
+ this.server.onerror = (error) => console.error('[MCP Error]', error);
70
+ }
71
+ setupToolHandlers() {
72
+ this.server.setRequestHandler(ListToolsRequestSchema, () => __awaiter(this, void 0, void 0, function* () {
73
+ return ({
74
+ tools: [{
75
+ name: 'create_workflow',
76
+ description: 'Create and configure n8n workflows programmatically',
77
+ inputSchema: {
78
+ type: 'object',
79
+ properties: {
80
+ nodes: {
81
+ type: 'array',
82
+ items: {
83
+ type: 'object',
84
+ properties: {
85
+ type: { type: 'string' },
86
+ name: { type: 'string' },
87
+ parameters: { type: 'object' }
88
+ },
89
+ required: ['type', 'name']
90
+ }
91
+ },
92
+ connections: {
93
+ type: 'array',
94
+ items: {
95
+ type: 'object',
96
+ properties: {
97
+ source: { type: 'string' },
98
+ target: { type: 'string' },
99
+ sourceOutput: { type: 'number', default: 0 },
100
+ targetInput: { type: 'number', default: 0 }
101
+ },
102
+ required: ['source', 'target']
103
+ }
104
+ }
105
+ },
106
+ required: ['nodes']
107
+ }
108
+ }]
109
+ });
110
+ }));
111
+ this.server.setRequestHandler(CallToolRequestSchema, (request) => __awaiter(this, void 0, void 0, function* () {
112
+ if (request.params.name !== 'create_workflow') {
113
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
114
+ }
115
+ try {
116
+ const builder = new N8NWorkflowBuilder();
117
+ function isWorkflowSpec(obj) {
118
+ return obj &&
119
+ typeof obj === 'object' &&
120
+ Array.isArray(obj.nodes) &&
121
+ obj.nodes.every((node) => typeof node === 'object' &&
122
+ typeof node.type === 'string' &&
123
+ typeof node.name === 'string') &&
124
+ (!obj.connections || (Array.isArray(obj.connections) &&
125
+ obj.connections.every((conn) => typeof conn === 'object' &&
126
+ typeof conn.source === 'string' &&
127
+ typeof conn.target === 'string')));
128
+ }
129
+ const args = request.params.arguments;
130
+ if (!isWorkflowSpec(args)) {
131
+ throw new McpError(ErrorCode.InvalidParams, 'Invalid workflow specification: must include nodes array with type and name properties');
132
+ }
133
+ const { nodes, connections } = args;
134
+ for (const node of nodes) {
135
+ builder.addNode(node.type, node.name, node.parameters || {});
136
+ }
137
+ for (const conn of connections || []) {
138
+ builder.connectNodes(conn.source, conn.target, conn.sourceOutput, conn.targetInput);
139
+ }
140
+ return {
141
+ content: [{
142
+ type: 'text',
143
+ text: JSON.stringify(builder.exportWorkflow(), null, 2)
144
+ }]
145
+ };
146
+ }
147
+ catch (error) {
148
+ throw new McpError(ErrorCode.InternalError, `Workflow creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
149
+ }
150
+ }));
151
+ }
152
+ run() {
153
+ return __awaiter(this, void 0, void 0, function* () {
154
+ const transport = new StdioServerTransport();
155
+ yield this.server.connect(transport);
156
+ console.error('N8N Workflow Builder MCP server running on stdio');
157
+ });
158
+ }
159
+ }
160
+ const server = new N8NWorkflowServer();
161
+ server.run().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@iflow-mcp/jimmy974-n8n-workflow-builder",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "start": "node dist/index.js"
7
+ },
8
+ "bin": {
9
+ "n8n-workflow-builder": "dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "^1.0.0"
13
+ },
14
+ "devDependencies": {
15
+ "typescript": "^5.0.0",
16
+ "@types/node": "^20.0.0"
17
+ }
18
+ }
package/push_info.json ADDED
@@ -0,0 +1 @@
1
+ {"push_platform":"github","fork_url":"https://github.com/iflow-mcp/jimmy974-n8n-workflow-builder","fork_branch":"iflow"}
package/smithery.yaml ADDED
@@ -0,0 +1,13 @@
1
+ # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml
2
+
3
+ startCommand:
4
+ type: stdio
5
+ configSchema:
6
+ # JSON Schema defining the configuration options for the MCP.
7
+ type: object
8
+ required: []
9
+ properties: {}
10
+ commandFunction:
11
+ # A function that produces the CLI command to start the MCP on stdio.
12
+ |-
13
+ (config) => ({command: 'node', args: ['dist/index.js']})
package/src/index.js ADDED
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
14
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
15
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
16
+ class N8NWorkflowBuilder {
17
+ constructor() {
18
+ this.nodes = [];
19
+ this.connections = [];
20
+ this.nextPosition = { x: 100, y: 100 };
21
+ }
22
+ addNode(nodeType, name, parameters) {
23
+ const node = {
24
+ type: nodeType,
25
+ name: name,
26
+ parameters: parameters,
27
+ position: Object.assign({}, this.nextPosition)
28
+ };
29
+ this.nodes.push(node);
30
+ this.nextPosition.x += 200;
31
+ return name;
32
+ }
33
+ connectNodes(source, target, sourceOutput = 0, targetInput = 0) {
34
+ this.connections.push({
35
+ source_node: source,
36
+ target_node: target,
37
+ source_output: sourceOutput,
38
+ target_input: targetInput
39
+ });
40
+ }
41
+ exportWorkflow() {
42
+ const workflow = {
43
+ nodes: this.nodes,
44
+ connections: { main: [] }
45
+ };
46
+ for (const conn of this.connections) {
47
+ const connection = {
48
+ node: conn.target_node,
49
+ type: 'main',
50
+ index: conn.target_input,
51
+ sourceNode: conn.source_node,
52
+ sourceIndex: conn.source_output
53
+ };
54
+ workflow.connections.main.push(connection);
55
+ }
56
+ return workflow;
57
+ }
58
+ }
59
+ class N8NWorkflowServer {
60
+ constructor() {
61
+ this.server = new index_js_1.Server({
62
+ name: 'n8n-workflow-builder',
63
+ version: '0.1.0'
64
+ }, {
65
+ capabilities: {
66
+ resources: {},
67
+ tools: {}
68
+ }
69
+ });
70
+ this.setupToolHandlers();
71
+ this.server.onerror = (error) => console.error('[MCP Error]', error);
72
+ }
73
+ setupToolHandlers() {
74
+ this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, () => __awaiter(this, void 0, void 0, function* () {
75
+ return ({
76
+ tools: [{
77
+ name: 'create_workflow',
78
+ description: 'Create and configure n8n workflows programmatically',
79
+ inputSchema: {
80
+ type: 'object',
81
+ properties: {
82
+ nodes: {
83
+ type: 'array',
84
+ items: {
85
+ type: 'object',
86
+ properties: {
87
+ type: { type: 'string' },
88
+ name: { type: 'string' },
89
+ parameters: { type: 'object' }
90
+ },
91
+ required: ['type', 'name']
92
+ }
93
+ },
94
+ connections: {
95
+ type: 'array',
96
+ items: {
97
+ type: 'object',
98
+ properties: {
99
+ source: { type: 'string' },
100
+ target: { type: 'string' },
101
+ sourceOutput: { type: 'number', default: 0 },
102
+ targetInput: { type: 'number', default: 0 }
103
+ },
104
+ required: ['source', 'target']
105
+ }
106
+ }
107
+ },
108
+ required: ['nodes']
109
+ }
110
+ }]
111
+ });
112
+ }));
113
+ this.server.setRequestHandler(types_js_1.CallToolRequestSchema, (request) => __awaiter(this, void 0, void 0, function* () {
114
+ if (request.params.name !== 'create_workflow') {
115
+ throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
116
+ }
117
+ try {
118
+ const builder = new N8NWorkflowBuilder();
119
+ function isWorkflowSpec(obj) {
120
+ return obj &&
121
+ typeof obj === 'object' &&
122
+ Array.isArray(obj.nodes) &&
123
+ obj.nodes.every((node) => typeof node === 'object' &&
124
+ typeof node.type === 'string' &&
125
+ typeof node.name === 'string') &&
126
+ (!obj.connections || (Array.isArray(obj.connections) &&
127
+ obj.connections.every((conn) => typeof conn === 'object' &&
128
+ typeof conn.source === 'string' &&
129
+ typeof conn.target === 'string')));
130
+ }
131
+ const args = request.params.arguments;
132
+ if (!isWorkflowSpec(args)) {
133
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Invalid workflow specification: must include nodes array with type and name properties');
134
+ }
135
+ const { nodes, connections } = args;
136
+ for (const node of nodes) {
137
+ builder.addNode(node.type, node.name, node.parameters || {});
138
+ }
139
+ for (const conn of connections || []) {
140
+ builder.connectNodes(conn.source, conn.target, conn.sourceOutput, conn.targetInput);
141
+ }
142
+ return {
143
+ content: [{
144
+ type: 'text',
145
+ text: JSON.stringify(builder.exportWorkflow(), null, 2)
146
+ }]
147
+ };
148
+ }
149
+ catch (error) {
150
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Workflow creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
151
+ }
152
+ }));
153
+ }
154
+ run() {
155
+ return __awaiter(this, void 0, void 0, function* () {
156
+ const transport = new stdio_js_1.StdioServerTransport();
157
+ yield this.server.connect(transport);
158
+ console.error('N8N Workflow Builder MCP server running on stdio');
159
+ });
160
+ }
161
+ }
162
+ const server = new N8NWorkflowServer();
163
+ server.run().catch(console.error);
package/src/index.ts ADDED
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema,
7
+ McpError,
8
+ ErrorCode
9
+ } from '@modelcontextprotocol/sdk/types.js';
10
+
11
+ class N8NWorkflowBuilder {
12
+ private nodes: any[];
13
+ private connections: any[];
14
+ private nextPosition: { x: number, y: number };
15
+
16
+ constructor() {
17
+ this.nodes = [];
18
+ this.connections = [];
19
+ this.nextPosition = { x: 100, y: 100 };
20
+ }
21
+
22
+ addNode(nodeType: string, name: string, parameters: any) {
23
+ const node = {
24
+ type: nodeType,
25
+ name: name,
26
+ parameters: parameters,
27
+ position: { ...this.nextPosition }
28
+ };
29
+ this.nodes.push(node);
30
+ this.nextPosition.x += 200;
31
+ return name;
32
+ }
33
+
34
+ connectNodes(source: string, target: string, sourceOutput = 0, targetInput = 0) {
35
+ this.connections.push({
36
+ source_node: source,
37
+ target_node: target,
38
+ source_output: sourceOutput,
39
+ target_input: targetInput
40
+ });
41
+ }
42
+
43
+ exportWorkflow(): any {
44
+ interface WorkflowConnection {
45
+ node: string;
46
+ type: string;
47
+ index: number;
48
+ sourceNode: string;
49
+ sourceIndex: number;
50
+ }
51
+
52
+ interface Workflow {
53
+ nodes: any[];
54
+ connections: {
55
+ main: WorkflowConnection[];
56
+ };
57
+ }
58
+
59
+ const workflow: Workflow = {
60
+ nodes: this.nodes,
61
+ connections: { main: [] }
62
+ };
63
+
64
+ for (const conn of this.connections) {
65
+ const connection: WorkflowConnection = {
66
+ node: conn.target_node,
67
+ type: 'main',
68
+ index: conn.target_input,
69
+ sourceNode: conn.source_node,
70
+ sourceIndex: conn.source_output
71
+ };
72
+ workflow.connections.main.push(connection);
73
+ }
74
+
75
+ return workflow;
76
+ }
77
+ }
78
+
79
+ class N8NWorkflowServer {
80
+ private server: Server;
81
+
82
+ constructor() {
83
+ this.server = new Server(
84
+ {
85
+ name: 'n8n-workflow-builder',
86
+ version: '0.1.0'
87
+ },
88
+ {
89
+ capabilities: {
90
+ resources: {},
91
+ tools: {}
92
+ }
93
+ }
94
+ );
95
+
96
+ this.setupToolHandlers();
97
+ this.server.onerror = (error) => console.error('[MCP Error]', error);
98
+ }
99
+
100
+ private setupToolHandlers() {
101
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
102
+ tools: [{
103
+ name: 'create_workflow',
104
+ description: 'Create and configure n8n workflows programmatically',
105
+ inputSchema: {
106
+ type: 'object',
107
+ properties: {
108
+ nodes: {
109
+ type: 'array',
110
+ items: {
111
+ type: 'object',
112
+ properties: {
113
+ type: { type: 'string' },
114
+ name: { type: 'string' },
115
+ parameters: { type: 'object' }
116
+ },
117
+ required: ['type', 'name']
118
+ }
119
+ },
120
+ connections: {
121
+ type: 'array',
122
+ items: {
123
+ type: 'object',
124
+ properties: {
125
+ source: { type: 'string' },
126
+ target: { type: 'string' },
127
+ sourceOutput: { type: 'number', default: 0 },
128
+ targetInput: { type: 'number', default: 0 }
129
+ },
130
+ required: ['source', 'target']
131
+ }
132
+ }
133
+ },
134
+ required: ['nodes']
135
+ }
136
+ }]
137
+ }));
138
+
139
+ interface WorkflowNode {
140
+ type: string;
141
+ name: string;
142
+ parameters?: Record<string, any>;
143
+ }
144
+
145
+ interface WorkflowConnectionSpec {
146
+ source: string;
147
+ target: string;
148
+ sourceOutput?: number;
149
+ targetInput?: number;
150
+ }
151
+
152
+ interface WorkflowSpec {
153
+ nodes: WorkflowNode[];
154
+ connections?: WorkflowConnectionSpec[];
155
+ }
156
+
157
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
158
+ if (request.params.name !== 'create_workflow') {
159
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
160
+ }
161
+
162
+ try {
163
+ const builder = new N8NWorkflowBuilder();
164
+ function isWorkflowSpec(obj: any): obj is WorkflowSpec {
165
+ return obj &&
166
+ typeof obj === 'object' &&
167
+ Array.isArray(obj.nodes) &&
168
+ obj.nodes.every((node: any) =>
169
+ typeof node === 'object' &&
170
+ typeof node.type === 'string' &&
171
+ typeof node.name === 'string'
172
+ ) &&
173
+ (!obj.connections || (
174
+ Array.isArray(obj.connections) &&
175
+ obj.connections.every((conn: any) =>
176
+ typeof conn === 'object' &&
177
+ typeof conn.source === 'string' &&
178
+ typeof conn.target === 'string'
179
+ )
180
+ ));
181
+ }
182
+
183
+ const args = request.params.arguments;
184
+ if (!isWorkflowSpec(args)) {
185
+ throw new McpError(
186
+ ErrorCode.InvalidParams,
187
+ 'Invalid workflow specification: must include nodes array with type and name properties'
188
+ );
189
+ }
190
+
191
+ const { nodes, connections } = args;
192
+
193
+ for (const node of nodes) {
194
+ builder.addNode(node.type, node.name, node.parameters || {});
195
+ }
196
+
197
+ for (const conn of connections || []) {
198
+ builder.connectNodes(
199
+ conn.source,
200
+ conn.target,
201
+ conn.sourceOutput,
202
+ conn.targetInput
203
+ );
204
+ }
205
+
206
+ return {
207
+ content: [{
208
+ type: 'text',
209
+ text: JSON.stringify(builder.exportWorkflow(), null, 2)
210
+ }]
211
+ };
212
+ } catch (error) {
213
+ throw new McpError(
214
+ ErrorCode.InternalError,
215
+ `Workflow creation failed: ${error instanceof Error ? error.message : 'Unknown error'}`
216
+ );
217
+ }
218
+ });
219
+ }
220
+
221
+ async run() {
222
+ const transport = new StdioServerTransport();
223
+ await this.server.connect(transport);
224
+ console.error('N8N Workflow Builder MCP server running on stdio');
225
+ }
226
+ }
227
+
228
+ const server = new N8NWorkflowServer();
229
+ server.run().catch(console.error);
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2016",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./src"
12
+ },
13
+ "include": ["src/**/*"],
14
+ "exclude": ["node_modules"]
15
+ }