feat: add HTTP server mode for remote deployment with token auth
This commit is contained in:
25
.env.example
25
.env.example
@@ -29,22 +29,17 @@ MCP_SERVER_HOST=localhost
|
||||
# MCP_AUTH_TOKEN=optional-for-local-development
|
||||
|
||||
# =========================
|
||||
# HTTP MODE CONFIGURATION
|
||||
# SIMPLE HTTP MODE
|
||||
# =========================
|
||||
# Used when running: npm run start:http or npm run dev:http
|
||||
# Used for private single-user deployments
|
||||
|
||||
# HTTP Server Configuration
|
||||
MCP_PORT=3000
|
||||
MCP_HOST=0.0.0.0
|
||||
MCP_DOMAIN=localhost
|
||||
# Server mode: stdio (local) or http (remote)
|
||||
MCP_MODE=stdio
|
||||
|
||||
# Authentication (REQUIRED for production HTTP mode)
|
||||
# Generate a secure token: openssl rand -hex 32
|
||||
# MCP_AUTH_TOKEN=your-secure-auth-token-here
|
||||
# HTTP Server Configuration (only used when MCP_MODE=http)
|
||||
PORT=3000
|
||||
HOST=0.0.0.0
|
||||
|
||||
# CORS - Enable for browser-based access
|
||||
MCP_CORS=false
|
||||
|
||||
# TLS Configuration (optional for HTTPS)
|
||||
# MCP_TLS_CERT=/path/to/cert.pem
|
||||
# MCP_TLS_KEY=/path/to/key.pem
|
||||
# Authentication token for HTTP mode (REQUIRED)
|
||||
# Generate with: openssl rand -base64 32
|
||||
AUTH_TOKEN=your-secure-token-here
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
|
||||
## [2.3.0] - 2024-12-06
|
||||
|
||||
### Added
|
||||
- **HTTP Remote Deployment**: Single-user HTTP server for remote access
|
||||
- Stateless architecture for simple deployments
|
||||
- Bearer token authentication
|
||||
- Compatible with mcp-remote adapter for Claude Desktop
|
||||
- New HTTP mode scripts and deployment helper
|
||||
- **Universal Node.js Compatibility**: Automatic database adapter fallback system
|
||||
- Primary adapter: `better-sqlite3` for optimal performance
|
||||
- Fallback adapter: `sql.js` (pure JavaScript) for version mismatches
|
||||
@@ -13,23 +18,28 @@ All notable changes to this project will be documented in this file.
|
||||
- Database adapter abstraction layer (`src/database/database-adapter.ts`)
|
||||
- Version detection and logging for troubleshooting
|
||||
- sql.js dependency for pure JavaScript SQLite implementation
|
||||
- HTTP server implementation (`src/http-server.ts`)
|
||||
- Deployment documentation and scripts
|
||||
|
||||
### Changed
|
||||
- Updated all database operations to use the adapter interface
|
||||
- Removed Node.js v20.17.0 requirement - now works with ANY version
|
||||
- Simplified Claude Desktop setup - no wrapper scripts needed
|
||||
- Enhanced error messages for database initialization
|
||||
- Made all MCP tool handlers async for proper initialization
|
||||
|
||||
### Fixed
|
||||
- NODE_MODULE_VERSION mismatch errors with Claude Desktop
|
||||
- Native module compilation issues in restricted environments
|
||||
- Compatibility issues when running with different Node.js versions
|
||||
- Database initialization race conditions in HTTP mode
|
||||
|
||||
### Technical Details
|
||||
- Better-sqlite3: ~10-50x faster (when compatible)
|
||||
- sql.js: ~2-5x slower but universally compatible
|
||||
- Both adapters maintain identical API and functionality
|
||||
- Automatic persistence for sql.js with 100ms debounced saves
|
||||
- HTTP server uses StreamableHTTPServerTransport for MCP compatibility
|
||||
|
||||
## [2.2.0] - 2024-12-06
|
||||
|
||||
|
||||
48
CLAUDE.md
48
CLAUDE.md
@@ -72,13 +72,19 @@ npm run rebuild # Rebuild node database
|
||||
npm run validate # Validate critical nodes
|
||||
npm run test-nodes # Test critical node properties/operations
|
||||
|
||||
# HTTP Server Commands:
|
||||
npm run start:http # Start server in HTTP mode
|
||||
npm run http # Build and start HTTP server
|
||||
npm run dev:http # HTTP server with auto-reload
|
||||
|
||||
# Legacy Commands (deprecated):
|
||||
npm run db:rebuild # Old rebuild command
|
||||
npm run db:init # Initialize empty database
|
||||
npm run docs:rebuild # Rebuild documentation from TypeScript source
|
||||
|
||||
# Production
|
||||
npm start # Run built application
|
||||
npm start # Run built application (stdio mode)
|
||||
npm run start:http # Run in HTTP mode for remote access
|
||||
```
|
||||
|
||||
## High-Level Architecture
|
||||
@@ -234,6 +240,46 @@ This project uses the Sustainable Use License. Key points:
|
||||
- ❌ Cannot host as a service without permission
|
||||
- ❌ Cannot include in commercial products without permission
|
||||
|
||||
## HTTP Remote Deployment (v2.3.0)
|
||||
|
||||
### ✅ HTTP Server Implementation Complete
|
||||
|
||||
The project now includes a simplified HTTP server mode for remote deployments:
|
||||
- **Single-user design**: Stateless architecture for private deployments
|
||||
- **Simple token auth**: Bearer token authentication
|
||||
- **MCP-compatible**: Works with mcp-remote adapter for Claude Desktop
|
||||
- **Easy deployment**: Minimal configuration required
|
||||
|
||||
### Quick Start
|
||||
```bash
|
||||
# Server setup
|
||||
export MCP_MODE=http
|
||||
export AUTH_TOKEN=$(openssl rand -base64 32)
|
||||
npm run start:http
|
||||
|
||||
# Client setup (Claude Desktop config)
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "mcp-remote",
|
||||
"args": [
|
||||
"https://your-server.com/mcp",
|
||||
"--header",
|
||||
"Authorization: Bearer your-auth-token"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Available Scripts
|
||||
- `npm run start:http` - Start in HTTP mode
|
||||
- `npm run http` - Build and start HTTP server
|
||||
- `npm run dev:http` - Development mode with auto-reload
|
||||
- `./scripts/deploy-http.sh` - Deployment helper script
|
||||
|
||||
For detailed deployment instructions, see [HTTP Deployment Guide](./docs/HTTP_DEPLOYMENT.md).
|
||||
|
||||
## Recent Problem Solutions
|
||||
|
||||
### SQLite Version Mismatch (Solved in v2.3)
|
||||
|
||||
48
README.md
48
README.md
@@ -184,21 +184,45 @@ Current implementation achieves:
|
||||
- ✅ 35 AI-capable tools detected
|
||||
- ✅ All critical nodes validated
|
||||
|
||||
## Future Development
|
||||
## Remote Deployment
|
||||
|
||||
### HTTP Remote Deployment (Planned)
|
||||
### HTTP Server Mode
|
||||
|
||||
We are planning to add HTTP transport support to enable remote deployment of the MCP server. This will allow:
|
||||
- Centralized hosting on cloud servers
|
||||
- Multiple users connecting to a single instance
|
||||
- No local installation required
|
||||
- Enterprise-ready authentication
|
||||
n8n-MCP now supports HTTP mode for remote deployments. This allows you to:
|
||||
- Host the MCP server on a cloud VPS
|
||||
- Connect from Claude Desktop using mcp-remote
|
||||
- Single-user design for private use
|
||||
- Simple token-based authentication
|
||||
|
||||
For detailed planning documents, see:
|
||||
- [HTTP Remote Deployment Plan](./HTTP_REMOTE_DEPLOYMENT_PLAN.md)
|
||||
- [HTTP Implementation Guide](./HTTP_IMPLEMENTATION_GUIDE.md)
|
||||
- [HTTP Implementation Roadmap](./HTTP_IMPLEMENTATION_ROADMAP.md)
|
||||
- [HTTP Remote Summary](./HTTP_REMOTE_SUMMARY.md)
|
||||
### Quick Start for HTTP Mode
|
||||
|
||||
1. On your server:
|
||||
```bash
|
||||
# Set environment variables
|
||||
export MCP_MODE=http
|
||||
export AUTH_TOKEN=$(openssl rand -base64 32)
|
||||
|
||||
# Start the server
|
||||
npm run start:http
|
||||
```
|
||||
|
||||
2. On your client, configure Claude Desktop with mcp-remote:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "mcp-remote",
|
||||
"args": [
|
||||
"https://your-server.com/mcp",
|
||||
"--header",
|
||||
"Authorization: Bearer your-auth-token"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For detailed instructions, see [HTTP Deployment Guide](./docs/HTTP_DEPLOYMENT.md).
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
214
docs/HTTP_DEPLOYMENT.md
Normal file
214
docs/HTTP_DEPLOYMENT.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# HTTP Deployment Guide
|
||||
|
||||
This guide explains how to deploy n8n-MCP as a private HTTP server for remote access.
|
||||
|
||||
## Overview
|
||||
|
||||
The HTTP mode allows you to run n8n-MCP on a remote server and connect to it from Claude Desktop using the mcp-remote adapter. This is designed for single-user private deployments.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js v16+ on the server
|
||||
- A server with a public IP or domain
|
||||
- HTTPS proxy (nginx/caddy) for secure connections
|
||||
- mcp-remote installed on the client
|
||||
|
||||
## Server Setup
|
||||
|
||||
### 1. Clone and Build
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourusername/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
npm install
|
||||
npm run build
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
### 2. Configure Environment
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env`:
|
||||
```env
|
||||
# HTTP mode configuration
|
||||
MCP_MODE=http
|
||||
PORT=3000
|
||||
HOST=0.0.0.0
|
||||
|
||||
# Generate secure token
|
||||
AUTH_TOKEN=your-secure-token-here
|
||||
|
||||
# Other settings
|
||||
NODE_DB_PATH=./data/nodes.db
|
||||
MCP_LOG_LEVEL=info
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
Generate a secure token:
|
||||
```bash
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
### 3. Start the Server
|
||||
|
||||
```bash
|
||||
# Using the deployment script
|
||||
./scripts/deploy-http.sh
|
||||
|
||||
# Or manually
|
||||
MCP_MODE=http npm start
|
||||
```
|
||||
|
||||
The server will start on `http://0.0.0.0:3000`
|
||||
|
||||
### 4. Setup HTTPS Proxy (Recommended)
|
||||
|
||||
#### Using nginx:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name your-domain.com;
|
||||
|
||||
ssl_certificate /path/to/cert.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Using Caddy:
|
||||
|
||||
```caddyfile
|
||||
your-domain.com {
|
||||
reverse_proxy localhost:3000
|
||||
}
|
||||
```
|
||||
|
||||
## Client Setup
|
||||
|
||||
### 1. Install mcp-remote
|
||||
|
||||
```bash
|
||||
npm install -g mcp-remote
|
||||
```
|
||||
|
||||
### 2. Configure Claude Desktop
|
||||
|
||||
Edit Claude Desktop config:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "mcp-remote",
|
||||
"args": [
|
||||
"https://your-domain.com/mcp",
|
||||
"--header",
|
||||
"Authorization: Bearer your-secure-token-here"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Test Connection
|
||||
|
||||
1. Restart Claude Desktop
|
||||
2. The MCP tools should be available
|
||||
3. Test with: "List all n8n nodes"
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Always use HTTPS** in production
|
||||
2. **Keep AUTH_TOKEN secret** - treat it like a password
|
||||
3. **Firewall rules** - Only expose necessary ports
|
||||
4. **Regular updates** - Keep dependencies updated
|
||||
5. **Monitor logs** - Check for unauthorized access attempts
|
||||
|
||||
## Health Monitoring
|
||||
|
||||
Check server health:
|
||||
```bash
|
||||
curl https://your-domain.com/health
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"mode": "http",
|
||||
"version": "2.3.0"
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Refused
|
||||
- Check firewall rules
|
||||
- Verify server is running
|
||||
- Check nginx/proxy configuration
|
||||
|
||||
### Authentication Failed
|
||||
- Verify AUTH_TOKEN matches in both server and client
|
||||
- Check Authorization header format
|
||||
|
||||
### MCP Tools Not Available
|
||||
- Restart Claude Desktop
|
||||
- Check mcp-remote installation
|
||||
- Verify server logs for errors
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. Use a VPS with good network connectivity
|
||||
2. Enable gzip compression in your proxy
|
||||
3. Consider using PM2 for process management:
|
||||
```bash
|
||||
pm2 start npm --name "n8n-mcp" -- run start:http
|
||||
```
|
||||
|
||||
## Example Systemd Service
|
||||
|
||||
Create `/etc/systemd/system/n8n-mcp.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=n8n MCP HTTP Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=your-user
|
||||
WorkingDirectory=/path/to/n8n-mcp
|
||||
ExecStart=/usr/bin/npm run start:http
|
||||
Restart=on-failure
|
||||
Environment=NODE_ENV=production
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start:
|
||||
```bash
|
||||
sudo systemctl enable n8n-mcp
|
||||
sudo systemctl start n8n-mcp
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
- Single-user design (no multi-tenancy)
|
||||
- Stateless (no session persistence)
|
||||
- No built-in rate limiting
|
||||
- Basic token authentication only
|
||||
|
||||
For multi-user deployments, consider implementing a proper API gateway with user management.
|
||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -11,7 +11,6 @@
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.12.1",
|
||||
"@n8n/n8n-nodes-langchain": "^1.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"better-sqlite3": "^11.10.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "^5.1.0",
|
||||
@@ -13151,15 +13150,6 @@
|
||||
"@babel/types": "^7.20.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/better-sqlite3": {
|
||||
"version": "7.6.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz",
|
||||
"integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
"validate": "node dist/scripts/validate.js",
|
||||
"test-nodes": "node dist/scripts/test-nodes.js",
|
||||
"start": "node dist/mcp/index.js",
|
||||
"start:http": "MCP_MODE=http node dist/mcp/index.js",
|
||||
"http": "npm run build && npm run start:http",
|
||||
"dev": "npm run build && npm run rebuild && npm run validate",
|
||||
"dev:http": "MCP_MODE=http nodemon --watch src --ext ts --exec 'npm run build && npm run start:http'",
|
||||
"test": "jest",
|
||||
"lint": "tsc --noEmit",
|
||||
"typecheck": "tsc --noEmit",
|
||||
|
||||
41
scripts/deploy-http.sh
Executable file
41
scripts/deploy-http.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
# Simple deployment script for n8n-MCP HTTP server
|
||||
# For private, single-user deployments only
|
||||
|
||||
set -e
|
||||
|
||||
echo "n8n-MCP HTTP Deployment Script"
|
||||
echo "=============================="
|
||||
echo ""
|
||||
|
||||
# Check if .env exists
|
||||
if [ ! -f .env ]; then
|
||||
echo "Creating .env file..."
|
||||
cp .env.example .env
|
||||
echo ""
|
||||
echo "⚠️ Please edit .env file and set:"
|
||||
echo " - AUTH_TOKEN (generate with: openssl rand -base64 32)"
|
||||
echo " - MCP_MODE=http"
|
||||
echo " - PORT (default 3000)"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if AUTH_TOKEN is set
|
||||
if ! grep -q "AUTH_TOKEN=.*[a-zA-Z0-9]" .env; then
|
||||
echo "ERROR: AUTH_TOKEN not set in .env file"
|
||||
echo "Generate one with: openssl rand -base64 32"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build and start
|
||||
echo "Building project..."
|
||||
npm run build
|
||||
|
||||
echo ""
|
||||
echo "Starting HTTP server..."
|
||||
echo "Use Ctrl+C to stop"
|
||||
echo ""
|
||||
|
||||
# Start with production settings
|
||||
NODE_ENV=production npm run start:http
|
||||
117
src/http-server.ts
Normal file
117
src/http-server.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Minimal HTTP server for n8n-MCP
|
||||
* Single-user, stateless design for private deployments
|
||||
*/
|
||||
import express from 'express';
|
||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
import { N8NDocumentationMCPServer } from './mcp/server-update';
|
||||
import { logger } from './utils/logger';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export async function startHTTPServer() {
|
||||
const app = express();
|
||||
app.use(express.json({ limit: '10mb' }));
|
||||
|
||||
// Simple token auth
|
||||
const authToken = process.env.AUTH_TOKEN;
|
||||
if (!authToken) {
|
||||
logger.error('AUTH_TOKEN environment variable required');
|
||||
console.error('ERROR: AUTH_TOKEN environment variable is required for HTTP mode');
|
||||
console.error('Generate one with: openssl rand -base64 32');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Request logging middleware
|
||||
app.use((req, res, next) => {
|
||||
logger.info(`${req.method} ${req.path}`, {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent')
|
||||
});
|
||||
next();
|
||||
});
|
||||
|
||||
// Health check endpoint
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'ok',
|
||||
mode: 'http',
|
||||
version: '2.3.0'
|
||||
});
|
||||
});
|
||||
|
||||
// Main MCP endpoint - Create a new server and transport for each request (stateless)
|
||||
app.post('/mcp', async (req: express.Request, res: express.Response): Promise<void> => {
|
||||
// Simple auth check
|
||||
const authHeader = req.headers.authorization;
|
||||
const token = authHeader?.startsWith('Bearer ')
|
||||
? authHeader.slice(7)
|
||||
: authHeader;
|
||||
|
||||
if (token !== authToken) {
|
||||
logger.warn('Authentication failed', { ip: req.ip });
|
||||
res.status(401).json({ error: 'Unauthorized' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new instances for each request (stateless)
|
||||
const mcpServer = new N8NDocumentationMCPServer();
|
||||
|
||||
try {
|
||||
// Create a stateless transport
|
||||
const transport = new StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: undefined, // Stateless mode
|
||||
});
|
||||
|
||||
// Connect server to transport
|
||||
await mcpServer.connect(transport);
|
||||
|
||||
// Handle the request
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
|
||||
// Clean up on close
|
||||
res.on('close', () => {
|
||||
logger.debug('Request closed, cleaning up');
|
||||
transport.close();
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('MCP request error:', error);
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: process.env.NODE_ENV === 'development' ? (error as Error).message : undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Error handler
|
||||
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.error('Request error:', err);
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: process.env.NODE_ENV === 'development' ? err.message : undefined
|
||||
});
|
||||
});
|
||||
|
||||
const port = parseInt(process.env.PORT || '3000');
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
|
||||
app.listen(port, host, () => {
|
||||
logger.info(`n8n MCP HTTP Server started`, { port, host });
|
||||
console.log(`n8n MCP HTTP Server running on ${host}:${port}`);
|
||||
console.log(`Health check: http://localhost:${port}/health`);
|
||||
console.log(`MCP endpoint: http://localhost:${port}/mcp`);
|
||||
});
|
||||
}
|
||||
|
||||
// Start if called directly
|
||||
if (require.main === module) {
|
||||
startHTTPServer().catch(error => {
|
||||
logger.error('Failed to start HTTP server:', error);
|
||||
console.error('Failed to start HTTP server:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
@@ -18,13 +18,21 @@ process.on('unhandledRejection', (reason, promise) => {
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.error('Starting n8n Documentation MCP Server...');
|
||||
const mode = process.env.MCP_MODE || 'stdio';
|
||||
|
||||
console.error(`Starting n8n Documentation MCP Server in ${mode} mode...`);
|
||||
console.error('Current directory:', process.cwd());
|
||||
console.error('Script directory:', __dirname);
|
||||
console.error('Node version:', process.version);
|
||||
|
||||
const server = new N8NDocumentationMCPServer();
|
||||
await server.run();
|
||||
if (mode === 'http') {
|
||||
// HTTP mode - for remote deployment
|
||||
const { startHTTPServer } = await import('../http-server');
|
||||
await startHTTPServer();
|
||||
} else {
|
||||
// Stdio mode - for local Claude Desktop
|
||||
const server = new N8NDocumentationMCPServer();
|
||||
await server.run();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to start MCP server:', error);
|
||||
logger.error('Failed to start MCP server', error);
|
||||
|
||||
@@ -150,7 +150,9 @@ export class N8NDocumentationMCPServer {
|
||||
}
|
||||
}
|
||||
|
||||
private listNodes(filters: any = {}): any {
|
||||
private async listNodes(filters: any = {}): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
|
||||
let query = 'SELECT * FROM nodes WHERE 1=1';
|
||||
const params: any[] = [];
|
||||
|
||||
@@ -199,7 +201,8 @@ export class N8NDocumentationMCPServer {
|
||||
};
|
||||
}
|
||||
|
||||
private getNodeInfo(nodeType: string): any {
|
||||
private async getNodeInfo(nodeType: string): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.repository) throw new Error('Repository not initialized');
|
||||
let node = this.repository.getNode(nodeType);
|
||||
|
||||
@@ -228,7 +231,8 @@ export class N8NDocumentationMCPServer {
|
||||
return node;
|
||||
}
|
||||
|
||||
private searchNodes(query: string, limit: number = 20): any {
|
||||
private async searchNodes(query: string, limit: number = 20): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
// Simple search across multiple fields
|
||||
const searchQuery = `%${query}%`;
|
||||
@@ -273,7 +277,8 @@ export class N8NDocumentationMCPServer {
|
||||
return 'low';
|
||||
}
|
||||
|
||||
private listAITools(): any {
|
||||
private async listAITools(): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.repository) throw new Error('Repository not initialized');
|
||||
const tools = this.repository.getAITools();
|
||||
|
||||
@@ -287,7 +292,8 @@ export class N8NDocumentationMCPServer {
|
||||
};
|
||||
}
|
||||
|
||||
private getNodeDocumentation(nodeType: string): any {
|
||||
private async getNodeDocumentation(nodeType: string): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
const node = this.db!.prepare(`
|
||||
SELECT node_type, display_name, documentation
|
||||
@@ -307,7 +313,8 @@ export class N8NDocumentationMCPServer {
|
||||
};
|
||||
}
|
||||
|
||||
private getDatabaseStatistics(): any {
|
||||
private async getDatabaseStatistics(): Promise<any> {
|
||||
await this.ensureInitialized();
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
const stats = this.db!.prepare(`
|
||||
SELECT
|
||||
@@ -345,6 +352,15 @@ export class N8NDocumentationMCPServer {
|
||||
};
|
||||
}
|
||||
|
||||
// Add connect method to accept any transport
|
||||
async connect(transport: any): Promise<void> {
|
||||
await this.ensureInitialized();
|
||||
await this.server.connect(transport);
|
||||
logger.info('MCP Server connected', {
|
||||
transportType: transport.constructor.name
|
||||
});
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
// Ensure database is initialized before starting server
|
||||
await this.ensureInitialized();
|
||||
|
||||
Reference in New Issue
Block a user