Cordon sits between your LLM client and your MCP servers. When an agent calls a tool flagged for approval, the call stops. You see exactly what it's about to do — tool name, arguments, context — and decide whether to let it run.
Most MCP setups are binary: a tool is either allowed or blocked. That works for tools you're certain about. It breaks down for tools that are safe in some contexts and dangerous in others.
delete_rows is fine when you're cleaning test data. It's not fine when an agent
misread the task and is about to wipe your production users table. An allowlist can't
tell the difference. You can.
A human checkpoint costs 10 seconds. It catches the cases a ruleset misses — and it gives you an exact record of what the agent tried to do and why you approved or denied it.
The approval is synchronous. Cordon intercepts the tool call at the proxy layer, before it reaches the MCP server. The agent's entire turn is suspended at that point. No tool fires. No result is fabricated. The agent waits.
The agent makes a tools/call request. Cordon intercepts it before the MCP server sees it.
Cordon checks the tool against your config. If the action is approve or approve-writes, the call is held.
Tool name, all arguments, the policy that triggered. Terminal or Slack — you choose.
Type A to approve — the tool runs and returns its result. Type D to deny — the agent gets an error and can try a different approach.
No Docker. No Kubernetes. Works with Claude Desktop out of the box.
npm install -g @getcordon/cli
cordon init
// cordon.config.ts
import { defineConfig } from '@getcordon/policy';
export default defineConfig({
servers: [
{
name: 'database',
transport: 'stdio',
command: 'npx',
args: ['-y', '@my-org/db-mcp'],
policy: 'approve-writes', // reads pass; writes require approval
tools: {
drop_table: { action: 'block' }, // this one never runs
},
},
],
approvals: {
channel: 'terminal', // or 'slack'
timeoutMs: 60_000, // 60s before auto-deny; the request is
// retained and replayable if approved late
},
audit: { enabled: true },
});
cordon start and restart Claude Desktop. From that point, every write
operation your agent attempts arrives in your terminal for a go / no-go before it runs.
Reads flow freely. Any insert, update, or delete pauses for approval. You see the exact query args before anything changes.
Let the agent read files without interruption. Block or approve any write — especially useful when an agent might overwrite a config or source file.
Reads from an API are fine. Any call that sends data outbound, posts to a webhook, or charges an account waits for a go-ahead.
Shell execution, deployment commands, and infra changes are often irreversible. A five-second approval is cheaper than a rollback.
Let the agent draft as much as it wants. Any send action pauses so you can read the output before it reaches the recipient.
One agent hands off to another. Insert a checkpoint before the hand-off tool fires so a human reviews the intermediate state before the next agent runs.
As of mid-2026. Enterprise gateways (MCPX/Lunar.dev, Kong, Docker MCP Gateway, Bifrost) enforce automated policy — allow or block against a ruleset, no human in the loop.
| Capability | Cordon | Typical enterprise MCP gateway |
|---|---|---|
| Synchronous human approval | ✓ Agent pauses until you decide | ✗ Automated policy only |
| Reads pass automatically | ✓ approve-writes policy |
✓ Configurable allow rules |
| Per-tool block list | ✓ Named tools can be always-block | ✓ Rule-based blocking |
| Call-graph sequence rules | ✓ Block read → write patterns in one turn | ✗ Per-tool rules only |
| Audit log | ✓ Every call, arg, decision, timestamp | ✓ Call logging |
| Install time | ✓ 2 minutes via npm | ✗ Kubernetes / Docker deployment |
| Pricing | ✓ Free and open source (MIT) | ✗ Enterprise / contact sales |
Comparing Cordon to a specific gateway? See the Cordon vs MCPX breakdown →
Install Cordon (npm install -g @getcordon/cli), run cordon init
to auto-patch Claude Desktop, then set policy: 'approve' or
policy: 'approve-writes' in your cordon.config.ts. When the
agent calls a matching tool, Cordon shows you the tool name and arguments and waits.
Type A to approve or D to deny.
Yes. The approval is synchronous. Cordon holds the tool call before it reaches the MCP server. The agent's turn is fully suspended — no tool runs, no result is returned — until you respond. The agent then continues from where it paused with the approved or denied result.
The call is denied after timeoutMs and the agent moves on with an error —
Cordon does not hold your agent open indefinitely. The request itself is kept, though.
Cordon retains the pending approval with its full context and lists it in the dashboard
under What changed → Timed-out approvals. If someone approves the card
after it expired, that late decision is recorded and you can run the call with
cordon replay <callId>, which executes the tool and logs the outcome
to the same audit stream. One limit worth knowing: replay recovers the
tool call, not the agent's session — the agent that originally asked is gone.
And only a call approved after timing out can be replayed, since replaying a
call that already ran would execute it twice.
Cordon is the only MCP gateway built around synchronous human-in-the-loop approval. Enterprise gateways (MCPX/Lunar.dev, Kong, Docker MCP Gateway, Bifrost) enforce automated allow/block policies only — there is no mechanism for a human to review and approve a pending tool call in real time.
Yes, and on the hosted plan it's one click. Connect your workspace once with
Add to Slack in the dashboard, then set
approvals: { channel: 'slack' }. There's no bot token to create or paste.
A flagged tool call posts an Approve / Deny card with the tool name and arguments to
your channel, the agent waits, and the approver's name lands on the audit record. If you
self-host Cordon you wire your own Slack app instead. Both paths are in the Slack
approvals setup guide.
Two options. Set the tool to always block:
tools: { drop_table: { action: 'block' } } — the call is rejected
every time. Or set it to approve: tools: { drop_table: { action: 'approve' } }
— it pauses so you can decide in context. Block is right when the tool should never run.
Approve is right when you occasionally need it but want a checkpoint every time.
Free, open source, no Docker required. Two minutes from npm install to your first approval prompt.