Audit logging for n8n workflows that call MCP tools

dev.to

If you run an n8n workflow that calls MCP tools, here's something you've probably hit. The execution log shows the MCP Client Tool node ran, but it doesn't show what the agent asked the tool to do, or what it got back.

That's a gap. If the agent loops, or hits a tool you didn't expect, or sends arguments you wouldn't have approved, the execution log just says "MCP Client Tool: success."

I built Cordon for this gap.

What Cordon is

Cordon is an MCP gateway that sits between your MCP client and any upstream MCP server, logs every tool call, and lets you write policies that block or pause calls before they fire. Open source, MIT, free.

n8n's MCP Client Tool node takes a URL and a bearer token. That's also exactly what Cordon's HTTP transport exposes. So the swap is a one-field change. Point the node at Cordon, point Cordon at the upstream server, and you get an audit trail of every call your agent makes through n8n.

Setup

Five minutes if you already have n8n running and at least one MCP server you want to put behind it.

1. Install Cordon

npm install -g @getcordon/cli
Enter fullscreen mode Exit fullscreen mode

2. Write a config

Cordon reads a cordon.config.ts in the directory you run it from. Point it at whatever MCP server your n8n workflow currently uses.

import { defineConfig } from '@getcordon/policy';

export default defineConfig({
  servers: [
    {
      name: 'filesystem',
      transport: 'stdio',
      command: 'npx',
      args: ['-y', '@modelcontextprotocol/server-filesystem', '/path/to/dir'],
      policy: 'allow',
    },
  ],
  gateway: {
    transport: 'http',
    port: 7777,
    authToken: process.env.CORDON_GATEWAY_TOKEN,
  },
  audit: { enabled: true, output: 'stdout' },
});
Enter fullscreen mode Exit fullscreen mode

3. Start the gateway

export CORDON_GATEWAY_TOKEN=$(openssl rand -hex 16)
cordon start --http
Enter fullscreen mode Exit fullscreen mode

Cordon spawns the upstream MCP server as a child process and listens on http://127.0.0.1:7777/mcp. The stderr line you're waiting for looks like this.

[cordon] HTTP gateway listening on http://127.0.0.1:7777/mcp
Enter fullscreen mode Exit fullscreen mode

4. Point n8n at Cordon

In your n8n workflow, open the MCP Client Tool node. Set Server Transport to HTTP Streamable. The SSE option is deprecated, and Cordon serves Streamable HTTP at /mcp. Set the endpoint URL to:

http://127.0.0.1:7777/mcp
Enter fullscreen mode Exit fullscreen mode

Set Authentication to Bearer and paste in your CORDON_GATEWAY_TOKEN. Save.

If you're running n8n in Docker and Cordon outside it, swap 127.0.0.1 for your host's IP, or run Cordon in the same Docker network and use the container name. If you're hosting Cordon behind a reverse proxy, the URL becomes https://<your-domain>/mcp and everything else is the same.

What you see

Run your workflow. Cordon prints a line of audit JSON to stderr for every tool call, with the tool name, the arguments, the response timing.

{"event":"tool_call_received","timestamp":1748000000000,"callId":"call_001","toolName":"read_file","args":{"path":"/data/notes.md"}}{"event":"tool_call_completed","timestamp":1748000000350,"callId":"call_001","toolName":"read_file","durationMs":350}
Enter fullscreen mode Exit fullscreen mode

That's the visibility n8n's execution log doesn't give you. Now you can see what the agent actually asked the tool to do.

If you want a friendlier surface, run cordon login to authenticate against the hosted dashboard and switch your config's audit output to 'hosted'. Same events, browser table, sortable, exportable.

Gating dangerous calls

You can also tag specific tools with policies. Change a tool's action to 'approve' and Cordon pauses for a human before the call fires. Slack or terminal prompt. Useful when an agent has access to a tool you don't fully trust the agent to use unsupervised.

tools: {
  delete_file: { action: 'block', reason: 'Delete is for manual ops only.' },
  write_file:  { action: 'approve', reason: 'Writes need human review.' },
}
Enter fullscreen mode Exit fullscreen mode

Try it

If you're running n8n workflows with MCP tools, adding Cordon is a config change and a node-URL swap and boom! You're seeing what's happening.

getcordon.com

If you want a worked example with a real production MCP server in front, here's how I run Cordon in front of Agent Toolbelt (27 tools my agents call for stock research, schema gen, regex and the small stuff). Same swap, more concrete.

marcoarras.com/writing/agent-toolbelt-behind-cordon

Source: dev.to

arrow_back Back to News