Files
n8n-mcp/docs/HTTP_DEPLOYMENT.md
czlonkowski 5dd932c19d docs: update HTTP deployment guide with comprehensive improvements
- Add security warnings for default AUTH_TOKEN
- Document AUTH_TOKEN_FILE support
- Add architecture diagram showing stdio → HTTP bridge
- Update configuration with all new env vars
- Improve troubleshooting section
- Add production-ready examples
- Reference Railway deployment guide
- Update to v2.7.17 features

Fixes #72
2025-07-18 09:37:01 +02:00

21 KiB

HTTP Deployment Guide for n8n-MCP

Deploy n8n-MCP as a remote HTTP server to provide n8n knowledge to compatible MCP Client from anywhere.

🎯 Overview

n8n-MCP HTTP mode enables:

  • ☁️ Cloud deployment (VPS, Docker, Kubernetes)
  • 🌐 Remote access from any Claude Desktop /Windsurf / other MCP Client
  • 🔒 Token-based authentication
  • Production-ready performance (~12ms response time)
  • 🚀 Optional n8n management tools (16 additional tools when configured)
  • Does not work with n8n MCP Tool

📐 Deployment Scenarios

1. Local Development (Simplest)

Use stdio mode - Claude Desktop connects directly to the Node.js process:

Claude Desktop → n8n-mcp (stdio mode)
  • No HTTP server needed
  • No authentication required
  • Fastest performance
  • Only works locally

2. Local HTTP Server

Run HTTP server locally for testing remote features:

Claude Desktop → http-bridge.js → localhost:3000
  • Test HTTP features locally
  • Multiple Claude instances can connect
  • Good for development
  • Still only local access

3. Remote Server

Deploy to cloud for access from anywhere:

Claude Desktop → mcp-remote → https://your-server.com
  • Access from anywhere
  • Team collaboration
  • Production-ready
  • Requires server setup
  • Deploy to your VPS - if you just want remote acces, consider deploying to Railway -> Railway Deployment Guide

📋 Prerequisites

Server Requirements:

  • Node.js 16+ or Docker
  • 512MB RAM minimum
  • Public IP or domain name
  • (Recommended) SSL certificate for HTTPS

Client Requirements:

  • Claude Desktop
  • Node.js 18+ (for mcp-remote)
  • Or Claude Pro/Team (for native remote MCP)

🚀 Quick Start

# 1. Create environment file
cat > .env << EOF
AUTH_TOKEN=$(openssl rand -base64 32)
USE_FIXED_HTTP=true
MCP_MODE=http
PORT=3000
# Optional: Enable n8n management tools
# N8N_API_URL=https://your-n8n-instance.com
# N8N_API_KEY=your-api-key-here
EOF

# 2. Deploy with Docker
docker run -d \
  --name n8n-mcp \
  --restart unless-stopped \
  --env-file .env \
  -p 3000:3000 \
  ghcr.io/czlonkowski/n8n-mcp:latest

# 3. Verify deployment
curl http://localhost:3000/health

Option 2: Local Development (Without Docker)

# 1. Clone and setup
git clone https://github.com/czlonkowski/n8n-mcp.git
cd n8n-mcp
npm install
npm run build
npm run rebuild

# 2. Configure environment
export MCP_MODE=http
export USE_FIXED_HTTP=true  # Important: Use fixed implementation
export AUTH_TOKEN=$(openssl rand -base64 32)
export PORT=3000

# 3. Start server
npm run start:http

Option 3: Direct stdio Mode (Simplest for Local)

Skip HTTP entirely and use stdio mode directly:

{
  "mcpServers": {
    "n8n-local": {
      "command": "node",
      "args": [
        "/path/to/n8n-mcp/dist/mcp/index.js"
      ],
      "env": {
        "N8N_API_URL": "https://your-n8n-instance.com",
        "N8N_API_KEY": "your-api-key-here"
      }
    }
  }
}

💡 Save your AUTH_TOKEN - clients will need it to connect!

⚙️ Configuration

Required Environment Variables

Variable Description Example
MCP_MODE Must be set to http http
USE_FIXED_HTTP Important: Set to true for stable implementation true
AUTH_TOKEN or AUTH_TOKEN_FILE Authentication method See security section

