Initial commit: n8n MCP server for VS Code integration
- Implemented MCP server with 8 n8n tools - Added n8n API client for workflow operations - Configured VS Code settings with API authentication - Added comprehensive documentation and setup guides - Tested and verified connection to n8n instance
This commit is contained in:
8
.env.example
Normal file
8
.env.example
Normal file
@@ -0,0 +1,8 @@
|
||||
# Example .env file for n8n MCP server
|
||||
# Copy this to .env and fill in your values
|
||||
|
||||
# n8n instance URL (default: http://srvdocker02:8098)
|
||||
N8N_BASE_URL=http://srvdocker02:8098
|
||||
|
||||
# n8n API key (optional, required for authenticated instances)
|
||||
# N8N_API_KEY=your-api-key-here
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
node_modules/
|
||||
dist/
|
||||
*.log
|
||||
.env
|
||||
.DS_Store
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
14
.vscode/settings.json
vendored
Normal file
14
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/n8n_vscode_integration/dist/index.js"
|
||||
],
|
||||
"env": {
|
||||
"N8N_BASE_URL": "http://srvdocker02:8098",
|
||||
"N8N_API_KEY": "n8n_api_42f1838c1e2de90cadcb669f78083de92697a85322c0b6009ad2e55760db992ab0bf61515a3cf0e1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
157
GETTING_STARTED.md
Normal file
157
GETTING_STARTED.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# 🎉 n8n VS Code Integration - Ready to Use!
|
||||
|
||||
Your n8n MCP (Model Context Protocol) server has been successfully set up and configured!
|
||||
|
||||
## ✅ What's Been Installed
|
||||
|
||||
1. **MCP Server** - TypeScript-based server that connects VS Code to n8n
|
||||
2. **n8n API Client** - Handles all communication with your n8n instance
|
||||
3. **Configuration Files** - Pre-configured with your n8n instance and API key
|
||||
4. **Documentation** - Complete setup and usage guides
|
||||
|
||||
## 🔧 Current Configuration
|
||||
|
||||
- **n8n Instance**: `http://srvdocker02:8098`
|
||||
- **API Key**: Configured ✓
|
||||
- **Connection Status**: ✅ Successfully connected
|
||||
- **Workflows Found**: 1 workflow ("My workflow")
|
||||
|
||||
## 🚀 Next Steps
|
||||
|
||||
### 1. Restart VS Code
|
||||
For the MCP server to be available in GitHub Copilot Chat, you need to restart VS Code:
|
||||
- Close and reopen VS Code
|
||||
- Or use `Cmd/Ctrl + Shift + P` → "Developer: Reload Window"
|
||||
|
||||
### 2. Start Using It!
|
||||
|
||||
Open GitHub Copilot Chat and try these commands:
|
||||
|
||||
#### List Workflows
|
||||
```
|
||||
@workspace List all my n8n workflows
|
||||
```
|
||||
|
||||
#### Get Workflow Details
|
||||
```
|
||||
@workspace Show me the details of the workflow "My workflow"
|
||||
```
|
||||
|
||||
#### Execute a Workflow
|
||||
```
|
||||
@workspace Execute the workflow with ID Zk4gbBzjxVppHiCB
|
||||
```
|
||||
|
||||
#### View Executions
|
||||
```
|
||||
@workspace Show me recent executions
|
||||
```
|
||||
|
||||
#### Update a Workflow
|
||||
```
|
||||
@workspace Update workflow Zk4gbBzjxVppHiCB to deactivate it
|
||||
```
|
||||
|
||||
## 📋 Available Operations
|
||||
|
||||
The MCP server provides these tools to GitHub Copilot:
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| `list_workflows` | List all workflows in your n8n instance |
|
||||
| `get_workflow` | Get complete workflow details including nodes |
|
||||
| `update_workflow` | Modify workflow configuration |
|
||||
| `activate_workflow` | Activate a workflow |
|
||||
| `deactivate_workflow` | Deactivate a workflow |
|
||||
| `execute_workflow` | Manually trigger a workflow |
|
||||
| `get_execution` | Get details of a specific execution |
|
||||
| `list_executions` | View execution history |
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
Test the connection anytime with:
|
||||
```bash
|
||||
node test-connection.js
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
✓ Successfully connected to n8n!
|
||||
✓ Found 1 workflow(s)
|
||||
```
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
n8n_vscode_integration/
|
||||
├── src/
|
||||
│ ├── index.ts # Main MCP server
|
||||
│ └── n8n-client.ts # n8n API client
|
||||
├── dist/ # Compiled JavaScript
|
||||
├── .vscode/
|
||||
│ └── settings.json # VS Code MCP configuration
|
||||
├── .env # Environment variables (API key)
|
||||
├── package.json # Dependencies
|
||||
├── README.md # Full documentation
|
||||
├── SETUP.md # Setup guide
|
||||
└── test-connection.js # Connection test script
|
||||
```
|
||||
|
||||
## 🔒 Security Note
|
||||
|
||||
Your API key is stored in:
|
||||
- `.env` file (for local testing)
|
||||
- `.vscode/settings.json` (for MCP server)
|
||||
|
||||
Both files are in `.gitignore` to prevent accidental commits. Keep your API key secure!
|
||||
|
||||
## 🛠️ Development
|
||||
|
||||
If you want to modify the server:
|
||||
|
||||
```bash
|
||||
# Watch for changes and rebuild automatically
|
||||
npm run watch
|
||||
|
||||
# Or build manually
|
||||
npm run build
|
||||
|
||||
# After rebuilding, restart VS Code to reload the MCP server
|
||||
```
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
- **README.md** - Complete documentation and API reference
|
||||
- **SETUP.md** - Detailed setup instructions
|
||||
- **THIS FILE** - Quick start guide
|
||||
|
||||
## 💡 Example Use Cases
|
||||
|
||||
1. **Workflow Development**: Ask Copilot to help you understand and modify workflows
|
||||
2. **Automation**: Execute workflows directly from VS Code
|
||||
3. **Monitoring**: Check execution history and debug failures
|
||||
4. **Documentation**: Have Copilot explain what your workflows do
|
||||
5. **Batch Operations**: Use Copilot to perform operations on multiple workflows
|
||||
|
||||
## 🆘 Need Help?
|
||||
|
||||
If something doesn't work:
|
||||
|
||||
1. Check that VS Code has been restarted
|
||||
2. Verify the connection: `node test-connection.js`
|
||||
3. Check VS Code Output panel: View → Output → GitHub Copilot Chat
|
||||
4. Review SETUP.md for troubleshooting steps
|
||||
|
||||
## 🎯 What You Can Ask Copilot
|
||||
|
||||
- "List all my n8n workflows"
|
||||
- "Show me the most recent executions"
|
||||
- "Execute workflow X"
|
||||
- "What does workflow Y do?" (Copilot will fetch and analyze it)
|
||||
- "Activate all inactive workflows"
|
||||
- "Show me failed executions"
|
||||
- "Update workflow X to change [setting]"
|
||||
|
||||
---
|
||||
|
||||
**You're all set! Restart VS Code and start using n8n with GitHub Copilot Chat! 🚀**
|
||||
210
README.md
Normal file
210
README.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# n8n MCP Server for VS Code
|
||||
|
||||
A Model Context Protocol (MCP) server that integrates n8n workflow automation directly into VS Code through GitHub Copilot Chat.
|
||||
|
||||
## Features
|
||||
|
||||
- **List Workflows**: Browse all workflows in your n8n instance
|
||||
- **Get Workflow Details**: View complete workflow configuration, nodes, and connections
|
||||
- **Update Workflows**: Modify workflow settings, nodes, and connections
|
||||
- **Activate/Deactivate**: Control workflow activation state
|
||||
- **Execute Workflows**: Manually trigger workflow execution
|
||||
- **View Executions**: Check execution history and results
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js (v18 or higher)
|
||||
- VS Code with GitHub Copilot Chat extension
|
||||
- Access to an n8n instance (running at `http://srvdocker02:8098` by default)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Clone or navigate to this repository:
|
||||
```bash
|
||||
cd /home/rwiegand/Nextcloud/entwicklung/Werkzeuge/n8n_vscode_integration
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Build the project:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
4. Configure your n8n instance URL (if different from default):
|
||||
- Copy `.env.example` to `.env`
|
||||
- Update `N8N_BASE_URL` with your n8n instance URL
|
||||
- If your n8n instance requires authentication, add your API key:
|
||||
```
|
||||
N8N_API_KEY=your-api-key-here
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### For VS Code
|
||||
|
||||
The `.vscode/settings.json` file is already configured to use this MCP server. The configuration looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/n8n_vscode_integration/dist/index.js"
|
||||
],
|
||||
"env": {
|
||||
"N8N_BASE_URL": "http://srvdocker02:8098"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### For GitHub Copilot Chat (Global Configuration)
|
||||
|
||||
To use this MCP server across all VS Code workspaces, add it to your global VS Code settings:
|
||||
|
||||
1. Open VS Code Settings (JSON) with `Cmd/Ctrl + Shift + P` → "Preferences: Open User Settings (JSON)"
|
||||
2. Add the MCP server configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"github.copilot.chat.mcp.servers": {
|
||||
"n8n": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/n8n_vscode_integration/dist/index.js"
|
||||
],
|
||||
"env": {
|
||||
"N8N_BASE_URL": "http://srvdocker02:8098"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If your n8n instance requires an API key, add it to the env section:
|
||||
```json
|
||||
"env": {
|
||||
"N8N_BASE_URL": "http://srvdocker02:8098",
|
||||
"N8N_API_KEY": "your-api-key-here"
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
After installation and configuration, you can interact with your n8n instance through GitHub Copilot Chat in VS Code using natural language:
|
||||
|
||||
### Example Commands
|
||||
|
||||
**List all workflows:**
|
||||
```
|
||||
@workspace List all my n8n workflows
|
||||
```
|
||||
|
||||
**Get workflow details:**
|
||||
```
|
||||
@workspace Show me the details of workflow ID 123
|
||||
```
|
||||
|
||||
**Update a workflow:**
|
||||
```
|
||||
@workspace Update workflow 123 to change its name to "New Name"
|
||||
```
|
||||
|
||||
**Activate/Deactivate workflows:**
|
||||
```
|
||||
@workspace Activate workflow 123
|
||||
@workspace Deactivate workflow 456
|
||||
```
|
||||
|
||||
**Execute a workflow:**
|
||||
```
|
||||
@workspace Execute workflow 123
|
||||
```
|
||||
|
||||
**View execution history:**
|
||||
```
|
||||
@workspace Show me the recent executions for workflow 123
|
||||
@workspace Show me the last 10 executions
|
||||
```
|
||||
|
||||
**Get execution details:**
|
||||
```
|
||||
@workspace Show me details of execution abc-123
|
||||
```
|
||||
|
||||
## Available MCP Tools
|
||||
|
||||
The server exposes the following tools:
|
||||
|
||||
1. **list_workflows** - List all workflows
|
||||
2. **get_workflow** - Get detailed workflow information
|
||||
3. **update_workflow** - Update workflow configuration
|
||||
4. **activate_workflow** - Activate a workflow
|
||||
5. **deactivate_workflow** - Deactivate a workflow
|
||||
6. **execute_workflow** - Execute a workflow manually
|
||||
7. **get_execution** - Get execution details
|
||||
8. **list_executions** - List workflow executions
|
||||
|
||||
## Development
|
||||
|
||||
### Watch Mode
|
||||
```bash
|
||||
npm run watch
|
||||
```
|
||||
|
||||
### Build
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run Directly
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Server Not Connecting
|
||||
|
||||
1. Verify the build is up to date: `npm run build`
|
||||
2. Check that the path in settings.json is correct
|
||||
3. Restart VS Code after making configuration changes
|
||||
4. Check the Output panel in VS Code for error messages
|
||||
|
||||
### Authentication Issues
|
||||
|
||||
If your n8n instance requires authentication:
|
||||
1. Generate an API key in your n8n instance (Settings → API)
|
||||
2. Add the `N8N_API_KEY` environment variable to your configuration
|
||||
|
||||
### Network Issues
|
||||
|
||||
If you can't connect to your n8n instance:
|
||||
1. Verify the n8n instance is running: `curl http://srvdocker02:8098/healthz`
|
||||
2. Check firewall settings
|
||||
3. Verify the URL in your configuration is correct
|
||||
|
||||
## API Reference
|
||||
|
||||
### n8n API Endpoints Used
|
||||
|
||||
- `GET /api/v1/workflows` - List workflows
|
||||
- `GET /api/v1/workflows/:id` - Get workflow
|
||||
- `PATCH /api/v1/workflows/:id` - Update workflow
|
||||
- `POST /api/v1/workflows/:id/execute` - Execute workflow
|
||||
- `GET /api/v1/executions` - List executions
|
||||
- `GET /api/v1/executions/:id` - Get execution
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||
114
SETUP.md
Normal file
114
SETUP.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Quick Setup Guide
|
||||
|
||||
## Step 1: Get Your n8n API Key
|
||||
|
||||
1. Open your n8n instance at `http://srvdocker02:8098`
|
||||
2. Go to **Settings** → **API**
|
||||
3. Click **Create API Key**
|
||||
4. Copy the generated API key
|
||||
|
||||
## Step 2: Configure the API Key
|
||||
|
||||
### Option A: Create .env file (Recommended for local testing)
|
||||
|
||||
Create a `.env` file in this directory:
|
||||
|
||||
```bash
|
||||
N8N_BASE_URL=http://srvdocker02:8098
|
||||
N8N_API_KEY=your-api-key-here
|
||||
```
|
||||
|
||||
### Option B: Update VS Code Settings
|
||||
|
||||
Edit `.vscode/settings.json` and add your API key:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/n8n_vscode_integration/dist/index.js"
|
||||
],
|
||||
"env": {
|
||||
"N8N_BASE_URL": "http://srvdocker02:8098",
|
||||
"N8N_API_KEY": "your-api-key-here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option C: Global VS Code Settings
|
||||
|
||||
For use across all workspaces, add to your User Settings JSON:
|
||||
|
||||
1. Press `Cmd/Ctrl + Shift + P`
|
||||
2. Type "Preferences: Open User Settings (JSON)"
|
||||
3. Add:
|
||||
|
||||
```json
|
||||
{
|
||||
"github.copilot.chat.mcp.servers": {
|
||||
"n8n": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/n8n_vscode_integration/dist/index.js"
|
||||
],
|
||||
"env": {
|
||||
"N8N_BASE_URL": "http://srvdocker02:8098",
|
||||
"N8N_API_KEY": "your-api-key-here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Step 3: Test the Connection
|
||||
|
||||
Run the test script:
|
||||
|
||||
```bash
|
||||
N8N_API_KEY=your-api-key-here node test-connection.js
|
||||
```
|
||||
|
||||
You should see:
|
||||
```
|
||||
✓ Successfully connected to n8n!
|
||||
✓ Found X workflow(s)
|
||||
```
|
||||
|
||||
## Step 4: Restart VS Code
|
||||
|
||||
After updating the configuration, restart VS Code to load the MCP server.
|
||||
|
||||
## Step 5: Use in Copilot Chat
|
||||
|
||||
Open Copilot Chat and try:
|
||||
|
||||
```
|
||||
@workspace List all my n8n workflows
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "401 Unauthorized" Error
|
||||
- Your API key is missing or incorrect
|
||||
- Make sure you've added `N8N_API_KEY` to the environment variables
|
||||
- Generate a new API key in n8n if needed
|
||||
|
||||
### "Connection Refused" Error
|
||||
- Verify n8n is running: `curl http://srvdocker02:8098/healthz`
|
||||
- Check if the URL is correct
|
||||
- Verify network connectivity to the server
|
||||
|
||||
### MCP Server Not Found in Copilot
|
||||
- Make sure you've run `npm run build`
|
||||
- Verify the path in settings.json is correct
|
||||
- Restart VS Code
|
||||
- Check VS Code Output panel for errors (View → Output → GitHub Copilot Chat)
|
||||
|
||||
### Changes Not Taking Effect
|
||||
- Run `npm run build` after code changes
|
||||
- Restart VS Code to reload the MCP server
|
||||
- Check that your settings.json is valid JSON
|
||||
1135
package-lock.json
generated
Normal file
1135
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
34
package.json
Normal file
34
package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "n8n-mcp-server",
|
||||
"version": "1.0.0",
|
||||
"description": "Model Context Protocol server for n8n integration with VS Code",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
"n8n-mcp-server": "dist/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "tsc --watch",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "npm run build && npm run start"
|
||||
},
|
||||
"keywords": [
|
||||
"n8n",
|
||||
"mcp",
|
||||
"model-context-protocol",
|
||||
"vscode",
|
||||
"workflow"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.4",
|
||||
"axios": "^1.7.9",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.5",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
||||
294
src/index.ts
Normal file
294
src/index.ts
Normal file
@@ -0,0 +1,294 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
Tool,
|
||||
} from '@modelcontextprotocol/sdk/types.js';
|
||||
import { N8nClient } from './n8n-client.js';
|
||||
|
||||
// Get n8n configuration from environment variables
|
||||
const N8N_BASE_URL = process.env.N8N_BASE_URL || 'http://srvdocker02:8098';
|
||||
const N8N_API_KEY = process.env.N8N_API_KEY;
|
||||
|
||||
// Initialize n8n client
|
||||
const n8nClient = new N8nClient({
|
||||
baseUrl: N8N_BASE_URL,
|
||||
apiKey: N8N_API_KEY,
|
||||
});
|
||||
|
||||
// Define available tools
|
||||
const tools: Tool[] = [
|
||||
{
|
||||
name: 'list_workflows',
|
||||
description: 'List all n8n workflows in the instance',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_workflow',
|
||||
description: 'Get detailed information about a specific n8n workflow including nodes and connections',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflowId: {
|
||||
type: 'string',
|
||||
description: 'The ID of the workflow to retrieve',
|
||||
},
|
||||
},
|
||||
required: ['workflowId'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'update_workflow',
|
||||
description: 'Update an existing n8n workflow with new configuration, nodes, or connections',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflowId: {
|
||||
type: 'string',
|
||||
description: 'The ID of the workflow to update',
|
||||
},
|
||||
workflow: {
|
||||
type: 'object',
|
||||
description: 'The workflow data to update (partial update supported)',
|
||||
},
|
||||
},
|
||||
required: ['workflowId', 'workflow'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'activate_workflow',
|
||||
description: 'Activate a workflow to make it run automatically',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflowId: {
|
||||
type: 'string',
|
||||
description: 'The ID of the workflow to activate',
|
||||
},
|
||||
},
|
||||
required: ['workflowId'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'deactivate_workflow',
|
||||
description: 'Deactivate a workflow to stop it from running automatically',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflowId: {
|
||||
type: 'string',
|
||||
description: 'The ID of the workflow to deactivate',
|
||||
},
|
||||
},
|
||||
required: ['workflowId'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'execute_workflow',
|
||||
description: 'Execute a workflow manually',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflowId: {
|
||||
type: 'string',
|
||||
description: 'The ID of the workflow to execute',
|
||||
},
|
||||
},
|
||||
required: ['workflowId'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'get_execution',
|
||||
description: 'Get details about a specific workflow execution',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
executionId: {
|
||||
type: 'string',
|
||||
description: 'The ID of the execution to retrieve',
|
||||
},
|
||||
},
|
||||
required: ['executionId'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'list_executions',
|
||||
description: 'List recent workflow executions, optionally filtered by workflow ID',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
workflowId: {
|
||||
type: 'string',
|
||||
description: 'Optional: Filter executions by workflow ID',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of executions to return (default: 20)',
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// Create MCP server
|
||||
const server = new Server(
|
||||
{
|
||||
name: 'n8n-mcp-server',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Handle list tools request
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return { tools };
|
||||
});
|
||||
|
||||
// Handle tool call request
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
try {
|
||||
switch (name) {
|
||||
case 'list_workflows': {
|
||||
const workflows = await n8nClient.listWorkflows();
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: JSON.stringify(workflows, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'get_workflow': {
|
||||
const { workflowId } = args as { workflowId: string };
|
||||
const workflow = await n8nClient.getWorkflow(workflowId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: JSON.stringify(workflow, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'update_workflow': {
|
||||
const { workflowId, workflow } = args as { workflowId: string; workflow: any };
|
||||
const updatedWorkflow = await n8nClient.updateWorkflow(workflowId, workflow);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: JSON.stringify(updatedWorkflow, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'activate_workflow': {
|
||||
const { workflowId } = args as { workflowId: string };
|
||||
const workflow = await n8nClient.activateWorkflow(workflowId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Workflow ${workflowId} activated successfully.\n${JSON.stringify(workflow, null, 2)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'deactivate_workflow': {
|
||||
const { workflowId } = args as { workflowId: string };
|
||||
const workflow = await n8nClient.deactivateWorkflow(workflowId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Workflow ${workflowId} deactivated successfully.\n${JSON.stringify(workflow, null, 2)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'execute_workflow': {
|
||||
const { workflowId } = args as { workflowId: string };
|
||||
const execution = await n8nClient.executeWorkflow(workflowId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Workflow ${workflowId} executed successfully.\nExecution ID: ${execution.id}\n${JSON.stringify(execution, null, 2)}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'get_execution': {
|
||||
const { executionId } = args as { executionId: string };
|
||||
const execution = await n8nClient.getExecution(executionId);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: JSON.stringify(execution, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
case 'list_executions': {
|
||||
const { workflowId, limit } = args as { workflowId?: string; limit?: number };
|
||||
const executions = await n8nClient.listExecutions(workflowId, limit);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: JSON.stringify(executions, null, 2),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `Error: ${error.message}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Start server
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error('n8n MCP server running on stdio');
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
129
src/n8n-client.ts
Normal file
129
src/n8n-client.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import axios, { AxiosInstance } from 'axios';
|
||||
|
||||
export interface N8nWorkflow {
|
||||
id: string;
|
||||
name: string;
|
||||
active: boolean;
|
||||
nodes: any[];
|
||||
connections: any;
|
||||
settings: any;
|
||||
tags?: any[];
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface N8nExecution {
|
||||
id: string;
|
||||
finished: boolean;
|
||||
mode: string;
|
||||
retryOf?: string;
|
||||
retrySuccessId?: string;
|
||||
startedAt: string;
|
||||
stoppedAt?: string;
|
||||
workflowId: string;
|
||||
workflowData?: any;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export interface N8nConfig {
|
||||
baseUrl: string;
|
||||
apiKey?: string;
|
||||
}
|
||||
|
||||
export class N8nClient {
|
||||
private client: AxiosInstance;
|
||||
|
||||
constructor(config: N8nConfig) {
|
||||
this.client = axios.create({
|
||||
baseURL: config.baseUrl,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(config.apiKey && { 'X-N8N-API-KEY': config.apiKey }),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async listWorkflows(): Promise<N8nWorkflow[]> {
|
||||
try {
|
||||
const response = await this.client.get('/api/v1/workflows');
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to list workflows: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getWorkflow(workflowId: string): Promise<N8nWorkflow> {
|
||||
try {
|
||||
const response = await this.client.get(`/api/v1/workflows/${workflowId}`);
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to get workflow ${workflowId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async updateWorkflow(workflowId: string, workflow: Partial<N8nWorkflow>): Promise<N8nWorkflow> {
|
||||
try {
|
||||
const response = await this.client.patch(`/api/v1/workflows/${workflowId}`, workflow);
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to update workflow ${workflowId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async activateWorkflow(workflowId: string): Promise<N8nWorkflow> {
|
||||
try {
|
||||
const response = await this.client.patch(`/api/v1/workflows/${workflowId}`, { active: true });
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to activate workflow ${workflowId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async deactivateWorkflow(workflowId: string): Promise<N8nWorkflow> {
|
||||
try {
|
||||
const response = await this.client.patch(`/api/v1/workflows/${workflowId}`, { active: false });
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to deactivate workflow ${workflowId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async executeWorkflow(workflowId: string): Promise<N8nExecution> {
|
||||
try {
|
||||
const response = await this.client.post(`/api/v1/workflows/${workflowId}/execute`);
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to execute workflow ${workflowId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getExecution(executionId: string): Promise<N8nExecution> {
|
||||
try {
|
||||
const response = await this.client.get(`/api/v1/executions/${executionId}`);
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to get execution ${executionId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async listExecutions(workflowId?: string, limit: number = 20): Promise<N8nExecution[]> {
|
||||
try {
|
||||
const params: any = { limit };
|
||||
if (workflowId) {
|
||||
params.workflowId = workflowId;
|
||||
}
|
||||
const response = await this.client.get('/api/v1/executions', { params });
|
||||
return response.data.data || response.data;
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to list executions: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteExecution(executionId: string): Promise<void> {
|
||||
try {
|
||||
await this.client.delete(`/api/v1/executions/${executionId}`);
|
||||
} catch (error: any) {
|
||||
throw new Error(`Failed to delete execution ${executionId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
test-connection.js
Normal file
49
test-connection.js
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Test script to verify n8n MCP server connectivity
|
||||
* Usage: node test-connection.js
|
||||
*/
|
||||
|
||||
import { N8nClient } from './dist/n8n-client.js';
|
||||
|
||||
const N8N_BASE_URL = process.env.N8N_BASE_URL || 'http://srvdocker02:8098';
|
||||
const N8N_API_KEY = process.env.N8N_API_KEY;
|
||||
|
||||
console.log('Testing n8n connection...');
|
||||
console.log('n8n URL:', N8N_BASE_URL);
|
||||
console.log('API Key:', N8N_API_KEY ? '***configured***' : 'not set');
|
||||
console.log('');
|
||||
|
||||
const client = new N8nClient({
|
||||
baseUrl: N8N_BASE_URL,
|
||||
apiKey: N8N_API_KEY,
|
||||
});
|
||||
|
||||
async function test() {
|
||||
try {
|
||||
console.log('Fetching workflows...');
|
||||
const workflows = await client.listWorkflows();
|
||||
console.log(`✓ Successfully connected to n8n!`);
|
||||
console.log(`✓ Found ${workflows.length} workflow(s)`);
|
||||
|
||||
if (workflows.length > 0) {
|
||||
console.log('\nFirst few workflows:');
|
||||
workflows.slice(0, 5).forEach((wf) => {
|
||||
console.log(` - ${wf.name} (ID: ${wf.id}, Active: ${wf.active})`);
|
||||
});
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('✗ Connection failed:', error.message);
|
||||
console.error('\nTroubleshooting:');
|
||||
console.error('1. Verify n8n is running:');
|
||||
console.error(` curl ${N8N_BASE_URL}/healthz`);
|
||||
console.error('2. Check if the URL is correct in your configuration');
|
||||
console.error('3. If authentication is required, set N8N_API_KEY environment variable');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user