docs: reorganize documentation files and update Docker build process
This commit is contained in:
1
.github/workflows/docker-build.yml
vendored
1
.github/workflows/docker-build.yml
vendored
@@ -35,6 +35,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
|
||||
@@ -13,8 +13,6 @@ COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
# Build TypeScript
|
||||
RUN npm run build
|
||||
# Pre-initialize database during build
|
||||
RUN mkdir -p /app/data && npm run rebuild || echo "Database will be initialized at runtime"
|
||||
|
||||
# Stage 3: Simple Runtime
|
||||
FROM node:20-alpine AS runtime
|
||||
@@ -32,8 +30,8 @@ RUN npm ci --only=production && \
|
||||
# Copy built application
|
||||
COPY --from=builder /app/dist ./dist
|
||||
|
||||
# Copy pre-built database if it exists
|
||||
COPY --from=builder /app/data/nodes.db ./data/nodes.db 2>/dev/null || true
|
||||
# Create data directory
|
||||
RUN mkdir -p /app/data
|
||||
|
||||
# Copy necessary source files for database initialization
|
||||
COPY src/database/schema.sql ./src/database/
|
||||
|
||||
@@ -1,792 +0,0 @@
|
||||
# HTTP Implementation Technical Guide
|
||||
|
||||
## Deep Technical Analysis
|
||||
|
||||
### Current MCP Transport Mechanism
|
||||
|
||||
The current implementation uses `StdioServerTransport` which:
|
||||
1. Reads JSON-RPC messages from stdin
|
||||
2. Writes responses to stdout
|
||||
3. Maintains a single, persistent connection
|
||||
4. Has implicit trust (local execution)
|
||||
|
||||
### Target HTTP Transport Mechanism
|
||||
|
||||
The `StreamableHTTPServerTransport`:
|
||||
1. Accepts HTTP POST requests with JSON-RPC payloads
|
||||
2. Can upgrade to Server-Sent Events (SSE) for server-initiated messages
|
||||
3. Requires session management for state persistence
|
||||
4. Needs explicit authentication
|
||||
|
||||
## Detailed Implementation Steps
|
||||
|
||||
### Step 1: Install Required Dependencies
|
||||
|
||||
```bash
|
||||
npm install express cors helmet compression dotenv
|
||||
npm install --save-dev @types/express @types/cors
|
||||
```
|
||||
|
||||
### Step 2: Create HTTP Server Structure
|
||||
|
||||
```typescript
|
||||
// src/mcp/transports/http-transport.ts
|
||||
import express, { Request, Response, NextFunction } from 'express';
|
||||
import cors from 'cors';
|
||||
import helmet from 'helmet';
|
||||
import compression from 'compression';
|
||||
import { randomUUID } from 'crypto';
|
||||
import {
|
||||
StreamableHTTPServerTransport,
|
||||
StreamableHTTPServerTransportOptions
|
||||
} from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
import { logger } from '../../utils/logger';
|
||||
|
||||
export interface HTTPServerConfig {
|
||||
port: number;
|
||||
host: string;
|
||||
authToken?: string;
|
||||
corsOrigins?: string[];
|
||||
sessionTimeout?: number; // in milliseconds
|
||||
maxSessions?: number;
|
||||
}
|
||||
|
||||
export interface MCPSession {
|
||||
id: string;
|
||||
transport: StreamableHTTPServerTransport;
|
||||
server: any; // Your MCP server instance
|
||||
createdAt: Date;
|
||||
lastActivity: Date;
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
|
||||
export class HTTPTransportServer {
|
||||
private app: express.Application;
|
||||
private sessions: Map<string, MCPSession> = new Map();
|
||||
private config: HTTPServerConfig;
|
||||
private cleanupInterval?: NodeJS.Timeout;
|
||||
|
||||
constructor(config: HTTPServerConfig) {
|
||||
this.config = {
|
||||
sessionTimeout: 30 * 60 * 1000, // 30 minutes default
|
||||
maxSessions: 100,
|
||||
...config
|
||||
};
|
||||
|
||||
this.app = express();
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
this.startSessionCleanup();
|
||||
}
|
||||
|
||||
private setupMiddleware(): void {
|
||||
// Security headers
|
||||
this.app.use(helmet());
|
||||
|
||||
// CORS configuration
|
||||
this.app.use(cors({
|
||||
origin: this.config.corsOrigins || true,
|
||||
credentials: true,
|
||||
methods: ['POST', 'GET', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'MCP-Session-ID']
|
||||
}));
|
||||
|
||||
// Compression
|
||||
this.app.use(compression());
|
||||
|
||||
// JSON parsing with size limit
|
||||
this.app.use(express.json({ limit: '10mb' }));
|
||||
|
||||
// Request logging
|
||||
this.app.use((req, res, next) => {
|
||||
logger.info(`${req.method} ${req.path}`, {
|
||||
sessionId: req.headers['mcp-session-id'],
|
||||
ip: req.ip
|
||||
});
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
private setupRoutes(): void {
|
||||
// Health check endpoint
|
||||
this.app.get('/health', (req, res) => {
|
||||
res.json({
|
||||
status: 'ok',
|
||||
sessions: this.sessions.size,
|
||||
uptime: process.uptime()
|
||||
});
|
||||
});
|
||||
|
||||
// Main MCP endpoint
|
||||
this.app.post('/mcp',
|
||||
this.authenticateRequest.bind(this),
|
||||
this.handleMCPRequest.bind(this)
|
||||
);
|
||||
|
||||
// Session management endpoint
|
||||
this.app.get('/sessions',
|
||||
this.authenticateRequest.bind(this),
|
||||
(req, res) => {
|
||||
const sessionInfo = Array.from(this.sessions.entries()).map(([id, session]) => ({
|
||||
id,
|
||||
createdAt: session.createdAt,
|
||||
lastActivity: session.lastActivity,
|
||||
metadata: session.metadata
|
||||
}));
|
||||
res.json({ sessions: sessionInfo });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private authenticateRequest(req: Request, res: Response, next: NextFunction): void {
|
||||
if (!this.config.authToken) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const authHeader = req.headers.authorization;
|
||||
const token = authHeader?.startsWith('Bearer ')
|
||||
? authHeader.slice(7)
|
||||
: authHeader;
|
||||
|
||||
if (token !== this.config.authToken) {
|
||||
logger.warn('Authentication failed', { ip: req.ip });
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
private async handleMCPRequest(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const sessionId = req.headers['mcp-session-id'] as string;
|
||||
let session = sessionId ? this.sessions.get(sessionId) : null;
|
||||
|
||||
// Create new session if needed
|
||||
if (!session) {
|
||||
if (this.sessions.size >= this.config.maxSessions!) {
|
||||
return res.status(503).json({ error: 'Server at capacity' });
|
||||
}
|
||||
|
||||
session = await this.createSession();
|
||||
res.setHeader('MCP-Session-ID', session.id);
|
||||
}
|
||||
|
||||
// Update last activity
|
||||
session.lastActivity = new Date();
|
||||
|
||||
// Handle the request through the transport
|
||||
await session.transport.handleRequest(req, res);
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Error handling MCP request', error);
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: error instanceof Error ? error.message : 'Unknown error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async createSession(): Promise<MCPSession> {
|
||||
const id = randomUUID();
|
||||
const transport = new StreamableHTTPServerTransport();
|
||||
|
||||
// Create your MCP server instance here
|
||||
const { N8NDocumentationMCPServer } = await import('../server-update');
|
||||
const server = new N8NDocumentationMCPServer();
|
||||
|
||||
// Connect transport to server
|
||||
await server.connect(transport);
|
||||
|
||||
const session: MCPSession = {
|
||||
id,
|
||||
transport,
|
||||
server,
|
||||
createdAt: new Date(),
|
||||
lastActivity: new Date()
|
||||
};
|
||||
|
||||
this.sessions.set(id, session);
|
||||
logger.info('Created new session', { sessionId: id });
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
private startSessionCleanup(): void {
|
||||
this.cleanupInterval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
const timeout = this.config.sessionTimeout!;
|
||||
|
||||
for (const [id, session] of this.sessions.entries()) {
|
||||
if (now - session.lastActivity.getTime() > timeout) {
|
||||
this.destroySession(id);
|
||||
}
|
||||
}
|
||||
}, 60000); // Check every minute
|
||||
}
|
||||
|
||||
private destroySession(id: string): void {
|
||||
const session = this.sessions.get(id);
|
||||
if (session) {
|
||||
// Cleanup server resources
|
||||
if (session.server && typeof session.server.close === 'function') {
|
||||
session.server.close();
|
||||
}
|
||||
|
||||
this.sessions.delete(id);
|
||||
logger.info('Destroyed session', { sessionId: id });
|
||||
}
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
this.app.listen(this.config.port, this.config.host, () => {
|
||||
logger.info(`HTTP MCP Server listening on ${this.config.host}:${this.config.port}`);
|
||||
});
|
||||
}
|
||||
|
||||
public stop(): void {
|
||||
if (this.cleanupInterval) {
|
||||
clearInterval(this.cleanupInterval);
|
||||
}
|
||||
|
||||
// Cleanup all sessions
|
||||
for (const id of this.sessions.keys()) {
|
||||
this.destroySession(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Modify MCP Server for Transport Flexibility
|
||||
|
||||
```typescript
|
||||
// src/mcp/server-update.ts modifications
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import { Transport } from '@modelcontextprotocol/sdk/types.js';
|
||||
|
||||
export class N8NDocumentationMCPServer {
|
||||
private server: Server;
|
||||
// ... existing code ...
|
||||
|
||||
// Add connect method to accept any transport
|
||||
async connect(transport: Transport): Promise<void> {
|
||||
await this.ensureInitialized();
|
||||
await this.server.connect(transport);
|
||||
logger.info('MCP Server connected with transport', {
|
||||
transportType: transport.constructor.name
|
||||
});
|
||||
}
|
||||
|
||||
// Modify run method to be transport-agnostic
|
||||
async run(transport?: Transport): Promise<void> {
|
||||
await this.ensureInitialized();
|
||||
|
||||
if (!transport) {
|
||||
// Default to stdio for backward compatibility
|
||||
transport = new StdioServerTransport();
|
||||
}
|
||||
|
||||
await this.connect(transport);
|
||||
logger.info('n8n Documentation MCP Server running');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Create Unified Entry Point
|
||||
|
||||
```typescript
|
||||
// src/mcp/index-universal.ts
|
||||
#!/usr/bin/env node
|
||||
import { N8NDocumentationMCPServer } from './server-update';
|
||||
import { HTTPTransportServer } from './transports/http-transport';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
import { logger } from '../utils/logger';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
interface CLIArgs {
|
||||
mode: 'stdio' | 'http';
|
||||
port?: number;
|
||||
host?: string;
|
||||
authToken?: string;
|
||||
}
|
||||
|
||||
function parseArgs(): CLIArgs {
|
||||
const args = process.argv.slice(2);
|
||||
const config: CLIArgs = {
|
||||
mode: 'stdio' // default
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
switch (args[i]) {
|
||||
case '--mode':
|
||||
config.mode = args[++i] as 'stdio' | 'http';
|
||||
break;
|
||||
case '--port':
|
||||
config.port = parseInt(args[++i]);
|
||||
break;
|
||||
case '--host':
|
||||
config.host = args[++i];
|
||||
break;
|
||||
case '--auth-token':
|
||||
config.authToken = args[++i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow environment variables to override
|
||||
config.mode = (process.env.MCP_MODE as any) || config.mode;
|
||||
config.port = parseInt(process.env.MCP_PORT || '') || config.port || 3000;
|
||||
config.host = process.env.MCP_HOST || config.host || '0.0.0.0';
|
||||
config.authToken = process.env.MCP_AUTH_TOKEN || config.authToken;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const config = parseArgs();
|
||||
logger.info('Starting MCP server', config);
|
||||
|
||||
if (config.mode === 'http') {
|
||||
// HTTP mode - server manages its own lifecycle
|
||||
const httpServer = new HTTPTransportServer({
|
||||
port: config.port!,
|
||||
host: config.host!,
|
||||
authToken: config.authToken,
|
||||
corsOrigins: process.env.MCP_CORS_ORIGINS?.split(','),
|
||||
sessionTimeout: parseInt(process.env.MCP_SESSION_TIMEOUT || '') || undefined,
|
||||
maxSessions: parseInt(process.env.MCP_MAX_SESSIONS || '') || undefined
|
||||
});
|
||||
|
||||
httpServer.start();
|
||||
|
||||
// Graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
logger.info('Shutting down HTTP server...');
|
||||
httpServer.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
} else {
|
||||
// Stdio mode - traditional single instance
|
||||
const server = new N8NDocumentationMCPServer();
|
||||
await server.run(); // Uses stdio by default
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
logger.error('Failed to start MCP server', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Environment Configuration
|
||||
|
||||
```bash
|
||||
# .env.example
|
||||
# Server mode: stdio or http
|
||||
MCP_MODE=http
|
||||
|
||||
# HTTP server configuration
|
||||
MCP_PORT=3000
|
||||
MCP_HOST=0.0.0.0
|
||||
MCP_AUTH_TOKEN=your-secure-token-here
|
||||
|
||||
# CORS origins (comma-separated)
|
||||
MCP_CORS_ORIGINS=https://claude.ai,http://localhost:3000
|
||||
|
||||
# Session management
|
||||
MCP_SESSION_TIMEOUT=1800000 # 30 minutes in milliseconds
|
||||
MCP_MAX_SESSIONS=100
|
||||
|
||||
# Existing configuration
|
||||
NODE_ENV=production
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
### Step 6: Docker Configuration for Remote Deployment
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile.http
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install production dependencies only
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production && npm cache clean --force
|
||||
|
||||
# Copy built application
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/data ./data
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nodejs -u 1001
|
||||
|
||||
# Change ownership
|
||||
RUN chown -R nodejs:nodejs /app
|
||||
|
||||
USER nodejs
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1); })"
|
||||
|
||||
# Start the server
|
||||
CMD ["node", "dist/mcp/index-universal.js", "--mode", "http"]
|
||||
```
|
||||
|
||||
### Step 7: Production Deployment Script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# deploy.sh
|
||||
|
||||
# Configuration
|
||||
DOMAIN="mcp.your-domain.com"
|
||||
EMAIL="your-email@example.com"
|
||||
AUTH_TOKEN=$(openssl rand -base64 32)
|
||||
|
||||
# Update system
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# Install dependencies
|
||||
sudo apt install -y docker.io docker-compose nginx certbot python3-certbot-nginx
|
||||
|
||||
# Clone repository
|
||||
git clone https://github.com/yourusername/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
|
||||
# Create .env file
|
||||
cat > .env << EOF
|
||||
MCP_MODE=http
|
||||
MCP_PORT=3000
|
||||
MCP_HOST=0.0.0.0
|
||||
MCP_AUTH_TOKEN=$AUTH_TOKEN
|
||||
MCP_CORS_ORIGINS=https://claude.ai
|
||||
NODE_ENV=production
|
||||
LOG_LEVEL=info
|
||||
EOF
|
||||
|
||||
# Build and run with Docker
|
||||
docker build -f Dockerfile.http -t n8n-mcp-http .
|
||||
docker run -d \
|
||||
--name n8n-mcp \
|
||||
--restart always \
|
||||
-p 127.0.0.1:3000:3000 \
|
||||
--env-file .env \
|
||||
n8n-mcp-http
|
||||
|
||||
# Configure Nginx
|
||||
sudo tee /etc/nginx/sites-available/mcp << EOF
|
||||
server {
|
||||
listen 80;
|
||||
server_name $DOMAIN;
|
||||
return 301 https://\$server_name\$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name $DOMAIN;
|
||||
|
||||
# SSL will be configured by certbot
|
||||
|
||||
location /mcp {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
|
||||
# Timeouts for long-running requests
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location /health {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Enable site
|
||||
sudo ln -s /etc/nginx/sites-available/mcp /etc/nginx/sites-enabled/
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
|
||||
# Get SSL certificate
|
||||
sudo certbot --nginx -d $DOMAIN --email $EMAIL --agree-tos --non-interactive
|
||||
|
||||
echo "Deployment complete!"
|
||||
echo "Your MCP server is available at: https://$DOMAIN/mcp"
|
||||
echo "Auth token: $AUTH_TOKEN"
|
||||
echo "Save this token - you'll need it for client configuration"
|
||||
```
|
||||
|
||||
### Step 8: Client Configuration with mcp-remote
|
||||
|
||||
```json
|
||||
// claude_desktop_config.json for remote server
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-remote": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"mcp-remote@latest",
|
||||
"connect",
|
||||
"https://mcp.your-domain.com/mcp"
|
||||
],
|
||||
"env": {
|
||||
"MCP_AUTH_TOKEN": "your-auth-token-here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 9: Monitoring and Logging
|
||||
|
||||
```typescript
|
||||
// src/utils/monitoring.ts
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
|
||||
export interface RequestMetrics {
|
||||
path: string;
|
||||
method: string;
|
||||
statusCode: number;
|
||||
duration: number;
|
||||
sessionId?: string;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export class MonitoringService {
|
||||
private metrics: RequestMetrics[] = [];
|
||||
|
||||
public middleware() {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
const start = Date.now();
|
||||
|
||||
res.on('finish', () => {
|
||||
const metric: RequestMetrics = {
|
||||
path: req.path,
|
||||
method: req.method,
|
||||
statusCode: res.statusCode,
|
||||
duration: Date.now() - start,
|
||||
sessionId: req.headers['mcp-session-id'] as string,
|
||||
timestamp: new Date()
|
||||
};
|
||||
|
||||
this.metrics.push(metric);
|
||||
|
||||
// Keep only last 1000 metrics in memory
|
||||
if (this.metrics.length > 1000) {
|
||||
this.metrics.shift();
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
public getMetrics() {
|
||||
return {
|
||||
requests: this.metrics.length,
|
||||
avgDuration: this.calculateAverage('duration'),
|
||||
errorRate: this.calculateErrorRate(),
|
||||
activeSessions: new Set(this.metrics.map(m => m.sessionId)).size
|
||||
};
|
||||
}
|
||||
|
||||
private calculateAverage(field: keyof RequestMetrics): number {
|
||||
if (this.metrics.length === 0) return 0;
|
||||
const sum = this.metrics.reduce((acc, m) => acc + (m[field] as number || 0), 0);
|
||||
return sum / this.metrics.length;
|
||||
}
|
||||
|
||||
private calculateErrorRate(): number {
|
||||
if (this.metrics.length === 0) return 0;
|
||||
const errors = this.metrics.filter(m => m.statusCode >= 400).length;
|
||||
return errors / this.metrics.length;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### 1. Authentication Token Management
|
||||
- Use strong, random tokens (minimum 32 characters)
|
||||
- Rotate tokens regularly
|
||||
- Never commit tokens to version control
|
||||
- Use environment variables or secret management systems
|
||||
|
||||
### 2. Rate Limiting
|
||||
```typescript
|
||||
import rateLimit from 'express-rate-limit';
|
||||
|
||||
const limiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 100, // limit each IP to 100 requests per windowMs
|
||||
message: 'Too many requests from this IP'
|
||||
});
|
||||
|
||||
app.use('/mcp', limiter);
|
||||
```
|
||||
|
||||
### 3. Input Validation
|
||||
- Validate JSON-RPC structure
|
||||
- Limit request body size
|
||||
- Sanitize any user inputs
|
||||
- Use schema validation for MCP tool parameters
|
||||
|
||||
### 4. HTTPS/TLS
|
||||
- Always use HTTPS in production
|
||||
- Use strong TLS configurations
|
||||
- Enable HSTS headers
|
||||
- Consider certificate pinning for high-security deployments
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### 1. Database Connection Pooling
|
||||
Since we're using SQLite through our adapter, consider:
|
||||
- Read-only replicas for query operations
|
||||
- In-memory caching for frequently accessed nodes
|
||||
- Connection pooling if switching to PostgreSQL
|
||||
|
||||
### 2. Response Caching
|
||||
```typescript
|
||||
const nodeCache = new NodeCache({ stdTTL: 600 }); // 10 minute cache
|
||||
|
||||
// In your tool handlers
|
||||
const cachedResult = nodeCache.get(cacheKey);
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Compression
|
||||
- Already implemented with compression middleware
|
||||
- Consider additional optimizations for large responses
|
||||
|
||||
### 4. CDN Integration
|
||||
- Serve static assets through CDN
|
||||
- Cache API responses where appropriate
|
||||
- Use geographic distribution for global access
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### 1. Unit Tests
|
||||
```typescript
|
||||
// src/test/http-transport.test.ts
|
||||
describe('HTTPTransportServer', () => {
|
||||
it('should create new session on first request', async () => {
|
||||
// Test implementation
|
||||
});
|
||||
|
||||
it('should reuse existing session', async () => {
|
||||
// Test implementation
|
||||
});
|
||||
|
||||
it('should cleanup expired sessions', async () => {
|
||||
// Test implementation
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Integration Tests
|
||||
- Test full request/response cycle
|
||||
- Verify authentication
|
||||
- Test session persistence
|
||||
- Validate error handling
|
||||
|
||||
### 3. Load Testing
|
||||
```bash
|
||||
# Using Apache Bench
|
||||
ab -n 1000 -c 10 -H "Authorization: Bearer your-token" https://your-server/mcp
|
||||
|
||||
# Using k6
|
||||
k6 run load-test.js
|
||||
```
|
||||
|
||||
## Troubleshooting Guide
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Connection Refused**
|
||||
- Check firewall rules
|
||||
- Verify nginx configuration
|
||||
- Ensure Docker container is running
|
||||
|
||||
2. **Authentication Failures**
|
||||
- Verify token format (Bearer prefix)
|
||||
- Check environment variables
|
||||
- Ensure token matches server configuration
|
||||
|
||||
3. **Session Timeout**
|
||||
- Adjust MCP_SESSION_TIMEOUT
|
||||
- Check client keep-alive settings
|
||||
- Monitor server resources
|
||||
|
||||
4. **Performance Issues**
|
||||
- Enable monitoring
|
||||
- Check database query performance
|
||||
- Review nginx access logs
|
||||
- Monitor Docker container resources
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **WebSocket Support**
|
||||
- Implement full duplex communication
|
||||
- Reduce latency for real-time updates
|
||||
- Better support for server-initiated messages
|
||||
|
||||
2. **OAuth2 Integration**
|
||||
- Support for third-party authentication
|
||||
- User-specific access controls
|
||||
- Integration with enterprise SSO
|
||||
|
||||
3. **Multi-tenancy**
|
||||
- Separate databases per organization
|
||||
- Role-based access control
|
||||
- Usage tracking and quotas
|
||||
|
||||
4. **Horizontal Scaling**
|
||||
- Redis for session storage
|
||||
- Load balancer configuration
|
||||
- Distributed caching
|
||||
|
||||
## Conclusion
|
||||
|
||||
This implementation provides a robust foundation for running n8n-MCP as a remote HTTP service. The dual-mode support ensures backward compatibility while enabling new deployment scenarios. With proper security measures and monitoring in place, this solution can scale from single-user deployments to enterprise-wide installations.
|
||||
@@ -1,371 +0,0 @@
|
||||
# HTTP Implementation Roadmap
|
||||
|
||||
## Quick Reference Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐
|
||||
│ Claude Desktop │ stdio │ mcp-remote │ HTTP │ n8n-MCP HTTP │
|
||||
│ ├────────>│ adapter ├────────>│ Server │
|
||||
└─────────────────┘ └──────────────┘ └─────────────────┘
|
||||
│ │
|
||||
│ Auth Token │
|
||||
└──────────────────────────┘
|
||||
```
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
### Prerequisites
|
||||
- [ ] Understand StreamableHTTPServerTransport API
|
||||
- [ ] Review mcp-remote documentation
|
||||
- [ ] Set up test environment with Express.js
|
||||
- [ ] Plan session management strategy
|
||||
|
||||
### Phase 1: Core HTTP Server (Days 1-3)
|
||||
|
||||
#### Day 1: Basic HTTP Server
|
||||
- [ ] Install dependencies: `express`, `cors`, `helmet`, `compression`
|
||||
- [ ] Create `src/mcp/transports/http-transport.ts`
|
||||
- [ ] Implement basic Express server structure
|
||||
- [ ] Add health check endpoint `/health`
|
||||
- [ ] Add MCP endpoint `/mcp` (placeholder)
|
||||
|
||||
#### Day 2: MCP Integration
|
||||
- [ ] Import StreamableHTTPServerTransport
|
||||
- [ ] Implement session management (in-memory)
|
||||
- [ ] Connect transport to MCP server
|
||||
- [ ] Handle JSON-RPC requests
|
||||
- [ ] Test with simple curl commands
|
||||
|
||||
#### Day 3: Authentication & Security
|
||||
- [ ] Implement Bearer token authentication
|
||||
- [ ] Add rate limiting
|
||||
- [ ] Configure CORS properly
|
||||
- [ ] Add request logging
|
||||
- [ ] Basic error handling
|
||||
|
||||
### Phase 2: Server Modifications (Days 4-6)
|
||||
|
||||
#### Day 4: Refactor Server Class
|
||||
- [ ] Modify `N8NDocumentationMCPServer` to accept any transport
|
||||
- [ ] Add `connect(transport)` method
|
||||
- [ ] Update `run()` method for backward compatibility
|
||||
- [ ] Test stdio mode still works
|
||||
|
||||
#### Day 5: Configuration System
|
||||
- [ ] Create configuration interface
|
||||
- [ ] Add environment variable support
|
||||
- [ ] Implement CLI argument parsing
|
||||
- [ ] Create `.env.example` file
|
||||
- [ ] Document all configuration options
|
||||
|
||||
#### Day 6: Unified Entry Point
|
||||
- [ ] Create `index-universal.ts`
|
||||
- [ ] Implement mode detection (stdio vs http)
|
||||
- [ ] Handle graceful shutdown
|
||||
- [ ] Test both modes work correctly
|
||||
|
||||
### Phase 3: Production Readiness (Days 7-9)
|
||||
|
||||
#### Day 7: Docker & Deployment
|
||||
- [ ] Create `Dockerfile.http`
|
||||
- [ ] Add health checks to Docker
|
||||
- [ ] Create `docker-compose.yml`
|
||||
- [ ] Write deployment script
|
||||
- [ ] Test container locally
|
||||
|
||||
#### Day 8: Monitoring & Logging
|
||||
- [ ] Enhance logging with correlation IDs
|
||||
- [ ] Add metrics collection
|
||||
- [ ] Implement `/metrics` endpoint
|
||||
- [ ] Add session analytics
|
||||
- [ ] Create monitoring dashboard
|
||||
|
||||
#### Day 9: Documentation
|
||||
- [ ] Write user setup guide
|
||||
- [ ] Create troubleshooting guide
|
||||
- [ ] Document API endpoints
|
||||
- [ ] Add architecture diagrams
|
||||
- [ ] Create video tutorial
|
||||
|
||||
### Phase 4: Testing & Launch (Days 10-14)
|
||||
|
||||
#### Day 10: Testing Suite
|
||||
- [ ] Unit tests for HTTP transport
|
||||
- [ ] Integration tests for full flow
|
||||
- [ ] Load testing with Apache Bench
|
||||
- [ ] Security testing (auth, injection)
|
||||
- [ ] Cross-platform client testing
|
||||
|
||||
#### Day 11: Beta Deployment
|
||||
- [ ] Deploy to test server
|
||||
- [ ] Configure nginx + SSL
|
||||
- [ ] Test with mcp-remote
|
||||
- [ ] Monitor performance
|
||||
- [ ] Gather initial feedback
|
||||
|
||||
#### Day 12: Performance Optimization
|
||||
- [ ] Implement response caching
|
||||
- [ ] Optimize database queries
|
||||
- [ ] Add connection pooling
|
||||
- [ ] Profile memory usage
|
||||
- [ ] Fine-tune nginx config
|
||||
|
||||
#### Day 13: Security Hardening
|
||||
- [ ] Security audit
|
||||
- [ ] Implement CSP headers
|
||||
- [ ] Add request validation
|
||||
- [ ] Set up fail2ban
|
||||
- [ ] Configure firewall rules
|
||||
|
||||
#### Day 14: Production Launch
|
||||
- [ ] Final deployment
|
||||
- [ ] Update documentation
|
||||
- [ ] Announce to community
|
||||
- [ ] Monitor closely
|
||||
- [ ] Respond to feedback
|
||||
|
||||
## Code Templates
|
||||
|
||||
### 1. Minimal Express Server Test
|
||||
```typescript
|
||||
// test-server.ts - Quick test to verify concept
|
||||
import express from 'express';
|
||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
const transport = new StreamableHTTPServerTransport();
|
||||
|
||||
app.post('/mcp', async (req, res) => {
|
||||
await transport.handleRequest(req, res);
|
||||
});
|
||||
|
||||
app.listen(3000, () => {
|
||||
console.log('Test server running on http://localhost:3000');
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Environment Variables
|
||||
```bash
|
||||
# .env
|
||||
MCP_MODE=http
|
||||
MCP_PORT=3000
|
||||
MCP_HOST=0.0.0.0
|
||||
MCP_AUTH_TOKEN=development-token-change-in-production
|
||||
MCP_SESSION_TIMEOUT=1800000
|
||||
MCP_MAX_SESSIONS=50
|
||||
MCP_CORS_ORIGINS=http://localhost:3000,https://claude.ai
|
||||
NODE_ENV=development
|
||||
LOG_LEVEL=debug
|
||||
```
|
||||
|
||||
### 3. Test Script
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# test-http.sh - Test HTTP endpoint
|
||||
|
||||
TOKEN="development-token-change-in-production"
|
||||
URL="http://localhost:3000/mcp"
|
||||
|
||||
# Test health check
|
||||
curl -s http://localhost:3000/health | jq .
|
||||
|
||||
# Test MCP endpoint
|
||||
curl -s -X POST $URL \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "tools/list",
|
||||
"id": 1
|
||||
}' | jq .
|
||||
```
|
||||
|
||||
### 4. nginx Configuration
|
||||
```nginx
|
||||
# /etc/nginx/sites-available/n8n-mcp
|
||||
server {
|
||||
listen 80;
|
||||
server_name mcp.yourdomain.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name mcp.yourdomain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
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_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Claude Desktop Config
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-docs-remote": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"mcp-remote@latest",
|
||||
"connect",
|
||||
"https://mcp.yourdomain.com/mcp"
|
||||
],
|
||||
"env": {
|
||||
"MCP_AUTH_TOKEN": "your-secure-token"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Scenarios
|
||||
|
||||
### Scenario 1: Basic Connectivity
|
||||
1. Start HTTP server locally
|
||||
2. Use curl to test endpoints
|
||||
3. Verify authentication works
|
||||
4. Check session creation
|
||||
|
||||
### Scenario 2: mcp-remote Integration
|
||||
1. Install mcp-remote globally
|
||||
2. Configure with local server
|
||||
3. Test all MCP tools work
|
||||
4. Verify session persistence
|
||||
|
||||
### Scenario 3: Load Testing
|
||||
```bash
|
||||
# Test 100 concurrent users
|
||||
ab -n 1000 -c 100 \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-p request.json \
|
||||
http://localhost:3000/mcp
|
||||
```
|
||||
|
||||
### Scenario 4: Security Testing
|
||||
1. Test without auth token (should fail)
|
||||
2. Test with invalid token (should fail)
|
||||
3. Test SQL injection attempts
|
||||
4. Test large payload handling
|
||||
5. Test rate limiting
|
||||
|
||||
## Deployment Commands
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Start in development mode
|
||||
npm run dev:http
|
||||
|
||||
# Watch logs
|
||||
tail -f logs/mcp-http.log
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
```bash
|
||||
# Build and deploy
|
||||
npm run build
|
||||
docker build -f Dockerfile.http -t n8n-mcp-http .
|
||||
docker run -d --name n8n-mcp-http \
|
||||
-p 3000:3000 \
|
||||
--env-file .env.production \
|
||||
--restart unless-stopped \
|
||||
n8n-mcp-http
|
||||
|
||||
# Check status
|
||||
docker logs n8n-mcp-http
|
||||
curl https://mcp.yourdomain.com/health
|
||||
```
|
||||
|
||||
## Monitoring Checklist
|
||||
|
||||
### Application Metrics
|
||||
- [ ] Request rate
|
||||
- [ ] Response times
|
||||
- [ ] Error rates
|
||||
- [ ] Active sessions
|
||||
- [ ] Memory usage
|
||||
- [ ] CPU usage
|
||||
|
||||
### Business Metrics
|
||||
- [ ] Unique users
|
||||
- [ ] Most used tools
|
||||
- [ ] Peak usage times
|
||||
- [ ] Geographic distribution
|
||||
|
||||
### Alerts to Configure
|
||||
- [ ] Server down
|
||||
- [ ] High error rate (> 5%)
|
||||
- [ ] Slow response times (> 1s)
|
||||
- [ ] Memory usage > 80%
|
||||
- [ ] Disk space < 20%
|
||||
- [ ] SSL certificate expiring
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If issues arise:
|
||||
|
||||
1. **Immediate**: Switch DNS back to maintenance page
|
||||
2. **Quick Fix**: Rollback Docker container to previous version
|
||||
3. **Investigate**: Check logs and metrics
|
||||
4. **Fix Forward**: Deploy hotfix if simple
|
||||
5. **Full Rollback**: Restore previous version if complex
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Week 1
|
||||
- [ ] HTTP server running locally
|
||||
- [ ] All MCP tools working via HTTP
|
||||
- [ ] Basic authentication working
|
||||
- [ ] Session management functional
|
||||
|
||||
### Week 2
|
||||
- [ ] Deployed to test environment
|
||||
- [ ] SSL/HTTPS working
|
||||
- [ ] mcp-remote integration tested
|
||||
- [ ] Documentation complete
|
||||
|
||||
### Week 3
|
||||
- [ ] Beta users testing
|
||||
- [ ] Performance acceptable
|
||||
- [ ] No security issues found
|
||||
- [ ] Monitoring in place
|
||||
|
||||
### Week 4
|
||||
- [ ] Production deployment
|
||||
- [ ] Public announcement
|
||||
- [ ] User adoption beginning
|
||||
- [ ] Positive feedback
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
After successful launch, consider:
|
||||
|
||||
1. **WebSocket Support** - Real-time bidirectional communication
|
||||
2. **OAuth2/SSO** - Enterprise authentication
|
||||
3. **Multi-tenancy** - Separate instances per organization
|
||||
4. **Usage Analytics** - Detailed usage tracking
|
||||
5. **API Keys** - Per-user authentication
|
||||
6. **Webhooks** - Event notifications
|
||||
7. **Clustering** - Horizontal scaling
|
||||
8. **GraphQL API** - Alternative query interface
|
||||
|
||||
This roadmap provides a clear, actionable path to implementing HTTP support in n8n-MCP. Each phase builds on the previous one, ensuring a stable and well-tested deployment.
|
||||
@@ -1,286 +0,0 @@
|
||||
# HTTP Remote Deployment Plan for n8n-MCP
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This document outlines the comprehensive plan to transform the n8n-MCP server from a local stdio-based implementation to a remote HTTP-accessible service that can be deployed on the internet and accessed by Claude Desktop users from anywhere.
|
||||
|
||||
## Current State Analysis
|
||||
|
||||
### Current Architecture
|
||||
- **Transport**: StdioServerTransport (requires local execution)
|
||||
- **Communication**: stdin/stdout between Claude Desktop and the MCP server
|
||||
- **Deployment**: Must run on the same machine as Claude Desktop
|
||||
- **Authentication**: None (implicit trust from local execution)
|
||||
- **State Management**: Single instance per process
|
||||
|
||||
### Limitations
|
||||
1. Users must install and maintain the server locally
|
||||
2. No centralized updates or management
|
||||
3. Limited to single-user scenarios
|
||||
4. Requires Node.js and dependencies on client machine
|
||||
|
||||
## Target Architecture
|
||||
|
||||
### Goals
|
||||
1. Deploy n8n-MCP server on remote infrastructure (VPS, cloud, etc.)
|
||||
2. Enable multiple Claude Desktop users to connect to a single server instance
|
||||
3. Maintain security through authentication and encryption
|
||||
4. Support both local (stdio) and remote (HTTP) modes for flexibility
|
||||
|
||||
### Technical Requirements
|
||||
|
||||
#### 1. HTTP Transport Implementation
|
||||
- Use `StreamableHTTPServerTransport` from `@modelcontextprotocol/sdk`
|
||||
- Implement session management for stateful connections
|
||||
- Support JSON-RPC 2.0 protocol over HTTP
|
||||
- Handle both request/response and server-sent events
|
||||
|
||||
#### 2. Authentication & Security
|
||||
- Implement Bearer token authentication
|
||||
- Use HTTPS/TLS for all communications
|
||||
- Consider OAuth2 for advanced scenarios
|
||||
- Rate limiting and DDoS protection
|
||||
|
||||
#### 3. Infrastructure Requirements
|
||||
- HTTP server (Express.js recommended)
|
||||
- SSL certificates (Let's Encrypt)
|
||||
- Reverse proxy (nginx/Caddy)
|
||||
- Process manager (PM2)
|
||||
- Domain name for stable endpoint
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Core HTTP Server Implementation
|
||||
|
||||
#### 1.1 Create HTTP Server Module
|
||||
```typescript
|
||||
// src/mcp/http-server.ts
|
||||
import express from 'express';
|
||||
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
import { N8NDocumentationMCPServer } from './server-update';
|
||||
|
||||
interface Session {
|
||||
id: string;
|
||||
transport: StreamableHTTPServerTransport;
|
||||
server: N8NDocumentationMCPServer;
|
||||
lastActivity: Date;
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 Session Management
|
||||
- Implement session creation and cleanup
|
||||
- Handle concurrent sessions
|
||||
- Add session timeout (e.g., 30 minutes)
|
||||
- Store session state in memory (consider Redis for production)
|
||||
|
||||
#### 1.3 Authentication Middleware
|
||||
```typescript
|
||||
const authenticateToken = (req: Request, res: Response, next: NextFunction) => {
|
||||
const authHeader = req.headers['authorization'];
|
||||
const token = authHeader && authHeader.split(' ')[1];
|
||||
|
||||
if (!token || token !== process.env.AUTH_TOKEN) {
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
```
|
||||
|
||||
### Phase 2: Dual-Mode Support
|
||||
|
||||
#### 2.1 Configuration System
|
||||
```typescript
|
||||
interface ServerConfig {
|
||||
mode: 'stdio' | 'http';
|
||||
http?: {
|
||||
port: number;
|
||||
host: string;
|
||||
authToken: string;
|
||||
ssl?: {
|
||||
cert: string;
|
||||
key: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 Entry Point Refactoring
|
||||
- Create unified entry point that can start either stdio or HTTP server
|
||||
- Use environment variables or CLI arguments for mode selection
|
||||
- Maintain backward compatibility with existing stdio mode
|
||||
|
||||
### Phase 3: Client Adapter Implementation
|
||||
|
||||
#### 3.1 mcp-remote Integration
|
||||
Since Claude Desktop doesn't natively support HTTP transport yet, we need to:
|
||||
1. Document how to use `mcp-remote` adapter
|
||||
2. Create wrapper scripts for easy setup
|
||||
3. Provide configuration examples
|
||||
|
||||
#### 3.2 Claude Desktop Configuration
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation-remote": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
"https://your-server.com/mcp",
|
||||
"--auth-token", "your-auth-token"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 4: Deployment Infrastructure
|
||||
|
||||
#### 4.1 Docker Container
|
||||
```dockerfile
|
||||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN npm ci --only=production
|
||||
RUN npm run build
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "run", "start:http"]
|
||||
```
|
||||
|
||||
#### 4.2 Nginx Configuration
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name mcp.your-domain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/mcp.your-domain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/mcp.your-domain.com/privkey.pem;
|
||||
|
||||
location /mcp {
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.3 PM2 Configuration
|
||||
```json
|
||||
{
|
||||
"apps": [{
|
||||
"name": "n8n-mcp-server",
|
||||
"script": "./dist/mcp/http-server.js",
|
||||
"env": {
|
||||
"NODE_ENV": "production",
|
||||
"PORT": 3000,
|
||||
"AUTH_TOKEN": "your-secure-token"
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Challenges & Solutions
|
||||
|
||||
### 1. State Management
|
||||
**Challenge**: MCP servers can be stateful, but HTTP is stateless by nature.
|
||||
**Solution**: Implement session management with unique session IDs in headers.
|
||||
|
||||
### 2. Authentication with mcp-remote
|
||||
**Challenge**: mcp-remote needs to pass authentication to the remote server.
|
||||
**Solution**: Use environment variables or command-line arguments for auth tokens.
|
||||
|
||||
### 3. Database Access
|
||||
**Challenge**: Multiple concurrent sessions accessing SQLite database.
|
||||
**Solution**: Our database adapter already handles this; sql.js runs in-memory with persistence.
|
||||
|
||||
### 4. Performance & Scaling
|
||||
**Challenge**: Single server instance handling multiple clients.
|
||||
**Solution**:
|
||||
- Implement connection pooling
|
||||
- Add caching layer for frequently accessed data
|
||||
- Consider horizontal scaling with load balancer
|
||||
|
||||
### 5. Security
|
||||
**Challenge**: Exposing MCP server to the internet.
|
||||
**Solution**:
|
||||
- Mandatory HTTPS
|
||||
- Strong authentication tokens
|
||||
- Rate limiting
|
||||
- Input validation
|
||||
- Regular security audits
|
||||
|
||||
## Implementation Timeline
|
||||
|
||||
### Week 1: Core HTTP Server
|
||||
- [ ] Implement basic HTTP server with Express
|
||||
- [ ] Integrate StreamableHTTPServerTransport
|
||||
- [ ] Add session management
|
||||
- [ ] Implement authentication
|
||||
|
||||
### Week 2: Dual-Mode Support
|
||||
- [ ] Refactor entry points
|
||||
- [ ] Add configuration system
|
||||
- [ ] Test both stdio and HTTP modes
|
||||
- [ ] Update documentation
|
||||
|
||||
### Week 3: Client Integration
|
||||
- [ ] Test with mcp-remote adapter
|
||||
- [ ] Create setup scripts
|
||||
- [ ] Document Claude Desktop configuration
|
||||
- [ ] Create troubleshooting guide
|
||||
|
||||
### Week 4: Deployment
|
||||
- [ ] Create Docker container
|
||||
- [ ] Set up test deployment
|
||||
- [ ] Configure nginx/SSL
|
||||
- [ ] Performance testing
|
||||
- [ ] Security hardening
|
||||
|
||||
## Alternative Approaches
|
||||
|
||||
### 1. Cloudflare Workers
|
||||
- **Pros**: Global edge deployment, built-in DDoS protection
|
||||
- **Cons**: Limited execution time, stateless by design
|
||||
|
||||
### 2. AWS Lambda
|
||||
- **Pros**: Serverless, auto-scaling
|
||||
- **Cons**: Cold starts, complex state management
|
||||
|
||||
### 3. Dedicated WebSocket Server
|
||||
- **Pros**: Real-time bidirectional communication
|
||||
- **Cons**: More complex implementation, not standard MCP transport
|
||||
|
||||
## Success Metrics
|
||||
|
||||
1. **Functionality**: All MCP tools work identically in remote mode
|
||||
2. **Performance**: Response time < 200ms for most operations
|
||||
3. **Reliability**: 99.9% uptime
|
||||
4. **Security**: No unauthorized access incidents
|
||||
5. **Usability**: Clear documentation and easy setup
|
||||
|
||||
## Risks & Mitigations
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|---------|------------|
|
||||
| Claude Desktop HTTP support delayed | High | Use mcp-remote adapter as bridge |
|
||||
| Security breach | High | Regular audits, penetration testing |
|
||||
| Performance degradation | Medium | Caching, CDN, horizontal scaling |
|
||||
| Database corruption | Medium | Regular backups, read replicas |
|
||||
| Cost overruns | Low | Start with single VPS, scale as needed |
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Validate Approach**: Test StreamableHTTPServerTransport with simple example
|
||||
2. **Prototype**: Build minimal HTTP server with single tool
|
||||
3. **Security Review**: Have security expert review authentication approach
|
||||
4. **Community Feedback**: Share plan with MCP community for input
|
||||
5. **Begin Implementation**: Start with Phase 1 core server
|
||||
|
||||
## Conclusion
|
||||
|
||||
Transitioning n8n-MCP to support remote HTTP deployment will significantly expand its usability and reach. While Claude Desktop doesn't yet natively support HTTP transport, the mcp-remote adapter provides a viable bridge solution. The implementation plan balances immediate functionality with future-proofing for when native HTTP support arrives.
|
||||
|
||||
The key to success will be maintaining compatibility with existing stdio users while providing a seamless experience for remote users. With proper security measures and careful implementation, n8n-MCP can become a centrally-hosted service that benefits the entire Claude Desktop community.
|
||||
@@ -1,251 +0,0 @@
|
||||
# HTTP Remote Deployment - Executive Summary
|
||||
|
||||
## Current Situation
|
||||
|
||||
The n8n-MCP server currently only works locally on the same machine as Claude Desktop. This limits its usefulness and prevents centralized deployment, updates, and management.
|
||||
|
||||
## Key Finding: Claude Desktop Limitation
|
||||
|
||||
**Critical Discovery**: Claude Desktop does NOT currently support remote MCP servers natively. It only supports the stdio (standard input/output) transport protocol, which requires local execution.
|
||||
|
||||
## The Solution: mcp-remote Bridge
|
||||
|
||||
The MCP community has developed `mcp-remote`, an adapter that bridges the gap:
|
||||
- Acts as a local stdio server that Claude Desktop can communicate with
|
||||
- Forwards requests to remote HTTP MCP servers
|
||||
- Handles authentication and session management
|
||||
- Provides transparent proxy functionality
|
||||
|
||||
## Implementation Overview
|
||||
|
||||
### 1. Server-Side Changes
|
||||
|
||||
We need to add HTTP transport support to n8n-MCP:
|
||||
|
||||
```typescript
|
||||
// New capabilities to add:
|
||||
- HTTP endpoint (/mcp) that accepts JSON-RPC requests
|
||||
- Session management for stateful connections
|
||||
- Bearer token authentication
|
||||
- HTTPS/TLS encryption
|
||||
- Health check endpoints
|
||||
```
|
||||
|
||||
### 2. Dual-Mode Operation
|
||||
|
||||
The server will support both modes:
|
||||
- **stdio mode**: Current local operation (no changes for existing users)
|
||||
- **http mode**: New remote operation for internet deployment
|
||||
|
||||
### 3. Client Configuration
|
||||
|
||||
Users will configure Claude Desktop like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-remote": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"mcp-remote@latest",
|
||||
"connect",
|
||||
"https://your-mcp-server.com/mcp"
|
||||
],
|
||||
"env": {
|
||||
"MCP_AUTH_TOKEN": "your-secure-token"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Architecture
|
||||
|
||||
### Components
|
||||
|
||||
1. **Express.js HTTP Server**
|
||||
- Handles incoming HTTP requests
|
||||
- Manages authentication
|
||||
- Provides CORS support
|
||||
|
||||
2. **StreamableHTTPServerTransport**
|
||||
- MCP SDK's HTTP transport implementation
|
||||
- Handles JSON-RPC protocol
|
||||
- Supports Server-Sent Events for bidirectional communication
|
||||
|
||||
3. **Session Manager**
|
||||
- Creates unique sessions per client
|
||||
- Maintains state between requests
|
||||
- Handles cleanup of inactive sessions
|
||||
|
||||
4. **Database Adapter**
|
||||
- Our existing adapter works perfectly
|
||||
- Handles concurrent access
|
||||
- No changes needed
|
||||
|
||||
## Security Model
|
||||
|
||||
1. **Authentication**: Bearer token in Authorization header
|
||||
2. **Encryption**: HTTPS/TLS required for production
|
||||
3. **Rate Limiting**: Prevent abuse and DDoS
|
||||
4. **Input Validation**: Sanitize all inputs
|
||||
5. **CORS**: Restrict allowed origins
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Option 1: VPS/Cloud VM
|
||||
- Full control over environment
|
||||
- Can handle many concurrent users
|
||||
- Requires server management
|
||||
|
||||
### Option 2: Docker Container
|
||||
- Easy deployment and updates
|
||||
- Consistent environment
|
||||
- Good for scaling
|
||||
|
||||
### Option 3: Managed Platforms
|
||||
- Cloudflare Workers (with limitations)
|
||||
- AWS Lambda (stateless challenges)
|
||||
- Heroku/Railway (simple deployment)
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Core HTTP Server (Week 1)
|
||||
- Implement Express server with MCP endpoint
|
||||
- Add StreamableHTTPServerTransport
|
||||
- Basic authentication
|
||||
- Session management
|
||||
|
||||
### Phase 2: Integration (Week 2)
|
||||
- Modify existing server for dual-mode
|
||||
- Add configuration system
|
||||
- Update entry points
|
||||
- Maintain backward compatibility
|
||||
|
||||
### Phase 3: Deployment (Week 3)
|
||||
- Create Docker container
|
||||
- Write deployment scripts
|
||||
- Set up nginx/SSL
|
||||
- Document setup process
|
||||
|
||||
### Phase 4: Testing & Launch (Week 4)
|
||||
- Security testing
|
||||
- Performance testing
|
||||
- Documentation
|
||||
- Community release
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Centralized Management**
|
||||
- Single server for multiple users
|
||||
- Easy updates and maintenance
|
||||
- Consistent experience
|
||||
|
||||
2. **No Local Installation**
|
||||
- Users don't need Node.js
|
||||
- No dependency management
|
||||
- Works on any OS
|
||||
|
||||
3. **Enterprise Ready**
|
||||
- Authentication and access control
|
||||
- Monitoring and logging
|
||||
- Scalable architecture
|
||||
|
||||
4. **Cost Effective**
|
||||
- One server serves many users
|
||||
- Efficient resource usage
|
||||
- Pay for what you use
|
||||
|
||||
## Challenges & Solutions
|
||||
|
||||
| Challenge | Solution |
|
||||
|-----------|----------|
|
||||
| Claude Desktop doesn't support HTTP | Use mcp-remote adapter |
|
||||
| Session state management | Implement session manager with timeout |
|
||||
| Security concerns | Strong auth, HTTPS, rate limiting |
|
||||
| Database concurrency | Our adapter already handles this |
|
||||
| Performance at scale | Caching, CDN, horizontal scaling |
|
||||
|
||||
## Cost Estimate
|
||||
|
||||
### Small Deployment (< 50 users)
|
||||
- VPS: $10-20/month
|
||||
- Domain: $10/year
|
||||
- SSL: Free (Let's Encrypt)
|
||||
- Total: ~$15/month
|
||||
|
||||
### Medium Deployment (50-500 users)
|
||||
- Better VPS: $40-80/month
|
||||
- CDN: $20/month
|
||||
- Monitoring: $10/month
|
||||
- Total: ~$70/month
|
||||
|
||||
### Large Deployment (500+ users)
|
||||
- Load balanced setup: $200+/month
|
||||
- Redis for sessions: $30/month
|
||||
- Advanced monitoring: $50/month
|
||||
- Total: ~$280/month
|
||||
|
||||
## Success Metrics
|
||||
|
||||
1. **Technical Success**
|
||||
- All MCP tools work remotely
|
||||
- Response time < 200ms
|
||||
- 99.9% uptime
|
||||
|
||||
2. **User Success**
|
||||
- Easy setup (< 5 minutes)
|
||||
- Clear documentation
|
||||
- Positive feedback
|
||||
|
||||
3. **Operational Success**
|
||||
- Low maintenance overhead
|
||||
- Automated monitoring
|
||||
- Smooth updates
|
||||
|
||||
## Recommended Next Steps
|
||||
|
||||
1. **Immediate Actions**
|
||||
- Review and approve the implementation plan
|
||||
- Set up development environment
|
||||
- Begin Phase 1 implementation
|
||||
|
||||
2. **Short Term (1-2 weeks)**
|
||||
- Complete HTTP server implementation
|
||||
- Test with mcp-remote
|
||||
- Deploy beta version
|
||||
|
||||
3. **Medium Term (3-4 weeks)**
|
||||
- Production deployment
|
||||
- Documentation and guides
|
||||
- Community announcement
|
||||
|
||||
4. **Long Term (2-3 months)**
|
||||
- Gather feedback
|
||||
- Implement enhancements
|
||||
- Consider enterprise features
|
||||
|
||||
## Conclusion
|
||||
|
||||
Adding HTTP remote deployment to n8n-MCP is technically feasible and highly beneficial. While Claude Desktop's current limitations require using the mcp-remote adapter, this is a proven solution already in use by other MCP servers.
|
||||
|
||||
The implementation is straightforward, building on our existing robust architecture. The database adapter system we recently implemented will work perfectly in a multi-user environment.
|
||||
|
||||
This enhancement will transform n8n-MCP from a local tool to a cloud-ready service, greatly expanding its reach and usefulness to the Claude Desktop community.
|
||||
|
||||
## Key Decision Points
|
||||
|
||||
1. **Should we proceed with HTTP implementation?**
|
||||
- Recommendation: Yes, the benefits far outweigh the complexity
|
||||
|
||||
2. **Which deployment option should we prioritize?**
|
||||
- Recommendation: Start with VPS + Docker for flexibility
|
||||
|
||||
3. **How should we handle authentication?**
|
||||
- Recommendation: Start with Bearer tokens, consider OAuth2 later
|
||||
|
||||
4. **When should we launch?**
|
||||
- Recommendation: Beta in 2 weeks, production in 4 weeks
|
||||
|
||||
The path forward is clear, and the technical approach is sound. With careful implementation and testing, n8n-MCP can become a premier remote MCP service for the Claude Desktop ecosystem.
|
||||
@@ -1,650 +0,0 @@
|
||||
# n8n-MCP Enhancement Implementation Plan v2.1 Final
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This ultra-focused MVP implementation plan delivers accurate n8n node documentation in 2 weeks by working directly with n8n's architecture. We prioritize simplicity and accuracy over complex features.
|
||||
|
||||
## Core MVP Principles
|
||||
|
||||
1. **Start with the simplest thing that works**
|
||||
2. **Test with real nodes early and often**
|
||||
3. **Don't try to be too clever** - n8n's structure is fine
|
||||
4. **Focus on accuracy over completeness**
|
||||
5. **Work WITH n8n's architecture, not against it**
|
||||
|
||||
## Key Insight
|
||||
|
||||
**We're not trying to understand n8n's nodes, we're just accurately cataloging them.**
|
||||
|
||||
## Simplified Architecture
|
||||
|
||||
```
|
||||
n8n-mcp/
|
||||
├── src/
|
||||
│ ├── loaders/
|
||||
│ │ └── node-loader.ts # Simple npm package loader
|
||||
│ ├── parsers/
|
||||
│ │ └── simple-parser.ts # Single parser for all nodes
|
||||
│ ├── mappers/
|
||||
│ │ └── docs-mapper.ts # Deterministic documentation mapping
|
||||
│ ├── scripts/
|
||||
│ │ ├── rebuild.ts # One-command rebuild
|
||||
│ │ └── validate.ts # Validation script
|
||||
│ └── mcp/
|
||||
│ └── server.ts # Enhanced MCP server
|
||||
└── data/
|
||||
└── nodes.db # Minimal SQLite database
|
||||
```
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Quick Win Approach
|
||||
Get *something* working end-to-end on Day 1, even if it only loads 5 nodes. This proves the architecture and builds momentum.
|
||||
|
||||
### Documentation Strategy
|
||||
Clone the n8n-docs repo locally for simpler file-based access:
|
||||
```bash
|
||||
git clone https://github.com/n8n-io/n8n-docs.git ../n8n-docs
|
||||
```
|
||||
|
||||
### Test-First Development
|
||||
Build the rebuild script first as a test harness:
|
||||
```bash
|
||||
npm run rebuild && sqlite3 data/nodes.db "SELECT node_type, display_name FROM nodes LIMIT 10"
|
||||
```
|
||||
|
||||
## Week 1: Core Implementation
|
||||
|
||||
### Day 1-2: Simple Node Loader + Initial Rebuild Script
|
||||
|
||||
**Start with the rebuild script to enable quick iteration!**
|
||||
|
||||
**File**: `src/scripts/rebuild.ts` (Build this first!)
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import Database from 'better-sqlite3';
|
||||
import { N8nNodeLoader } from '../loaders/node-loader';
|
||||
import { SimpleParser } from '../parsers/simple-parser';
|
||||
import { DocsMapper } from '../mappers/docs-mapper';
|
||||
|
||||
async function rebuild() {
|
||||
console.log('🔄 Rebuilding n8n node database...\n');
|
||||
|
||||
const db = new Database('./data/nodes.db');
|
||||
const loader = new N8nNodeLoader();
|
||||
const parser = new SimpleParser();
|
||||
const mapper = new DocsMapper();
|
||||
|
||||
// Initialize database
|
||||
const schema = require('fs').readFileSync('./src/database/schema.sql', 'utf8');
|
||||
db.exec(schema);
|
||||
|
||||
// Clear existing data
|
||||
db.exec('DELETE FROM nodes');
|
||||
console.log('🗑️ Cleared existing data\n');
|
||||
|
||||
// Load all nodes
|
||||
const nodes = await loader.loadAllNodes();
|
||||
console.log(`📦 Loaded ${nodes.length} nodes from packages\n`);
|
||||
|
||||
// Statistics
|
||||
let successful = 0;
|
||||
let failed = 0;
|
||||
let aiTools = 0;
|
||||
|
||||
// Process each node
|
||||
for (const { packageName, nodeName, NodeClass } of nodes) {
|
||||
try {
|
||||
// Parse node
|
||||
const parsed = parser.parse(NodeClass);
|
||||
|
||||
// Get documentation
|
||||
const docs = await mapper.fetchDocumentation(parsed.nodeType);
|
||||
|
||||
// Insert into database
|
||||
db.prepare(`
|
||||
INSERT INTO nodes (
|
||||
node_type, package_name, display_name, description,
|
||||
category, development_style, is_ai_tool, is_trigger,
|
||||
is_webhook, is_versioned, version, documentation,
|
||||
properties_schema, operations, credentials_required
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
parsed.nodeType,
|
||||
packageName,
|
||||
parsed.displayName,
|
||||
parsed.description,
|
||||
parsed.category,
|
||||
parsed.style,
|
||||
parsed.isAITool ? 1 : 0,
|
||||
parsed.isTrigger ? 1 : 0,
|
||||
parsed.isWebhook ? 1 : 0,
|
||||
parsed.isVersioned ? 1 : 0,
|
||||
parsed.version,
|
||||
docs,
|
||||
JSON.stringify(parsed.properties),
|
||||
JSON.stringify(parsed.operations),
|
||||
JSON.stringify(parsed.credentials)
|
||||
);
|
||||
|
||||
successful++;
|
||||
if (parsed.isAITool) aiTools++;
|
||||
|
||||
console.log(`✅ ${parsed.nodeType}`);
|
||||
} catch (error) {
|
||||
failed++;
|
||||
console.error(`❌ Failed to process ${nodeName}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Summary
|
||||
console.log('\n📊 Summary:');
|
||||
console.log(` Total nodes: ${nodes.length}`);
|
||||
console.log(` Successful: ${successful}`);
|
||||
console.log(` Failed: ${failed}`);
|
||||
console.log(` AI Tools: ${aiTools}`);
|
||||
console.log('\n✨ Rebuild complete!');
|
||||
|
||||
db.close();
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (require.main === module) {
|
||||
rebuild().catch(console.error);
|
||||
}
|
||||
```
|
||||
|
||||
**File**: `src/loaders/node-loader.ts`
|
||||
|
||||
```typescript
|
||||
export class N8nNodeLoader {
|
||||
private readonly CORE_PACKAGES = [
|
||||
'n8n-nodes-base',
|
||||
'@n8n/n8n-nodes-langchain'
|
||||
];
|
||||
|
||||
async loadAllNodes() {
|
||||
const results = [];
|
||||
|
||||
for (const pkg of this.CORE_PACKAGES) {
|
||||
try {
|
||||
// Direct require - no complex path resolution
|
||||
const packageJson = require(`${pkg}/package.json`);
|
||||
const nodes = await this.loadPackageNodes(pkg, packageJson);
|
||||
results.push(...nodes);
|
||||
} catch (error) {
|
||||
console.error(`Failed to load ${pkg}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private async loadPackageNodes(packageName: string, packageJson: any) {
|
||||
const n8nConfig = packageJson.n8n || {};
|
||||
const nodes = [];
|
||||
|
||||
// Load from n8n.nodes configuration
|
||||
for (const [nodeName, nodePath] of Object.entries(n8nConfig.nodes || {})) {
|
||||
const fullPath = require.resolve(`${packageName}/${nodePath}`);
|
||||
const nodeModule = require(fullPath);
|
||||
|
||||
// Handle default export
|
||||
const NodeClass = nodeModule.default || nodeModule[nodeName];
|
||||
nodes.push({ packageName, nodeName, NodeClass });
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Day 3: Simple Parser
|
||||
|
||||
**File**: `src/parsers/simple-parser.ts`
|
||||
|
||||
```typescript
|
||||
export interface ParsedNode {
|
||||
style: 'declarative' | 'programmatic';
|
||||
nodeType: string;
|
||||
displayName: string;
|
||||
description?: string;
|
||||
category?: string;
|
||||
properties: any[];
|
||||
credentials: string[];
|
||||
isAITool: boolean;
|
||||
isTrigger: boolean;
|
||||
isWebhook: boolean;
|
||||
operations: any[];
|
||||
version?: string;
|
||||
isVersioned: boolean;
|
||||
}
|
||||
|
||||
export class SimpleParser {
|
||||
parse(nodeClass: any): ParsedNode {
|
||||
const description = nodeClass.description || {};
|
||||
const isDeclarative = !!description.routing;
|
||||
|
||||
return {
|
||||
style: isDeclarative ? 'declarative' : 'programmatic',
|
||||
nodeType: description.name,
|
||||
displayName: description.displayName,
|
||||
description: description.description,
|
||||
category: description.group?.[0] || description.categories?.[0],
|
||||
properties: description.properties || [],
|
||||
credentials: description.credentials || [],
|
||||
isAITool: description.usableAsTool === true,
|
||||
isTrigger: description.polling === true || description.trigger === true,
|
||||
isWebhook: description.webhooks?.length > 0,
|
||||
operations: isDeclarative ? this.extractOperations(description.routing) : [],
|
||||
version: this.extractVersion(nodeClass),
|
||||
isVersioned: this.isVersionedNode(nodeClass)
|
||||
};
|
||||
}
|
||||
|
||||
private extractOperations(routing: any): any[] {
|
||||
// Simple extraction without complex logic
|
||||
const operations = [];
|
||||
const resources = routing?.request?.resource?.options || [];
|
||||
|
||||
resources.forEach(resource => {
|
||||
operations.push({
|
||||
resource: resource.value,
|
||||
name: resource.name
|
||||
});
|
||||
});
|
||||
|
||||
return operations;
|
||||
}
|
||||
|
||||
private extractVersion(nodeClass: any): string {
|
||||
if (nodeClass.baseDescription?.defaultVersion) {
|
||||
return nodeClass.baseDescription.defaultVersion.toString();
|
||||
}
|
||||
return nodeClass.description?.version || '1';
|
||||
}
|
||||
|
||||
private isVersionedNode(nodeClass: any): boolean {
|
||||
return !!(nodeClass.baseDescription && nodeClass.nodeVersions);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Day 4: Documentation Mapper
|
||||
|
||||
**File**: `src/mappers/docs-mapper.ts`
|
||||
|
||||
```typescript
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
export class DocsMapper {
|
||||
private docsPath = path.join(__dirname, '../../../n8n-docs');
|
||||
|
||||
// Known documentation mapping fixes
|
||||
private readonly KNOWN_FIXES = {
|
||||
'n8n-nodes-base.httpRequest': 'httprequest',
|
||||
'n8n-nodes-base.code': 'code',
|
||||
'n8n-nodes-base.webhook': 'webhook',
|
||||
'n8n-nodes-base.respondToWebhook': 'respondtowebhook'
|
||||
};
|
||||
|
||||
async fetchDocumentation(nodeType: string): Promise<string | null> {
|
||||
// Apply known fixes first
|
||||
const fixedType = this.KNOWN_FIXES[nodeType] || nodeType;
|
||||
|
||||
// Extract node name
|
||||
const nodeName = fixedType.split('.').pop()?.toLowerCase();
|
||||
if (!nodeName) return null;
|
||||
|
||||
// Try different documentation paths
|
||||
const possiblePaths = [
|
||||
`docs/integrations/builtin/core-nodes/n8n-nodes-base.${nodeName}.md`,
|
||||
`docs/integrations/builtin/app-nodes/n8n-nodes-base.${nodeName}.md`,
|
||||
`docs/integrations/builtin/trigger-nodes/n8n-nodes-base.${nodeName}.md`,
|
||||
`docs/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.${nodeName}.md`
|
||||
];
|
||||
|
||||
// Try each path
|
||||
for (const relativePath of possiblePaths) {
|
||||
try {
|
||||
const fullPath = path.join(this.docsPath, relativePath);
|
||||
const content = await fs.readFile(fullPath, 'utf-8');
|
||||
return content;
|
||||
} catch (error) {
|
||||
// File doesn't exist, try next
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Day 5: Database Setup
|
||||
|
||||
**File**: `src/database/schema.sql`
|
||||
|
||||
```sql
|
||||
-- Ultra-simple schema for MVP
|
||||
CREATE TABLE IF NOT EXISTS nodes (
|
||||
node_type TEXT PRIMARY KEY,
|
||||
package_name TEXT NOT NULL,
|
||||
display_name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
category TEXT,
|
||||
development_style TEXT CHECK(development_style IN ('declarative', 'programmatic')),
|
||||
is_ai_tool INTEGER DEFAULT 0,
|
||||
is_trigger INTEGER DEFAULT 0,
|
||||
is_webhook INTEGER DEFAULT 0,
|
||||
is_versioned INTEGER DEFAULT 0,
|
||||
version TEXT,
|
||||
documentation TEXT,
|
||||
properties_schema TEXT,
|
||||
operations TEXT,
|
||||
credentials_required TEXT,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Minimal indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_package ON nodes(package_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_ai_tool ON nodes(is_ai_tool);
|
||||
CREATE INDEX IF NOT EXISTS idx_category ON nodes(category);
|
||||
```
|
||||
|
||||
## Week 2: Integration and Testing
|
||||
|
||||
### Day 6-7: Test Priority Nodes
|
||||
|
||||
Focus on these nodes first (they cover most edge cases):
|
||||
|
||||
1. **HTTP Request** - Known documentation mismatch
|
||||
2. **Slack** - Complex declarative node
|
||||
3. **Code** - Versioned node with documentation issues
|
||||
4. **AI Agent** - LangChain node with AI tool flag
|
||||
|
||||
### Day 8-9: MCP Server Updates
|
||||
|
||||
**File**: `src/mcp/tools-update.ts`
|
||||
|
||||
```typescript
|
||||
// Simplified get_node_info tool
|
||||
async function getNodeInfo(nodeType: string) {
|
||||
const node = db.prepare(`
|
||||
SELECT * FROM nodes WHERE node_type = ?
|
||||
`).get(nodeType);
|
||||
|
||||
if (!node) {
|
||||
throw new Error(`Node ${nodeType} not found`);
|
||||
}
|
||||
|
||||
return {
|
||||
nodeType: node.node_type,
|
||||
displayName: node.display_name,
|
||||
description: node.description,
|
||||
category: node.category,
|
||||
developmentStyle: node.development_style,
|
||||
isAITool: !!node.is_ai_tool,
|
||||
isTrigger: !!node.is_trigger,
|
||||
isWebhook: !!node.is_webhook,
|
||||
version: node.version,
|
||||
properties: JSON.parse(node.properties_schema),
|
||||
operations: JSON.parse(node.operations || '[]'),
|
||||
credentials: JSON.parse(node.credentials_required),
|
||||
documentation: node.documentation
|
||||
};
|
||||
}
|
||||
|
||||
// New tool: list_ai_tools
|
||||
{
|
||||
name: 'list_ai_tools',
|
||||
description: 'List all nodes that can be used as AI Agent tools',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
|
||||
async function listAITools() {
|
||||
const tools = db.prepare(`
|
||||
SELECT node_type, display_name, description, package_name
|
||||
FROM nodes
|
||||
WHERE is_ai_tool = 1
|
||||
ORDER BY display_name
|
||||
`).all();
|
||||
|
||||
return {
|
||||
tools,
|
||||
totalCount: tools.length,
|
||||
requirements: {
|
||||
environmentVariable: 'N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true',
|
||||
nodeProperty: 'usableAsTool: true'
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Day 10: Validation Script
|
||||
|
||||
**File**: `src/scripts/validate.ts`
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import Database from 'better-sqlite3';
|
||||
|
||||
async function validate() {
|
||||
const db = new Database('./data/nodes.db');
|
||||
|
||||
console.log('🔍 Validating critical nodes...\n');
|
||||
|
||||
const criticalChecks = [
|
||||
{
|
||||
type: 'n8n-nodes-base.httpRequest',
|
||||
checks: {
|
||||
hasDocumentation: true,
|
||||
documentationContains: 'httprequest',
|
||||
style: 'programmatic'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'n8n-nodes-base.code',
|
||||
checks: {
|
||||
hasDocumentation: true,
|
||||
documentationContains: 'code',
|
||||
isVersioned: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'n8n-nodes-base.slack',
|
||||
checks: {
|
||||
hasOperations: true,
|
||||
style: 'declarative'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: '@n8n/n8n-nodes-langchain.agent',
|
||||
checks: {
|
||||
isAITool: true,
|
||||
packageName: '@n8n/n8n-nodes-langchain'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (const check of criticalChecks) {
|
||||
const node = db.prepare('SELECT * FROM nodes WHERE node_type = ?').get(check.type);
|
||||
|
||||
if (!node) {
|
||||
console.log(`❌ ${check.type}: NOT FOUND`);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
let nodeOk = true;
|
||||
const issues = [];
|
||||
|
||||
// Run checks
|
||||
if (check.checks.hasDocumentation && !node.documentation) {
|
||||
nodeOk = false;
|
||||
issues.push('missing documentation');
|
||||
}
|
||||
|
||||
if (check.checks.documentationContains &&
|
||||
!node.documentation?.includes(check.checks.documentationContains)) {
|
||||
nodeOk = false;
|
||||
issues.push(`documentation doesn't contain "${check.checks.documentationContains}"`);
|
||||
}
|
||||
|
||||
if (check.checks.style && node.development_style !== check.checks.style) {
|
||||
nodeOk = false;
|
||||
issues.push(`wrong style: ${node.development_style}`);
|
||||
}
|
||||
|
||||
if (check.checks.hasOperations) {
|
||||
const operations = JSON.parse(node.operations || '[]');
|
||||
if (!operations.length) {
|
||||
nodeOk = false;
|
||||
issues.push('no operations found');
|
||||
}
|
||||
}
|
||||
|
||||
if (check.checks.isAITool && !node.is_ai_tool) {
|
||||
nodeOk = false;
|
||||
issues.push('not marked as AI tool');
|
||||
}
|
||||
|
||||
if (check.checks.isVersioned && !node.is_versioned) {
|
||||
nodeOk = false;
|
||||
issues.push('not marked as versioned');
|
||||
}
|
||||
|
||||
if (nodeOk) {
|
||||
console.log(`✅ ${check.type}`);
|
||||
passed++;
|
||||
} else {
|
||||
console.log(`❌ ${check.type}: ${issues.join(', ')}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n📊 Results: ${passed} passed, ${failed} failed`);
|
||||
|
||||
// Additional statistics
|
||||
const stats = db.prepare(`
|
||||
SELECT
|
||||
COUNT(*) as total,
|
||||
SUM(is_ai_tool) as ai_tools,
|
||||
SUM(is_trigger) as triggers,
|
||||
SUM(is_versioned) as versioned,
|
||||
COUNT(DISTINCT package_name) as packages
|
||||
FROM nodes
|
||||
`).get();
|
||||
|
||||
console.log('\n📈 Database Statistics:');
|
||||
console.log(` Total nodes: ${stats.total}`);
|
||||
console.log(` AI tools: ${stats.ai_tools}`);
|
||||
console.log(` Triggers: ${stats.triggers}`);
|
||||
console.log(` Versioned: ${stats.versioned}`);
|
||||
console.log(` Packages: ${stats.packages}`);
|
||||
|
||||
db.close();
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
validate().catch(console.error);
|
||||
}
|
||||
```
|
||||
|
||||
## MVP Deliverables Checklist
|
||||
|
||||
### Week 1 ✅
|
||||
- [ ] Clone n8n-docs repository locally
|
||||
- [ ] Build rebuild script first (test harness)
|
||||
- [ ] Basic node loader for n8n-nodes-base and langchain packages
|
||||
- [ ] Simple parser (no complex analysis)
|
||||
- [ ] Documentation fetcher with file-based access
|
||||
- [ ] SQLite database setup with minimal schema
|
||||
- [ ] Get 5 nodes working end-to-end on Day 1
|
||||
|
||||
### Week 2 ✅
|
||||
- [ ] Test priority nodes (HTTP Request, Slack, Code, AI Agent)
|
||||
- [ ] Fix all documentation mapping issues
|
||||
- [ ] Update MCP tools for simplified schema
|
||||
- [ ] Add AI tools listing functionality
|
||||
- [ ] Create validation script
|
||||
- [ ] Document usage instructions
|
||||
- [ ] Run full validation suite
|
||||
|
||||
## What We're Deferring Post-MVP
|
||||
|
||||
1. **Version history tracking** - Just current version
|
||||
2. **Source code extraction** - Not needed for documentation
|
||||
3. **Complex property type analysis** - Keep n8n's structure as-is
|
||||
4. **Custom node directory support** - Focus on npm packages only
|
||||
5. **Performance optimizations** - SQLite is fast enough
|
||||
6. **Real-time monitoring** - Static documentation only
|
||||
7. **Web UI** - CLI tools only
|
||||
8. **Multi-tenant support** - Single instance
|
||||
9. **Advanced search** - Basic SQL queries are sufficient
|
||||
10. **Community nodes** - Just official packages for now
|
||||
|
||||
## Success Metrics
|
||||
|
||||
1. **Accuracy**: 100% correct node-to-documentation mapping for test nodes
|
||||
2. **Coverage**: All nodes from n8n-nodes-base and n8n-nodes-langchain
|
||||
3. **Performance**: Full rebuild in <30 seconds
|
||||
4. **Simplicity**: Single command rebuild (`npm run rebuild`)
|
||||
5. **Reliability**: No failures on standard nodes
|
||||
6. **Validation**: All critical nodes pass validation script
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
```bash
|
||||
# Setup
|
||||
git clone https://github.com/n8n-io/n8n-docs.git ../n8n-docs
|
||||
npm install
|
||||
|
||||
# Build
|
||||
npm run build
|
||||
|
||||
# Rebuild database
|
||||
npm run rebuild
|
||||
|
||||
# Validate
|
||||
npm run validate
|
||||
|
||||
# Start MCP server
|
||||
npm start
|
||||
```
|
||||
|
||||
## NPM Scripts
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"rebuild": "node dist/scripts/rebuild.js",
|
||||
"validate": "node dist/scripts/validate.js",
|
||||
"start": "node dist/mcp/server.js",
|
||||
"dev": "npm run build && npm run rebuild && npm run validate"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
This v2.1 Final plan delivers a working MVP in 2 weeks by:
|
||||
- **Starting with the test harness** - Build rebuild script first
|
||||
- **Getting quick wins** - 5 nodes on Day 1
|
||||
- **Testing critical nodes early** - HTTP Request, Slack, Code, AI Agent
|
||||
- **Using local documentation** - Clone n8n-docs for file access
|
||||
- **Validating success** - Automated validation script
|
||||
|
||||
The result: A reliable, accurate node documentation service that can be enhanced incrementally post-MVP.
|
||||
|
||||
**Ready to build! 🚀**
|
||||
@@ -1,101 +0,0 @@
|
||||
# Claude Desktop Configuration for n8n-MCP
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
1. **Build the project first:**
|
||||
```bash
|
||||
cd /Users/romualdczlonkowski/Pliki/n8n-mcp/n8n-mcp
|
||||
npm run build
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
2. **Locate your Claude Desktop config file:**
|
||||
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
||||
|
||||
3. **Add the n8n-documentation server to your config:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/Users/johndoe/projects/n8n-mcp/dist/mcp/index.js"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: Update the path in `args` to match your actual installation directory.
|
||||
|
||||
4. **Restart Claude Desktop** to load the new configuration.
|
||||
|
||||
## Available Tools
|
||||
|
||||
Once configured, you'll have access to these tools in Claude:
|
||||
|
||||
- **`list_nodes`** - List and filter n8n nodes
|
||||
```
|
||||
list_nodes({ package: "n8n-nodes-base", limit: 10 })
|
||||
```
|
||||
|
||||
- **`get_node_info`** - Get detailed information about a specific node
|
||||
```
|
||||
get_node_info({ nodeType: "httpRequest" })
|
||||
```
|
||||
|
||||
- **`search_nodes`** - Search across all node documentation
|
||||
```
|
||||
search_nodes({ query: "webhook", limit: 20 })
|
||||
```
|
||||
|
||||
- **`list_ai_tools`** - List nodes that can be used as AI Agent tools
|
||||
```
|
||||
list_ai_tools({})
|
||||
```
|
||||
|
||||
- **`get_node_documentation`** - Get full documentation for a node
|
||||
```
|
||||
get_node_documentation({ nodeType: "slack" })
|
||||
```
|
||||
|
||||
- **`get_database_statistics`** - Get statistics about the node database
|
||||
```
|
||||
get_database_statistics({})
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. **If the server doesn't appear in Claude:**
|
||||
- Check that the path in `args` is absolute and correct
|
||||
- Ensure you've run `npm run build` and `npm run rebuild`
|
||||
- Check `~/.n8n-mcp/logs/` for error logs
|
||||
|
||||
2. **If tools return errors:**
|
||||
- Ensure the database exists: `data/nodes.db`
|
||||
- Run `npm run validate` to check the database
|
||||
- Rebuild if necessary: `npm run rebuild`
|
||||
|
||||
3. **For development/testing:**
|
||||
You can also run with more verbose logging:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/path/to/your/n8n-mcp/dist/mcp/index.js"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"LOG_LEVEL": "debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
62
docs/DOCKER_BUILD_FIX.md
Normal file
62
docs/DOCKER_BUILD_FIX.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Docker Build Fix
|
||||
|
||||
## Issue
|
||||
The Docker build was failing with the error:
|
||||
```
|
||||
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref: "/data/nodes.db": not found
|
||||
```
|
||||
|
||||
## Root Cause
|
||||
The Dockerfile contained an invalid COPY command that tried to use shell operators:
|
||||
```dockerfile
|
||||
# This doesn't work in Docker
|
||||
COPY --from=builder /app/data/nodes.db ./data/nodes.db 2>/dev/null || true
|
||||
```
|
||||
|
||||
Docker's COPY command doesn't support shell operators like `2>/dev/null || true`.
|
||||
|
||||
## Solution
|
||||
1. Removed the problematic COPY command
|
||||
2. Created the data directory with RUN instead
|
||||
3. Removed database pre-initialization from build stage
|
||||
4. Database is now initialized at runtime by the entrypoint script
|
||||
|
||||
## Changes Made
|
||||
|
||||
### Dockerfile
|
||||
```diff
|
||||
- # Pre-initialize database during build
|
||||
- RUN mkdir -p /app/data && npm run rebuild || echo "Database will be initialized at runtime"
|
||||
+ # Build TypeScript only
|
||||
+ RUN npm run build
|
||||
|
||||
- # Copy pre-built database if it exists
|
||||
- COPY --from=builder /app/data/nodes.db ./data/nodes.db 2>/dev/null || true
|
||||
+ # Create data directory
|
||||
+ RUN mkdir -p /app/data
|
||||
```
|
||||
|
||||
### GitHub Actions Workflow
|
||||
Added conditional login to prevent failures on pull requests:
|
||||
```diff
|
||||
- name: Log in to GitHub Container Registry
|
||||
+ if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v3
|
||||
```
|
||||
|
||||
## Result
|
||||
✅ Docker build now succeeds
|
||||
✅ Database initialization happens at container startup
|
||||
✅ GitHub Actions workflow will work properly
|
||||
✅ No manual intervention required
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Build locally
|
||||
docker build -t n8n-mcp:test .
|
||||
|
||||
# Run and verify
|
||||
docker run -d --name test -e MCP_MODE=http -e AUTH_TOKEN=test -p 3000:3000 n8n-mcp:test
|
||||
docker logs test
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
@@ -74,10 +74,11 @@
|
||||
|
||||
### 🔧 Recommended Fixes
|
||||
|
||||
1. **Immediate (Phase 1)**
|
||||
- Include schema.sql in Docker image
|
||||
- Add scripts directory for rebuild functionality
|
||||
- Test database initialization in clean environment
|
||||
1. **Immediate (Phase 1)** ✅ FIXED
|
||||
- ✅ Include schema.sql in Docker image
|
||||
- ✅ Add scripts directory for rebuild functionality
|
||||
- ✅ Removed invalid COPY syntax that caused build errors
|
||||
- ✅ Database initialization happens at runtime, not build time
|
||||
|
||||
2. **Future Improvements (Phase 2)**
|
||||
- Optimize image size with multi-stage pruning
|
||||
|
||||
@@ -6,17 +6,70 @@ This guide explains how to deploy n8n-MCP as a private HTTP server for remote ac
|
||||
|
||||
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
|
||||
## Deployment Options
|
||||
|
||||
- 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
|
||||
### Option 1: Docker Deployment (Recommended) 🐳
|
||||
|
||||
## Server Setup
|
||||
The easiest way to deploy n8n-MCP is using Docker:
|
||||
|
||||
### 1. Clone and Build
|
||||
#### Quick Start
|
||||
```bash
|
||||
# 1. Create configuration
|
||||
echo "AUTH_TOKEN=$(openssl rand -base64 32)" > .env
|
||||
|
||||
# 2. Start with Docker Compose
|
||||
docker compose up -d
|
||||
|
||||
# 3. Check health
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
#### Production Deployment
|
||||
```bash
|
||||
# 1. Clone repository
|
||||
git clone https://github.com/yourusername/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
|
||||
# 2. Create production .env
|
||||
cat > .env << EOF
|
||||
AUTH_TOKEN=$(openssl rand -base64 32)
|
||||
NODE_ENV=production
|
||||
LOG_LEVEL=info
|
||||
PORT=3000
|
||||
EOF
|
||||
|
||||
# 3. Deploy with Docker Compose
|
||||
docker compose up -d
|
||||
|
||||
# 4. Check logs
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
#### Using Pre-built Images
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
services:
|
||||
n8n-mcp:
|
||||
image: ghcr.io/czlonkowski/n8n-mcp:latest
|
||||
environment:
|
||||
MCP_MODE: http
|
||||
AUTH_TOKEN: ${AUTH_TOKEN:?Required}
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- n8n-mcp-data:/app/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
n8n-mcp-data:
|
||||
```
|
||||
|
||||
### Option 2: Manual Installation
|
||||
|
||||
If you prefer not to use Docker:
|
||||
|
||||
#### 1. Clone and Build
|
||||
```bash
|
||||
git clone https://github.com/yourusername/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
@@ -25,8 +78,7 @@ npm run build
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
### 2. Configure Environment
|
||||
|
||||
#### 2. Configure Environment
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
@@ -47,13 +99,7 @@ MCP_LOG_LEVEL=info
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
Generate a secure token:
|
||||
```bash
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
### 3. Start the Server
|
||||
|
||||
#### 3. Start the Server
|
||||
```bash
|
||||
# Using the deployment script
|
||||
./scripts/deploy-http.sh
|
||||
@@ -220,33 +266,95 @@ The test script checks:
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Refused
|
||||
### Docker-specific Issues
|
||||
|
||||
#### Container won't start
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs n8n-mcp
|
||||
|
||||
# Check if port is already in use
|
||||
lsof -i :3000
|
||||
|
||||
# Rebuild and restart
|
||||
docker compose down
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
#### Database initialization fails
|
||||
```bash
|
||||
# Copy existing database
|
||||
docker cp data/nodes.db n8n-mcp:/app/data/
|
||||
|
||||
# Or rebuild inside container
|
||||
docker compose exec n8n-mcp npm run rebuild
|
||||
```
|
||||
|
||||
#### Permission issues
|
||||
```bash
|
||||
# Fix volume permissions
|
||||
docker compose exec n8n-mcp chown -R nodejs:nodejs /app/data
|
||||
```
|
||||
|
||||
### General Issues
|
||||
|
||||
#### Connection Refused
|
||||
- Check firewall rules
|
||||
- Verify server is running
|
||||
- Check nginx/proxy configuration
|
||||
- Run the test script to diagnose
|
||||
- For Docker: ensure ports are mapped correctly
|
||||
|
||||
### Authentication Failed
|
||||
#### Authentication Failed
|
||||
- Verify AUTH_TOKEN matches in both server and client
|
||||
- Check Authorization header format
|
||||
- Token should be at least 32 characters
|
||||
- Docker: check .env file is loaded
|
||||
|
||||
### MCP Tools Not Available
|
||||
#### MCP Tools Not Available
|
||||
- Restart Claude Desktop
|
||||
- Check mcp-remote installation
|
||||
- Verify server logs for errors
|
||||
- Ensure CORS headers are working
|
||||
- Docker: check container health status
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. Use a VPS with good network connectivity
|
||||
2. Enable gzip compression in your proxy
|
||||
3. Consider using PM2 for process management:
|
||||
3. For Docker deployments:
|
||||
- Use `--restart unless-stopped` for reliability
|
||||
- Monitor with `docker stats n8n-mcp`
|
||||
- Set memory limits in docker-compose.yml
|
||||
4. For manual deployments, use PM2:
|
||||
```bash
|
||||
pm2 start npm --name "n8n-mcp" -- run start:http
|
||||
```
|
||||
|
||||
## Example Systemd Service
|
||||
## Production Deployment Examples
|
||||
|
||||
### Using Docker with Systemd
|
||||
|
||||
Create `/etc/systemd/system/n8n-mcp-docker.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=n8n MCP Docker Container
|
||||
After=docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/n8n-mcp
|
||||
ExecStart=/usr/bin/docker compose up
|
||||
ExecStop=/usr/bin/docker compose down
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
### Manual Installation with Systemd
|
||||
|
||||
Create `/etc/systemd/system/n8n-mcp.service`:
|
||||
|
||||
|
||||
331
docs/INSTALLATION.md
Normal file
331
docs/INSTALLATION.md
Normal file
@@ -0,0 +1,331 @@
|
||||
# Installation Guide
|
||||
|
||||
This guide covers all installation methods for n8n-MCP.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Quick Start](#quick-start)
|
||||
- [Docker Installation](#docker-installation)
|
||||
- [Manual Installation](#manual-installation)
|
||||
- [Development Setup](#development-setup)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Quick Start
|
||||
|
||||
The fastest way to get n8n-MCP running:
|
||||
|
||||
```bash
|
||||
# Using Docker (recommended)
|
||||
echo "AUTH_TOKEN=$(openssl rand -base64 32)" > .env
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Docker Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker Desktop or Docker Engine
|
||||
- Docker Compose (included with Docker Desktop)
|
||||
|
||||
### Method 1: Using Pre-built Images
|
||||
|
||||
1. **Create a project directory:**
|
||||
```bash
|
||||
mkdir n8n-mcp && cd n8n-mcp
|
||||
```
|
||||
|
||||
2. **Create docker-compose.yml:**
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
n8n-mcp:
|
||||
image: ghcr.io/czlonkowski/n8n-mcp:latest
|
||||
container_name: n8n-mcp
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
MCP_MODE: ${MCP_MODE:-http}
|
||||
AUTH_TOKEN: ${AUTH_TOKEN:?AUTH_TOKEN is required}
|
||||
NODE_ENV: ${NODE_ENV:-production}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
PORT: ${PORT:-3000}
|
||||
|
||||
volumes:
|
||||
- n8n-mcp-data:/app/data
|
||||
|
||||
ports:
|
||||
- "${PORT:-3000}:3000"
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:3000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
n8n-mcp-data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
3. **Create .env file:**
|
||||
```bash
|
||||
echo "AUTH_TOKEN=$(openssl rand -base64 32)" > .env
|
||||
```
|
||||
|
||||
4. **Start the container:**
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
5. **Verify installation:**
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
### Method 2: Building from Source
|
||||
|
||||
1. **Clone the repository:**
|
||||
```bash
|
||||
git clone https://github.com/czlonkowski/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
```
|
||||
|
||||
2. **Build the image:**
|
||||
```bash
|
||||
docker build -t n8n-mcp:local .
|
||||
```
|
||||
|
||||
3. **Run with docker-compose:**
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Docker Management Commands
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Stop the container
|
||||
docker compose stop
|
||||
|
||||
# Remove container and volumes
|
||||
docker compose down -v
|
||||
|
||||
# Update to latest image
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
# Execute commands inside container
|
||||
docker compose exec n8n-mcp npm run validate
|
||||
|
||||
# Backup database
|
||||
docker cp n8n-mcp:/app/data/nodes.db ./nodes-backup.db
|
||||
```
|
||||
|
||||
## Manual Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js v16+ (v20+ recommended)
|
||||
- npm or yarn
|
||||
- Git
|
||||
|
||||
### Step-by-Step Installation
|
||||
|
||||
1. **Clone the repository:**
|
||||
```bash
|
||||
git clone https://github.com/czlonkowski/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
```
|
||||
|
||||
2. **Clone n8n documentation (optional but recommended):**
|
||||
```bash
|
||||
git clone https://github.com/n8n-io/n8n-docs.git ../n8n-docs
|
||||
```
|
||||
|
||||
3. **Install dependencies:**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
4. **Build the project:**
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
5. **Initialize the database:**
|
||||
```bash
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
6. **Validate installation:**
|
||||
```bash
|
||||
npm run test-nodes
|
||||
```
|
||||
|
||||
### Running the Server
|
||||
|
||||
#### stdio Mode (for Claude Desktop)
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
#### HTTP Mode (for remote access)
|
||||
```bash
|
||||
npm run start:http
|
||||
```
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
Create a `.env` file in the project root:
|
||||
|
||||
```env
|
||||
# Server configuration
|
||||
MCP_MODE=http # or stdio
|
||||
PORT=3000
|
||||
HOST=0.0.0.0
|
||||
NODE_ENV=production
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Authentication (required for HTTP mode)
|
||||
AUTH_TOKEN=your-secure-token-here
|
||||
|
||||
# Database
|
||||
NODE_DB_PATH=./data/nodes.db
|
||||
REBUILD_ON_START=false
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- All manual installation prerequisites
|
||||
- TypeScript knowledge
|
||||
- Familiarity with MCP protocol
|
||||
|
||||
### Setup Steps
|
||||
|
||||
1. **Clone and install:**
|
||||
```bash
|
||||
git clone https://github.com/czlonkowski/n8n-mcp.git
|
||||
cd n8n-mcp
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Set up development environment:**
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your settings
|
||||
```
|
||||
|
||||
3. **Development commands:**
|
||||
```bash
|
||||
# Run in development mode with auto-reload
|
||||
npm run dev
|
||||
|
||||
# Run tests
|
||||
npm test
|
||||
|
||||
# Type checking
|
||||
npm run typecheck
|
||||
|
||||
# Linting
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Docker Development
|
||||
|
||||
1. **Use docker-compose override:**
|
||||
```bash
|
||||
cp docker-compose.override.yml.example docker-compose.override.yml
|
||||
```
|
||||
|
||||
2. **Edit override for development:**
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
n8n-mcp:
|
||||
build: .
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
LOG_LEVEL: debug
|
||||
volumes:
|
||||
- ./src:/app/src:ro
|
||||
- ./dist:/app/dist
|
||||
```
|
||||
|
||||
3. **Run with live reload:**
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Port Already in Use
|
||||
```bash
|
||||
# Find process using port 3000
|
||||
lsof -i :3000
|
||||
|
||||
# Use a different port
|
||||
PORT=3001 docker compose up -d
|
||||
```
|
||||
|
||||
#### Database Initialization Failed
|
||||
```bash
|
||||
# For Docker
|
||||
docker compose exec n8n-mcp npm run rebuild
|
||||
|
||||
# For manual installation
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
#### Permission Denied Errors
|
||||
```bash
|
||||
# Fix permissions (Linux/macOS)
|
||||
sudo chown -R $(whoami) ./data
|
||||
|
||||
# For Docker volumes
|
||||
docker compose exec n8n-mcp chown -R nodejs:nodejs /app/data
|
||||
```
|
||||
|
||||
#### Node Version Mismatch
|
||||
The project includes automatic fallback to sql.js for compatibility. If you still have issues:
|
||||
```bash
|
||||
# Check Node version
|
||||
node --version
|
||||
|
||||
# Use nvm to switch versions
|
||||
nvm use 20
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
1. Check the logs:
|
||||
- Docker: `docker compose logs`
|
||||
- Manual: Check console output or `LOG_LEVEL=debug npm start`
|
||||
|
||||
2. Validate the database:
|
||||
```bash
|
||||
npm run validate
|
||||
```
|
||||
|
||||
3. Run tests:
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
4. Report issues:
|
||||
- GitHub Issues: https://github.com/czlonkowski/n8n-mcp/issues
|
||||
- Include logs and environment details
|
||||
|
||||
## Next Steps
|
||||
|
||||
After installation, configure Claude Desktop to use n8n-MCP:
|
||||
- See [Claude Desktop Setup Guide](./README_CLAUDE_SETUP.md)
|
||||
- For remote deployments, see [HTTP Deployment Guide](./HTTP_DEPLOYMENT.md)
|
||||
- For Docker details, see [Docker README](../DOCKER_README.md)
|
||||
66
docs/README.md
Normal file
66
docs/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# n8n-MCP Documentation
|
||||
|
||||
Welcome to the n8n-MCP documentation. This directory contains comprehensive guides for installation, configuration, and troubleshooting.
|
||||
|
||||
## 📚 Documentation Index
|
||||
|
||||
### Getting Started
|
||||
- **[Installation Guide](./INSTALLATION.md)** - All installation methods including Docker, manual, and development setup
|
||||
- **[Claude Desktop Setup](./README_CLAUDE_SETUP.md)** - Configure Claude Desktop to use n8n-MCP
|
||||
- **[Quick Start Tutorial](../README.md)** - Basic overview and quick start instructions
|
||||
|
||||
### Deployment
|
||||
- **[HTTP Deployment Guide](./HTTP_DEPLOYMENT.md)** - Deploy n8n-MCP as an HTTP server for remote access
|
||||
- **[Docker Deployment](../DOCKER_README.md)** - Comprehensive Docker deployment guide
|
||||
- **[Docker Testing Results](./DOCKER_TESTING_RESULTS.md)** - Docker implementation test results and findings
|
||||
|
||||
### Development
|
||||
- **[Implementation Plan](../IMPLEMENTATION_PLAN.md)** - Technical implementation details
|
||||
- **[HTTP Implementation Guide](./HTTP_IMPLEMENTATION_GUIDE.md)** - HTTP server implementation details
|
||||
- **[Development Setup](./INSTALLATION.md#development-setup)** - Set up development environment
|
||||
|
||||
### Reference
|
||||
- **[Troubleshooting Guide](./TROUBLESHOOTING.md)** - Solutions for common issues
|
||||
- **[API Reference](./API_REFERENCE.md)** - MCP tools and API documentation (if available)
|
||||
- **[Environment Variables](./INSTALLATION.md#environment-configuration)** - Configuration options
|
||||
|
||||
## 🚀 Quick Links
|
||||
|
||||
### For Users
|
||||
1. **First Time Setup**: Start with the [Installation Guide](./INSTALLATION.md)
|
||||
2. **Claude Desktop Users**: Follow [Claude Desktop Setup](./README_CLAUDE_SETUP.md)
|
||||
3. **Remote Deployment**: See [HTTP Deployment Guide](./HTTP_DEPLOYMENT.md)
|
||||
|
||||
### For Developers
|
||||
1. **Local Development**: See [Development Setup](./INSTALLATION.md#development-setup)
|
||||
2. **Docker Development**: Check [Docker README](../DOCKER_README.md)
|
||||
3. **Contributing**: Read the implementation plans and guides
|
||||
|
||||
## 🐳 Docker Quick Start
|
||||
|
||||
```bash
|
||||
# Quick start with Docker
|
||||
echo "AUTH_TOKEN=$(openssl rand -base64 32)" > .env
|
||||
docker compose up -d
|
||||
|
||||
# Check health
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
## 📖 Documentation Updates
|
||||
|
||||
This documentation is actively maintained. Recent updates include:
|
||||
- ✅ Docker deployment support (Phase 1 complete)
|
||||
- ✅ Simplified installation process
|
||||
- ✅ Enhanced troubleshooting guide
|
||||
- ✅ Multiple deployment options
|
||||
|
||||
## 🤝 Getting Help
|
||||
|
||||
- **Issues**: [GitHub Issues](https://github.com/czlonkowski/n8n-mcp/issues)
|
||||
- **Discussions**: [GitHub Discussions](https://github.com/czlonkowski/n8n-mcp/discussions)
|
||||
- **Troubleshooting**: [Troubleshooting Guide](./TROUBLESHOOTING.md)
|
||||
|
||||
## 📝 License
|
||||
|
||||
This project is licensed under the Sustainable Use License. See [LICENSE](../LICENSE) for details.
|
||||
203
docs/README_CLAUDE_SETUP.md
Normal file
203
docs/README_CLAUDE_SETUP.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Claude Desktop Configuration for n8n-MCP
|
||||
|
||||
## Setup Options
|
||||
|
||||
You can set up n8n-MCP with Claude Desktop in three ways:
|
||||
|
||||
### Option 1: Docker (Recommended) 🐳
|
||||
|
||||
The easiest way to get started is using Docker:
|
||||
|
||||
#### 1a. Docker with HTTP Mode (Remote Access)
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-remote": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/mcp-remote@latest",
|
||||
"connect",
|
||||
"http://localhost:3000/mcp"
|
||||
],
|
||||
"env": {
|
||||
"MCP_AUTH_TOKEN": "your-auth-token-here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Setup steps:**
|
||||
1. Create a `.env` file:
|
||||
```bash
|
||||
echo "AUTH_TOKEN=$(openssl rand -base64 32)" > .env
|
||||
```
|
||||
2. Start the server:
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
3. Copy the AUTH_TOKEN to your Claude config
|
||||
|
||||
#### 1b. Docker with stdio Mode (Direct)
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-docker": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"--rm",
|
||||
"-i",
|
||||
"-e", "MCP_MODE=stdio",
|
||||
"-v", "n8n-mcp-data:/app/data",
|
||||
"ghcr.io/czlonkowski/n8n-mcp:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option 2: Local Installation
|
||||
|
||||
1. **Build the project first:**
|
||||
```bash
|
||||
cd /path/to/n8n-mcp
|
||||
npm install
|
||||
npm run build
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
2. **Add to Claude Desktop config:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/path/to/n8n-mcp/dist/mcp/index.js"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: NPM Global Install (Coming Soon)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"n8n-mcp@latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration File Locations
|
||||
|
||||
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
- **Linux**: `~/.config/Claude/claude_desktop_config.json`
|
||||
|
||||
After updating the config, **restart Claude Desktop** to load the new configuration.
|
||||
|
||||
## Available Tools
|
||||
|
||||
Once configured, you'll have access to these tools in Claude:
|
||||
|
||||
- **`list_nodes`** - List and filter n8n nodes
|
||||
```
|
||||
list_nodes({ package: "n8n-nodes-base", limit: 10 })
|
||||
```
|
||||
|
||||
- **`get_node_info`** - Get detailed information about a specific node
|
||||
```
|
||||
get_node_info({ nodeType: "httpRequest" })
|
||||
```
|
||||
|
||||
- **`search_nodes`** - Search across all node documentation
|
||||
```
|
||||
search_nodes({ query: "webhook", limit: 20 })
|
||||
```
|
||||
|
||||
- **`list_ai_tools`** - List nodes that can be used as AI Agent tools
|
||||
```
|
||||
list_ai_tools({})
|
||||
```
|
||||
|
||||
- **`get_node_documentation`** - Get full documentation for a node
|
||||
```
|
||||
get_node_documentation({ nodeType: "slack" })
|
||||
```
|
||||
|
||||
- **`get_database_statistics`** - Get statistics about the node database
|
||||
```
|
||||
get_database_statistics({})
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Docker Issues
|
||||
|
||||
1. **Container fails to start:**
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs -f
|
||||
|
||||
# Check if port is in use
|
||||
lsof -i :3000
|
||||
```
|
||||
|
||||
2. **Authentication errors:**
|
||||
- Ensure AUTH_TOKEN matches in .env and Claude config
|
||||
- Token should be at least 32 characters
|
||||
- Check quotes in JSON config
|
||||
|
||||
3. **Database not found:**
|
||||
- The container will auto-initialize on first run
|
||||
- To rebuild: `docker compose exec n8n-mcp npm run rebuild`
|
||||
|
||||
### Local Installation Issues
|
||||
|
||||
1. **If the server doesn't appear in Claude:**
|
||||
- Check that the path in `args` is absolute and correct
|
||||
- Ensure you've run `npm run build` and `npm run rebuild`
|
||||
- Verify Node.js version compatibility
|
||||
|
||||
2. **If tools return errors:**
|
||||
- Ensure the database exists: `data/nodes.db`
|
||||
- Run `npm run validate` to check the database
|
||||
- Rebuild if necessary: `npm run rebuild`
|
||||
|
||||
3. **For development/testing:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/path/to/your/n8n-mcp/dist/mcp/index.js"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"LOG_LEVEL": "debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Common Solutions
|
||||
|
||||
- **Restart Claude Desktop** after config changes
|
||||
- **Check file permissions** on Unix systems
|
||||
- **Use absolute paths** in configuration
|
||||
- **Verify JSON syntax** in claude_desktop_config.json
|
||||
402
docs/TROUBLESHOOTING.md
Normal file
402
docs/TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,402 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
This guide helps resolve common issues with n8n-MCP.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Docker Issues](#docker-issues)
|
||||
- [Installation Issues](#installation-issues)
|
||||
- [Runtime Errors](#runtime-errors)
|
||||
- [Claude Desktop Issues](#claude-desktop-issues)
|
||||
- [Database Problems](#database-problems)
|
||||
- [Network and Authentication](#network-and-authentication)
|
||||
- [Performance Issues](#performance-issues)
|
||||
|
||||
## Docker Issues
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
#### Symptoms
|
||||
- `docker compose up` fails
|
||||
- Container exits immediately
|
||||
- No logs available
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Check if port is in use:**
|
||||
```bash
|
||||
lsof -i :3000
|
||||
# or
|
||||
netstat -tulpn | grep 3000
|
||||
```
|
||||
|
||||
2. **View detailed logs:**
|
||||
```bash
|
||||
docker compose logs -f --tail 100
|
||||
```
|
||||
|
||||
3. **Check Docker resources:**
|
||||
```bash
|
||||
docker system df
|
||||
docker system prune -a # Clean up unused resources
|
||||
```
|
||||
|
||||
4. **Verify image download:**
|
||||
```bash
|
||||
docker compose pull
|
||||
```
|
||||
|
||||
### Database Initialization Fails in Docker
|
||||
|
||||
#### Symptoms
|
||||
- Error: `ENOENT: no such file or directory, open '/app/src/database/schema.sql'`
|
||||
- Database not found errors
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Rebuild the image with latest Dockerfile:**
|
||||
```bash
|
||||
docker compose build --no-cache
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
2. **Copy existing database:**
|
||||
```bash
|
||||
# From host to container
|
||||
docker cp data/nodes.db n8n-mcp:/app/data/
|
||||
|
||||
# Restart container
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
3. **Initialize inside container:**
|
||||
```bash
|
||||
docker compose exec n8n-mcp npm run rebuild
|
||||
```
|
||||
|
||||
### Permission Denied in Docker
|
||||
|
||||
#### Symptoms
|
||||
- Cannot write to /app/data
|
||||
- Permission denied errors in logs
|
||||
|
||||
#### Solutions
|
||||
|
||||
```bash
|
||||
# Fix permissions
|
||||
docker compose exec n8n-mcp chown -R nodejs:nodejs /app/data
|
||||
|
||||
# Or run as root temporarily
|
||||
docker compose exec -u root n8n-mcp chown -R nodejs:nodejs /app
|
||||
```
|
||||
|
||||
### Docker Compose Variables Not Loading
|
||||
|
||||
#### Symptoms
|
||||
- AUTH_TOKEN not recognized
|
||||
- Environment variables missing
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Check .env file location:**
|
||||
```bash
|
||||
ls -la .env
|
||||
cat .env
|
||||
```
|
||||
|
||||
2. **Verify compose file:**
|
||||
```bash
|
||||
docker compose config
|
||||
```
|
||||
|
||||
3. **Set variables explicitly:**
|
||||
```bash
|
||||
AUTH_TOKEN=mytoken docker compose up -d
|
||||
```
|
||||
|
||||
## Installation Issues
|
||||
|
||||
### npm install Fails
|
||||
|
||||
#### Symptoms
|
||||
- Dependency errors
|
||||
- Node version mismatch
|
||||
- Native module compilation fails
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Clear npm cache:**
|
||||
```bash
|
||||
npm cache clean --force
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Check Node version:**
|
||||
```bash
|
||||
node --version # Should be v16+
|
||||
npm --version # Should be v7+
|
||||
```
|
||||
|
||||
3. **Use fallback for better-sqlite3:**
|
||||
The project automatically falls back to sql.js if native modules fail.
|
||||
|
||||
### Build Errors
|
||||
|
||||
#### Symptoms
|
||||
- TypeScript compilation errors
|
||||
- Missing type definitions
|
||||
|
||||
#### Solutions
|
||||
|
||||
```bash
|
||||
# Clean build
|
||||
rm -rf dist
|
||||
npm run build
|
||||
|
||||
# Check TypeScript version
|
||||
npx tsc --version
|
||||
|
||||
# Install missing types
|
||||
npm install --save-dev @types/node
|
||||
```
|
||||
|
||||
## Runtime Errors
|
||||
|
||||
### MCP Tools Not Available
|
||||
|
||||
#### Symptoms
|
||||
- Tools don't appear in Claude Desktop
|
||||
- "Unknown tool" errors
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Verify server is running:**
|
||||
```bash
|
||||
# For Docker
|
||||
docker compose ps
|
||||
docker compose logs
|
||||
|
||||
# For local
|
||||
ps aux | grep node
|
||||
```
|
||||
|
||||
2. **Check database:**
|
||||
```bash
|
||||
npm run validate
|
||||
npm run test-nodes
|
||||
```
|
||||
|
||||
3. **Restart Claude Desktop** after configuration changes
|
||||
|
||||
### Stream Not Readable Error
|
||||
|
||||
#### Symptoms
|
||||
- Error: "InternalServerError: stream is not readable"
|
||||
- MCP endpoint returns errors
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Check database initialization:**
|
||||
```bash
|
||||
ls -la data/nodes.db
|
||||
npm run validate
|
||||
```
|
||||
|
||||
2. **Verify HTTP headers:**
|
||||
```bash
|
||||
curl -H "Accept: application/json, text/event-stream" \
|
||||
-H "Authorization: Bearer $AUTH_TOKEN" \
|
||||
http://localhost:3000/mcp
|
||||
```
|
||||
|
||||
## Claude Desktop Issues
|
||||
|
||||
### Server Not Appearing
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Verify config file location:**
|
||||
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
- Linux: `~/.config/Claude/claude_desktop_config.json`
|
||||
|
||||
2. **Check JSON syntax:**
|
||||
```bash
|
||||
# Validate JSON
|
||||
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | jq .
|
||||
```
|
||||
|
||||
3. **Use absolute paths:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"n8n-documentation": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"/absolute/path/to/n8n-mcp/dist/mcp/index.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Authentication Errors with Claude
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Match tokens exactly:**
|
||||
```bash
|
||||
# In .env
|
||||
AUTH_TOKEN=your-token-here
|
||||
|
||||
# In Claude config
|
||||
"MCP_AUTH_TOKEN": "your-token-here"
|
||||
```
|
||||
|
||||
2. **Check for special characters:**
|
||||
- Avoid quotes in token values
|
||||
- Use base64 encoding for safety
|
||||
|
||||
## Database Problems
|
||||
|
||||
### Database Corruption
|
||||
|
||||
#### Symptoms
|
||||
- SQLite errors
|
||||
- Unexpected results
|
||||
- Missing nodes
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Rebuild database:**
|
||||
```bash
|
||||
# Backup first
|
||||
cp data/nodes.db data/nodes.db.bak
|
||||
|
||||
# Rebuild
|
||||
npm run rebuild
|
||||
```
|
||||
|
||||
2. **Validate after rebuild:**
|
||||
```bash
|
||||
npm run validate
|
||||
npm run test-nodes
|
||||
```
|
||||
|
||||
### Database Locked
|
||||
|
||||
#### Symptoms
|
||||
- SQLITE_BUSY errors
|
||||
- Cannot write to database
|
||||
|
||||
#### Solutions
|
||||
|
||||
```bash
|
||||
# Find processes using the database
|
||||
lsof data/nodes.db
|
||||
|
||||
# For Docker
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
## Network and Authentication
|
||||
|
||||
### CORS Errors
|
||||
|
||||
#### Symptoms
|
||||
- Browser console shows CORS errors
|
||||
- Preflight requests fail
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Check server CORS settings:**
|
||||
- Verify MCP_MODE=http
|
||||
- Check proxy configuration
|
||||
|
||||
2. **Test with curl:**
|
||||
```bash
|
||||
curl -X OPTIONS http://localhost:3000/mcp \
|
||||
-H "Origin: http://localhost" \
|
||||
-H "Access-Control-Request-Method: POST"
|
||||
```
|
||||
|
||||
### SSL/HTTPS Issues
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **For development, use HTTP:**
|
||||
```json
|
||||
"connect", "http://localhost:3000/mcp"
|
||||
```
|
||||
|
||||
2. **For production, use reverse proxy:**
|
||||
- See nginx/Caddy examples in HTTP_DEPLOYMENT.md
|
||||
|
||||
## Performance Issues
|
||||
|
||||
### Slow Response Times
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Check resource usage:**
|
||||
```bash
|
||||
# Docker
|
||||
docker stats n8n-mcp
|
||||
|
||||
# System
|
||||
top
|
||||
htop
|
||||
```
|
||||
|
||||
2. **Increase memory limits:**
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
```
|
||||
|
||||
3. **Enable query logging:**
|
||||
```bash
|
||||
LOG_LEVEL=debug npm start
|
||||
```
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
#### Solutions
|
||||
|
||||
1. **Monitor with Docker:**
|
||||
```bash
|
||||
docker compose exec n8n-mcp ps aux
|
||||
```
|
||||
|
||||
2. **Restart periodically:**
|
||||
```bash
|
||||
# Add to crontab
|
||||
0 */6 * * * docker compose restart
|
||||
```
|
||||
|
||||
## Getting More Help
|
||||
|
||||
1. **Enable debug logging:**
|
||||
```bash
|
||||
LOG_LEVEL=debug docker compose up
|
||||
```
|
||||
|
||||
2. **Collect diagnostic info:**
|
||||
```bash
|
||||
# System info
|
||||
uname -a
|
||||
node --version
|
||||
docker --version
|
||||
|
||||
# Project info
|
||||
git rev-parse HEAD
|
||||
npm list
|
||||
```
|
||||
|
||||
3. **Report issues:**
|
||||
- GitHub: https://github.com/czlonkowski/n8n-mcp/issues
|
||||
- Include logs, environment, and steps to reproduce
|
||||
Reference in New Issue
Block a user