Optional Settings

Variable Description Default Since
PORT Server port 3000 v1.0
HOST Bind address 0.0.0.0 v1.0
LOG_LEVEL Log verbosity (error/warn/info/debug) info v1.0
NODE_ENV Environment production v1.0
TRUST_PROXY Trust proxy headers (0=off, 1+=hops) 0 v2.7.6
BASE_URL Explicit public URL Auto-detected v2.7.14
PUBLIC_URL Alternative to BASE_URL Auto-detected v2.7.14
CORS_ORIGIN CORS allowed origins * v2.7.8
AUTH_TOKEN_FILE Path to token file - v2.7.10

n8n Management Tools (Optional)

Enable 16 additional tools for managing n8n workflows by configuring API access:

⚠️ Requires v2.7.1+ - Earlier versions had an issue with tool registration in Docker environments.

Variable Description Example
N8N_API_URL Your n8n instance URL https://your-n8n.com
N8N_API_KEY n8n API key (from Settings > API) n8n_api_key_xxx
N8N_API_TIMEOUT Request timeout (ms) 30000
N8N_API_MAX_RETRIES Max retry attempts 3

What This Enables

When configured, you get 16 additional tools (total: 39 tools):

Workflow Management (11 tools):

  • n8n_create_workflow - Create new workflows
  • n8n_get_workflow - Get workflow by ID
  • n8n_update_full_workflow - Update entire workflow
  • n8n_update_partial_workflow - Update using diff operations (v2.7.0+)
  • n8n_delete_workflow - Delete workflows
  • n8n_list_workflows - List all workflows
  • And more workflow detail/structure tools

Execution Management (4 tools):

  • n8n_trigger_webhook_workflow - Execute via webhooks
  • n8n_get_execution - Get execution details
  • n8n_list_executions - List workflow runs
  • n8n_delete_execution - Delete execution records

System Tools:

  • n8n_health_check - Check n8n connectivity
  • n8n_diagnostic - System diagnostics
  • n8n_validate_workflow - Validate from n8n instance

Getting Your n8n API Key

  1. Log into your n8n instance
  2. Go to Settings > API
  3. Click Create API Key
  4. Copy the generated key

⚠️ Security Note: Store API keys securely and never commit them to version control.

🏗️ Architecture

How HTTP Mode Works

┌─────────────────┐        ┌─────────────┐        ┌──────────────┐
│ Claude Desktop  │ stdio  │ mcp-remote  │  HTTP  │  n8n-MCP     │
│ (stdio only)    ├───────►│ (bridge)    ├───────►│  HTTP Server │
└─────────────────┘        └─────────────┘        └──────────────┘
                                                           │
                                                           ▼
                                                   ┌──────────────┐
                                                   │ Your n8n     │
                                                   │ Instance     │
                                                   └──────────────┘

Key Points:

  • Claude Desktop only supports stdio communication
  • mcp-remote acts as a bridge, converting stdio ↔ HTTP
  • n8n-MCP server connects to one n8n instance (configured server-side)
  • All clients share the same n8n instance (single-tenant design)

🌐 Reverse Proxy Configuration

URL Configuration (v2.7.14+)

n8n-MCP intelligently detects your public URL:

Priority Order:

  1. Explicit Configuration (highest priority):

    BASE_URL=https://n8n-mcp.example.com  # Full public URL
    # or
    PUBLIC_URL=https://api.company.com:8443/mcp
    
  2. Auto-Detection (when TRUST_PROXY is enabled):

    TRUST_PROXY=1  # Required for proxy header detection
    # Server reads X-Forwarded-Proto and X-Forwarded-Host
    
  3. Fallback (local binding):

    # No configuration needed
    # Shows: http://localhost:3000 (or configured HOST:PORT)
    

What You'll See in Logs:

[INFO] Starting n8n-MCP HTTP Server v2.7.17...
[INFO] Server running at https://n8n-mcp.example.com
[INFO] Endpoints:
[INFO]   Health: https://n8n-mcp.example.com/health
[INFO]   MCP:    https://n8n-mcp.example.com/mcp

Trust Proxy for Correct IP Logging

When running n8n-MCP behind a reverse proxy (Nginx, Traefik, etc.), enable trust proxy to log real client IPs instead of proxy IPs:

