I run a small MCP setup to let Claude trigger real automations in n8n. This guide shows how I containerise Claude (MCP client), a tiny MCP server (Node.js or Python), and n8n with Docker. I explain the Docker compose pattern I use, how the MCP server exposes a simple tool like run_n8n_workflow, and how that tool triggers n8n via webhook or the execution API. Expect practical commands, a Node.js example, and clear checks to prove it works.
Get Docker and docker-compose on the machine you plan to run on. On most Linux boxes that means apt install docker.io docker-compose or the distro equivalent. Make sure your user can talk to Docker or run the compose commands as root. My minimal deploy groups three containers: claude-client (or your local MCP client), mcp-server (Node.js or Python), and n8n. I keep data directories mounted and expose only the ports I need. A compact docker-compose snippet I use looks like this:
yaml
version: ‘3.7’
services:
mcp-server:
image: my/mcp-server:latest
build: ./mcp-server
ports: [‘3000:3000’]
environment:
MCPSECRET: ‘replace-with-secret’
n8n:
image: n8nio/n8n:latest
ports: [‘5678:5678’]
environment:
N8NBASICAUTHACTIVE: ‘true’
N8NBASICAUTHUSER: ‘admin’
N8NBASICAUTHPASSWORD: ‘strongpass’
claude-client:
image: my/claude-client:latest
environment:
MCP_SERVER: ‘http://mcp-server:3000’
Start it with docker-compose up -d. Check docker-compose ps to see containers running. If n8n refuses to start, inspect docker-compose logs n8n for port or database problems.
I keep the MCP server as the glue layer. It exposes small, stable tool definitions to Claude. One tool is run_n8n_workflow. Claude calls that tool with a payload like workflow name and parameters. The MCP server either posts to an n8n webhook endpoint or calls the executions API. I prefer webhooks for simple triggers and the executions API for passing structured data and waiting for results.
Here is the flow I implement in Node.js for a webhook trigger. It is short and reliable.
js
const fetch = require(‘node-fetch’);
async function runN8nWebhook(workflowKey, payload) {
const url = http://n8n:5678/webhook/${workflowKey};
const res = await fetch(url, {
method: ‘POST’,
body: JSON.stringify(payload),
headers: { ‘Content-Type’: ‘application/json’ }
});
return res.ok ? await res.text() : { error: res.status };
}
If you prefer the execution API, POST to /rest/executions in n8n and include credentials. On self-hosted n8n with basic auth enabled, pass the basic auth header or the API key. Make sure the MCP server has network access to the n8n container by using the compose network name. In Docker compose the service name n8n resolves from mcp-server.
Test the whole chain with a predictable payload. I create a simple n8n workflow that accepts a webhook, logs the payload, and returns a known result in the final HTTP response. Trigger from the MCP server with a curl-style call or the Node.js snippet above. Verify with docker-compose logs mcp-server and docker-compose logs n8n. The logs will show the incoming webhook and any downstream steps like Slack or email nodes. If the workflow needs to return results to Claude, have n8n post back to the MCP server webhook or let the MCP server poll the n8n execution until it finishes, then forward the result to Claude via the MCP response channel.
Keep secrets out of images. I inject N8N_BASIC_AUTH_PASSWORD and MCP_SECRET through environment variables or a secrets backend. For larger payloads or long-running workflows use n8n’s execution API and poll for completion. For quick notifications use the webhook approach. If you want the model to decide when to trigger automations, expose small, predictable tools from the MCP server rather than giving the model raw API keys.
Concrete checks I run after initial setup: confirm all containers are healthy, POST a test payload to the MCP server tool endpoint, watch n8n receive the webhook, and confirm the workflow performs the expected final action such as sending an email or returning JSON. That proves the end-to-end chain: Claude calls MCP, MCP triggers n8n, n8n executes, and the result is delivered. Keep the MCP server code small. Put complex steps inside n8n. That keeps the model as a controller and the automation deterministic.






