confirm-mcp
# confirm-mcp
An [MCP](https://modelcontextprotocol.io) server that gives any MCP-compatible agent (Claude Desktop, Cursor, and others) a human-approval tool. Before the agent does something irreversible, it calls `request_approval`, a human approves or edits the action at [confirm.dev](https://confirm.dev), and the agent proceeds with the approved result. Every decision is logged.
## Setup
Get an API key at [confirm.dev](https://confirm.dev), then add the server to your MCP client config.
**Claude Desktop** (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"confirm": {
"command": "npx",
"args": ["-y", "confirm-mcp"],
"env": { "CONFIRM_API_KEY": "cfm_live_..." }
}
}
}
```
That's it. The agent now has two tools.
## Tools
### `request_approval`
Pause and ask a human to approve a sensitive action. Blocks until the human decides or the wait elapses.
| Input | Description |
|---|---|
| `summary` | One line the human reads, e.g. "Refund $10,000 to customer #4821". Required. |
| `notify` | Approver email, or `group:<key>` to escalate to an approver group. Required. |
| `payload` | The exact action as structured data. The human can edit it before approving. |
| `reasoning` | Why the agent wants to do this. |
| `recent_actions` | The agent's recent steps, for context (max 10). |
| `ttl_minutes` | How long the request stays valid (5 to 10080). |
| `wait_minutes` | How long to block before returning "pending" (default 15). |
On **APPROVED**, the tool 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 so the agent can poll later.
### `check_approval`
Poll a previously created request by `id` to see whether a human has decided.
## Why a tool, not a prompt
The approval is enforced server-side: the agent cannot fake a verdict, and every decision is recorded in an immutable audit log. Teaching the agent *when* to call this (via a system prompt or an [agent skill](https://confirm.dev/docs)) is the coverage layer; the tool is the enforcement layer.
For production agents where you need guaranteed coverage of specific actions, use the deterministic policy engine in [`@confirm/sdk`](https://www.npmjs.com/package/@confirm/sdk) (`guard()`) rather than relying on the model to remember to call the tool.
Docs: [confirm.dev/docs](https://confirm.dev/docs). Node 18+.
## Development
This package is developed in a private monorepo alongside the Confirm.dev service and mirrored here on every release, which is why the history starts at the first public release. Issues and PRs are welcome; PRs get cherry-picked upstream.
Build: `npm install && npm run build`. Test: `node smoke.mjs` (after a build; uses a mocked client, no network).
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: one initiates an approval request and blocks, the other polls an existing request's status. There is no overlap or ambiguity between them.
Both tool names follow the consistent verb_noun pattern (request_approval, check_approval), using snake_case and parallel structure. This is a predictable and coherent naming convention.
With only 2 tools, the server is slightly under the typical 3-15 range, but the scope is highly focused on approval workflows. Both tools are essential and the count does not feel excessive or severely lacking.
The core lifecycle of approval is covered: creating a request and checking its status. A possible gap is cancellation of an approval request, but the blocking behavior of request_approval partially mitigates this, so the missing functionality is minor.