# Enable trust proxy in your environment
TRUST_PROXY=1  # Trust 1 proxy hop (standard setup)
# or
TRUST_PROXY=2  # Trust 2 proxy hops (CDN → Load Balancer → n8n-mcp)

Without TRUST_PROXY:

[INFO] GET /health { ip: '172.19.0.2' }  # Docker internal IP

With TRUST_PROXY=1:

[INFO] GET /health { ip: '203.0.113.1' }  # Real client IP

This is especially important when:

  • Running in Docker/Kubernetes
  • Using load balancers
  • Debugging client issues
  • Implementing rate limiting

🔐 Security Setup

Authentication

All requests require Bearer token authentication:

# Test authentication
curl -H "Authorization: Bearer $AUTH_TOKEN" \
     https://your-server.com/health

Use a reverse proxy for SSL termination:

Nginx example:

server {
    listen 443 ssl;
    server_name your-domain.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location /mcp {
        proxy_pass http://localhost:3000;
        proxy_set_header Authorization $http_authorization;
        # Important: Forward client IP headers
        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;
    }
}

Caddy example (automatic HTTPS):

your-domain.com {
    reverse_proxy /mcp localhost:3000
}

💻 Client Configuration

⚠️ Requirements: Node.js 18+ must be installed on the client machine for mcp-remote

{
  "mcpServers": {
    "n8n-remote": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://your-server.com/mcp",
        "--header",
        "Authorization: Bearer YOUR_AUTH_TOKEN_HERE"
      ]
    }
  }
}

Note: Replace YOUR_AUTH_TOKEN_HERE with your actual token. Do NOT use ${AUTH_TOKEN} syntax - Claude Desktop doesn't support environment variable substitution in args.

Method 2: Using Custom Bridge Script

For local testing or when mcp-remote isn't available:

{
  "mcpServers": {
    "n8n-local-http": {
      "command": "node",
      "args": [
        "/path/to/n8n-mcp/scripts/http-bridge.js"
      ],
      "env": {
        "MCP_URL": "http://localhost:3000/mcp",
        "AUTH_TOKEN": "your-auth-token-here"
      }
    }
  }
}

Local Development with Docker

When testing locally with Docker:

{
  "mcpServers": {
    "n8n-docker-http": {
      "command": "node",
      "args": [
        "/path/to/n8n-mcp/scripts/http-bridge.js"
      ],
      "env": {
        "MCP_URL": "http://localhost:3001/mcp",
        "AUTH_TOKEN": "docker-test-token"
      }
    }
  }
}

🌐 Production Deployment

Docker Compose (Complete Example)

version: '3.8'

services:
  n8n-mcp:
    image: ghcr.io/czlonkowski/n8n-mcp:latest
    container_name: n8n-mcp
    restart: unless-stopped
    environment:
      # Core configuration
      MCP_MODE: http
      USE_FIXED_HTTP: true
      NODE_ENV: production
      
      # Security - Using file-based secret
      AUTH_TOKEN_FILE: /run/secrets/auth_token
      
      # Networking
      HOST: 0.0.0.0
      PORT: 3000
      TRUST_PROXY: 1  # Behind Nginx/Traefik
      CORS_ORIGIN: https://app.example.com  # Restrict in production
      
      # URL Configuration
      BASE_URL: https://n8n-mcp.example.com
      
      # Logging
      LOG_LEVEL: info
      
      # Optional: n8n API Integration
      N8N_API_URL: ${N8N_API_URL}
      N8N_API_KEY_FILE: /run/secrets/n8n_api_key
      
    secrets:
      - auth_token
      - n8n_api_key
      
    ports:
      - "127.0.0.1:3000:3000"  # Only expose to localhost
      
    volumes:
      - n8n-mcp-data:/app/data:ro  # Read-only database
      
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
      
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'
        reservations:
          memory: 128M
          cpus: '0.1'
    
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

secrets:
  auth_token:
    file: ./secrets/auth_token.txt
  n8n_api_key:
    file: ./secrets/n8n_api_key.txt

volumes:
  n8n-mcp-data:

Systemd Service (Production Linux)

