docs/DOCKER_TROUBLESHOOTING.md
This guide helps resolve common issues when running n8n-mcp with Docker, especially when connecting to n8n instances.
Symptoms:
Solutions:
# Correct - mount as read-only
docker run -v $(pwd)/config.json:/app/config.json:ro ...
# Check if file is accessible
docker exec n8n-mcp cat /app/config.json
# Validate JSON file
cat config.json | jq .
docker logs n8n-mcp | grep -i config
/app/config.json)Symptoms:
NODE_DB_PATH environment variable is set but ignored/app/data/nodes.dbRoot Cause: Fixed in v2.7.16. Earlier versions had hardcoded paths in docker-entrypoint.sh.
Solutions:
docker pull ghcr.io/czlonkowski/n8n-mcp:latest
# Correct
NODE_DB_PATH=/app/data/custom/my-nodes.db
# Incorrect (will be rejected)
NODE_DB_PATH=/app/data/custom/my-nodes
services:
n8n-mcp:
environment:
NODE_DB_PATH: /app/data/custom/nodes.db
volumes:
- n8n-mcp-data:/app/data # Ensure parent directory is mounted
Symptoms:
n8n_health_check returns 502 errorRoot Cause: Network connectivity issues between n8n-mcp container and n8n instance.
Solutions:
Use Docker's special hostnames instead of localhost:
{
"mcpServers": {
"n8n-mcp": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "N8N_API_URL=http://host.docker.internal:5678",
"-e", "N8N_API_KEY=your-api-key",
"ghcr.io/czlonkowski/n8n-mcp:latest"
]
}
}
}
Alternative hostnames to try:
host.docker.internal (Docker Desktop on macOS/Windows)172.17.0.1 (Default Docker bridge IP on Linux)192.168.1.100)# Create a shared network
docker network create n8n-network
# Run n8n in the network
docker run -d --name n8n --network n8n-network -p 5678:5678 n8nio/n8n
# Configure n8n-mcp to use container name
{
"N8N_API_URL": "http://n8n:5678"
}
# docker-compose.yml
services:
n8n:
image: n8nio/n8n
container_name: n8n
networks:
- n8n-net
ports:
- "5678:5678"
n8n-mcp:
image: ghcr.io/czlonkowski/n8n-mcp:latest
environment:
N8N_API_URL: http://n8n:5678
N8N_API_KEY: ${N8N_API_KEY}
networks:
- n8n-net
networks:
n8n-net:
driver: bridge
Symptoms:
--rm flag doesn't work as expectedRoot Cause: Fixed in v2.7.20 - containers weren't handling termination signals properly.
Solutions:
{
"command": "docker",
"args": [
"run", "-i", "--rm", "--init",
"ghcr.io/czlonkowski/n8n-mcp:latest"
]
}
# Remove all stopped n8n-mcp containers
docker ps -a | grep n8n-mcp | grep Exited | awk '{print $1}' | xargs -r docker rm
Symptoms:
n8n_trigger_webhook_workflow fails with "SSRF protection" errorRoot Cause: Default strict SSRF protection blocks localhost access to prevent attacks.
Solution: Use moderate security mode for local development
# For Docker run
docker run -d \
--name n8n-mcp \
-e MCP_MODE=http \
-e AUTH_TOKEN=your-token \
-e WEBHOOK_SECURITY_MODE=moderate \
-p 3000:3000 \
ghcr.io/czlonkowski/n8n-mcp:latest
# For Docker Compose - add to environment:
services:
n8n-mcp:
environment:
WEBHOOK_SECURITY_MODE: moderate
Security Modes Explained:
strict (default): Blocks localhost + private IPs + cloud metadata (production)moderate: Allows localhost, blocks private IPs + cloud metadata (local development)permissive: Allows localhost + private IPs, blocks cloud metadata (testing only)Important: Always use strict mode in production. Cloud metadata is blocked in all modes.
Symptoms:
Solutions:
Verify n8n API is enabled:
Test API directly:
# From host machine
curl -H "X-N8N-API-KEY: your-key" http://localhost:5678/api/v1/workflows
# From inside Docker container
docker run --rm curlimages/curl \
-H "X-N8N-API-KEY: your-key" \
http://host.docker.internal:5678/api/v1/workflows
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=user
- N8N_BASIC_AUTH_PASSWORD=password
| Scenario | Use This URL | Why |
|---|---|---|
| n8n on host, n8n-mcp in Docker | http://host.docker.internal:5678 | Docker can't reach host's localhost |
| Both in same Docker network | http://container-name:5678 | Direct container-to-container |
| n8n behind reverse proxy | http://your-domain.com | Use public URL |
| Local development | http://YOUR_LOCAL_IP:5678 | Use machine's IP address |
# Check if n8n is running in Docker
docker ps | grep n8n
# Find Docker network
docker network ls
# Get container details
docker inspect n8n | grep NetworkMode
# Find your local IP
# macOS/Linux
ifconfig | grep "inet " | grep -v 127.0.0.1
# Windows
ipconfig | findstr IPv4
{
"command": "docker",
"args": [
"run", "-i", "--rm",
"--network", "host",
"-e", "N8N_API_URL=http://localhost:5678",
"ghcr.io/czlonkowski/n8n-mcp:latest"
]
}
{
"N8N_API_URL": "http://192.168.1.100:5678" // Replace with your IP
}
Deploy n8n-mcp as HTTP server to avoid stdio/Docker issues:
# Start HTTP server
docker run -d \
-p 3000:3000 \
-e MCP_MODE=http \
-e AUTH_TOKEN=your-token \
-e N8N_API_URL=http://host.docker.internal:5678 \
-e N8N_API_KEY=your-n8n-key \
ghcr.io/czlonkowski/n8n-mcp:latest
# Configure Claude with mcp-remote
{
"env": {
"LOG_LEVEL": "debug",
"DEBUG_MCP": "true"
}
}
# Test from n8n-mcp container
docker run --rm ghcr.io/czlonkowski/n8n-mcp:latest \
sh -c "apk add curl && curl -v http://host.docker.internal:5678/api/v1/workflows"
# View n8n-mcp logs
docker logs $(docker ps -q -f ancestor=ghcr.io/czlonkowski/n8n-mcp:latest)
# View n8n logs
docker logs n8n
# Check what n8n-mcp sees
docker run --rm ghcr.io/czlonkowski/n8n-mcp:latest \
sh -c "env | grep N8N"
# Check Docker networks
docker network inspect bridge
# Test DNS resolution
docker run --rm busybox nslookup host.docker.internal
host.docker.internal works out of the boxhost.docker.internal requires Docker 20.10+--add-host=host.docker.internal:host-gateway172.17.0.1host.docker.internal or WSL2 IP0.0.0.0 not 127.0.0.1# Remove all n8n-mcp containers
docker rm -f $(docker ps -aq -f ancestor=ghcr.io/czlonkowski/n8n-mcp:latest)
# Test n8n API with curl
curl -H "X-N8N-API-KEY: your-key" http://localhost:5678/api/v1/workflows
# Run interactive debug session
docker run -it --rm \
-e LOG_LEVEL=debug \
-e N8N_API_URL=http://host.docker.internal:5678 \
-e N8N_API_KEY=your-key \
ghcr.io/czlonkowski/n8n-mcp:latest \
sh
# Check container networking
docker run --rm alpine ping -c 4 host.docker.internal