#
tokens: 43199/50000 9/10 files (page 1/2)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 1 of 2. Use http://codebase.md/illuminaresolutions/n8n-mcp-server?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── DEVELOPMENT.md
├── LICENSE
├── LLM_GUIDE.md
├── N8N_API.yml
├── package-lock.json
├── package.json
├── README.md
├── smithery.yml
├── src
│   └── index.ts
├── tsconfig.json
└── TYPEKIT_MCP_SDK.md
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Build
 2 | build/
 3 | dist/
 4 | *.tsbuildinfo
 5 | 
 6 | # Dependencies
 7 | node_modules/
 8 | .pnp/
 9 | .pnp.js
10 | .npm/
11 | 
12 | # Environment
13 | .env
14 | .env.local
15 | .env.*.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 | 
20 | # Logs
21 | logs/
22 | *.log
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | lerna-debug.log*
27 | 
28 | # IDE
29 | .idea/
30 | .vscode/
31 | *.swp
32 | *.swo
33 | .project
34 | .classpath
35 | .settings/
36 | *.sublime-workspace
37 | *.sublime-project
38 | 
39 | # OS
40 | .DS_Store
41 | .DS_Store?
42 | ._*
43 | .Spotlight-V100
44 | .Trashes
45 | ehthumbs.db
46 | Thumbs.db
47 | Desktop.ini
48 | 
49 | # Testing
50 | coverage/
51 | .nyc_output/
52 | junit.xml
53 | *.lcov
54 | 
55 | # Temporary files
56 | *.tmp
57 | *.temp
58 | .cache/
59 | .temp/
60 | tmp/
61 | 
62 | # TypeScript
63 | *.js.map
64 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # n8n MCP Server
  2 | 
  3 | An MCP server that provides access to n8n workflows, executions, credentials, and more through the Model Context Protocol. This allows Large Language Models (LLMs) to interact with n8n instances in a secure and standardized way.
  4 | 
  5 | ## Installation
  6 | 
  7 | ### Get your n8n API Key
  8 | 
  9 | 1. Log into your n8n instance
 10 | 2. Click your user icon in the bottom left
 11 | 3. Go to Settings
 12 | 4. Select API
 13 | 5. Click "Create API Key"
 14 | 6. Copy your API key (you won't be able to see it again)
 15 | 
 16 | ### Install the MCP Server
 17 | 
 18 | #### Option 1: Install from npm (Recommended)
 19 | 
 20 | ```bash
 21 | npm install -g @illuminaresolutions/n8n-mcp-server
 22 | ```
 23 | 
 24 | #### Option 2: Install from Source
 25 | 
 26 | 1. Clone the repository:
 27 |    ```bash
 28 |    git clone https://github.com/illuminaresolutions/n8n-mcp-server.git
 29 |    cd n8n-mcp-server
 30 |    ```
 31 | 
 32 | 2. Install dependencies and build:
 33 |    ```bash
 34 |    npm install
 35 |    npm run build
 36 |    ```
 37 | 
 38 | 3. Start the server in the background:
 39 |    ```bash
 40 |    nohup npm start > n8n-mcp.log 2>&1 &
 41 |    ```
 42 | 
 43 |    To stop the server:
 44 |    ```bash
 45 |    pkill -f "node build/index.js"
 46 |    ```
 47 | 
 48 | Note: When installing from npm, the server will be available as `n8n-mcp-server` in your PATH.
 49 | 
 50 | ## Configuration
 51 | 
 52 | ### Claude Desktop
 53 | 
 54 | 1. Open your Claude Desktop configuration:
 55 |    ```
 56 |    ~/Library/Application Support/Claude/claude_desktop_config.json
 57 |    ```
 58 | 
 59 | 2. Add the n8n configuration:
 60 |    ```json
 61 |    {
 62 |      "mcpServers": {
 63 |         "n8n": {
 64 |          "command": "n8n-mcp-server",
 65 |          "env": {
 66 |            "N8N_HOST": "https://your-n8n-instance.com",
 67 |            "N8N_API_KEY": "your-api-key-here"
 68 |          }
 69 |        }
 70 |      }
 71 |    }
 72 |    ```
 73 | 
 74 | ### Cline (VS Code)
 75 | 
 76 | 1. Install the server (follow Installation steps above)
 77 | 2. Open VS Code
 78 | 3. Open the Cline extension from the left sidebar
 79 | 4. Click the 'MCP Servers' icon at the top of the pane
 80 | 5. Scroll to bottom and click 'Configure MCP Servers'
 81 | 6. Add to the opened settings file:
 82 |    ```json
 83 |    {
 84 |      "mcpServers": {
 85 |        "n8n": {
 86 |          "command": "n8n-mcp-server",
 87 |          "env": {
 88 |            "N8N_HOST": "https://your-n8n-instance.com",
 89 |            "N8N_API_KEY": "your-api-key-here"
 90 |          }
 91 |        }
 92 |      }
 93 |    }
 94 |    ```
 95 | 7. Save the file
 96 | 8. Ensure the MCP toggle is enabled (green) and the status indicator is green
 97 | 9. Start using MCP commands in Cline
 98 | 
 99 | ### Sage
100 | 
101 | Coming soon! The n8n MCP server will be available through:
102 | - Smithery.ai marketplace
103 | - Import from Claude Desktop
104 | 
105 | For now, please use Claude Desktop or Cline.
106 | 
107 | ## Validation
108 | 
109 | After configuration:
110 | 
111 | 1. Restart your LLM application
112 | 2. Ask: "List my n8n workflows"
113 | 3. You should see your workflows listed
114 | 
115 | If you get an error:
116 | - Check that your n8n instance is running
117 | - Verify your API key has correct permissions
118 | - Ensure N8N_HOST has no trailing slash
119 | 
120 | ## Features
121 | 
122 | ### Core Features
123 | - List and manage workflows
124 | - View workflow details
125 | - Execute workflows
126 | - Manage credentials
127 | - Handle tags and executions
128 | - Generate security audits
129 | - Manage workflow tags
130 | 
131 | ### Enterprise Features
132 | These features require an n8n Enterprise license:
133 | - Project management
134 | - Variable management
135 | - Advanced user management
136 | 
137 | ## Troubleshooting
138 | 
139 | ### Common Issues
140 | 
141 | 1. "Client not initialized"
142 |    - Check N8N_HOST and N8N_API_KEY are set correctly
143 |    - Ensure n8n instance is accessible
144 |    - Verify API key permissions
145 | 
146 | 2. "License required"
147 |    - You're trying to use an Enterprise feature
148 |    - Either upgrade to n8n Enterprise or use core features only
149 | 
150 | 3. Connection Issues
151 |    - Verify n8n instance is running
152 |    - Check URL protocol (http/https)
153 |    - Remove trailing slash from N8N_HOST
154 | 
155 | ## Security Best Practices
156 | 
157 | 1. API Key Management
158 |    - Use minimal permissions necessary
159 |    - Rotate keys regularly
160 |    - Never commit keys to version control
161 | 
162 | 2. Instance Access
163 |    - Use HTTPS for production
164 |    - Enable n8n authentication
165 |    - Keep n8n updated
166 | 
167 | ## Support
168 | 
169 | - [GitHub Issues](https://github.com/illuminaresolutions/n8n-mcp-server/issues)
170 | - [n8n Documentation](https://docs.n8n.io)
171 | 
172 | ## License
173 | 
174 | [MIT License](LICENSE)
175 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |     "compilerOptions": {
 3 |       "target": "ES2022",
 4 |       "module": "ES2022",
 5 |       "moduleResolution": "node",
 6 |       "outDir": "./build",
 7 |       "rootDir": "./src",
 8 |       "strict": true,
 9 |       "esModuleInterop": true,
10 |       "skipLibCheck": true,
11 |       "forceConsistentCasingInFileNames": true,
12 |       "allowJs": true
13 |     },
14 |     "include": ["src/**/*"]
15 |   }
```

--------------------------------------------------------------------------------
/smithery.yml:
--------------------------------------------------------------------------------

```yaml
 1 | name: n8n-mcp-server
 2 | version: 1.0.0
 3 | description: An MCP server that provides access to n8n workflows, executions, credentials, and more through the Model Context Protocol
 4 | 
 5 | author: Illuminare Solutions
 6 | license: MIT
 7 | repository: https://github.com/illuminaresolutions/n8n-mcp-server
 8 | 
 9 | type: mcp-server
10 | category: automation
11 | 
12 | requirements:
13 |   node: ">=18.0.0"
14 | 
15 | installation:
16 |   npm: "@illuminaresolutions/n8n-mcp-server"
17 | 
18 | configuration:
19 |   env:
20 |     N8N_HOST:
21 |       description: "Your n8n instance URL (e.g., https://your-n8n-instance.com)"
22 |       required: true
23 |     N8N_API_KEY:
24 |       description: "Your n8n API key"
25 |       required: true
26 |       secret: true
27 | 
28 | capabilities:
29 |   - workflow-management
30 |   - credential-management
31 |   - execution-monitoring
32 |   - tag-management
33 |   - security-audit
34 |   - user-management
35 |   - project-management
36 |   - variable-management
37 | 
38 | tags:
39 |   - n8n
40 |   - automation
41 |   - workflow
42 |   - mcp
43 |   - llm
44 |   - ai
45 |   - claude
46 | 
47 | documentation:
48 |   getting_started: https://github.com/illuminaresolutions/n8n-mcp-server#installation
49 |   configuration: https://github.com/illuminaresolutions/n8n-mcp-server#configuration
50 |   api_reference: https://github.com/illuminaresolutions/n8n-mcp-server/blob/main/N8N_API.yml
51 | 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "@illuminaresolutions/n8n-mcp-server",
 3 |   "description": "An MCP server that provides access to n8n workflows, executions, credentials, and more through the Model Context Protocol",
 4 |   "version": "1.0.0",
 5 |   "type": "module",
 6 |   "bin": {
 7 |     "n8n-mcp-server": "build/index.js"
 8 |   },
 9 |   "files": [
10 |     "build",
11 |     "README.md",
12 |     "LICENSE"
13 |   ],
14 |   "license": "MIT",
15 |   "author": "Illuminare Solutions",
16 |   "publishConfig": {
17 |     "access": "public"
18 |   },
19 |   "repository": {
20 |     "type": "git",
21 |     "url": "git+https://github.com/illuminaresolutions/n8n-mcp-server.git"
22 |   },
23 |   "bugs": {
24 |     "url": "https://github.com/illuminaresolutions/n8n-mcp-server/issues"
25 |   },
26 |   "homepage": "https://github.com/illuminaresolutions/n8n-mcp-server#readme",
27 |   "engines": {
28 |     "node": ">=18.0.0"
29 |   },
30 |   "keywords": [
31 |     "n8n",
32 |     "mcp",
33 |     "automation",
34 |     "workflow",
35 |     "llm",
36 |     "ai",
37 |     "claude",
38 |     "modelcontextprotocol"
39 |   ],
40 |   "scripts": {
41 |     "build": "tsc && chmod +x build/index.js",
42 |     "start": "node build/index.js",
43 |     "prepublishOnly": "npm run build",
44 |     "clean": "rm -rf build",
45 |     "lint": "tsc --noEmit"
46 |   },
47 |   "dependencies": {
48 |     "@modelcontextprotocol/sdk": "^0.7.0",
49 |     "zod": "^3.22.4",
50 |     "node-fetch": "^3.3.2"
51 |   },
52 |   "devDependencies": {
53 |     "@types/node": "^20.11.5",
54 |     "typescript": "^5.3.3"
55 |   }
56 | }
57 | 
```

--------------------------------------------------------------------------------
/DEVELOPMENT.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Development Guide
 2 | 
 3 | ## Core Principles
 4 | 
 5 | 1. **Keep It Simple**
 6 |    - Expand src/index.ts as needed - avoid complex directory structures
 7 |    - Focus on core functionality first
 8 |    - Use built-in Node.js features when possible
 9 |    - Check N8N_API.yml for correct endpoints/methods
10 | 
11 | 2. **Document Only What Works**
12 |    - No *public* "roadmap" or planned features
13 |    - Only document implemented functionality
14 |    - Keep documentation clear and focused
15 | 
16 | 3. **JSON Requirements**
17 |    - All tool arguments must be compact, single-line JSON
18 |    - Example: `{"clientId":"abc123","id":"workflow123"}`
19 | 
20 | 4. **Workflow Creation**
21 |    - Include nodes and connections arrays (even if empty)
22 |    - 'active' property is read-only
23 |    ```json
24 |    {
25 |      "clientId": "abc123",
26 |      "name": "My Workflow",
27 |      "nodes": [],
28 |      "connections": {}
29 |    }
30 |    ```
31 | 
32 | 5. **Enterprise Features**
33 |    - Project/variable management require Enterprise license
34 |    - Base workflow features work without license
35 |    - Clear error messages for license requirements
36 | 
37 | ## What Not To Do
38 | 
39 | 1. **No Overcomplication**
40 |    - Don't create complex directory structures
41 |    - Don't add unnecessary dependencies
42 |    - Use built-in fetch instead of importing it
43 |    - Check if functionality exists before adding imports
44 | 
45 | 2. **No Speculative Documentation**
46 |    - Don't document unimplemented features
47 |    - Don't maintain *public* planning documents
48 |    - Don't commit planning docs as implementation
49 | 
50 | 3. **No Feature Creep**
51 |    - Add features only when fully designed
52 |    - Follow github repo's simple approach
53 |    - Focus on core functionality first
54 | 
55 | 4. **No Roadmaps**
56 |    - Document only what exists
57 |    - Keep focus on current functionality
58 |    - Clear, concise documentation
59 | 
```

--------------------------------------------------------------------------------
/TYPEKIT_MCP_SDK.md:
--------------------------------------------------------------------------------

```markdown
  1 | # MCP TypeScript SDK ![NPM Version](https://img.shields.io/npm/v/%40modelcontextprotocol%2Fsdk) ![MIT licensed](https://img.shields.io/npm/l/%40modelcontextprotocol%2Fsdk)
  2 | 
  3 | ## Table of Contents
  4 | - [Overview](#overview)
  5 | - [Installation](#installation)
  6 | - [Quickstart](#quickstart)
  7 | - [What is MCP?](#what-is-mcp)
  8 | - [Core Concepts](#core-concepts)
  9 |   - [Server](#server)
 10 |   - [Resources](#resources)
 11 |   - [Tools](#tools)
 12 |   - [Prompts](#prompts)
 13 | - [Running Your Server](#running-your-server)
 14 |   - [stdio](#stdio)
 15 |   - [HTTP with SSE](#http-with-sse)
 16 |   - [Testing and Debugging](#testing-and-debugging)
 17 | - [Examples](#examples)
 18 |   - [Echo Server](#echo-server)
 19 |   - [SQLite Explorer](#sqlite-explorer)
 20 | - [Advanced Usage](#advanced-usage)
 21 |   - [Low-Level Server](#low-level-server)
 22 |   - [Writing MCP Clients](#writing-mcp-clients)
 23 |   - [Server Capabilities](#server-capabilities)
 24 | 
 25 | ## Overview
 26 | 
 27 | The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. This TypeScript SDK implements the full MCP specification, making it easy to:
 28 | 
 29 | - Build MCP clients that can connect to any MCP server
 30 | - Create MCP servers that expose resources, prompts and tools
 31 | - Use standard transports like stdio and SSE
 32 | - Handle all MCP protocol messages and lifecycle events
 33 | 
 34 | ## Installation
 35 | 
 36 | ```bash
 37 | npm install @modelcontextprotocol/sdk
 38 | ```
 39 | 
 40 | ## Quick Start
 41 | 
 42 | Let's create a simple MCP server that exposes a calculator tool and some data:
 43 | 
 44 | ```typescript
 45 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
 46 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 47 | import { z } from "zod";
 48 | 
 49 | // Create an MCP server
 50 | const server = new McpServer({
 51 |   name: "Demo",
 52 |   version: "1.0.0"
 53 | });
 54 | 
 55 | // Add an addition tool
 56 | server.tool("add",
 57 |   { a: z.number(), b: z.number() },
 58 |   async ({ a, b }) => ({
 59 |     content: [{ type: "text", text: String(a + b) }]
 60 |   })
 61 | );
 62 | 
 63 | // Add a dynamic greeting resource
 64 | server.resource(
 65 |   "greeting",
 66 |   new ResourceTemplate("greeting://{name}", { list: undefined }),
 67 |   async (uri, { name }) => ({
 68 |     contents: [{
 69 |       uri: uri.href,
 70 |       text: `Hello, ${name}!`
 71 |     }]
 72 |   })
 73 | );
 74 | 
 75 | // Start receiving messages on stdin and sending messages on stdout
 76 | const transport = new StdioServerTransport();
 77 | await server.connect(transport);
 78 | ```
 79 | 
 80 | ## What is MCP?
 81 | 
 82 | The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions. MCP servers can:
 83 | 
 84 | - Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
 85 | - Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
 86 | - Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
 87 | - And more!
 88 | 
 89 | ## Core Concepts
 90 | 
 91 | ### Server
 92 | 
 93 | The McpServer is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
 94 | 
 95 | ```typescript
 96 | const server = new McpServer({
 97 |   name: "My App",
 98 |   version: "1.0.0"
 99 | });
100 | ```
101 | 
102 | ### Resources
103 | 
104 | Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:
105 | 
106 | ```typescript
107 | // Static resource
108 | server.resource(
109 |   "config",
110 |   "config://app",
111 |   async (uri) => ({
112 |     contents: [{
113 |       uri: uri.href,
114 |       text: "App configuration here"
115 |     }]
116 |   })
117 | );
118 | 
119 | // Dynamic resource with parameters
120 | server.resource(
121 |   "user-profile",
122 |   new ResourceTemplate("users://{userId}/profile", { list: undefined }),
123 |   async (uri, { userId }) => ({
124 |     contents: [{
125 |       uri: uri.href,
126 |       text: `Profile data for user ${userId}`
127 |     }]
128 |   })
129 | );
130 | ```
131 | 
132 | ### Tools
133 | 
134 | Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
135 | 
136 | ```typescript
137 | // Simple tool with parameters
138 | server.tool(
139 |   "calculate-bmi",
140 |   {
141 |     weightKg: z.number(),
142 |     heightM: z.number()
143 |   },
144 |   async ({ weightKg, heightM }) => ({
145 |     content: [{
146 |       type: "text",
147 |       text: String(weightKg / (heightM * heightM))
148 |     }]
149 |   })
150 | );
151 | 
152 | // Async tool with external API call
153 | server.tool(
154 |   "fetch-weather",
155 |   { city: z.string() },
156 |   async ({ city }) => {
157 |     const response = await fetch(`https://api.weather.com/${city}`);
158 |     const data = await response.text();
159 |     return {
160 |       content: [{ type: "text", text: data }]
161 |     };
162 |   }
163 | );
164 | ```
165 | 
166 | ### Prompts
167 | 
168 | Prompts are reusable templates that help LLMs interact with your server effectively:
169 | 
170 | ```typescript
171 | server.prompt(
172 |   "review-code",
173 |   { code: z.string() },
174 |   ({ code }) => ({
175 |     messages: [{
176 |       role: "user",
177 |       content: {
178 |         type: "text",
179 |         text: `Please review this code:\n\n${code}`
180 |       }
181 |     }]
182 |   })
183 | );
184 | ```
185 | 
186 | ## Running Your Server
187 | 
188 | MCP servers in TypeScript need to be connected to a transport to communicate with clients. How you start the server depends on the choice of transport:
189 | 
190 | ### stdio
191 | 
192 | For command-line tools and direct integrations:
193 | 
194 | ```typescript
195 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
196 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
197 | 
198 | const server = new McpServer({
199 |   name: "example-server",
200 |   version: "1.0.0"
201 | });
202 | 
203 | // ... set up server resources, tools, and prompts ...
204 | 
205 | const transport = new StdioServerTransport();
206 | await server.connect(transport);
207 | ```
208 | 
209 | ### HTTP with SSE
210 | 
211 | For remote servers, start a web server with a Server-Sent Events (SSE) endpoint, and a separate endpoint for the client to send its messages to:
212 | 
213 | ```typescript
214 | import express from "express";
215 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
216 | import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
217 | 
218 | const server = new McpServer({
219 |   name: "example-server",
220 |   version: "1.0.0"
221 | });
222 | 
223 | // ... set up server resources, tools, and prompts ...
224 | 
225 | const app = express();
226 | 
227 | app.get("/sse", async (req, res) => {
228 |   const transport = new SSEServerTransport("/messages", res);
229 |   await server.connect(transport);
230 | });
231 | 
232 | app.post("/messages", async (req, res) => {
233 |   // Note: to support multiple simultaneous connections, these messages will
234 |   // need to be routed to a specific matching transport. (This logic isn't
235 |   // implemented here, for simplicity.)
236 |   await transport.handlePostMessage(req, res);
237 | });
238 | 
239 | app.listen(3001);
240 | ```
241 | 
242 | ### Testing and Debugging
243 | 
244 | To test your server, you can use the [MCP Inspector](https://github.com/modelcontextprotocol/inspector). See its README for more information.
245 | 
246 | ## Examples
247 | 
248 | ### Echo Server
249 | 
250 | A simple server demonstrating resources, tools, and prompts:
251 | 
252 | ```typescript
253 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
254 | import { z } from "zod";
255 | 
256 | const server = new McpServer({
257 |   name: "Echo",
258 |   version: "1.0.0"
259 | });
260 | 
261 | server.resource(
262 |   "echo",
263 |   new ResourceTemplate("echo://{message}", { list: undefined }),
264 |   async (uri, { message }) => ({
265 |     contents: [{
266 |       uri: uri.href,
267 |       text: `Resource echo: ${message}`
268 |     }]
269 |   })
270 | );
271 | 
272 | server.tool(
273 |   "echo",
274 |   { message: z.string() },
275 |   async ({ message }) => ({
276 |     content: [{ type: "text", text: `Tool echo: ${message}` }]
277 |   })
278 | );
279 | 
280 | server.prompt(
281 |   "echo",
282 |   { message: z.string() },
283 |   ({ message }) => ({
284 |     messages: [{
285 |       role: "user",
286 |       content: {
287 |         type: "text",
288 |         text: `Please process this message: ${message}`
289 |       }
290 |     }]
291 |   })
292 | );
293 | ```
294 | 
295 | ### SQLite Explorer
296 | 
297 | A more complex example showing database integration:
298 | 
299 | ```typescript
300 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
301 | import sqlite3 from "sqlite3";
302 | import { promisify } from "util";
303 | import { z } from "zod";
304 | 
305 | const server = new McpServer({
306 |   name: "SQLite Explorer",
307 |   version: "1.0.0"
308 | });
309 | 
310 | // Helper to create DB connection
311 | const getDb = () => {
312 |   const db = new sqlite3.Database("database.db");
313 |   return {
314 |     all: promisify<string, any[]>(db.all.bind(db)),
315 |     close: promisify(db.close.bind(db))
316 |   };
317 | };
318 | 
319 | server.resource(
320 |   "schema",
321 |   "schema://main",
322 |   async (uri) => {
323 |     const db = getDb();
324 |     try {
325 |       const tables = await db.all(
326 |         "SELECT sql FROM sqlite_master WHERE type='table'"
327 |       );
328 |       return {
329 |         contents: [{
330 |           uri: uri.href,
331 |           text: tables.map((t: {sql: string}) => t.sql).join("\n")
332 |         }]
333 |       };
334 |     } finally {
335 |       await db.close();
336 |     }
337 |   }
338 | );
339 | 
340 | server.tool(
341 |   "query",
342 |   { sql: z.string() },
343 |   async ({ sql }) => {
344 |     const db = getDb();
345 |     try {
346 |       const results = await db.all(sql);
347 |       return {
348 |         content: [{
349 |           type: "text",
350 |           text: JSON.stringify(results, null, 2)
351 |         }]
352 |       };
353 |     } catch (err: unknown) {
354 |       const error = err as Error;
355 |       return {
356 |         content: [{
357 |           type: "text",
358 |           text: `Error: ${error.message}`
359 |         }],
360 |         isError: true
361 |       };
362 |     } finally {
363 |       await db.close();
364 |     }
365 |   }
366 | );
367 | ```
368 | 
369 | ## Advanced Usage
370 | 
371 | ### Low-Level Server
372 | 
373 | For more control, you can use the low-level Server class directly:
374 | 
375 | ```typescript
376 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
377 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
378 | import {
379 |   ListPromptsRequestSchema,
380 |   GetPromptRequestSchema
381 | } from "@modelcontextprotocol/sdk/types.js";
382 | 
383 | const server = new Server(
384 |   {
385 |     name: "example-server",
386 |     version: "1.0.0"
387 |   },
388 |   {
389 |     capabilities: {
390 |       prompts: {}
391 |     }
392 |   }
393 | );
394 | 
395 | server.setRequestHandler(ListPromptsRequestSchema, async () => {
396 |   return {
397 |     prompts: [{
398 |       name: "example-prompt",
399 |       description: "An example prompt template",
400 |       arguments: [{
401 |         name: "arg1",
402 |         description: "Example argument",
403 |         required: true
404 |       }]
405 |     }]
406 |   };
407 | });
408 | 
409 | server.setRequestHandler(GetPromptRequestSchema, async (request) => {
410 |   if (request.params.name !== "example-prompt") {
411 |     throw new Error("Unknown prompt");
412 |   }
413 |   return {
414 |     description: "Example prompt",
415 |     messages: [{
416 |       role: "user",
417 |       content: {
418 |         type: "text",
419 |         text: "Example prompt text"
420 |       }
421 |     }]
422 |   };
423 | });
424 | 
425 | const transport = new StdioServerTransport();
426 | await server.connect(transport);
427 | ```
428 | 
429 | ### Writing MCP Clients
430 | 
431 | The SDK provides a high-level client interface:
432 | 
433 | ```typescript
434 | import { Client } from "@modelcontextprotocol/sdk/client/index.js";
435 | import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
436 | 
437 | const transport = new StdioClientTransport({
438 |   command: "node",
439 |   args: ["server.js"]
440 | });
441 | 
442 | const client = new Client(
443 |   {
444 |     name: "example-client",
445 |     version: "1.0.0"
446 |   },
447 |   {
448 |     capabilities: {
449 |       prompts: {},
450 |       resources: {},
451 |       tools: {}
452 |     }
453 |   }
454 | );
455 | 
456 | await client.connect(transport);
457 | 
458 | // List prompts
459 | const prompts = await client.listPrompts();
460 | 
461 | // Get a prompt
462 | const prompt = await client.getPrompt("example-prompt", {
463 |   arg1: "value"
464 | });
465 | 
466 | // List resources
467 | const resources = await client.listResources();
468 | 
469 | // Read a resource
470 | const resource = await client.readResource("file:///example.txt");
471 | 
472 | // Call a tool
473 | const result = await client.callTool({
474 |   name: "example-tool",
475 |   arguments: {
476 |     arg1: "value"
477 |   }
478 | });
479 | ```
480 | 
481 | ## Documentation
482 | 
483 | - [Model Context Protocol documentation](https://modelcontextprotocol.io)
484 | - [MCP Specification](https://spec.modelcontextprotocol.io)
485 | - [Example Servers](https://github.com/modelcontextprotocol/servers)
486 | 
487 | ## Contributing
488 | 
489 | Issues and pull requests are welcome on GitHub at https://github.com/modelcontextprotocol/typescript-sdk.
490 | 
491 | ## License
492 | 
493 | This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details.
```

--------------------------------------------------------------------------------
/N8N_API.yml:
--------------------------------------------------------------------------------

```yaml
   1 | openapi: 3.0.0
   2 | info:
   3 |   title: n8n Public API
   4 |   description: n8n Public API
   5 |   termsOfService: https://n8n.io/legal/terms
   6 |   contact:
   7 |     email: [email protected]
   8 |   license:
   9 |     name: Sustainable Use License
  10 |     url: https://github.com/n8n-io/n8n/blob/master/LICENSE.md
  11 |   version: 1.1.1
  12 | servers:
  13 |   - url: /api/v1
  14 | security:
  15 |   - ApiKeyAuth: []
  16 | tags:
  17 |   - name: User
  18 |     description: Operations about users
  19 |   - name: Audit
  20 |     description: Operations about security audit
  21 |   - name: Execution
  22 |     description: Operations about executions
  23 |   - name: Workflow
  24 |     description: Operations about workflows
  25 |   - name: Credential
  26 |     description: Operations about credentials
  27 |   - name: Tags
  28 |     description: Operations about tags
  29 |   - name: SourceControl
  30 |     description: Operations about source control
  31 |   - name: Variables
  32 |     description: Operations about variables
  33 |   - name: Projects
  34 |     description: Operations about projects
  35 | externalDocs:
  36 |   description: n8n API documentation
  37 |   url: https://docs.n8n.io/api/
  38 | paths:
  39 |   /audit:
  40 |     post:
  41 |       x-eov-operation-id: generateAudit
  42 |       x-eov-operation-handler: v1/handlers/audit/audit.handler
  43 |       tags:
  44 |         - Audit
  45 |       summary: Generate an audit
  46 |       description: Generate a security audit for your n8n instance.
  47 |       requestBody:
  48 |         required: false
  49 |         content:
  50 |           application/json:
  51 |             schema:
  52 |               type: object
  53 |               properties:
  54 |                 additionalOptions:
  55 |                   type: object
  56 |                   properties:
  57 |                     daysAbandonedWorkflow:
  58 |                       type: integer
  59 |                       description: Days for a workflow to be considered abandoned if not executed
  60 |                     categories:
  61 |                       type: array
  62 |                       items:
  63 |                         type: string
  64 |                         enum:
  65 |                           - credentials
  66 |                           - database
  67 |                           - nodes
  68 |                           - filesystem
  69 |                           - instance
  70 |       responses:
  71 |         '200':
  72 |           description: Operation successful.
  73 |           content:
  74 |             application/json:
  75 |               schema:
  76 |                 $ref: '#/components/schemas/audit'
  77 |         '401':
  78 |           $ref: '#/components/responses/unauthorized'
  79 |         '500':
  80 |           description: Internal server error.
  81 |   /credentials:
  82 |     post:
  83 |       x-eov-operation-id: createCredential
  84 |       x-eov-operation-handler: v1/handlers/credentials/credentials.handler
  85 |       tags:
  86 |         - Credential
  87 |       summary: Create a credential
  88 |       description: Creates a credential that can be used by nodes of the specified type.
  89 |       requestBody:
  90 |         description: Credential to be created.
  91 |         required: true
  92 |         content:
  93 |           application/json:
  94 |             schema:
  95 |               $ref: '#/components/schemas/credential'
  96 |       responses:
  97 |         '200':
  98 |           description: Operation successful.
  99 |           content:
 100 |             application/json:
 101 |               schema:
 102 |                 $ref: '#/components/schemas/credential'
 103 |         '401':
 104 |           $ref: '#/components/responses/unauthorized'
 105 |         '415':
 106 |           description: Unsupported media type.
 107 |   /credentials/{id}:
 108 |     delete:
 109 |       x-eov-operation-id: deleteCredential
 110 |       x-eov-operation-handler: v1/handlers/credentials/credentials.handler
 111 |       tags:
 112 |         - Credential
 113 |       summary: Delete credential by ID
 114 |       description: Deletes a credential from your instance. You must be the owner of the credentials
 115 |       operationId: deleteCredential
 116 |       parameters:
 117 |         - name: id
 118 |           in: path
 119 |           description: The credential ID that needs to be deleted
 120 |           required: true
 121 |           schema:
 122 |             type: string
 123 |       responses:
 124 |         '200':
 125 |           description: Operation successful.
 126 |           content:
 127 |             application/json:
 128 |               schema:
 129 |                 $ref: '#/components/schemas/credential'
 130 |         '401':
 131 |           $ref: '#/components/responses/unauthorized'
 132 |         '404':
 133 |           $ref: '#/components/responses/notFound'
 134 |   /credentials/schema/{credentialTypeName}:
 135 |     get:
 136 |       x-eov-operation-id: getCredentialType
 137 |       x-eov-operation-handler: v1/handlers/credentials/credentials.handler
 138 |       tags:
 139 |         - Credential
 140 |       summary: Show credential data schema
 141 |       parameters:
 142 |         - name: credentialTypeName
 143 |           in: path
 144 |           description: The credential type name that you want to get the schema for
 145 |           required: true
 146 |           schema:
 147 |             type: string
 148 |       responses:
 149 |         '200':
 150 |           description: Operation successful.
 151 |           content:
 152 |             application/json:
 153 |               schema:
 154 |                 type: object
 155 |               examples:
 156 |                 freshdeskApi:
 157 |                   value:
 158 |                     additionalProperties: false
 159 |                     type: object
 160 |                     properties:
 161 |                       apiKey:
 162 |                         type: string
 163 |                       domain:
 164 |                         type: string
 165 |                     required:
 166 |                       - apiKey
 167 |                       - domain
 168 |                 slackOAuth2Api:
 169 |                   value:
 170 |                     additionalProperties: false
 171 |                     type: object
 172 |                     properties:
 173 |                       clientId:
 174 |                         type: string
 175 |                       clientSecret:
 176 |                         type: string
 177 |                     required:
 178 |                       - clientId
 179 |                       - clientSecret
 180 |         '401':
 181 |           $ref: '#/components/responses/unauthorized'
 182 |         '404':
 183 |           $ref: '#/components/responses/notFound'
 184 |   /executions:
 185 |     get:
 186 |       x-eov-operation-id: getExecutions
 187 |       x-eov-operation-handler: v1/handlers/executions/executions.handler
 188 |       tags:
 189 |         - Execution
 190 |       summary: Retrieve all executions
 191 |       description: Retrieve all executions from your instance.
 192 |       parameters:
 193 |         - $ref: '#/components/parameters/includeData'
 194 |         - name: status
 195 |           in: query
 196 |           description: Status to filter the executions by.
 197 |           required: false
 198 |           schema:
 199 |             type: string
 200 |             enum:
 201 |               - error
 202 |               - success
 203 |               - waiting
 204 |         - name: workflowId
 205 |           in: query
 206 |           description: Workflow to filter the executions by.
 207 |           required: false
 208 |           schema:
 209 |             type: string
 210 |             example: '1000'
 211 |         - name: projectId
 212 |           in: query
 213 |           required: false
 214 |           explode: false
 215 |           allowReserved: true
 216 |           schema:
 217 |             type: string
 218 |             example: VmwOO9HeTEj20kxM
 219 |         - $ref: '#/components/parameters/limit'
 220 |         - $ref: '#/components/parameters/cursor'
 221 |       responses:
 222 |         '200':
 223 |           description: Operation successful.
 224 |           content:
 225 |             application/json:
 226 |               schema:
 227 |                 $ref: '#/components/schemas/executionList'
 228 |         '401':
 229 |           $ref: '#/components/responses/unauthorized'
 230 |         '404':
 231 |           $ref: '#/components/responses/notFound'
 232 |   /executions/{id}:
 233 |     get:
 234 |       x-eov-operation-id: getExecution
 235 |       x-eov-operation-handler: v1/handlers/executions/executions.handler
 236 |       tags:
 237 |         - Execution
 238 |       summary: Retrieve an execution
 239 |       description: Retrieve an execution from your instance.
 240 |       parameters:
 241 |         - $ref: '#/components/parameters/executionId'
 242 |         - $ref: '#/components/parameters/includeData'
 243 |       responses:
 244 |         '200':
 245 |           description: Operation successful.
 246 |           content:
 247 |             application/json:
 248 |               schema:
 249 |                 $ref: '#/components/schemas/execution'
 250 |         '401':
 251 |           $ref: '#/components/responses/unauthorized'
 252 |         '404':
 253 |           $ref: '#/components/responses/notFound'
 254 |     delete:
 255 |       x-eov-operation-id: deleteExecution
 256 |       x-eov-operation-handler: v1/handlers/executions/executions.handler
 257 |       tags:
 258 |         - Execution
 259 |       summary: Delete an execution
 260 |       description: Deletes an execution from your instance.
 261 |       parameters:
 262 |         - $ref: '#/components/parameters/executionId'
 263 |       responses:
 264 |         '200':
 265 |           description: Operation successful.
 266 |           content:
 267 |             application/json:
 268 |               schema:
 269 |                 $ref: '#/components/schemas/execution'
 270 |         '401':
 271 |           $ref: '#/components/responses/unauthorized'
 272 |         '404':
 273 |           $ref: '#/components/responses/notFound'
 274 |   /tags:
 275 |     post:
 276 |       x-eov-operation-id: createTag
 277 |       x-eov-operation-handler: v1/handlers/tags/tags.handler
 278 |       tags:
 279 |         - Tags
 280 |       summary: Create a tag
 281 |       description: Create a tag in your instance.
 282 |       requestBody:
 283 |         description: Created tag object.
 284 |         content:
 285 |           application/json:
 286 |             schema:
 287 |               $ref: '#/components/schemas/tag'
 288 |         required: true
 289 |       responses:
 290 |         '201':
 291 |           description: A tag object
 292 |           content:
 293 |             application/json:
 294 |               schema:
 295 |                 $ref: '#/components/schemas/tag'
 296 |         '400':
 297 |           $ref: '#/components/responses/badRequest'
 298 |         '401':
 299 |           $ref: '#/components/responses/unauthorized'
 300 |         '409':
 301 |           $ref: '#/components/responses/conflict'
 302 |     get:
 303 |       x-eov-operation-id: getTags
 304 |       x-eov-operation-handler: v1/handlers/tags/tags.handler
 305 |       tags:
 306 |         - Tags
 307 |       summary: Retrieve all tags
 308 |       description: Retrieve all tags from your instance.
 309 |       parameters:
 310 |         - $ref: '#/components/parameters/limit'
 311 |         - $ref: '#/components/parameters/cursor'
 312 |       responses:
 313 |         '200':
 314 |           description: Operation successful.
 315 |           content:
 316 |             application/json:
 317 |               schema:
 318 |                 $ref: '#/components/schemas/tagList'
 319 |         '401':
 320 |           $ref: '#/components/responses/unauthorized'
 321 |   /tags/{id}:
 322 |     get:
 323 |       x-eov-operation-id: getTag
 324 |       x-eov-operation-handler: v1/handlers/tags/tags.handler
 325 |       tags:
 326 |         - Tags
 327 |       summary: Retrieves a tag
 328 |       description: Retrieves a tag.
 329 |       parameters:
 330 |         - $ref: '#/components/parameters/tagId'
 331 |       responses:
 332 |         '200':
 333 |           description: Operation successful.
 334 |           content:
 335 |             application/json:
 336 |               schema:
 337 |                 $ref: '#/components/schemas/tag'
 338 |         '401':
 339 |           $ref: '#/components/responses/unauthorized'
 340 |         '404':
 341 |           $ref: '#/components/responses/notFound'
 342 |     delete:
 343 |       x-eov-operation-id: deleteTag
 344 |       x-eov-operation-handler: v1/handlers/tags/tags.handler
 345 |       tags:
 346 |         - Tags
 347 |       summary: Delete a tag
 348 |       description: Deletes a tag.
 349 |       parameters:
 350 |         - $ref: '#/components/parameters/tagId'
 351 |       responses:
 352 |         '200':
 353 |           description: Operation successful.
 354 |           content:
 355 |             application/json:
 356 |               schema:
 357 |                 $ref: '#/components/schemas/tag'
 358 |         '401':
 359 |           $ref: '#/components/responses/unauthorized'
 360 |         '403':
 361 |           $ref: '#/components/responses/forbidden'
 362 |         '404':
 363 |           $ref: '#/components/responses/notFound'
 364 |     put:
 365 |       x-eov-operation-id: updateTag
 366 |       x-eov-operation-handler: v1/handlers/tags/tags.handler
 367 |       tags:
 368 |         - Tags
 369 |       summary: Update a tag
 370 |       description: Update a tag.
 371 |       parameters:
 372 |         - $ref: '#/components/parameters/tagId'
 373 |       requestBody:
 374 |         description: Updated tag object.
 375 |         content:
 376 |           application/json:
 377 |             schema:
 378 |               $ref: '#/components/schemas/tag'
 379 |         required: true
 380 |       responses:
 381 |         '200':
 382 |           description: Tag object
 383 |           content:
 384 |             application/json:
 385 |               schema:
 386 |                 $ref: '#/components/schemas/tag'
 387 |         '400':
 388 |           $ref: '#/components/responses/badRequest'
 389 |         '401':
 390 |           $ref: '#/components/responses/unauthorized'
 391 |         '404':
 392 |           $ref: '#/components/responses/notFound'
 393 |         '409':
 394 |           $ref: '#/components/responses/conflict'
 395 |   /workflows:
 396 |     post:
 397 |       x-eov-operation-id: createWorkflow
 398 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 399 |       tags:
 400 |         - Workflow
 401 |       summary: Create a workflow
 402 |       description: Create a workflow in your instance.
 403 |       requestBody:
 404 |         description: Created workflow object.
 405 |         content:
 406 |           application/json:
 407 |             schema:
 408 |               $ref: '#/components/schemas/workflow'
 409 |         required: true
 410 |       responses:
 411 |         '200':
 412 |           description: A workflow object
 413 |           content:
 414 |             application/json:
 415 |               schema:
 416 |                 $ref: '#/components/schemas/workflow'
 417 |         '400':
 418 |           $ref: '#/components/responses/badRequest'
 419 |         '401':
 420 |           $ref: '#/components/responses/unauthorized'
 421 |     get:
 422 |       x-eov-operation-id: getWorkflows
 423 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 424 |       tags:
 425 |         - Workflow
 426 |       summary: Retrieve all workflows
 427 |       description: Retrieve all workflows from your instance.
 428 |       parameters:
 429 |         - name: active
 430 |           in: query
 431 |           schema:
 432 |             type: boolean
 433 |             example: true
 434 |         - name: tags
 435 |           in: query
 436 |           required: false
 437 |           explode: false
 438 |           allowReserved: true
 439 |           schema:
 440 |             type: string
 441 |             example: test,production
 442 |         - name: name
 443 |           in: query
 444 |           required: false
 445 |           explode: false
 446 |           allowReserved: true
 447 |           schema:
 448 |             type: string
 449 |             example: My Workflow
 450 |         - name: projectId
 451 |           in: query
 452 |           required: false
 453 |           explode: false
 454 |           allowReserved: true
 455 |           schema:
 456 |             type: string
 457 |             example: VmwOO9HeTEj20kxM
 458 |         - $ref: '#/components/parameters/limit'
 459 |         - $ref: '#/components/parameters/cursor'
 460 |       responses:
 461 |         '200':
 462 |           description: Operation successful.
 463 |           content:
 464 |             application/json:
 465 |               schema:
 466 |                 $ref: '#/components/schemas/workflowList'
 467 |         '401':
 468 |           $ref: '#/components/responses/unauthorized'
 469 |   /workflows/{id}:
 470 |     get:
 471 |       x-eov-operation-id: getWorkflow
 472 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 473 |       tags:
 474 |         - Workflow
 475 |       summary: Retrieves a workflow
 476 |       description: Retrieves a workflow.
 477 |       parameters:
 478 |         - $ref: '#/components/parameters/workflowId'
 479 |       responses:
 480 |         '200':
 481 |           description: Operation successful.
 482 |           content:
 483 |             application/json:
 484 |               schema:
 485 |                 $ref: '#/components/schemas/workflow'
 486 |         '401':
 487 |           $ref: '#/components/responses/unauthorized'
 488 |         '404':
 489 |           $ref: '#/components/responses/notFound'
 490 |     delete:
 491 |       x-eov-operation-id: deleteWorkflow
 492 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 493 |       tags:
 494 |         - Workflow
 495 |       summary: Delete a workflow
 496 |       description: Deletes a workflow.
 497 |       parameters:
 498 |         - $ref: '#/components/parameters/workflowId'
 499 |       responses:
 500 |         '200':
 501 |           description: Operation successful.
 502 |           content:
 503 |             application/json:
 504 |               schema:
 505 |                 $ref: '#/components/schemas/workflow'
 506 |         '401':
 507 |           $ref: '#/components/responses/unauthorized'
 508 |         '404':
 509 |           $ref: '#/components/responses/notFound'
 510 |     put:
 511 |       x-eov-operation-id: updateWorkflow
 512 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 513 |       tags:
 514 |         - Workflow
 515 |       summary: Update a workflow
 516 |       description: Update a workflow.
 517 |       parameters:
 518 |         - $ref: '#/components/parameters/workflowId'
 519 |       requestBody:
 520 |         description: Updated workflow object.
 521 |         content:
 522 |           application/json:
 523 |             schema:
 524 |               $ref: '#/components/schemas/workflow'
 525 |         required: true
 526 |       responses:
 527 |         '200':
 528 |           description: Workflow object
 529 |           content:
 530 |             application/json:
 531 |               schema:
 532 |                 $ref: '#/components/schemas/workflow'
 533 |         '400':
 534 |           $ref: '#/components/responses/badRequest'
 535 |         '401':
 536 |           $ref: '#/components/responses/unauthorized'
 537 |         '404':
 538 |           $ref: '#/components/responses/notFound'
 539 |   /workflows/{id}/activate:
 540 |     post:
 541 |       x-eov-operation-id: activateWorkflow
 542 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 543 |       tags:
 544 |         - Workflow
 545 |       summary: Activate a workflow
 546 |       description: Active a workflow.
 547 |       parameters:
 548 |         - $ref: '#/components/parameters/workflowId'
 549 |       responses:
 550 |         '200':
 551 |           description: Workflow object
 552 |           content:
 553 |             application/json:
 554 |               schema:
 555 |                 $ref: '#/components/schemas/workflow'
 556 |         '401':
 557 |           $ref: '#/components/responses/unauthorized'
 558 |         '404':
 559 |           $ref: '#/components/responses/notFound'
 560 |   /workflows/{id}/deactivate:
 561 |     post:
 562 |       x-eov-operation-id: deactivateWorkflow
 563 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 564 |       tags:
 565 |         - Workflow
 566 |       summary: Deactivate a workflow
 567 |       description: Deactivate a workflow.
 568 |       parameters:
 569 |         - $ref: '#/components/parameters/workflowId'
 570 |       responses:
 571 |         '200':
 572 |           description: Workflow object
 573 |           content:
 574 |             application/json:
 575 |               schema:
 576 |                 $ref: '#/components/schemas/workflow'
 577 |         '401':
 578 |           $ref: '#/components/responses/unauthorized'
 579 |         '404':
 580 |           $ref: '#/components/responses/notFound'
 581 |   /workflows/{id}/transfer:
 582 |     put:
 583 |       x-eov-operation-id: transferWorkflow
 584 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 585 |       tags:
 586 |         - Workflow
 587 |       summary: Transfer a workflow to another project.
 588 |       description: Transfer a workflow to another project.
 589 |       parameters:
 590 |         - $ref: '#/components/parameters/workflowId'
 591 |       requestBody:
 592 |         description: Destination project information for the workflow transfer.
 593 |         content:
 594 |           application/json:
 595 |             schema:
 596 |               type: object
 597 |               properties:
 598 |                 destinationProjectId:
 599 |                   type: string
 600 |                   description: The ID of the project to transfer the workflow to.
 601 |               required:
 602 |                 - destinationProjectId
 603 |         required: true
 604 |       responses:
 605 |         '200':
 606 |           description: Operation successful.
 607 |         '400':
 608 |           $ref: '#/components/responses/badRequest'
 609 |         '401':
 610 |           $ref: '#/components/responses/unauthorized'
 611 |         '404':
 612 |           $ref: '#/components/responses/notFound'
 613 |   /credentials/{id}/transfer:
 614 |     put:
 615 |       x-eov-operation-id: transferCredential
 616 |       x-eov-operation-handler: v1/handlers/credentials/credentials.handler
 617 |       tags:
 618 |         - Workflow
 619 |       summary: Transfer a credential to another project.
 620 |       description: Transfer a credential to another project.
 621 |       parameters:
 622 |         - $ref: '#/components/parameters/credentialId'
 623 |       requestBody:
 624 |         description: Destination project for the credential transfer.
 625 |         content:
 626 |           application/json:
 627 |             schema:
 628 |               type: object
 629 |               properties:
 630 |                 destinationProjectId:
 631 |                   type: string
 632 |                   description: The ID of the project to transfer the credential to.
 633 |               required:
 634 |                 - destinationProjectId
 635 |         required: true
 636 |       responses:
 637 |         '200':
 638 |           description: Operation successful.
 639 |         '400':
 640 |           $ref: '#/components/responses/badRequest'
 641 |         '401':
 642 |           $ref: '#/components/responses/unauthorized'
 643 |         '404':
 644 |           $ref: '#/components/responses/notFound'
 645 |   /workflows/{id}/tags:
 646 |     get:
 647 |       x-eov-operation-id: getWorkflowTags
 648 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 649 |       tags:
 650 |         - Workflow
 651 |       summary: Get workflow tags
 652 |       description: Get workflow tags.
 653 |       parameters:
 654 |         - $ref: '#/components/parameters/workflowId'
 655 |       responses:
 656 |         '200':
 657 |           description: List of tags
 658 |           content:
 659 |             application/json:
 660 |               schema:
 661 |                 $ref: '#/components/schemas/workflowTags'
 662 |         '400':
 663 |           $ref: '#/components/responses/badRequest'
 664 |         '401':
 665 |           $ref: '#/components/responses/unauthorized'
 666 |         '404':
 667 |           $ref: '#/components/responses/notFound'
 668 |     put:
 669 |       x-eov-operation-id: updateWorkflowTags
 670 |       x-eov-operation-handler: v1/handlers/workflows/workflows.handler
 671 |       tags:
 672 |         - Workflow
 673 |       summary: Update tags of a workflow
 674 |       description: Update tags of a workflow.
 675 |       parameters:
 676 |         - $ref: '#/components/parameters/workflowId'
 677 |       requestBody:
 678 |         description: List of tags
 679 |         content:
 680 |           application/json:
 681 |             schema:
 682 |               $ref: '#/components/schemas/tagIds'
 683 |         required: true
 684 |       responses:
 685 |         '200':
 686 |           description: List of tags after add the tag
 687 |           content:
 688 |             application/json:
 689 |               schema:
 690 |                 $ref: '#/components/schemas/workflowTags'
 691 |         '400':
 692 |           $ref: '#/components/responses/badRequest'
 693 |         '401':
 694 |           $ref: '#/components/responses/unauthorized'
 695 |         '404':
 696 |           $ref: '#/components/responses/notFound'
 697 |   /users:
 698 |     get:
 699 |       x-eov-operation-id: getUsers
 700 |       x-eov-operation-handler: v1/handlers/users/users.handler.ee
 701 |       tags:
 702 |         - User
 703 |       summary: Retrieve all users
 704 |       description: Retrieve all users from your instance. Only available for the instance owner.
 705 |       parameters:
 706 |         - $ref: '#/components/parameters/limit'
 707 |         - $ref: '#/components/parameters/cursor'
 708 |         - $ref: '#/components/parameters/includeRole'
 709 |         - name: projectId
 710 |           in: query
 711 |           required: false
 712 |           explode: false
 713 |           allowReserved: true
 714 |           schema:
 715 |             type: string
 716 |             example: VmwOO9HeTEj20kxM
 717 |       responses:
 718 |         '200':
 719 |           description: Operation successful.
 720 |           content:
 721 |             application/json:
 722 |               schema:
 723 |                 $ref: '#/components/schemas/userList'
 724 |         '401':
 725 |           $ref: '#/components/responses/unauthorized'
 726 |     post:
 727 |       x-eov-operation-id: createUser
 728 |       x-eov-operation-handler: v1/handlers/users/users.handler.ee
 729 |       tags:
 730 |         - User
 731 |       summary: Create multiple users
 732 |       description: Create one or more users.
 733 |       requestBody:
 734 |         description: Array of users to be created.
 735 |         required: true
 736 |         content:
 737 |           application/json:
 738 |             schema:
 739 |               type: array
 740 |               items:
 741 |                 type: object
 742 |                 properties:
 743 |                   email:
 744 |                     type: string
 745 |                     format: email
 746 |                   role:
 747 |                     type: string
 748 |                     enum:
 749 |                       - global:admin
 750 |                       - global:member
 751 |                 required:
 752 |                   - email
 753 |       responses:
 754 |         '200':
 755 |           description: Operation successful.
 756 |           content:
 757 |             application/json:
 758 |               schema:
 759 |                 type: object
 760 |                 properties:
 761 |                   user:
 762 |                     type: object
 763 |                     properties:
 764 |                       id:
 765 |                         type: string
 766 |                       email:
 767 |                         type: string
 768 |                       inviteAcceptUrl:
 769 |                         type: string
 770 |                       emailSent:
 771 |                         type: boolean
 772 |                   error:
 773 |                     type: string
 774 |         '401':
 775 |           $ref: '#/components/responses/unauthorized'
 776 |         '403':
 777 |           $ref: '#/components/responses/forbidden'
 778 |   /users/{id}:
 779 |     get:
 780 |       x-eov-operation-id: getUser
 781 |       x-eov-operation-handler: v1/handlers/users/users.handler.ee
 782 |       tags:
 783 |         - User
 784 |       summary: Get user by ID/Email
 785 |       description: Retrieve a user from your instance. Only available for the instance owner.
 786 |       parameters:
 787 |         - $ref: '#/components/parameters/userIdentifier'
 788 |         - $ref: '#/components/parameters/includeRole'
 789 |       responses:
 790 |         '200':
 791 |           description: Operation successful.
 792 |           content:
 793 |             application/json:
 794 |               schema:
 795 |                 $ref: '#/components/schemas/user'
 796 |         '401':
 797 |           $ref: '#/components/responses/unauthorized'
 798 |     delete:
 799 |       x-eov-operation-id: deleteUser
 800 |       x-eov-operation-handler: v1/handlers/users/users.handler.ee
 801 |       tags:
 802 |         - User
 803 |       summary: Delete a user
 804 |       description: Delete a user from your instance.
 805 |       parameters:
 806 |         - $ref: '#/components/parameters/userIdentifier'
 807 |       responses:
 808 |         '204':
 809 |           description: Operation successful.
 810 |         '401':
 811 |           $ref: '#/components/responses/unauthorized'
 812 |         '403':
 813 |           $ref: '#/components/responses/forbidden'
 814 |         '404':
 815 |           $ref: '#/components/responses/notFound'
 816 |   /users/{id}/role:
 817 |     patch:
 818 |       x-eov-operation-id: changeRole
 819 |       x-eov-operation-handler: v1/handlers/users/users.handler.ee
 820 |       tags:
 821 |         - User
 822 |       summary: Change a user's global role
 823 |       description: Change a user's global role
 824 |       parameters:
 825 |         - $ref: '#/components/parameters/userIdentifier'
 826 |       requestBody:
 827 |         description: New role for the user
 828 |         required: true
 829 |         content:
 830 |           application/json:
 831 |             schema:
 832 |               type: object
 833 |               properties:
 834 |                 newRoleName:
 835 |                   type: string
 836 |                   enum:
 837 |                     - global:admin
 838 |                     - global:member
 839 |               required:
 840 |                 - newRoleName
 841 |       responses:
 842 |         '200':
 843 |           description: Operation successful.
 844 |         '401':
 845 |           $ref: '#/components/responses/unauthorized'
 846 |         '403':
 847 |           $ref: '#/components/responses/forbidden'
 848 |         '404':
 849 |           $ref: '#/components/responses/notFound'
 850 |   /source-control/pull:
 851 |     post:
 852 |       x-eov-operation-id: pull
 853 |       x-eov-operation-handler: v1/handlers/sourceControl/sourceControl.handler
 854 |       tags:
 855 |         - SourceControl
 856 |       summary: Pull changes from the remote repository
 857 |       description: Requires the Source Control feature to be licensed and connected to a repository.
 858 |       requestBody:
 859 |         description: Pull options
 860 |         required: true
 861 |         content:
 862 |           application/json:
 863 |             schema:
 864 |               $ref: '#/components/schemas/pull'
 865 |       responses:
 866 |         '200':
 867 |           description: Import result
 868 |           content:
 869 |             application/json:
 870 |               schema:
 871 |                 $ref: '#/components/schemas/importResult'
 872 |         '400':
 873 |           $ref: '#/components/responses/badRequest'
 874 |         '409':
 875 |           $ref: '#/components/responses/conflict'
 876 |   /variables:
 877 |     post:
 878 |       x-eov-operation-id: createVariable
 879 |       x-eov-operation-handler: v1/handlers/variables/variables.handler
 880 |       tags:
 881 |         - Variables
 882 |       summary: Create a variable
 883 |       description: Create a variable in your instance.
 884 |       requestBody:
 885 |         description: Payload for variable to create.
 886 |         content:
 887 |           application/json:
 888 |             schema:
 889 |               $ref: '#/components/schemas/variable'
 890 |         required: true
 891 |       responses:
 892 |         '201':
 893 |           description: Operation successful.
 894 |         '400':
 895 |           $ref: '#/components/responses/badRequest'
 896 |         '401':
 897 |           $ref: '#/components/responses/unauthorized'
 898 |     get:
 899 |       x-eov-operation-id: getVariables
 900 |       x-eov-operation-handler: v1/handlers/variables/variables.handler
 901 |       tags:
 902 |         - Variables
 903 |       summary: Retrieve variables
 904 |       description: Retrieve variables from your instance.
 905 |       parameters:
 906 |         - $ref: '#/components/parameters/limit'
 907 |         - $ref: '#/components/parameters/cursor'
 908 |       responses:
 909 |         '200':
 910 |           description: Operation successful.
 911 |           content:
 912 |             application/json:
 913 |               schema:
 914 |                 $ref: '#/components/schemas/variableList'
 915 |         '401':
 916 |           $ref: '#/components/responses/unauthorized'
 917 |   /variables/{id}:
 918 |     delete:
 919 |       x-eov-operation-id: deleteVariable
 920 |       x-eov-operation-handler: v1/handlers/variables/variables.handler
 921 |       tags:
 922 |         - Variables
 923 |       summary: Delete a variable
 924 |       description: Delete a variable from your instance.
 925 |       parameters:
 926 |         - $ref: '#/components/parameters/variableId'
 927 |       responses:
 928 |         '204':
 929 |           description: Operation successful.
 930 |         '401':
 931 |           $ref: '#/components/responses/unauthorized'
 932 |         '404':
 933 |           $ref: '#/components/responses/notFound'
 934 |   /projects:
 935 |     post:
 936 |       x-eov-operation-id: createProject
 937 |       x-eov-operation-handler: v1/handlers/projects/projects.handler
 938 |       tags:
 939 |         - Projects
 940 |       summary: Create a project
 941 |       description: Create a project in your instance.
 942 |       requestBody:
 943 |         description: Payload for project to create.
 944 |         content:
 945 |           application/json:
 946 |             schema:
 947 |               $ref: '#/components/schemas/project'
 948 |         required: true
 949 |       responses:
 950 |         '201':
 951 |           description: Operation successful.
 952 |         '400':
 953 |           $ref: '#/components/responses/badRequest'
 954 |         '401':
 955 |           $ref: '#/components/responses/unauthorized'
 956 |     get:
 957 |       x-eov-operation-id: getProjects
 958 |       x-eov-operation-handler: v1/handlers/projects/projects.handler
 959 |       tags:
 960 |         - Projects
 961 |       summary: Retrieve projects
 962 |       description: Retrieve projects from your instance.
 963 |       parameters:
 964 |         - $ref: '#/components/parameters/limit'
 965 |         - $ref: '#/components/parameters/cursor'
 966 |       responses:
 967 |         '200':
 968 |           description: Operation successful.
 969 |           content:
 970 |             application/json:
 971 |               schema:
 972 |                 $ref: '#/components/schemas/projectList'
 973 |         '401':
 974 |           $ref: '#/components/responses/unauthorized'
 975 |   /projects/{projectId}:
 976 |     delete:
 977 |       x-eov-operation-id: deleteProject
 978 |       x-eov-operation-handler: v1/handlers/projects/projects.handler
 979 |       tags:
 980 |         - Projects
 981 |       summary: Delete a project
 982 |       description: Delete a project from your instance.
 983 |       parameters:
 984 |         - $ref: '#/components/parameters/projectId'
 985 |       responses:
 986 |         '204':
 987 |           description: Operation successful.
 988 |         '401':
 989 |           $ref: '#/components/responses/unauthorized'
 990 |         '403':
 991 |           $ref: '#/components/responses/forbidden'
 992 |         '404':
 993 |           $ref: '#/components/responses/notFound'
 994 |     put:
 995 |       x-eov-operation-id: updateProject
 996 |       x-eov-operation-handler: v1/handlers/projects/projects.handler
 997 |       tags:
 998 |         - Project
 999 |       summary: Update a project
1000 |       description: Update a project.
1001 |       requestBody:
1002 |         description: Updated project object.
1003 |         content:
1004 |           application/json:
1005 |             schema:
1006 |               $ref: '#/components/schemas/project'
1007 |         required: true
1008 |       responses:
1009 |         '204':
1010 |           description: Operation successful.
1011 |         '400':
1012 |           $ref: '#/components/responses/badRequest'
1013 |         '401':
1014 |           $ref: '#/components/responses/unauthorized'
1015 |         '403':
1016 |           $ref: '#/components/responses/forbidden'
1017 |         '404':
1018 |           $ref: '#/components/responses/notFound'
1019 | components:
1020 |   schemas:
1021 |     audit:
1022 |       type: object
1023 |       properties:
1024 |         Credentials Risk Report:
1025 |           type: object
1026 |           example:
1027 |             risk: credentials
1028 |             sections:
1029 |               - title: Credentials not used in any workflow
1030 |                 description: These credentials are not used in any workflow. Keeping unused credentials in your instance is an unneeded security risk.
1031 |                 recommendation: Consider deleting these credentials if you no longer need them.
1032 |                 location:
1033 |                   - kind: credential
1034 |                     id: '1'
1035 |                     name: My Test Account
1036 |         Database Risk Report:
1037 |           type: object
1038 |           example:
1039 |             risk: database
1040 |             sections:
1041 |               - title: Expressions in "Execute Query" fields in SQL nodes
1042 |                 description: This SQL node has an expression in the "Query" field of an "Execute Query" operation. Building a SQL query with an expression may lead to a SQL injection attack.
1043 |                 recommendation: Consider using the "Query Parameters" field to pass parameters to the query
1044 |                 or validating the input of the expression in the "Query" field.: null
1045 |                 location:
1046 |                   - kind: node
1047 |                     workflowId: '1'
1048 |                     workflowName: My Workflow
1049 |                     nodeId: 51eb5852-ce0b-4806-b4ff-e41322a4041a
1050 |                     nodeName: MySQL
1051 |                     nodeType: n8n-nodes-base.mySql
1052 |         Filesystem Risk Report:
1053 |           type: object
1054 |           example:
1055 |             risk: filesystem
1056 |             sections:
1057 |               - title: Nodes that interact with the filesystem
1058 |                 description: This node reads from and writes to any accessible file in the host filesystem. Sensitive file content may be manipulated through a node operation.
1059 |                 recommendation: Consider protecting any sensitive files in the host filesystem
1060 |                 or refactoring the workflow so that it does not require host filesystem interaction.: null
1061 |                 location:
1062 |                   - kind: node
1063 |                     workflowId: '1'
1064 |                     workflowName: My Workflow
1065 |                     nodeId: 51eb5852-ce0b-4806-b4ff-e41322a4041a
1066 |                     nodeName: Ready Binary file
1067 |                     nodeType: n8n-nodes-base.readBinaryFile
1068 |         Nodes Risk Report:
1069 |           type: object
1070 |           example:
1071 |             risk: nodes
1072 |             sections:
1073 |               - title: Community nodes
1074 |                 description: This node is sourced from the community. Community nodes are not vetted by the n8n team and have full access to the host system.
1075 |                 recommendation: Consider reviewing the source code in any community nodes installed in this n8n instance
1076 |                 and uninstalling any community nodes no longer used.: null
1077 |                 location:
1078 |                   - kind: community
1079 |                     nodeType: n8n-nodes-test.test
1080 |                     packageUrl: https://www.npmjs.com/package/n8n-nodes-test
1081 |         Instance Risk Report:
1082 |           type: object
1083 |           example:
1084 |             risk: execution
1085 |             sections:
1086 |               - title: Unprotected webhooks in instance
1087 |                 description: These webhook nodes have the "Authentication" field set to "None" and are not directly connected to a node to validate the payload. Every unprotected webhook allows your workflow to be called by any third party who knows the webhook URL.
1088 |                 recommendation: Consider setting the "Authentication" field to an option other than "None"
1089 |                 or validating the payload with one of the following nodes.: null
1090 |                 location:
1091 |                   - kind: community
1092 |                     nodeType: n8n-nodes-test.test
1093 |                     packageUrl: https://www.npmjs.com/package/n8n-nodes-test
1094 |     credential:
1095 |       required:
1096 |         - name
1097 |         - type
1098 |         - data
1099 |       type: object
1100 |       properties:
1101 |         id:
1102 |           type: string
1103 |           readOnly: true
1104 |           example: R2DjclaysHbqn778
1105 |         name:
1106 |           type: string
1107 |           example: Joe's Github Credentials
1108 |         type:
1109 |           type: string
1110 |           example: github
1111 |         data:
1112 |           type: object
1113 |           writeOnly: true
1114 |           example:
1115 |             token: ada612vad6fa5df4adf5a5dsf4389adsf76da7s
1116 |         createdAt:
1117 |           type: string
1118 |           format: date-time
1119 |           readOnly: true
1120 |           example: '2022-04-29T11:02:29.842Z'
1121 |         updatedAt:
1122 |           type: string
1123 |           format: date-time
1124 |           readOnly: true
1125 |           example: '2022-04-29T11:02:29.842Z'
1126 |     execution:
1127 |       type: object
1128 |       properties:
1129 |         id:
1130 |           type: number
1131 |           example: 1000
1132 |         data:
1133 |           type: object
1134 |         finished:
1135 |           type: boolean
1136 |           example: true
1137 |         mode:
1138 |           type: string
1139 |           enum:
1140 |             - cli
1141 |             - error
1142 |             - integrated
1143 |             - internal
1144 |             - manual
1145 |             - retry
1146 |             - trigger
1147 |             - webhook
1148 |         retryOf:
1149 |           type: number
1150 |           nullable: true
1151 |         retrySuccessId:
1152 |           type: number
1153 |           nullable: true
1154 |           example: '2'
1155 |         startedAt:
1156 |           type: string
1157 |           format: date-time
1158 |         stoppedAt:
1159 |           type: string
1160 |           format: date-time
1161 |         workflowId:
1162 |           type: number
1163 |           example: '1000'
1164 |         waitTill:
1165 |           type: string
1166 |           nullable: true
1167 |           format: date-time
1168 |         customData:
1169 |           type: object
1170 |     executionList:
1171 |       type: object
1172 |       properties:
1173 |         data:
1174 |           type: array
1175 |           items:
1176 |             $ref: '#/components/schemas/execution'
1177 |         nextCursor:
1178 |           type: string
1179 |           description: Paginate through executions by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection.
1180 |           nullable: true
1181 |           example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA
1182 |     tag:
1183 |       type: object
1184 |       additionalProperties: false
1185 |       required:
1186 |         - name
1187 |       properties:
1188 |         id:
1189 |           type: string
1190 |           readOnly: true
1191 |           example: 2tUt1wbLX592XDdX
1192 |         name:
1193 |           type: string
1194 |           example: Production
1195 |         createdAt:
1196 |           type: string
1197 |           format: date-time
1198 |           readOnly: true
1199 |         updatedAt:
1200 |           type: string
1201 |           format: date-time
1202 |           readOnly: true
1203 |     tagList:
1204 |       type: object
1205 |       properties:
1206 |         data:
1207 |           type: array
1208 |           items:
1209 |             $ref: '#/components/schemas/tag'
1210 |         nextCursor:
1211 |           type: string
1212 |           description: Paginate through tags by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection.
1213 |           nullable: true
1214 |           example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA
1215 |     node:
1216 |       type: object
1217 |       additionalProperties: false
1218 |       properties:
1219 |         id:
1220 |           type: string
1221 |           example: 0f5532f9-36ba-4bef-86c7-30d607400b15
1222 |         name:
1223 |           type: string
1224 |           example: Jira
1225 |         webhookId:
1226 |           type: string
1227 |         disabled:
1228 |           type: boolean
1229 |         notesInFlow:
1230 |           type: boolean
1231 |         notes:
1232 |           type: string
1233 |         type:
1234 |           type: string
1235 |           example: n8n-nodes-base.Jira
1236 |         typeVersion:
1237 |           type: number
1238 |           example: 1
1239 |         executeOnce:
1240 |           type: boolean
1241 |           example: false
1242 |         alwaysOutputData:
1243 |           type: boolean
1244 |           example: false
1245 |         retryOnFail:
1246 |           type: boolean
1247 |           example: false
1248 |         maxTries:
1249 |           type: number
1250 |         waitBetweenTries:
1251 |           type: number
1252 |         continueOnFail:
1253 |           type: boolean
1254 |           example: false
1255 |           description: use onError instead
1256 |           deprecated: true
1257 |         onError:
1258 |           type: string
1259 |           example: stopWorkflow
1260 |         position:
1261 |           type: array
1262 |           items:
1263 |             type: number
1264 |           example:
1265 |             - -100
1266 |             - 80
1267 |         parameters:
1268 |           type: object
1269 |           example:
1270 |             additionalProperties: {}
1271 |         credentials:
1272 |           type: object
1273 |           example:
1274 |             jiraSoftwareCloudApi:
1275 |               id: '35'
1276 |               name: jiraApi
1277 |         createdAt:
1278 |           type: string
1279 |           format: date-time
1280 |           readOnly: true
1281 |         updatedAt:
1282 |           type: string
1283 |           format: date-time
1284 |           readOnly: true
1285 |     workflowSettings:
1286 |       type: object
1287 |       additionalProperties: false
1288 |       properties:
1289 |         saveExecutionProgress:
1290 |           type: boolean
1291 |         saveManualExecutions:
1292 |           type: boolean
1293 |         saveDataErrorExecution:
1294 |           type: string
1295 |           enum:
1296 |             - all
1297 |             - none
1298 |         saveDataSuccessExecution:
1299 |           type: string
1300 |           enum:
1301 |             - all
1302 |             - none
1303 |         executionTimeout:
1304 |           type: number
1305 |           example: 3600
1306 |           maxLength: 3600
1307 |         errorWorkflow:
1308 |           type: string
1309 |           example: VzqKEW0ShTXA5vPj
1310 |           description: The ID of the workflow that contains the error trigger node.
1311 |         timezone:
1312 |           type: string
1313 |           example: America/New_York
1314 |         executionOrder:
1315 |           type: string
1316 |           example: v1
1317 |     workflow:
1318 |       type: object
1319 |       additionalProperties: false
1320 |       required:
1321 |         - name
1322 |         - nodes
1323 |         - connections
1324 |         - settings
1325 |       properties:
1326 |         id:
1327 |           type: string
1328 |           readOnly: true
1329 |           example: 2tUt1wbLX592XDdX
1330 |         name:
1331 |           type: string
1332 |           example: Workflow 1
1333 |         active:
1334 |           type: boolean
1335 |           readOnly: true
1336 |         createdAt:
1337 |           type: string
1338 |           format: date-time
1339 |           readOnly: true
1340 |         updatedAt:
1341 |           type: string
1342 |           format: date-time
1343 |           readOnly: true
1344 |         nodes:
1345 |           type: array
1346 |           items:
1347 |             $ref: '#/components/schemas/node'
1348 |         connections:
1349 |           type: object
1350 |           example:
1351 |             main:
1352 |               - node: Jira
1353 |                 type: main
1354 |                 index: 0
1355 |         settings:
1356 |           $ref: '#/components/schemas/workflowSettings'
1357 |         staticData:
1358 |           example:
1359 |             lastId: 1
1360 |           anyOf:
1361 |             - type: string
1362 |               format: jsonString
1363 |               nullable: true
1364 |             - type: object
1365 |               nullable: true
1366 |         tags:
1367 |           type: array
1368 |           items:
1369 |             $ref: '#/components/schemas/tag'
1370 |           readOnly: true
1371 |     workflowList:
1372 |       type: object
1373 |       properties:
1374 |         data:
1375 |           type: array
1376 |           items:
1377 |             $ref: '#/components/schemas/workflow'
1378 |         nextCursor:
1379 |           type: string
1380 |           description: Paginate through workflows by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection.
1381 |           nullable: true
1382 |           example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA
1383 |     workflowTags:
1384 |       type: array
1385 |       items:
1386 |         $ref: '#/components/schemas/tag'
1387 |     tagIds:
1388 |       type: array
1389 |       items:
1390 |         type: object
1391 |         additionalProperties: false
1392 |         required:
1393 |           - id
1394 |         properties:
1395 |           id:
1396 |             type: string
1397 |             example: 2tUt1wbLX592XDdX
1398 |     user:
1399 |       required:
1400 |         - email
1401 |       type: object
1402 |       properties:
1403 |         id:
1404 |           type: string
1405 |           readOnly: true
1406 |           example: 123e4567-e89b-12d3-a456-426614174000
1407 |         email:
1408 |           type: string
1409 |           format: email
1410 |           example: [email protected]
1411 |         firstName:
1412 |           maxLength: 32
1413 |           type: string
1414 |           description: User's first name
1415 |           readOnly: true
1416 |           example: john
1417 |         lastName:
1418 |           maxLength: 32
1419 |           type: string
1420 |           description: User's last name
1421 |           readOnly: true
1422 |           example: Doe
1423 |         isPending:
1424 |           type: boolean
1425 |           description: Whether the user finished setting up their account in response to the invitation (true) or not (false).
1426 |           readOnly: true
1427 |         createdAt:
1428 |           type: string
1429 |           description: Time the user was created.
1430 |           format: date-time
1431 |           readOnly: true
1432 |         updatedAt:
1433 |           type: string
1434 |           description: Last time the user was updated.
1435 |           format: date-time
1436 |           readOnly: true
1437 |         role:
1438 |           type: string
1439 |           example: owner
1440 |           readOnly: true
1441 |     userList:
1442 |       type: object
1443 |       properties:
1444 |         data:
1445 |           type: array
1446 |           items:
1447 |             $ref: '#/components/schemas/user'
1448 |         nextCursor:
1449 |           type: string
1450 |           description: Paginate through users by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection.
1451 |           nullable: true
1452 |           example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA
1453 |     pull:
1454 |       type: object
1455 |       properties:
1456 |         force:
1457 |           type: boolean
1458 |           example: true
1459 |         variables:
1460 |           type: object
1461 |           example:
1462 |             foo: bar
1463 |     importResult:
1464 |       type: object
1465 |       additionalProperties: true
1466 |       properties:
1467 |         variables:
1468 |           type: object
1469 |           properties:
1470 |             added:
1471 |               type: array
1472 |               items:
1473 |                 type: string
1474 |             changed:
1475 |               type: array
1476 |               items:
1477 |                 type: string
1478 |         credentials:
1479 |           type: array
1480 |           items:
1481 |             type: object
1482 |             properties:
1483 |               id:
1484 |                 type: string
1485 |               name:
1486 |                 type: string
1487 |               type:
1488 |                 type: string
1489 |         workflows:
1490 |           type: array
1491 |           items:
1492 |             type: object
1493 |             properties:
1494 |               id:
1495 |                 type: string
1496 |               name:
1497 |                 type: string
1498 |         tags:
1499 |           type: object
1500 |           properties:
1501 |             tags:
1502 |               type: array
1503 |               items:
1504 |                 type: object
1505 |                 properties:
1506 |                   id:
1507 |                     type: string
1508 |                   name:
1509 |                     type: string
1510 |             mappings:
1511 |               type: array
1512 |               items:
1513 |                 type: object
1514 |                 properties:
1515 |                   workflowId:
1516 |                     type: string
1517 |                   tagId:
1518 |                     type: string
1519 |     variable:
1520 |       type: object
1521 |       additionalProperties: false
1522 |       required:
1523 |         - key
1524 |         - value
1525 |       properties:
1526 |         id:
1527 |           type: string
1528 |           readOnly: true
1529 |         key:
1530 |           type: string
1531 |         value:
1532 |           type: string
1533 |           example: test
1534 |         type:
1535 |           type: string
1536 |           readOnly: true
1537 |     variableList:
1538 |       type: object
1539 |       properties:
1540 |         data:
1541 |           type: array
1542 |           items:
1543 |             $ref: '#/components/schemas/variable'
1544 |         nextCursor:
1545 |           type: string
1546 |           description: Paginate through variables by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection.
1547 |           nullable: true
1548 |           example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA
1549 |     project:
1550 |       type: object
1551 |       additionalProperties: false
1552 |       required:
1553 |         - name
1554 |       properties:
1555 |         id:
1556 |           type: string
1557 |           readOnly: true
1558 |         name:
1559 |           type: string
1560 |         type:
1561 |           type: string
1562 |           readOnly: true
1563 |     projectList:
1564 |       type: object
1565 |       properties:
1566 |         data:
1567 |           type: array
1568 |           items:
1569 |             $ref: '#/components/schemas/project'
1570 |         nextCursor:
1571 |           type: string
1572 |           description: Paginate through projects by setting the cursor parameter to a nextCursor attribute returned by a previous request. Default value fetches the first "page" of the collection.
1573 |           nullable: true
1574 |           example: MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA
1575 |     error:
1576 |       required:
1577 |         - message
1578 |       type: object
1579 |       properties:
1580 |         code:
1581 |           type: string
1582 |         message:
1583 |           type: string
1584 |         description:
1585 |           type: string
1586 |     role:
1587 |       readOnly: true
1588 |       type: object
1589 |       properties:
1590 |         id:
1591 |           type: number
1592 |           readOnly: true
1593 |           example: 1
1594 |         name:
1595 |           type: string
1596 |           example: owner
1597 |           readOnly: true
1598 |         scope:
1599 |           type: string
1600 |           readOnly: true
1601 |           example: global
1602 |         createdAt:
1603 |           type: string
1604 |           description: Time the role was created.
1605 |           format: date-time
1606 |           readOnly: true
1607 |         updatedAt:
1608 |           type: string
1609 |           description: Last time the role was updated.
1610 |           format: date-time
1611 |           readOnly: true
1612 |     credentialType:
1613 |       type: object
1614 |       properties:
1615 |         displayName:
1616 |           type: string
1617 |           readOnly: true
1618 |           example: Email
1619 |         name:
1620 |           type: string
1621 |           readOnly: true
1622 |           example: email
1623 |         type:
1624 |           type: string
1625 |           readOnly: true
1626 |           example: string
1627 |         default:
1628 |           type: string
1629 |           readOnly: true
1630 |           example: string
1631 |     Error:
1632 |       $ref: '#/components/schemas/error'
1633 |     Role:
1634 |       $ref: '#/components/schemas/role'
1635 |     Execution:
1636 |       $ref: '#/components/schemas/execution'
1637 |     Node:
1638 |       $ref: '#/components/schemas/node'
1639 |     Tag:
1640 |       $ref: '#/components/schemas/tag'
1641 |     Workflow:
1642 |       $ref: '#/components/schemas/workflow'
1643 |     WorkflowSettings:
1644 |       $ref: '#/components/schemas/workflowSettings'
1645 |     ExecutionList:
1646 |       $ref: '#/components/schemas/executionList'
1647 |     WorkflowList:
1648 |       $ref: '#/components/schemas/workflowList'
1649 |     Credential:
1650 |       $ref: '#/components/schemas/credential'
1651 |     CredentialType:
1652 |       $ref: '#/components/schemas/credentialType'
1653 |     Audit:
1654 |       $ref: '#/components/schemas/audit'
1655 |     Pull:
1656 |       $ref: '#/components/schemas/pull'
1657 |     ImportResult:
1658 |       $ref: '#/components/schemas/importResult'
1659 |     UserList:
1660 |       $ref: '#/components/schemas/userList'
1661 |     User:
1662 |       $ref: '#/components/schemas/user'
1663 |   responses:
1664 |     unauthorized:
1665 |       description: Unauthorized
1666 |     notFound:
1667 |       description: The specified resource was not found.
1668 |     badRequest:
1669 |       description: The request is invalid or provides malformed data.
1670 |     conflict:
1671 |       description: Conflict
1672 |     forbidden:
1673 |       description: Forbidden
1674 |     NotFound:
1675 |       $ref: '#/components/responses/notFound'
1676 |     Unauthorized:
1677 |       $ref: '#/components/responses/unauthorized'
1678 |     BadRequest:
1679 |       $ref: '#/components/responses/badRequest'
1680 |     Conflict:
1681 |       $ref: '#/components/responses/conflict'
1682 |     Forbidden:
1683 |       $ref: '#/components/responses/forbidden'
1684 |   parameters:
1685 |     includeData:
1686 |       name: includeData
1687 |       in: query
1688 |       description: Whether or not to include the execution's detailed data.
1689 |       required: false
1690 |       schema:
1691 |         type: boolean
1692 |     limit:
1693 |       name: limit
1694 |       in: query
1695 |       description: The maximum number of items to return.
1696 |       required: false
1697 |       schema:
1698 |         type: number
1699 |         example: 100
1700 |         default: 100
1701 |         maximum: 250
1702 |     cursor:
1703 |       name: cursor
1704 |       in: query
1705 |       description: Paginate by setting the cursor parameter to the nextCursor attribute returned by the previous request's response. Default value fetches the first "page" of the collection. See pagination for more detail.
1706 |       required: false
1707 |       style: form
1708 |       schema:
1709 |         type: string
1710 |     executionId:
1711 |       name: id
1712 |       in: path
1713 |       description: The ID of the execution.
1714 |       required: true
1715 |       schema:
1716 |         type: number
1717 |     tagId:
1718 |       name: id
1719 |       in: path
1720 |       description: The ID of the tag.
1721 |       required: true
1722 |       schema:
1723 |         type: string
1724 |     workflowId:
1725 |       name: id
1726 |       in: path
1727 |       description: The ID of the workflow.
1728 |       required: true
1729 |       schema:
1730 |         type: string
1731 |     credentialId:
1732 |       name: id
1733 |       in: path
1734 |       description: The ID of the credential.
1735 |       required: true
1736 |       schema:
1737 |         type: string
1738 |     includeRole:
1739 |       name: includeRole
1740 |       in: query
1741 |       description: Whether to include the user's role or not.
1742 |       required: false
1743 |       schema:
1744 |         type: boolean
1745 |         example: true
1746 |         default: false
1747 |     userIdentifier:
1748 |       name: id
1749 |       in: path
1750 |       description: The ID or email of the user.
1751 |       required: true
1752 |       schema:
1753 |         type: string
1754 |         format: identifier
1755 |     variableId:
1756 |       name: id
1757 |       in: path
1758 |       description: The ID of the variable.
1759 |       required: true
1760 |       schema:
1761 |         type: string
1762 |     projectId:
1763 |       name: projectId
1764 |       in: path
1765 |       description: The ID of the project.
1766 |       required: true
1767 |       schema:
1768 |         type: string
1769 |     Cursor:
1770 |       $ref: '#/components/parameters/cursor'
1771 |     Limit:
1772 |       $ref: '#/components/parameters/limit'
1773 |     ExecutionId:
1774 |       $ref: '#/components/parameters/executionId'
1775 |     WorkflowId:
1776 |       $ref: '#/components/parameters/workflowId'
1777 |     TagId:
1778 |       $ref: '#/components/parameters/tagId'
1779 |     IncludeData:
1780 |       $ref: '#/components/parameters/includeData'
1781 |     UserIdentifier:
1782 |       $ref: '#/components/parameters/userIdentifier'
1783 |     IncludeRole:
1784 |       $ref: '#/components/parameters/includeRole'
1785 |   securitySchemes:
1786 |     ApiKeyAuth:
1787 |       type: apiKey
1788 |       in: header
1789 |       name: X-N8N-API-KEY
1790 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
   1 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
   2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
   3 | import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
   4 | import { z } from "zod";
   5 | import fetch from 'node-fetch';
   6 | 
   7 | // Type definitions for n8n API responses
   8 | interface N8nUser {
   9 |   id: string;
  10 |   email: string;
  11 |   firstName?: string;
  12 |   lastName?: string;
  13 |   isPending: boolean;
  14 |   role?: string;
  15 |   createdAt: string;
  16 |   updatedAt: string;
  17 | }
  18 | 
  19 | interface N8nUserList {
  20 |   data: N8nUser[];
  21 |   nextCursor?: string;
  22 | }
  23 | 
  24 | interface N8nWorkflow {
  25 |   id: number;
  26 |   name: string;
  27 |   active: boolean;
  28 |   createdAt: string;
  29 |   updatedAt: string;
  30 |   tags: string[];
  31 | }
  32 | 
  33 | interface N8nWorkflowList {
  34 |   data: N8nWorkflow[];
  35 |   nextCursor?: string;
  36 | }
  37 | 
  38 | interface N8nProject {
  39 |   id: string;
  40 |   name: string;
  41 |   type?: string;
  42 | }
  43 | 
  44 | interface N8nProjectList {
  45 |   data: N8nProject[];
  46 |   nextCursor?: string;
  47 | }
  48 | 
  49 | interface N8nVariable {
  50 |   id: string;
  51 |   key: string;
  52 |   value: string;
  53 |   type?: string;
  54 | }
  55 | 
  56 | interface N8nVariableList {
  57 |   data: N8nVariable[];
  58 |   nextCursor?: string;
  59 | }
  60 | 
  61 | interface N8nExecution {
  62 |   id: number;
  63 |   data?: any;
  64 |   finished: boolean;
  65 |   mode: string;
  66 |   retryOf?: number;
  67 |   retrySuccessId?: number;
  68 |   startedAt: string;
  69 |   stoppedAt?: string;
  70 |   workflowId: number;
  71 |   waitTill?: string;
  72 | }
  73 | 
  74 | interface N8nExecutionList {
  75 |   data: N8nExecution[];
  76 |   nextCursor?: string;
  77 | }
  78 | 
  79 | interface N8nTag {
  80 |   id: string;
  81 |   name: string;
  82 |   createdAt?: string;
  83 |   updatedAt?: string;
  84 | }
  85 | 
  86 | interface N8nTagList {
  87 |   data: N8nTag[];
  88 |   nextCursor?: string;
  89 | }
  90 | 
  91 | interface N8nAuditResult {
  92 |   'Credentials Risk Report'?: any;
  93 |   'Database Risk Report'?: any;
  94 |   'Filesystem Risk Report'?: any;
  95 |   'Nodes Risk Report'?: any;
  96 |   'Instance Risk Report'?: any;
  97 | }
  98 | 
  99 | class N8nClient {
 100 |   constructor(
 101 |     private baseUrl: string,
 102 |     private apiKey: string
 103 |   ) {
 104 |     // Remove trailing slash if present
 105 |     this.baseUrl = baseUrl.replace(/\/$/, '');
 106 |   }
 107 | 
 108 |   private async makeRequest<T>(endpoint: string, options: any = {}): Promise<T> {
 109 |     const url = `${this.baseUrl}/api/v1${endpoint}`;
 110 |     const headers = {
 111 |       'X-N8N-API-KEY': this.apiKey,
 112 |       'Accept': 'application/json',
 113 |       'Content-Type': 'application/json',
 114 |     };
 115 | 
 116 |     try {
 117 |       const response = await fetch(url, {
 118 |         ...options,
 119 |         headers: {
 120 |           ...headers,
 121 |           ...options.headers,
 122 |         },
 123 |       });
 124 | 
 125 |       if (!response.ok) {
 126 |         const errorText = await response.text();
 127 |         let errorMessage: string;
 128 |         try {
 129 |           const errorJson = JSON.parse(errorText);
 130 |           // Check for license-related errors
 131 |           if (errorJson.message && errorJson.message.includes('license')) {
 132 |             errorMessage = `This operation requires an n8n Enterprise license with project management features enabled. Error: ${errorJson.message}`;
 133 |           } else {
 134 |             errorMessage = errorJson.message || errorText;
 135 |           }
 136 |         } catch {
 137 |           errorMessage = errorText;
 138 |         }
 139 |         throw new Error(`N8N API error: ${errorMessage}`);
 140 |       }
 141 | 
 142 |       // Handle 204 No Content responses
 143 |       if (response.status === 204) {
 144 |         return {} as T;
 145 |       }
 146 | 
 147 |       return await response.json() as T;
 148 |     } catch (error) {
 149 |       if (error instanceof Error) {
 150 |         throw new Error(`Failed to connect to n8n: ${error.message}`);
 151 |       }
 152 |       throw error;
 153 |     }
 154 |   }
 155 | 
 156 |   async listWorkflows(): Promise<N8nWorkflowList> {
 157 |     return this.makeRequest<N8nWorkflowList>('/workflows');
 158 |   }
 159 | 
 160 |   async getWorkflow(id: string): Promise<N8nWorkflow> {
 161 |     return this.makeRequest<N8nWorkflow>(`/workflows/${id}`);
 162 |   }
 163 | 
 164 |   async createWorkflow(name: string, nodes: any[] = [], connections: any = {}): Promise<N8nWorkflow> {
 165 |     return this.makeRequest<N8nWorkflow>('/workflows', {
 166 |       method: 'POST',
 167 |       body: JSON.stringify({
 168 |         name,
 169 |         nodes,
 170 |         connections,
 171 |         settings: {
 172 |           saveManualExecutions: true,
 173 |           saveExecutionProgress: true,
 174 |         },
 175 |       }),
 176 |     });
 177 |   }
 178 | 
 179 |   async updateWorkflow(id: string, workflow: Partial<N8nWorkflow>): Promise<N8nWorkflow> {
 180 |     return this.makeRequest<N8nWorkflow>(`/workflows/${id}`, {
 181 |       method: 'PUT',
 182 |       body: JSON.stringify(workflow),
 183 |     });
 184 |   }
 185 | 
 186 |   async deleteWorkflow(id: string): Promise<N8nWorkflow> {
 187 |     return this.makeRequest<N8nWorkflow>(`/workflows/${id}`, {
 188 |       method: 'DELETE',
 189 |     });
 190 |   }
 191 | 
 192 |   async activateWorkflow(id: string): Promise<N8nWorkflow> {
 193 |     return this.makeRequest<N8nWorkflow>(`/workflows/${id}/activate`, {
 194 |       method: 'POST',
 195 |     });
 196 |   }
 197 | 
 198 |   async deactivateWorkflow(id: string): Promise<N8nWorkflow> {
 199 |     return this.makeRequest<N8nWorkflow>(`/workflows/${id}/deactivate`, {
 200 |       method: 'POST',
 201 |     });
 202 |   }
 203 | 
 204 |   // Project management methods (requires n8n Enterprise license)
 205 |   async listProjects(): Promise<N8nProjectList> {
 206 |     return this.makeRequest<N8nProjectList>('/projects');
 207 |   }
 208 | 
 209 |   async createProject(name: string): Promise<void> {
 210 |     return this.makeRequest<void>('/projects', {
 211 |       method: 'POST',
 212 |       body: JSON.stringify({ name }),
 213 |     });
 214 |   }
 215 | 
 216 |   async deleteProject(projectId: string): Promise<void> {
 217 |     return this.makeRequest<void>(`/projects/${projectId}`, {
 218 |       method: 'DELETE',
 219 |     });
 220 |   }
 221 | 
 222 |   async updateProject(projectId: string, name: string): Promise<void> {
 223 |     return this.makeRequest<void>(`/projects/${projectId}`, {
 224 |       method: 'PUT',
 225 |       body: JSON.stringify({ name }),
 226 |     });
 227 |   }
 228 | 
 229 |   // User management methods
 230 |   async listUsers(): Promise<N8nUserList> {
 231 |     return this.makeRequest<N8nUserList>('/users');
 232 |   }
 233 | 
 234 |   async createUsers(users: Array<{ email: string; role?: 'global:admin' | 'global:member' }>): Promise<any> {
 235 |     return this.makeRequest('/users', {
 236 |       method: 'POST',
 237 |       body: JSON.stringify(users),
 238 |     });
 239 |   }
 240 | 
 241 |   async getUser(idOrEmail: string): Promise<N8nUser> {
 242 |     return this.makeRequest<N8nUser>(`/users/${idOrEmail}`);
 243 |   }
 244 | 
 245 |   async deleteUser(idOrEmail: string): Promise<void> {
 246 |     return this.makeRequest<void>(`/users/${idOrEmail}`, {
 247 |       method: 'DELETE',
 248 |     });
 249 |   }
 250 | 
 251 |   // Variable management methods
 252 |   async listVariables(): Promise<N8nVariableList> {
 253 |     return this.makeRequest<N8nVariableList>('/variables');
 254 |   }
 255 | 
 256 |   async createVariable(key: string, value: string): Promise<void> {
 257 |     return this.makeRequest<void>('/variables', {
 258 |       method: 'POST',
 259 |       body: JSON.stringify({ key, value }),
 260 |     });
 261 |   }
 262 | 
 263 |   async deleteVariable(id: string): Promise<void> {
 264 |     return this.makeRequest<void>(`/variables/${id}`, {
 265 |       method: 'DELETE',
 266 |     });
 267 |   }
 268 | 
 269 |   // Execution management methods
 270 |   async getExecutions(options: { 
 271 |     includeData?: boolean; 
 272 |     status?: 'error' | 'success' | 'waiting';
 273 |     workflowId?: string;
 274 |     limit?: number;
 275 |   } = {}): Promise<N8nExecutionList> {
 276 |     const params = new URLSearchParams();
 277 |     if (options.includeData !== undefined) params.append('includeData', String(options.includeData));
 278 |     if (options.status) params.append('status', options.status);
 279 |     if (options.workflowId) params.append('workflowId', options.workflowId);
 280 |     if (options.limit) params.append('limit', String(options.limit));
 281 | 
 282 |     return this.makeRequest<N8nExecutionList>(`/executions?${params.toString()}`);
 283 |   }
 284 | 
 285 |   async getExecution(id: number, includeData: boolean = false): Promise<N8nExecution> {
 286 |     const params = new URLSearchParams();
 287 |     if (includeData) params.append('includeData', 'true');
 288 | 
 289 |     return this.makeRequest<N8nExecution>(`/executions/${id}?${params.toString()}`);
 290 |   }
 291 | 
 292 |   async deleteExecution(id: number): Promise<N8nExecution> {
 293 |     return this.makeRequest<N8nExecution>(`/executions/${id}`, {
 294 |       method: 'DELETE',
 295 |     });
 296 |   }
 297 | 
 298 |   // Tag management methods
 299 |   async createTag(name: string): Promise<N8nTag> {
 300 |     return this.makeRequest<N8nTag>('/tags', {
 301 |       method: 'POST',
 302 |       body: JSON.stringify({ name }),
 303 |     });
 304 |   }
 305 | 
 306 |   async getTags(options: { limit?: number } = {}): Promise<N8nTagList> {
 307 |     const params = new URLSearchParams();
 308 |     if (options.limit) params.append('limit', String(options.limit));
 309 | 
 310 |     return this.makeRequest<N8nTagList>(`/tags?${params.toString()}`);
 311 |   }
 312 | 
 313 |   async getTag(id: string): Promise<N8nTag> {
 314 |     return this.makeRequest<N8nTag>(`/tags/${id}`);
 315 |   }
 316 | 
 317 |   async updateTag(id: string, name: string): Promise<N8nTag> {
 318 |     return this.makeRequest<N8nTag>(`/tags/${id}`, {
 319 |       method: 'PUT',
 320 |       body: JSON.stringify({ name }),
 321 |     });
 322 |   }
 323 | 
 324 |   async deleteTag(id: string): Promise<N8nTag> {
 325 |     return this.makeRequest<N8nTag>(`/tags/${id}`, {
 326 |       method: 'DELETE',
 327 |     });
 328 |   }
 329 | 
 330 |   async getWorkflowTags(workflowId: string): Promise<N8nTag[]> {
 331 |     return this.makeRequest<N8nTag[]>(`/workflows/${workflowId}/tags`);
 332 |   }
 333 | 
 334 |   async updateWorkflowTags(workflowId: string, tagIds: { id: string }[]): Promise<N8nTag[]> {
 335 |     return this.makeRequest<N8nTag[]>(`/workflows/${workflowId}/tags`, {
 336 |       method: 'PUT',
 337 |       body: JSON.stringify(tagIds),
 338 |     });
 339 |   }
 340 | 
 341 |   // Security audit method
 342 |   async generateAudit(options: {
 343 |     daysAbandonedWorkflow?: number;
 344 |     categories?: Array<'credentials' | 'database' | 'nodes' | 'filesystem' | 'instance'>;
 345 |   } = {}): Promise<N8nAuditResult> {
 346 |     return this.makeRequest<N8nAuditResult>('/audit', {
 347 |       method: 'POST',
 348 |       body: JSON.stringify({
 349 |         additionalOptions: {
 350 |           daysAbandonedWorkflow: options.daysAbandonedWorkflow,
 351 |           categories: options.categories,
 352 |         },
 353 |       }),
 354 |     });
 355 |   }
 356 | 
 357 |   // Credential management methods
 358 |   async createCredential(name: string, type: string, data: Record<string, any>): Promise<any> {
 359 |     return this.makeRequest('/credentials', {
 360 |       method: 'POST',
 361 |       body: JSON.stringify({
 362 |         name,
 363 |         type,
 364 |         data
 365 |       }),
 366 |     });
 367 |   }
 368 | 
 369 |   async deleteCredential(id: string): Promise<any> {
 370 |     return this.makeRequest(`/credentials/${id}`, {
 371 |       method: 'DELETE',
 372 |     });
 373 |   }
 374 | 
 375 |   async getCredentialSchema(credentialTypeName: string): Promise<any> {
 376 |     return this.makeRequest(`/credentials/schema/${credentialTypeName}`);
 377 |   }
 378 | }
 379 | 
 380 | // Create an MCP server
 381 | const server = new Server(
 382 |   {
 383 |     name: "n8n-integration",
 384 |     version: "1.0.0"
 385 |   },
 386 |   {
 387 |     capabilities: {
 388 |       tools: {}
 389 |     }
 390 |   }
 391 | );
 392 | 
 393 | // Store client instances
 394 | const clients = new Map<string, N8nClient>();
 395 | 
 396 | // List tools handler
 397 | server.setRequestHandler(ListToolsRequestSchema, async () => {
 398 |   return {
 399 |     tools: [
 400 |       {
 401 |         name: "init-n8n",
 402 |         description: "Initialize connection to n8n instance. Use this tool whenever an n8n URL and API key are shared to establish the connection. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 403 |         inputSchema: {
 404 |           type: "object",
 405 |           properties: {
 406 |             url: { type: "string" },
 407 |             apiKey: { type: "string" }
 408 |           },
 409 |           required: ["url", "apiKey"]
 410 |         }
 411 |       },
 412 |       {
 413 |         name: "list-workflows",
 414 |         description: "List all workflows from n8n. Use after init-n8n to see available workflows. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 415 |         inputSchema: {
 416 |           type: "object",
 417 |           properties: {
 418 |             clientId: { type: "string" }
 419 |           },
 420 |           required: ["clientId"]
 421 |         }
 422 |       },
 423 |       {
 424 |         name: "get-workflow",
 425 |         description: "Retrieve a workflow by ID. Use after list-workflows to get detailed information about a specific workflow. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 426 |         inputSchema: {
 427 |           type: "object",
 428 |           properties: {
 429 |             clientId: { type: "string" },
 430 |             id: { type: "string" }
 431 |           },
 432 |           required: ["clientId", "id"]
 433 |         }
 434 |       },
 435 |       {
 436 |         name: "create-workflow",
 437 |         description: "Create a new workflow in n8n. Use to set up a new workflow with optional nodes and connections. IMPORTANT: 1) Arguments must be provided as compact, single-line JSON without whitespace or newlines. 2) Must provide full workflow structure including nodes and connections arrays, even if empty. The 'active' property should not be included as it is read-only.",
 438 |         inputSchema: {
 439 |           type: "object",
 440 |           properties: {
 441 |             clientId: { type: "string" },
 442 |             name: { type: "string" },
 443 |             nodes: { type: "array" },
 444 |             connections: { type: "object" }
 445 |           },
 446 |           required: ["clientId", "name"]
 447 |         }
 448 |       },
 449 |       {
 450 |         name: "update-workflow",
 451 |         description: "Update an existing workflow in n8n. Use after get-workflow to modify a workflow's properties, nodes, or connections. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 452 |         inputSchema: {
 453 |           type: "object",
 454 |           properties: {
 455 |             clientId: { type: "string" },
 456 |             id: { type: "string" },
 457 |             workflow: {
 458 |               type: "object",
 459 |               properties: {
 460 |                 name: { type: "string" },
 461 |                 active: { type: "boolean" },
 462 |                 nodes: { type: "array" },
 463 |                 connections: { type: "object" },
 464 |                 settings: { type: "object" }
 465 |               }
 466 |             }
 467 |           },
 468 |           required: ["clientId", "id", "workflow"]
 469 |         }
 470 |       },
 471 |       {
 472 |         name: "delete-workflow",
 473 |         description: "Delete a workflow by ID. This action cannot be undone. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 474 |         inputSchema: {
 475 |           type: "object",
 476 |           properties: {
 477 |             clientId: { type: "string" },
 478 |             id: { type: "string" }
 479 |           },
 480 |           required: ["clientId", "id"]
 481 |         }
 482 |       },
 483 |       {
 484 |         name: "activate-workflow",
 485 |         description: "Activate a workflow by ID. This will enable the workflow to run. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 486 |         inputSchema: {
 487 |           type: "object",
 488 |           properties: {
 489 |             clientId: { type: "string" },
 490 |             id: { type: "string" }
 491 |           },
 492 |           required: ["clientId", "id"]
 493 |         }
 494 |       },
 495 |       {
 496 |         name: "deactivate-workflow",
 497 |         description: "Deactivate a workflow by ID. This will prevent the workflow from running. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 498 |         inputSchema: {
 499 |           type: "object",
 500 |           properties: {
 501 |             clientId: { type: "string" },
 502 |             id: { type: "string" }
 503 |           },
 504 |           required: ["clientId", "id"]
 505 |         }
 506 |       },
 507 |       {
 508 |         name: "list-projects",
 509 |         description: "List all projects from n8n. NOTE: Requires n8n Enterprise license with project management features enabled. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 510 |         inputSchema: {
 511 |           type: "object",
 512 |           properties: {
 513 |             clientId: { type: "string" }
 514 |           },
 515 |           required: ["clientId"]
 516 |         }
 517 |       },
 518 |       {
 519 |         name: "create-project",
 520 |         description: "Create a new project in n8n. NOTE: Requires n8n Enterprise license with project management features enabled. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 521 |         inputSchema: {
 522 |           type: "object",
 523 |           properties: {
 524 |             clientId: { type: "string" },
 525 |             name: { type: "string" }
 526 |           },
 527 |           required: ["clientId", "name"]
 528 |         }
 529 |       },
 530 |       {
 531 |         name: "delete-project",
 532 |         description: "Delete a project by ID. NOTE: Requires n8n Enterprise license with project management features enabled. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 533 |         inputSchema: {
 534 |           type: "object",
 535 |           properties: {
 536 |             clientId: { type: "string" },
 537 |             projectId: { type: "string" }
 538 |           },
 539 |           required: ["clientId", "projectId"]
 540 |         }
 541 |       },
 542 |       {
 543 |         name: "update-project",
 544 |         description: "Update a project's name. NOTE: Requires n8n Enterprise license with project management features enabled. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 545 |         inputSchema: {
 546 |           type: "object",
 547 |           properties: {
 548 |             clientId: { type: "string" },
 549 |             projectId: { type: "string" },
 550 |             name: { type: "string" }
 551 |           },
 552 |           required: ["clientId", "projectId", "name"]
 553 |         }
 554 |       },
 555 |       {
 556 |         name: "list-users",
 557 |         description: "Retrieve all users from your instance. Only available for the instance owner.",
 558 |         inputSchema: {
 559 |           type: "object",
 560 |           properties: {
 561 |             clientId: { type: "string" }
 562 |           },
 563 |           required: ["clientId"]
 564 |         }
 565 |       },
 566 |       {
 567 |         name: "create-users",
 568 |         description: "Create one or more users in your instance.",
 569 |         inputSchema: {
 570 |           type: "object",
 571 |           properties: {
 572 |             clientId: { type: "string" },
 573 |             users: {
 574 |               type: "array",
 575 |               items: {
 576 |                 type: "object",
 577 |                 properties: {
 578 |                   email: { type: "string" },
 579 |                   role: { 
 580 |                     type: "string",
 581 |                     enum: ["global:admin", "global:member"]
 582 |                   }
 583 |                 },
 584 |                 required: ["email"]
 585 |               }
 586 |             }
 587 |           },
 588 |           required: ["clientId", "users"]
 589 |         }
 590 |       },
 591 |       {
 592 |         name: "get-user",
 593 |         description: "Get user by ID or email address.",
 594 |         inputSchema: {
 595 |           type: "object",
 596 |           properties: {
 597 |             clientId: { type: "string" },
 598 |             idOrEmail: { type: "string" }
 599 |           },
 600 |           required: ["clientId", "idOrEmail"]
 601 |         }
 602 |       },
 603 |       {
 604 |         name: "delete-user",
 605 |         description: "Delete a user from your instance.",
 606 |         inputSchema: {
 607 |           type: "object",
 608 |           properties: {
 609 |             clientId: { type: "string" },
 610 |             idOrEmail: { type: "string" }
 611 |           },
 612 |           required: ["clientId", "idOrEmail"]
 613 |         }
 614 |       },
 615 |       {
 616 |         name: "list-variables",
 617 |         description: "List all variables from n8n. NOTE: Requires n8n Enterprise license with variable management features enabled. Use after init-n8n to see available variables. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 618 |         inputSchema: {
 619 |           type: "object",
 620 |           properties: {
 621 |             clientId: { type: "string" }
 622 |           },
 623 |           required: ["clientId"]
 624 |         }
 625 |       },
 626 |       {
 627 |         name: "create-variable",
 628 |         description: "Create a new variable in n8n. NOTE: Requires n8n Enterprise license with variable management features enabled. Variables can be used across workflows to store and share data. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 629 |         inputSchema: {
 630 |           type: "object",
 631 |           properties: {
 632 |             clientId: { type: "string" },
 633 |             key: { type: "string" },
 634 |             value: { type: "string" }
 635 |           },
 636 |           required: ["clientId", "key", "value"]
 637 |         }
 638 |       },
 639 |       {
 640 |         name: "delete-variable",
 641 |         description: "Delete a variable by ID. NOTE: Requires n8n Enterprise license with variable management features enabled. Use after list-variables to get the ID of the variable to delete. This action cannot be undone. IMPORTANT: Arguments must be provided as compact, single-line JSON without whitespace or newlines.",
 642 |         inputSchema: {
 643 |           type: "object",
 644 |           properties: {
 645 |             clientId: { type: "string" },
 646 |             id: { type: "string" }
 647 |           },
 648 |           required: ["clientId", "id"]
 649 |         }
 650 |       },
 651 |       {
 652 |         name: "create-credential",
 653 |         description: "Create a credential that can be used by nodes of the specified type. The credential type name can be found in the n8n UI when creating credentials (e.g., 'cloudflareApi', 'githubApi', 'slackOAuth2Api'). Use get-credential-schema first to see what fields are required for the credential type you want to create.",
 654 |         inputSchema: {
 655 |           type: "object",
 656 |           properties: {
 657 |             clientId: { type: "string" },
 658 |             name: { type: "string" },
 659 |             type: { type: "string" },
 660 |             data: { type: "object" }
 661 |           },
 662 |           required: ["clientId", "name", "type", "data"]
 663 |         }
 664 |       },
 665 |       {
 666 |         name: "delete-credential",
 667 |         description: "Delete a credential by ID. You must be the owner of the credentials.",
 668 |         inputSchema: {
 669 |           type: "object",
 670 |           properties: {
 671 |             clientId: { type: "string" },
 672 |             id: { type: "string" }
 673 |           },
 674 |           required: ["clientId", "id"]
 675 |         }
 676 |       },
 677 |       {
 678 |         name: "get-credential-schema",
 679 |         description: "Show credential data schema for a specific credential type. The credential type name can be found in the n8n UI when creating credentials (e.g., 'cloudflareApi', 'githubApi', 'slackOAuth2Api'). This will show you what fields are required for creating credentials of this type.",
 680 |         inputSchema: {
 681 |           type: "object",
 682 |           properties: {
 683 |             clientId: { type: "string" },
 684 |             credentialTypeName: { type: "string" }
 685 |           },
 686 |           required: ["clientId", "credentialTypeName"]
 687 |         }
 688 |       },
 689 |       // Execution Management Tools
 690 |       {
 691 |         name: "list-executions",
 692 |         description: "Retrieve all executions from your instance with optional filtering.",
 693 |         inputSchema: {
 694 |           type: "object",
 695 |           properties: {
 696 |             clientId: { type: "string" },
 697 |             includeData: { type: "boolean" },
 698 |             status: { 
 699 |               type: "string",
 700 |               enum: ["error", "success", "waiting"]
 701 |             },
 702 |             workflowId: { type: "string" },
 703 |             limit: { type: "number" }
 704 |           },
 705 |           required: ["clientId"]
 706 |         }
 707 |       },
 708 |       {
 709 |         name: "get-execution",
 710 |         description: "Retrieve a specific execution by ID.",
 711 |         inputSchema: {
 712 |           type: "object",
 713 |           properties: {
 714 |             clientId: { type: "string" },
 715 |             id: { type: "number" },
 716 |             includeData: { type: "boolean" }
 717 |           },
 718 |           required: ["clientId", "id"]
 719 |         }
 720 |       },
 721 |       {
 722 |         name: "delete-execution",
 723 |         description: "Delete a specific execution by ID.",
 724 |         inputSchema: {
 725 |           type: "object",
 726 |           properties: {
 727 |             clientId: { type: "string" },
 728 |             id: { type: "number" }
 729 |           },
 730 |           required: ["clientId", "id"]
 731 |         }
 732 |       },
 733 |       // Tag Management Tools
 734 |       {
 735 |         name: "create-tag",
 736 |         description: "Create a new tag in your instance.",
 737 |         inputSchema: {
 738 |           type: "object",
 739 |           properties: {
 740 |             clientId: { type: "string" },
 741 |             name: { type: "string" }
 742 |           },
 743 |           required: ["clientId", "name"]
 744 |         }
 745 |       },
 746 |       {
 747 |         name: "list-tags",
 748 |         description: "Retrieve all tags from your instance.",
 749 |         inputSchema: {
 750 |           type: "object",
 751 |           properties: {
 752 |             clientId: { type: "string" },
 753 |             limit: { type: "number" }
 754 |           },
 755 |           required: ["clientId"]
 756 |         }
 757 |       },
 758 |       {
 759 |         name: "get-tag",
 760 |         description: "Retrieve a specific tag by ID.",
 761 |         inputSchema: {
 762 |           type: "object",
 763 |           properties: {
 764 |             clientId: { type: "string" },
 765 |             id: { type: "string" }
 766 |           },
 767 |           required: ["clientId", "id"]
 768 |         }
 769 |       },
 770 |       {
 771 |         name: "update-tag",
 772 |         description: "Update a tag's name.",
 773 |         inputSchema: {
 774 |           type: "object",
 775 |           properties: {
 776 |             clientId: { type: "string" },
 777 |             id: { type: "string" },
 778 |             name: { type: "string" }
 779 |           },
 780 |           required: ["clientId", "id", "name"]
 781 |         }
 782 |       },
 783 |       {
 784 |         name: "delete-tag",
 785 |         description: "Delete a tag by ID.",
 786 |         inputSchema: {
 787 |           type: "object",
 788 |           properties: {
 789 |             clientId: { type: "string" },
 790 |             id: { type: "string" }
 791 |           },
 792 |           required: ["clientId", "id"]
 793 |         }
 794 |       },
 795 |       {
 796 |         name: "get-workflow-tags",
 797 |         description: "Get tags associated with a workflow.",
 798 |         inputSchema: {
 799 |           type: "object",
 800 |           properties: {
 801 |             clientId: { type: "string" },
 802 |             workflowId: { type: "string" }
 803 |           },
 804 |           required: ["clientId", "workflowId"]
 805 |         }
 806 |       },
 807 |       {
 808 |         name: "update-workflow-tags",
 809 |         description: "Update tags associated with a workflow.",
 810 |         inputSchema: {
 811 |           type: "object",
 812 |           properties: {
 813 |             clientId: { type: "string" },
 814 |             workflowId: { type: "string" },
 815 |             tagIds: {
 816 |               type: "array",
 817 |               items: {
 818 |                 type: "object",
 819 |                 properties: {
 820 |                   id: { type: "string" }
 821 |                 },
 822 |                 required: ["id"]
 823 |               }
 824 |             }
 825 |           },
 826 |           required: ["clientId", "workflowId", "tagIds"]
 827 |         }
 828 |       },
 829 |       // Security Audit Tool
 830 |       {
 831 |         name: "generate-audit",
 832 |         description: "Generate a security audit for your n8n instance.",
 833 |         inputSchema: {
 834 |           type: "object",
 835 |           properties: {
 836 |             clientId: { type: "string" },
 837 |             daysAbandonedWorkflow: { type: "number" },
 838 |             categories: {
 839 |               type: "array",
 840 |               items: {
 841 |                 type: "string",
 842 |                 enum: ["credentials", "database", "nodes", "filesystem", "instance"]
 843 |               }
 844 |             }
 845 |           },
 846 |           required: ["clientId"]
 847 |         }
 848 |       }
 849 |     ]
 850 |   };
 851 | });
 852 | 
 853 | // Tool execution handler
 854 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
 855 |   const { name, arguments: args } = request.params;
 856 | 
 857 |   switch (name) {
 858 |     case "init-n8n": {
 859 |       const { url, apiKey } = args as { url: string; apiKey: string };
 860 |       try {
 861 |         const client = new N8nClient(url, apiKey);
 862 |         
 863 |         // Test connection by listing workflows
 864 |         await client.listWorkflows();
 865 |         
 866 |         // Generate a unique client ID
 867 |         const clientId = Buffer.from(url).toString('base64');
 868 |         clients.set(clientId, client);
 869 | 
 870 |         return {
 871 |           content: [{
 872 |             type: "text",
 873 |             text: `Successfully connected to n8n at ${url}. Use this client ID for future operations: ${clientId}`,
 874 |           }]
 875 |         };
 876 |       } catch (error) {
 877 |         return {
 878 |           content: [{
 879 |             type: "text",
 880 |             text: error instanceof Error ? error.message : "Unknown error occurred",
 881 |           }],
 882 |           isError: true
 883 |         };
 884 |       }
 885 |     }
 886 | 
 887 |     case "list-workflows": {
 888 |       const { clientId } = args as { clientId: string };
 889 |       const client = clients.get(clientId);
 890 |       if (!client) {
 891 |         return {
 892 |           content: [{
 893 |             type: "text",
 894 |             text: "Client not initialized. Please run init-n8n first.",
 895 |           }],
 896 |           isError: true
 897 |         };
 898 |       }
 899 | 
 900 |       try {
 901 |         const workflows = await client.listWorkflows();
 902 |         const formattedWorkflows = workflows.data.map(wf => ({
 903 |           id: wf.id,
 904 |           name: wf.name,
 905 |           active: wf.active,
 906 |           created: wf.createdAt,
 907 |           updated: wf.updatedAt,
 908 |           tags: wf.tags,
 909 |         }));
 910 | 
 911 |         return {
 912 |           content: [{
 913 |             type: "text",
 914 |             text: JSON.stringify(formattedWorkflows, null, 2),
 915 |           }]
 916 |         };
 917 |       } catch (error) {
 918 |         return {
 919 |           content: [{
 920 |             type: "text",
 921 |             text: error instanceof Error ? error.message : "Unknown error occurred",
 922 |           }],
 923 |           isError: true
 924 |         };
 925 |       }
 926 |     }
 927 | 
 928 |     case "get-workflow": {
 929 |       const { clientId, id } = args as { clientId: string; id: string };
 930 |       const client = clients.get(clientId);
 931 |       if (!client) {
 932 |         return {
 933 |           content: [{
 934 |             type: "text",
 935 |             text: "Client not initialized. Please run init-n8n first.",
 936 |           }],
 937 |           isError: true
 938 |         };
 939 |       }
 940 | 
 941 |       try {
 942 |         const workflow = await client.getWorkflow(id);
 943 |         return {
 944 |           content: [{
 945 |             type: "text",
 946 |             text: JSON.stringify(workflow, null, 2),
 947 |           }]
 948 |         };
 949 |       } catch (error) {
 950 |         return {
 951 |           content: [{
 952 |             type: "text",
 953 |             text: error instanceof Error ? error.message : "Unknown error occurred",
 954 |           }],
 955 |           isError: true
 956 |         };
 957 |       }
 958 |     }
 959 | 
 960 |     case "update-workflow": {
 961 |       const { clientId, id, workflow } = args as {
 962 |         clientId: string;
 963 |         id: string;
 964 |         workflow: Partial<N8nWorkflow>;
 965 |       };
 966 | 
 967 |       const client = clients.get(clientId);
 968 |       if (!client) {
 969 |         return {
 970 |           content: [{
 971 |             type: "text",
 972 |             text: "Client not initialized. Please run init-n8n first.",
 973 |           }],
 974 |           isError: true
 975 |         };
 976 |       }
 977 | 
 978 |       try {
 979 |         const updatedWorkflow = await client.updateWorkflow(id, workflow);
 980 |         return {
 981 |           content: [{
 982 |             type: "text",
 983 |             text: `Successfully updated workflow:\n${JSON.stringify(updatedWorkflow, null, 2)}`,
 984 |           }]
 985 |         };
 986 |       } catch (error) {
 987 |         return {
 988 |           content: [{
 989 |             type: "text",
 990 |             text: error instanceof Error ? error.message : "Unknown error occurred",
 991 |           }],
 992 |           isError: true
 993 |         };
 994 |       }
 995 |     }
 996 | 
 997 |     case "create-workflow": {
 998 |       const { clientId, name, nodes = [], connections = {} } = args as {
 999 |         clientId: string;
1000 |         name: string;
1001 |         nodes?: any[];
1002 |         connections?: Record<string, any>;
1003 |       };
1004 | 
1005 |       const client = clients.get(clientId);
1006 |       if (!client) {
1007 |         return {
1008 |           content: [{
1009 |             type: "text",
1010 |             text: "Client not initialized. Please run init-n8n first.",
1011 |           }],
1012 |           isError: true
1013 |         };
1014 |       }
1015 | 
1016 |       try {
1017 |         const workflow = await client.createWorkflow(name, nodes, connections);
1018 |         return {
1019 |           content: [{
1020 |             type: "text",
1021 |             text: `Successfully created workflow:\n${JSON.stringify(workflow, null, 2)}`,
1022 |           }]
1023 |         };
1024 |       } catch (error) {
1025 |         return {
1026 |           content: [{
1027 |             type: "text",
1028 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1029 |           }],
1030 |           isError: true
1031 |         };
1032 |       }
1033 |     }
1034 | 
1035 |     case "delete-workflow": {
1036 |       const { clientId, id } = args as { clientId: string; id: string };
1037 |       const client = clients.get(clientId);
1038 |       if (!client) {
1039 |         return {
1040 |           content: [{
1041 |             type: "text",
1042 |             text: "Client not initialized. Please run init-n8n first.",
1043 |           }],
1044 |           isError: true
1045 |         };
1046 |       }
1047 | 
1048 |       try {
1049 |         const workflow = await client.deleteWorkflow(id);
1050 |         return {
1051 |           content: [{
1052 |             type: "text",
1053 |             text: `Successfully deleted workflow:\n${JSON.stringify(workflow, null, 2)}`,
1054 |           }]
1055 |         };
1056 |       } catch (error) {
1057 |         return {
1058 |           content: [{
1059 |             type: "text",
1060 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1061 |           }],
1062 |           isError: true
1063 |         };
1064 |       }
1065 |     }
1066 | 
1067 |     case "activate-workflow": {
1068 |       const { clientId, id } = args as { clientId: string; id: string };
1069 |       const client = clients.get(clientId);
1070 |       if (!client) {
1071 |         return {
1072 |           content: [{
1073 |             type: "text",
1074 |             text: "Client not initialized. Please run init-n8n first.",
1075 |           }],
1076 |           isError: true
1077 |         };
1078 |       }
1079 | 
1080 |       try {
1081 |         const workflow = await client.activateWorkflow(id);
1082 |         return {
1083 |           content: [{
1084 |             type: "text",
1085 |             text: `Successfully activated workflow:\n${JSON.stringify(workflow, null, 2)}`,
1086 |           }]
1087 |         };
1088 |       } catch (error) {
1089 |         return {
1090 |           content: [{
1091 |             type: "text",
1092 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1093 |           }],
1094 |           isError: true
1095 |         };
1096 |       }
1097 |     }
1098 | 
1099 |     case "deactivate-workflow": {
1100 |       const { clientId, id } = args as { clientId: string; id: string };
1101 |       const client = clients.get(clientId);
1102 |       if (!client) {
1103 |         return {
1104 |           content: [{
1105 |             type: "text",
1106 |             text: "Client not initialized. Please run init-n8n first.",
1107 |           }],
1108 |           isError: true
1109 |         };
1110 |       }
1111 | 
1112 |       try {
1113 |         const workflow = await client.deactivateWorkflow(id);
1114 |         return {
1115 |           content: [{
1116 |             type: "text",
1117 |             text: `Successfully deactivated workflow:\n${JSON.stringify(workflow, null, 2)}`,
1118 |           }]
1119 |         };
1120 |       } catch (error) {
1121 |         return {
1122 |           content: [{
1123 |             type: "text",
1124 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1125 |           }],
1126 |           isError: true
1127 |         };
1128 |       }
1129 |     }
1130 | 
1131 |     case "list-projects": {
1132 |       const { clientId } = args as { clientId: string };
1133 |       const client = clients.get(clientId);
1134 |       if (!client) {
1135 |         return {
1136 |           content: [{
1137 |             type: "text",
1138 |             text: "Client not initialized. Please run init-n8n first.",
1139 |           }],
1140 |           isError: true
1141 |         };
1142 |       }
1143 | 
1144 |       try {
1145 |         const projects = await client.listProjects();
1146 |         return {
1147 |           content: [{
1148 |             type: "text",
1149 |             text: JSON.stringify(projects.data, null, 2),
1150 |           }]
1151 |         };
1152 |       } catch (error) {
1153 |         return {
1154 |           content: [{
1155 |             type: "text",
1156 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1157 |           }],
1158 |           isError: true
1159 |         };
1160 |       }
1161 |     }
1162 | 
1163 |     case "create-project": {
1164 |       const { clientId, name } = args as { clientId: string; name: string };
1165 |       const client = clients.get(clientId);
1166 |       if (!client) {
1167 |         return {
1168 |           content: [{
1169 |             type: "text",
1170 |             text: "Client not initialized. Please run init-n8n first.",
1171 |           }],
1172 |           isError: true
1173 |         };
1174 |       }
1175 | 
1176 |       try {
1177 |         await client.createProject(name);
1178 |         return {
1179 |           content: [{
1180 |             type: "text",
1181 |             text: `Successfully created project: ${name}`,
1182 |           }]
1183 |         };
1184 |       } catch (error) {
1185 |         return {
1186 |           content: [{
1187 |             type: "text",
1188 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1189 |           }],
1190 |           isError: true
1191 |         };
1192 |       }
1193 |     }
1194 | 
1195 |     case "delete-project": {
1196 |       const { clientId, projectId } = args as { clientId: string; projectId: string };
1197 |       const client = clients.get(clientId);
1198 |       if (!client) {
1199 |         return {
1200 |           content: [{
1201 |             type: "text",
1202 |             text: "Client not initialized. Please run init-n8n first.",
1203 |           }],
1204 |           isError: true
1205 |         };
1206 |       }
1207 | 
1208 |       try {
1209 |         await client.deleteProject(projectId);
1210 |         return {
1211 |           content: [{
1212 |             type: "text",
1213 |             text: `Successfully deleted project with ID: ${projectId}`,
1214 |           }]
1215 |         };
1216 |       } catch (error) {
1217 |         return {
1218 |           content: [{
1219 |             type: "text",
1220 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1221 |           }],
1222 |           isError: true
1223 |         };
1224 |       }
1225 |     }
1226 | 
1227 |     case "update-project": {
1228 |       const { clientId, projectId, name } = args as { clientId: string; projectId: string; name: string };
1229 |       const client = clients.get(clientId);
1230 |       if (!client) {
1231 |         return {
1232 |           content: [{
1233 |             type: "text",
1234 |             text: "Client not initialized. Please run init-n8n first.",
1235 |           }],
1236 |           isError: true
1237 |         };
1238 |       }
1239 | 
1240 |       try {
1241 |         await client.updateProject(projectId, name);
1242 |         return {
1243 |           content: [{
1244 |             type: "text",
1245 |             text: `Successfully updated project ${projectId} with new name: ${name}`,
1246 |           }]
1247 |         };
1248 |       } catch (error) {
1249 |         return {
1250 |           content: [{
1251 |             type: "text",
1252 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1253 |           }],
1254 |           isError: true
1255 |         };
1256 |       }
1257 |     }
1258 | 
1259 |     case "list-users": {
1260 |       const { clientId } = args as { clientId: string };
1261 |       const client = clients.get(clientId);
1262 |       if (!client) {
1263 |         return {
1264 |           content: [{
1265 |             type: "text",
1266 |             text: "Client not initialized. Please run init-n8n first.",
1267 |           }],
1268 |           isError: true
1269 |         };
1270 |       }
1271 | 
1272 |       try {
1273 |         const users = await client.listUsers();
1274 |         return {
1275 |           content: [{
1276 |             type: "text",
1277 |             text: JSON.stringify(users.data, null, 2),
1278 |           }]
1279 |         };
1280 |       } catch (error) {
1281 |         return {
1282 |           content: [{
1283 |             type: "text",
1284 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1285 |           }],
1286 |           isError: true
1287 |         };
1288 |       }
1289 |     }
1290 | 
1291 |     case "create-users": {
1292 |       const { clientId, users } = args as { 
1293 |         clientId: string; 
1294 |         users: Array<{ 
1295 |           email: string; 
1296 |           role?: 'global:admin' | 'global:member'
1297 |         }> 
1298 |       };
1299 |       const client = clients.get(clientId);
1300 |       if (!client) {
1301 |         return {
1302 |           content: [{
1303 |             type: "text",
1304 |             text: "Client not initialized. Please run init-n8n first.",
1305 |           }],
1306 |           isError: true
1307 |         };
1308 |       }
1309 | 
1310 |       try {
1311 |         const result = await client.createUsers(users);
1312 |         return {
1313 |           content: [{
1314 |             type: "text",
1315 |             text: JSON.stringify(result, null, 2),
1316 |           }]
1317 |         };
1318 |       } catch (error) {
1319 |         return {
1320 |           content: [{
1321 |             type: "text",
1322 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1323 |           }],
1324 |           isError: true
1325 |         };
1326 |       }
1327 |     }
1328 | 
1329 |     case "get-user": {
1330 |       const { clientId, idOrEmail } = args as { clientId: string; idOrEmail: string };
1331 |       const client = clients.get(clientId);
1332 |       if (!client) {
1333 |         return {
1334 |           content: [{
1335 |             type: "text",
1336 |             text: "Client not initialized. Please run init-n8n first.",
1337 |           }],
1338 |           isError: true
1339 |         };
1340 |       }
1341 | 
1342 |       try {
1343 |         const user = await client.getUser(idOrEmail);
1344 |         return {
1345 |           content: [{
1346 |             type: "text",
1347 |             text: JSON.stringify(user, null, 2),
1348 |           }]
1349 |         };
1350 |       } catch (error) {
1351 |         return {
1352 |           content: [{
1353 |             type: "text",
1354 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1355 |           }],
1356 |           isError: true
1357 |         };
1358 |       }
1359 |     }
1360 | 
1361 |     case "delete-user": {
1362 |       const { clientId, idOrEmail } = args as { clientId: string; idOrEmail: string };
1363 |       const client = clients.get(clientId);
1364 |       if (!client) {
1365 |         return {
1366 |           content: [{
1367 |             type: "text",
1368 |             text: "Client not initialized. Please run init-n8n first.",
1369 |           }],
1370 |           isError: true
1371 |         };
1372 |       }
1373 | 
1374 |       try {
1375 |         await client.deleteUser(idOrEmail);
1376 |         return {
1377 |           content: [{
1378 |             type: "text",
1379 |             text: `Successfully deleted user: ${idOrEmail}`,
1380 |           }]
1381 |         };
1382 |       } catch (error) {
1383 |         return {
1384 |           content: [{
1385 |             type: "text",
1386 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1387 |           }],
1388 |           isError: true
1389 |         };
1390 |       }
1391 |     }
1392 | 
1393 |     case "list-variables": {
1394 |       const { clientId } = args as { clientId: string };
1395 |       const client = clients.get(clientId);
1396 |       if (!client) {
1397 |         return {
1398 |           content: [{
1399 |             type: "text",
1400 |             text: "Client not initialized. Please run init-n8n first.",
1401 |           }],
1402 |           isError: true
1403 |         };
1404 |       }
1405 | 
1406 |       try {
1407 |         const variables = await client.listVariables();
1408 |         return {
1409 |           content: [{
1410 |             type: "text",
1411 |             text: JSON.stringify(variables.data, null, 2),
1412 |           }]
1413 |         };
1414 |       } catch (error) {
1415 |         return {
1416 |           content: [{
1417 |             type: "text",
1418 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1419 |           }],
1420 |           isError: true
1421 |         };
1422 |       }
1423 |     }
1424 | 
1425 |     case "create-variable": {
1426 |       const { clientId, key, value } = args as { clientId: string; key: string; value: string };
1427 |       const client = clients.get(clientId);
1428 |       if (!client) {
1429 |         return {
1430 |           content: [{
1431 |             type: "text",
1432 |             text: "Client not initialized. Please run init-n8n first.",
1433 |           }],
1434 |           isError: true
1435 |         };
1436 |       }
1437 | 
1438 |       try {
1439 |         await client.createVariable(key, value);
1440 |         return {
1441 |           content: [{
1442 |             type: "text",
1443 |             text: `Successfully created variable with key: ${key}`,
1444 |           }]
1445 |         };
1446 |       } catch (error) {
1447 |         return {
1448 |           content: [{
1449 |             type: "text",
1450 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1451 |           }],
1452 |           isError: true
1453 |         };
1454 |       }
1455 |     }
1456 | 
1457 |     case "delete-variable": {
1458 |       const { clientId, id } = args as { clientId: string; id: string };
1459 |       const client = clients.get(clientId);
1460 |       if (!client) {
1461 |         return {
1462 |           content: [{
1463 |             type: "text",
1464 |             text: "Client not initialized. Please run init-n8n first.",
1465 |           }],
1466 |           isError: true
1467 |         };
1468 |       }
1469 | 
1470 |       try {
1471 |         await client.deleteVariable(id);
1472 |         return {
1473 |           content: [{
1474 |             type: "text",
1475 |             text: `Successfully deleted variable with ID: ${id}`,
1476 |           }]
1477 |         };
1478 |       } catch (error) {
1479 |         return {
1480 |           content: [{
1481 |             type: "text",
1482 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1483 |           }],
1484 |           isError: true
1485 |         };
1486 |       }
1487 |     }
1488 | 
1489 |     case "create-credential": {
1490 |       const { clientId, name, type, data } = args as {
1491 |         clientId: string;
1492 |         name: string;
1493 |         type: string;
1494 |         data: Record<string, any>;
1495 |       };
1496 |       const client = clients.get(clientId);
1497 |       if (!client) {
1498 |         return {
1499 |           content: [{
1500 |             type: "text",
1501 |             text: "Client not initialized. Please run init-n8n first.",
1502 |           }],
1503 |           isError: true
1504 |         };
1505 |       }
1506 | 
1507 |       try {
1508 |         const credential = await client.createCredential(name, type, data);
1509 |         return {
1510 |           content: [{
1511 |             type: "text",
1512 |             text: `Successfully created credential:\n${JSON.stringify(credential, null, 2)}`,
1513 |           }]
1514 |         };
1515 |       } catch (error) {
1516 |         return {
1517 |           content: [{
1518 |             type: "text",
1519 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1520 |           }],
1521 |           isError: true
1522 |         };
1523 |       }
1524 |     }
1525 | 
1526 |     case "delete-credential": {
1527 |       const { clientId, id } = args as { clientId: string; id: string };
1528 |       const client = clients.get(clientId);
1529 |       if (!client) {
1530 |         return {
1531 |           content: [{
1532 |             type: "text",
1533 |             text: "Client not initialized. Please run init-n8n first.",
1534 |           }],
1535 |           isError: true
1536 |         };
1537 |       }
1538 | 
1539 |       try {
1540 |         const result = await client.deleteCredential(id);
1541 |         return {
1542 |           content: [{
1543 |             type: "text",
1544 |             text: `Successfully deleted credential:\n${JSON.stringify(result, null, 2)}`,
1545 |           }]
1546 |         };
1547 |       } catch (error) {
1548 |         return {
1549 |           content: [{
1550 |             type: "text",
1551 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1552 |           }],
1553 |           isError: true
1554 |         };
1555 |       }
1556 |     }
1557 | 
1558 |     case "get-credential-schema": {
1559 |       const { clientId, credentialTypeName } = args as { clientId: string; credentialTypeName: string };
1560 |       const client = clients.get(clientId);
1561 |       if (!client) {
1562 |         return {
1563 |           content: [{
1564 |             type: "text",
1565 |             text: "Client not initialized. Please run init-n8n first.",
1566 |           }],
1567 |           isError: true
1568 |         };
1569 |       }
1570 | 
1571 |       try {
1572 |         const schema = await client.getCredentialSchema(credentialTypeName);
1573 |         return {
1574 |           content: [{
1575 |             type: "text",
1576 |             text: JSON.stringify(schema, null, 2),
1577 |           }]
1578 |         };
1579 |       } catch (error) {
1580 |         return {
1581 |           content: [{
1582 |             type: "text",
1583 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1584 |           }],
1585 |           isError: true
1586 |         };
1587 |       }
1588 |     }
1589 | 
1590 |     // Execution Management Handlers
1591 |     case "list-executions": {
1592 |       const { clientId, includeData, status, workflowId, limit } = args as {
1593 |         clientId: string;
1594 |         includeData?: boolean;
1595 |         status?: 'error' | 'success' | 'waiting';
1596 |         workflowId?: string;
1597 |         limit?: number;
1598 |       };
1599 |       const client = clients.get(clientId);
1600 |       if (!client) {
1601 |         return {
1602 |           content: [{
1603 |             type: "text",
1604 |             text: "Client not initialized. Please run init-n8n first.",
1605 |           }],
1606 |           isError: true
1607 |         };
1608 |       }
1609 | 
1610 |       try {
1611 |         const executions = await client.getExecutions({ includeData, status, workflowId, limit });
1612 |         return {
1613 |           content: [{
1614 |             type: "text",
1615 |             text: JSON.stringify(executions.data, null, 2),
1616 |           }]
1617 |         };
1618 |       } catch (error) {
1619 |         return {
1620 |           content: [{
1621 |             type: "text",
1622 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1623 |           }],
1624 |           isError: true
1625 |         };
1626 |       }
1627 |     }
1628 | 
1629 |     case "get-execution": {
1630 |       const { clientId, id, includeData } = args as { clientId: string; id: number; includeData?: boolean };
1631 |       const client = clients.get(clientId);
1632 |       if (!client) {
1633 |         return {
1634 |           content: [{
1635 |             type: "text",
1636 |             text: "Client not initialized. Please run init-n8n first.",
1637 |           }],
1638 |           isError: true
1639 |         };
1640 |       }
1641 | 
1642 |       try {
1643 |         const execution = await client.getExecution(id, includeData);
1644 |         return {
1645 |           content: [{
1646 |             type: "text",
1647 |             text: JSON.stringify(execution, null, 2),
1648 |           }]
1649 |         };
1650 |       } catch (error) {
1651 |         return {
1652 |           content: [{
1653 |             type: "text",
1654 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1655 |           }],
1656 |           isError: true
1657 |         };
1658 |       }
1659 |     }
1660 | 
1661 |     case "delete-execution": {
1662 |       const { clientId, id } = args as { clientId: string; id: number };
1663 |       const client = clients.get(clientId);
1664 |       if (!client) {
1665 |         return {
1666 |           content: [{
1667 |             type: "text",
1668 |             text: "Client not initialized. Please run init-n8n first.",
1669 |           }],
1670 |           isError: true
1671 |         };
1672 |       }
1673 | 
1674 |       try {
1675 |         const execution = await client.deleteExecution(id);
1676 |         return {
1677 |           content: [{
1678 |             type: "text",
1679 |             text: `Successfully deleted execution:\n${JSON.stringify(execution, null, 2)}`,
1680 |           }]
1681 |         };
1682 |       } catch (error) {
1683 |         return {
1684 |           content: [{
1685 |             type: "text",
1686 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1687 |           }],
1688 |           isError: true
1689 |         };
1690 |       }
1691 |     }
1692 | 
1693 |     // Tag Management Handlers
1694 |     case "create-tag": {
1695 |       const { clientId, name } = args as { clientId: string; name: string };
1696 |       const client = clients.get(clientId);
1697 |       if (!client) {
1698 |         return {
1699 |           content: [{
1700 |             type: "text",
1701 |             text: "Client not initialized. Please run init-n8n first.",
1702 |           }],
1703 |           isError: true
1704 |         };
1705 |       }
1706 | 
1707 |       try {
1708 |         const tag = await client.createTag(name);
1709 |         return {
1710 |           content: [{
1711 |             type: "text",
1712 |             text: `Successfully created tag:\n${JSON.stringify(tag, null, 2)}`,
1713 |           }]
1714 |         };
1715 |       } catch (error) {
1716 |         return {
1717 |           content: [{
1718 |             type: "text",
1719 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1720 |           }],
1721 |           isError: true
1722 |         };
1723 |       }
1724 |     }
1725 | 
1726 |     case "list-tags": {
1727 |       const { clientId, limit } = args as { clientId: string; limit?: number };
1728 |       const client = clients.get(clientId);
1729 |       if (!client) {
1730 |         return {
1731 |           content: [{
1732 |             type: "text",
1733 |             text: "Client not initialized. Please run init-n8n first.",
1734 |           }],
1735 |           isError: true
1736 |         };
1737 |       }
1738 | 
1739 |       try {
1740 |         const tags = await client.getTags({ limit });
1741 |         return {
1742 |           content: [{
1743 |             type: "text",
1744 |             text: JSON.stringify(tags.data, null, 2),
1745 |           }]
1746 |         };
1747 |       } catch (error) {
1748 |         return {
1749 |           content: [{
1750 |             type: "text",
1751 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1752 |           }],
1753 |           isError: true
1754 |         };
1755 |       }
1756 |     }
1757 | 
1758 |     case "get-tag": {
1759 |       const { clientId, id } = args as { clientId: string; id: string };
1760 |       const client = clients.get(clientId);
1761 |       if (!client) {
1762 |         return {
1763 |           content: [{
1764 |             type: "text",
1765 |             text: "Client not initialized. Please run init-n8n first.",
1766 |           }],
1767 |           isError: true
1768 |         };
1769 |       }
1770 | 
1771 |       try {
1772 |         const tag = await client.getTag(id);
1773 |         return {
1774 |           content: [{
1775 |             type: "text",
1776 |             text: JSON.stringify(tag, null, 2),
1777 |           }]
1778 |         };
1779 |       } catch (error) {
1780 |         return {
1781 |           content: [{
1782 |             type: "text",
1783 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1784 |           }],
1785 |           isError: true
1786 |         };
1787 |       }
1788 |     }
1789 | 
1790 |     case "update-tag": {
1791 |       const { clientId, id, name } = args as { clientId: string; id: string; name: string };
1792 |       const client = clients.get(clientId);
1793 |       if (!client) {
1794 |         return {
1795 |           content: [{
1796 |             type: "text",
1797 |             text: "Client not initialized. Please run init-n8n first.",
1798 |           }],
1799 |           isError: true
1800 |         };
1801 |       }
1802 | 
1803 |       try {
1804 |         const tag = await client.updateTag(id, name);
1805 |         return {
1806 |           content: [{
1807 |             type: "text",
1808 |             text: `Successfully updated tag:\n${JSON.stringify(tag, null, 2)}`,
1809 |           }]
1810 |         };
1811 |       } catch (error) {
1812 |         return {
1813 |           content: [{
1814 |             type: "text",
1815 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1816 |           }],
1817 |           isError: true
1818 |         };
1819 |       }
1820 |     }
1821 | 
1822 |     case "delete-tag": {
1823 |       const { clientId, id } = args as { clientId: string; id: string };
1824 |       const client = clients.get(clientId);
1825 |       if (!client) {
1826 |         return {
1827 |           content: [{
1828 |             type: "text",
1829 |             text: "Client not initialized. Please run init-n8n first.",
1830 |           }],
1831 |           isError: true
1832 |         };
1833 |       }
1834 | 
1835 |       try {
1836 |         const tag = await client.deleteTag(id);
1837 |         return {
1838 |           content: [{
1839 |             type: "text",
1840 |             text: `Successfully deleted tag:\n${JSON.stringify(tag, null, 2)}`,
1841 |           }]
1842 |         };
1843 |       } catch (error) {
1844 |         return {
1845 |           content: [{
1846 |             type: "text",
1847 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1848 |           }],
1849 |           isError: true
1850 |         };
1851 |       }
1852 |     }
1853 | 
1854 |     case "get-workflow-tags": {
1855 |       const { clientId, workflowId } = args as { clientId: string; workflowId: string };
1856 |       const client = clients.get(clientId);
1857 |       if (!client) {
1858 |         return {
1859 |           content: [{
1860 |             type: "text",
1861 |             text: "Client not initialized. Please run init-n8n first.",
1862 |           }],
1863 |           isError: true
1864 |         };
1865 |       }
1866 | 
1867 |       try {
1868 |         const tags = await client.getWorkflowTags(workflowId);
1869 |         return {
1870 |           content: [{
1871 |             type: "text",
1872 |             text: JSON.stringify(tags, null, 2),
1873 |           }]
1874 |         };
1875 |       } catch (error) {
1876 |         return {
1877 |           content: [{
1878 |             type: "text",
1879 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1880 |           }],
1881 |           isError: true
1882 |         };
1883 |       }
1884 |     }
1885 | 
1886 |     case "update-workflow-tags": {
1887 |       const { clientId, workflowId, tagIds } = args as {
1888 |         clientId: string;
1889 |         workflowId: string;
1890 |         tagIds: { id: string }[];
1891 |       };
1892 |       const client = clients.get(clientId);
1893 |       if (!client) {
1894 |         return {
1895 |           content: [{
1896 |             type: "text",
1897 |             text: "Client not initialized. Please run init-n8n first.",
1898 |           }],
1899 |           isError: true
1900 |         };
1901 |       }
1902 | 
1903 |       try {
1904 |         const tags = await client.updateWorkflowTags(workflowId, tagIds);
1905 |         return {
1906 |           content: [{
1907 |             type: "text",
1908 |             text: `Successfully updated workflow tags:\n${JSON.stringify(tags, null, 2)}`,
1909 |           }]
1910 |         };
1911 |       } catch (error) {
1912 |         return {
1913 |           content: [{
1914 |             type: "text",
1915 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1916 |           }],
1917 |           isError: true
1918 |         };
1919 |       }
1920 |     }
1921 | 
1922 |     case "generate-audit": {
1923 |       const { clientId, daysAbandonedWorkflow, categories } = args as {
1924 |         clientId: string;
1925 |         daysAbandonedWorkflow?: number;
1926 |         categories?: Array<'credentials' | 'database' | 'nodes' | 'filesystem' | 'instance'>;
1927 |       };
1928 |       const client = clients.get(clientId);
1929 |       if (!client) {
1930 |         return {
1931 |           content: [{
1932 |             type: "text",
1933 |             text: "Client not initialized. Please run init-n8n first.",
1934 |           }],
1935 |           isError: true
1936 |         };
1937 |       }
1938 | 
1939 |       try {
1940 |         const audit = await client.generateAudit({ daysAbandonedWorkflow, categories });
1941 |         return {
1942 |           content: [{
1943 |             type: "text",
1944 |             text: JSON.stringify(audit, null, 2),
1945 |           }]
1946 |         };
1947 |       } catch (error) {
1948 |         return {
1949 |           content: [{
1950 |             type: "text",
1951 |             text: error instanceof Error ? error.message : "Unknown error occurred",
1952 |           }],
1953 |           isError: true
1954 |         };
1955 |       }
1956 |     }
1957 | 
1958 |     default:
1959 |       return {
1960 |         content: [{
1961 |           type: "text",
1962 |           text: `Unknown tool: ${name}`,
1963 |         }],
1964 |         isError: true
1965 |       };
1966 |   }
1967 | });
1968 | 
1969 | // Start the server
1970 | const transport = new StdioServerTransport();
1971 | await server.connect(transport);
1972 | console.error("N8N MCP Server running on stdio");
1973 | 
```
Page 1/2FirstPrevNextLast