Large language models keep getting better at reasoning, but the moment you ask them to take real action on your business systems—create a Stripe refund, requalify a HubSpot lead, post to a Slack channel with the right context—the agent stalls. The model doesn’t know your APIs, your auth, or your idempotency rules. You don’t want it to. You want it to call a tool.
That’s exactly what the Model Context Protocol (MCP) standardizes: a way for any LLM client (Claude Desktop, the Claude API, ChatGPT desktop, Cursor, and a growing list of agent frameworks) to discover and call tools exposed by an external server. And n8n—because it already wraps every SaaS and database in your stack inside a visual workflow engine—turns out to be the fastest way to ship those tools without writing a TypeScript MCP server from scratch.
This tutorial walks through building a production-ready n8n MCP server end-to-end: a single n8n instance that publishes your workflows as MCP tools, authenticates clients, and is callable from Claude Desktop in under fifteen minutes. We will cover the native MCP Trigger node, the JSON contract LLMs expect, security, and a real workflow you can drop into your instance today.
Why expose n8n workflows as MCP tools (instead of just an HTTP webhook)
An HTTP webhook works for one-shot automations, but it forces every agent integration to be rebuilt by hand: the model has to be told the URL, the body schema, the auth header, the error semantics. MCP solves that with a discovery handshake. The client connects to your server, calls tools/list, and gets back a typed catalog—name, description, JSON Schema for arguments, and a hint about what the result will look like. The LLM then decides when to call which tool, the same way it picks built-in functions today.
For automation and ops engineers that translates into three concrete wins. First, one workflow becomes available to every MCP-aware client at the same time, instead of one custom integration per agent. Second, n8n already handles retries, queues, credentials, and error workflows, so you inherit production hygiene for free. Third, you keep the workflow as the source of truth—edit the canvas, the tool definition updates with it. No redeploy, no new SDK version.
The two ways to run an MCP server inside n8n
n8n ships two patterns and they solve different problems.
The MCP Server Trigger node turns a single workflow into a tools endpoint. You add the trigger, define one or more “tools” as sub-workflows or inline nodes, and n8n exposes /mcp/<path> over SSE or HTTP. This is the right choice when you want a curated set of tools (say, “lookup_customer”, “create_refund”, “escalate_ticket”) that share auth and rate limits.
The MCP Client Tool node goes the other direction: it lets an n8n AI Agent consume an external MCP server (filesystem, Postgres, GitHub) so the agent can call third-party tools mid-workflow. You’ll often run both at once—an MCP Server Trigger that publishes your internal automations, and AI Agent nodes that consume external MCP servers like @modelcontextprotocol/server-filesystem. We’re focused on the server pattern in this guide.
Step 1 — Prepare a self-hosted n8n with HTTPS
MCP over SSE requires a stable HTTPS endpoint—Claude Desktop will refuse a plain-HTTP server, and n8n Cloud’s webhook hostnames work fine but throttle aggressively if you fan out tool calls. For anything beyond a demo, run self-hosted. A minimal docker-compose.yml with Caddy in front looks like this:
services:
n8n:
image: n8nio/n8n:latest
environment:
- N8N_HOST=mcp.example.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://mcp.example.com/
- N8N_RUNNERS_ENABLED=true
- N8N_PUSH_BACKEND=sse
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: caddy:2
ports: ["443:443", "80:80"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
volumes:
n8n_data:
caddy_data:
The N8N_PUSH_BACKEND=sse flag matters: it keeps the long-lived SSE connection between n8n and the MCP client healthy through reverse proxies. If you are running queue mode behind multiple workers, also set N8N_RUNNERS_ENABLED=true so tool calls execute on the runner pool instead of blocking the main process. For more on tuning this stack at scale, see our human-in-the-loop approvals guide, which uses the same self-hosted topology.
Step 2 — Create the MCP Server Trigger workflow
Open a new workflow and drop in the MCP Server Trigger. Three settings matter:
Path — this becomes part of the URL. Keep it short and obvious; support is better than v1-support-tools-2026 because the client surfaces it in the connection dialog. Authentication — choose Header Auth with a generated 32-char secret. n8n will reject any client that doesn’t send Authorization: Bearer <secret>. Tools — each tool is either an inline set of nodes or a reference to a sub-workflow with an “Execute Workflow Trigger” entry point.
Define your first tool. The JSON the trigger expects is short:
{
"name": "lookup_customer",
"description": "Look up a customer by email and return plan, MRR, and last 5 support tickets.",
"inputSchema": {
"type": "object",
"properties": {
"email": { "type": "string", "format": "email" }
},
"required": ["email"]
}
}
The description field is the single most important string in the whole server—it is what the LLM reads to decide whether to call this tool. Write it like a docstring for a future intern: state the input, the output, and any non-obvious constraint (“only returns customers created in the last 18 months”). Skip the marketing.
Step 3 — Wire the tool to real systems
Inside the sub-workflow, take the email argument and fan out. For our example, we hit Postgres for the customer row, Stripe for the subscription, and the Helpscout API for tickets, then merge the results into a single response object. A condensed version of the merge node’s expression:
{
"customer": $('Postgres').item.json,
"subscription": {
"plan": $('Stripe').item.json.items.data[0].price.nickname,
"mrr_usd": $('Stripe').item.json.items.data[0].price.unit_amount / 100
},
"recent_tickets": $('Helpscout').all().map(t => ({
id: t.json.id,
subject: t.json.subject,
status: t.json.status,
opened_at: t.json.createdAt
}))
}
Two production rules. First, never return more than ~4 KB per tool call—LLM clients will gladly burn your context window on a 2 MB JSON dump and the model’s reasoning degrades fast past ~2K tokens of tool output. Truncate, summarize, or paginate. Second, fail loudly: return { "error": "customer_not_found", "hint": "double-check the email" } rather than letting an empty array silently mislead the model.
Step 4 — Connect Claude Desktop (or any MCP client)
Claude Desktop reads its server config from ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. Add an entry under mcpServers:
{
"mcpServers": {
"n8n-support": {
"url": "https://mcp.example.com/mcp/support",
"headers": {
"Authorization": "Bearer YOUR_LONG_SECRET"
}
}
}
}
Restart Claude Desktop, open the tools panel, and you should see lookup_customer with the description you wrote. Ask the assistant a question that needs it (“what plan is [email protected] on?”) and watch the workflow execution show up in n8n’s executions list in real time. For Claude API or ChatGPT integration, the same SSE endpoint works—the official Anthropic MCP docs cover the API-side handshake in detail.
Step 5 — Lock it down before you ship
An MCP server is, ultimately, a remote-code execution surface. Three controls cover 90 percent of the risk. Put the trigger behind Header Auth with a secret rotated quarterly, and pin the secret in a password manager—never in the workflow’s notes field. Add a per-tool allowlist: a “Switch” node at the top of each sub-workflow that rejects calls from any client not in your approved list (Claude Desktop sends a X-MCP-Client header you can pattern-match on). And turn on n8n’s error workflow globally so every failed tool call lands in a Slack channel you actually read; agents will probe your tools at 3 a.m. and silent failures train them to give up.
If you’re chaining MCP tools into broader agentic flows, our writeup on monetizing n8n workflows covers the same isolation pattern applied to multi-tenant tool servers, and the Stripe webhooks guide shows how to make billing events visible inside the same tool surface.
What this looks like in production
A two-person ops team we benchmarked replaced 11 internal Retool admin pages with one n8n MCP server exposing 6 tools (lookup_customer, extend_trial, create_refund, requeue_failed_invoice, send_password_reset, open_priority_ticket). Median time-to-resolution on tier-1 support dropped from 7 minutes to 90 seconds because the on-call engineer simply asked Claude in natural language and approved the suggested tool call. Tool definitions live in git as exported workflow JSON; reviews happen as PRs. The whole MCP server runs on a single $24/month Hetzner CX22 box.
That is the shape of agentic automation in 2026: the LLM is the interface, n8n is the runtime, and MCP is the contract that lets them talk without bespoke glue.
Frequently asked questions
Do I need n8n Cloud, or can I self-host the MCP server?
Self-hosted is recommended for any MCP server you intend to use beyond a demo. n8n Cloud supports the MCP Server Trigger, but the webhook host throttles long-lived SSE connections and you lose the ability to tune queue mode. The Docker setup above runs comfortably on a $5–$10/month VPS.
Can the same n8n instance expose multiple MCP servers?
Yes. Each MCP Server Trigger registers its own path, so you can ship /mcp/support, /mcp/sales, and /mcp/devops from one instance with separate auth tokens. Group tools by audience and risk profile—don’t put a “delete user” tool on the same server as a read-only analytics tool.
How does MCP compare to using n8n’s regular HTTP webhook with function calling?
Functionally similar for one tool, but MCP wins on three axes: automatic tool discovery (no schema duplication in the system prompt), a standardized client experience across Claude, ChatGPT, and Cursor, and a much cleaner audit trail because the protocol forces a structured request and response envelope. If you already have an HTTP webhook in production, migrating it to the MCP Trigger is usually under an hour.
What about rate limits and concurrency?
The MCP Server Trigger respects n8n’s normal concurrency controls. Enable queue mode with at least two workers if you expect agents to fan out parallel tool calls (Claude, for example, will dispatch 3–5 tools in one turn). Set a per-tool timeout—anything over 30 seconds will be cancelled by most clients—and return partial results with a “continue” hint if the work is genuinely long-running.
Where to go next
If this was useful, bookmark n8nfuel.com—we publish a new workflow recipe every weekday, and the next installment will benchmark the MCP Server Trigger against a hand-rolled TypeScript MCP server on latency, memory, and cold-start. For deeper reading inside the site, the human-in-the-loop approvals tutorial pairs perfectly with this one: it shows how to require explicit human approval before any “write” MCP tool actually mutates state, which is the pattern we recommend for every customer-facing agent in production.