MCP server

confirm-mcp gives any MCP-compatible agent a human-approval tool. Before the agent does something irreversible, it calls request_approval, a human approves or edits the action, and the agent proceeds with the approved result. Every decision is logged.

Setup

Create an API key under Dashboard → API Keys, then add the server to your MCP client. The same block works in Claude Desktop (claude_desktop_config.json) and Cursor (~/.cursor/mcp.json, or .cursor/mcp.json for one project):

claude_desktop_config.json / ~/.cursor/mcp.json
{
  "mcpServers": {
    "confirm": {
      "command": "npx",
      "args": ["-y", "confirm-mcp"],
      "env": { "CONFIRM_API_KEY": "cfm_live_..." }
    }
  }
}

Restart the client. The agent now has two tools, request_approval and check_approval. Needs Node 18+ (the npx command pulls confirm-mcp on first run).

In practice

Tell the agent who approves what, and it calls the tool on its own before the risky step:

chat
You: You can issue refunds. Anything over $100 needs my approval
     at me@acme.com before you do it.

Agent: [calls request_approval]
       summary: "Refund $240 to customer #4821"
       payload: { "customerId": "4821", "amount": 240 }
       notify:  "me@acme.com"
       reasoning: "Customer was double-charged on order #88213."

  ... you get an email, open the link, approve (or edit the amount) ...

Agent: Approved. I've issued the $240 refund to customer #4821.

The agent decides when to ask; the tool enforces that it actually waits for a human and executes the approved effectivePayload. Pair it with the agent skill so the model reliably knows which actions to gate.

Tools

request_approval

Pause and ask a human to approve a sensitive action. Blocks until the human decides or the wait elapses. Inputs: summary, notify (email or group:<key>), payload, reasoning, recent_actions, ttl_minutes, and wait_minutes (how long to block, default 15).

On APPROVED it returns the effectivePayload to use (the human may have edited it). On REJECTED or EXPIRED it tells the agent to stop. If the wait elapses while still pending, it returns the request id.

check_approval

Poll a previously created request by id to see whether a human has decided.

The tool is the enforcement layer: the verdict is server-side and every decision is audited. Teaching the agent when to call it (via a system prompt or the confirm-approvals skill) is the coverage layer. For guaranteed coverage of specific actions, use the deterministic SDK policy engine (guard()) rather than relying on the model to remember.