mcp serve
n8n-decanter mcp serve [--port N]
Starts the MCP guard-proxy: a localhost HTTP endpoint that speaks n8n’s
MCP protocol and forwards everything to your instance’s /mcp-server/http —
with decanter as the sole credential holder and one rule enforced
technically. It is the HTTP variant of the guard: for agents whose MCP
config can spawn a command, prefer mcp connect —
the stdio form the scaffolded .mcp.json already wires, with no secret to
manage. mcp serve exists for harnesses that only take an MCP URL:
- Blocked:
update_workflowcalls that write Code-node source. That covers both routes n8n exposes: ajsCodekey anywhere in the arguments (updateNodeParameters,addNode), and asetNodeParameterwhose JSON-PointerpathtargetsjsCode(where the code rides a scalarvalueand nojsCodekey appears). The caller gets an instructive tool error pointing at the file + push flow instead — Code-node source lives in this repo, not in ad-hoc MCP writes. The full op vocabulary is deliberately not enumerated; only the two source-writing routes are intercepted. - Blocked:
publish_workflowwhen the draft it would take live carries a dangling$('…')reference — the same checktestandpublishrun. Without it the go-live gate is bypassable: an agent could publish over raw MCP and skip the verb entirely. Fail-closed — if the check itself cannot run (n8n unreachable), the publish is refused too, and the message says the check failed rather than blaming the workflow. - Everything else passes through untouched, including SSE responses: reads, structure edits, wiring, the n8n build/lifecycle tools.
Like mcp connect, a forwarded structure edit also
triggers the live mirror — a debounced background pull that refreshes the
read-only workflow.json snapshot with no manual pull (fire-and-forget,
git-gated, tracked-only; on by default, "liveMirror": false to disable).
Point your agent’s MCP config at the printed URL with the printed
session secret as its Authorization header — the agent never sees an
n8n credential, and the secret rotates on every mcp serve run. The current
endpoint + secret also land in a gitignored .decanter-proxy.json, which the
scaffolded mcp-route-check.mjs session hook uses to nudge agents whose MCP
config still points at the instance directly.
{
"mcpServers": {
"n8n-instance": {
"type": "http",
"url": "http://127.0.0.1:5680/mcp-server/http",
"headers": { "Authorization": "Bearer <printed secret>" }
}
}
}
Safety properties: binds 127.0.0.1 only; unparseable request bodies are
refused (fail closed), oversized bodies are capped; requests without the
session secret never reach n8n. The blast radius of a proxy outage is
availability, not integrity — decanter’s own sync (pull/push/watch)
never routes through the proxy.
--port picks the listen port (default 5680; 0 for an ephemeral one —
note your agent config then changes every run). Stop with Ctrl-C.