# /etc/systemd/system/n8n-mcp.service
[Unit]
Description=n8n-MCP HTTP Server
Documentation=https://github.com/czlonkowski/n8n-mcp
After=network.target
Requires=network.target

[Service]
Type=simple
User=n8n-mcp
Group=n8n-mcp
WorkingDirectory=/opt/n8n-mcp

# Use file-based secret
Environment="AUTH_TOKEN_FILE=/etc/n8n-mcp/auth_token"
Environment="MCP_MODE=http"
Environment="USE_FIXED_HTTP=true"
Environment="NODE_ENV=production"
Environment="TRUST_PROXY=1"
Environment="BASE_URL=https://n8n-mcp.example.com"

# Additional config from file
EnvironmentFile=-/etc/n8n-mcp/config.env

ExecStartPre=/usr/bin/test -f /etc/n8n-mcp/auth_token
ExecStart=/usr/bin/node dist/mcp/index.js --http

# Restart configuration
Restart=always
RestartSec=10
StartLimitBurst=5
StartLimitInterval=60s

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/n8n-mcp/data
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictSUIDSGID=true
LockPersonality=true

# Resource limits
LimitNOFILE=65536
MemoryLimit=512M
CPUQuota=50%

[Install]
WantedBy=multi-user.target

Setup:

# Create user and directories
sudo useradd -r -s /bin/false n8n-mcp
sudo mkdir -p /opt/n8n-mcp /etc/n8n-mcp
sudo chown n8n-mcp:n8n-mcp /opt/n8n-mcp

# Create secure token
sudo sh -c 'openssl rand -base64 32 > /etc/n8n-mcp/auth_token'
sudo chmod 600 /etc/n8n-mcp/auth_token
sudo chown n8n-mcp:n8n-mcp /etc/n8n-mcp/auth_token

# Deploy application
sudo -u n8n-mcp git clone https://github.com/czlonkowski/n8n-mcp.git /opt/n8n-mcp
cd /opt/n8n-mcp
sudo -u n8n-mcp npm install --production
sudo -u n8n-mcp npm run build
sudo -u n8n-mcp npm run rebuild

# Start service
sudo systemctl daemon-reload
sudo systemctl enable n8n-mcp
sudo systemctl start n8n-mcp

Enable:

sudo systemctl enable n8n-mcp
sudo systemctl start n8n-mcp

📡 Monitoring & Maintenance

Health Endpoint Details

# Basic health check
curl -H "Authorization: Bearer $AUTH_TOKEN" \
     https://your-server.com/health

# Response:
{
  "status": "ok",
  "mode": "http-fixed",
  "version": "2.7.17",
  "uptime": 3600,
  "memory": {
    "used": 95,
    "total": 512,
    "percentage": 18.5
  },
  "node": {
    "version": "v20.11.0",
    "platform": "linux"
  },
  "features": {
    "n8nApi": true,  // If N8N_API_URL configured
    "authFile": true  // If using AUTH_TOKEN_FILE
  }
}

🔒 Security Best Practices

1. Token Management

DO:

  • Use tokens with 32+ characters
  • Store tokens in secure files or secrets management
  • Rotate tokens regularly (monthly minimum)
  • Use different tokens for each environment
  • Monitor logs for authentication failures

DON'T:

  • Use default or example tokens
  • Commit tokens to version control
  • Share tokens between environments
  • Log tokens in plain text
# Generate strong token
openssl rand -base64 32

# Secure storage options:
# 1. Docker secrets (recommended)
echo $(openssl rand -base64 32) | docker secret create auth_token -

# 2. Kubernetes secrets
kubectl create secret generic n8n-mcp-auth \
  --from-literal=token=$(openssl rand -base64 32)

# 3. HashiCorp Vault
vault kv put secret/n8n-mcp token=$(openssl rand -base64 32)

2. Network Security

  • Always use HTTPS in production
  • Firewall rules to limit access
  • VPN for internal deployments
  • Rate limiting at proxy level

3. Container Security

# Run as non-root user (already configured)
# Read-only filesystem
docker run --read-only \
  --tmpfs /tmp \
  -v n8n-mcp-data:/app/data \
  n8n-mcp

# Security scanning
docker scan ghcr.io/czlonkowski/n8n-mcp:latest

🔍 Troubleshooting

Common Issues & Solutions

Authentication Issues

"Unauthorized" error:

# Check token is set correctly
docker exec n8n-mcp env | grep AUTH

# Test with curl
curl -v -H "Authorization: Bearer YOUR_TOKEN" \
     https://your-server.com/health

# Common causes:
# - Extra spaces in token
# - Missing "Bearer " prefix
# - Token file has newline at end
# - Wrong quotes in JSON config

Default token warning:

⚠️ SECURITY WARNING: Using default AUTH_TOKEN
  • Change token immediately via environment variable
  • Server shows this warning every 5 minutes

Connection Issues

"TransformStream is not defined":

# Check Node.js version on CLIENT machine
node --version  # Must be 18+

# Update Node.js
# macOS: brew upgrade node
# Linux: Use NodeSource repository
# Windows: Download from nodejs.org

"Cannot connect to server":

# 1. Check server is running
docker ps | grep n8n-mcp

# 2. Check logs for errors
docker logs n8n-mcp --tail 50

# 3. Test locally first
curl http://localhost:3000/health

# 4. Check firewall
sudo ufw status  # Linux

"Stream is not readable":

  • Ensure USE_FIXED_HTTP=true is set
  • Fixed in v2.3.2+

Bridge script not working:

# Test the bridge manually
export MCP_URL=http://localhost:3000/mcp
export AUTH_TOKEN=your-token
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node /path/to/http-bridge.js

Connection refused:

# Check server is running
curl http://localhost:3000/health

# Check Docker status
docker ps
docker logs n8n-mcp

# Check firewall
sudo ufw status

Authentication failed:

  • Verify AUTH_TOKEN matches exactly
  • Check for extra spaces or quotes
  • Test with curl first

Bridge Configuration Issues

"Why use 'node' instead of 'docker' in Claude config?"

Claude Desktop only supports stdio. The architecture is:

Claude → stdio → mcp-remote → HTTP → Docker container

The node command runs mcp-remote (the bridge), not the server directly.

"Command not found: npx":

# Install Node.js 18+ which includes npx
# Or use full path:
which npx  # Find npx location
# Use that path in Claude config

Debug Mode

# 1. Enable debug logging
docker run -e LOG_LEVEL=debug ...

# 2. Test MCP endpoint
curl -X POST https://your-server.com/mcp \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "id": 1
  }'

# 3. Test with mcp-remote directly
MCP_URL=https://your-server.com/mcp \
AUTH_TOKEN=your-token \
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | \
  npx mcp-remote $MCP_URL --header "Authorization: Bearer $AUTH_TOKEN"

Cloud Platform Deployments

Railway: See our Railway Deployment Guide

🔧 Using n8n Management Tools

When n8n API is configured, Claude can manage workflows directly:

Example: Create a Workflow via Claude

# Test n8n connectivity first
curl -X POST https://your-server.com/mcp \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "n8n_health_check",
    "params": {},
    "id": 1
  }'

Common Use Cases

  1. Workflow Automation: Claude can create, update, and manage workflows
  2. CI/CD Integration: Deploy workflows from version control
  3. Workflow Templates: Claude can apply templates to new workflows
  4. Monitoring: Track execution status and debug failures
  5. Incremental Updates: Use diff-based updates for efficient changes

Security Best Practices for n8n API

  • 🔐 Use separate API keys for different environments
  • 🔄 Rotate API keys regularly
  • 📝 Audit workflow changes via n8n's audit log
  • 🚫 Never expose n8n API directly to the internet
  • Use MCP server as a security layer

📦 Updates & Maintenance

Version Updates

# Check current version
docker exec n8n-mcp node -e "console.log(require('./package.json').version)"

# Update to latest
docker pull ghcr.io/czlonkowski/n8n-mcp:latest
docker stop n8n-mcp
docker rm n8n-mcp
# Re-run with same environment

# Update to specific version
docker pull ghcr.io/czlonkowski/n8n-mcp:v2.7.17

Database Management

# The database is read-only and pre-built
# No backups needed for the node database
# Updates include new database versions

# Check database stats
curl -X POST https://your-server.com/mcp \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "get_database_statistics",
    "id": 1
  }'

🆘 Getting Help