io.github.itcustomsolution/approval-gate-mcp·Agent infra

approval-gate-mcp

Fail-closed human approval gates for AI agent actions. Default-deny, TTL expiry, audit log.

Stars
0
Version
0.1.0
License
MIT
Review
Passed
Language
TypeScript
Last commit
4h ago
Forks
0
Open issues
1
Registry update
Oct 15, 2026
ai-agentsai-safetyapproval-workflowaudit-logguardrailshuman-in-the-loopmcpmcp-servermodel-context-protocoltypescript

Connect

npm
Terminal
$claude mcp add approval-gate-mcp \  -- npx -y @itcustomsolution/[email protected]

Environment variables

Nothing to configure — it works as is.

Security review

Review passed

Reviewed 1h ago.

metadata
scanned
packages
1 checked

No findings.

Tools

This server runs on your machine, so its tool list is not fetched before install — the README below describes what it offers.

approval-gate-mcp

An MCP server that makes your AI agent stop and ask a human before it sends, deletes, publishes, pays or deploys.

npm

license: MIT

Why

Agents are good at doing things. The hard part is making sure the consequential things (sending an email, deleting data, publishing, spending money) only happen when a human said yes. This server is that gate, extracted from a system I have run in production for years: after an automation incident taught me the lesson the hard way, my standing rule became no automated destructive action without a human gate, ever. This is the generic, reusable version of that rule.

30-second quickstart

claude mcp add approval-gate -- npx -y @itcustomsolution/approval-gate-mcp

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "approval-gate": {
      "command": "npx",
      "args": ["-y", "@itcustomsolution/approval-gate-mcp"]
    }
  }
}

Approve or deny from your terminal with npx -p @itcustomsolution/approval-gate-mcp approval-gate list.

Example

  1. Your agent wants to email a customer. It calls request_approval with action: "send email to [email protected], subject: Invoice 1042" and gets back id a1b2c3d4e5f6.
  2. It calls wait_for_approval. Nothing is sent.
  3. In your own terminal: approval-gate list, then approval-gate approve a1b2c3d4e5f6 looks right.
  4. The agent sees approved and sends. Had you denied, ignored it, or let it expire, the answer is no.
  5. ~/.approval-gate/audit.jsonl now has the request and your decision.

Design principles

  • Fail closed. The only thing that authorizes an action is an explicit approved. Pending, denied, expired, timeout, error: all of those mean no.
  • The gate never executes anything. It records intent and decisions. Your agent asks first, then acts only on approval. Separation of decision and execution keeps the gate simple and auditable.
  • Decisions are out-of-band. A human approves or denies with a CLI in their own terminal, not inside the agent's context, so the agent cannot talk itself through the gate.
  • Everything is audited. Every request, decision, and expiry is appended to ~/.approval-gate/audit.jsonl.
  • Requests expire. Default TTL is 1 hour; a stale approval is not an approval.

Install

From npm:

npm install -g @itcustomsolution/approval-gate-mcp   # installs `approval-gate` and `approval-gate-mcp`

From source:

npm install
npm run build
npm link        # makes `approval-gate` and `approval-gate-mcp` available on PATH

Wire it into an MCP client

Claude Code:

claude mcp add approval-gate -- node /path/to/approval-gate-mcp/dist/index.js

Or in any MCP client config:

{
  "mcpServers": {
    "approval-gate": {
      "command": "node",
      "args": ["/path/to/approval-gate-mcp/dist/index.js"]
    }
  }
}

Tools

ToolPurpose
request_approvalRegister an intended action (action, reason, optional ttl_seconds). Returns an id.
check_approvalPoll a request's status: pending / approved / denied / expired.
wait_for_approvalBlock up to timeout_seconds for a decision. Timeout = still pending = not approved.
list_pendingList requests awaiting a human.
decide_approvalRecord a decision when the human is driving the session. Agents must never self-approve; prefer the CLI.

The human side

approval-gate list                # pending requests
approval-gate show a1b2c3d4e5f6
approval-gate approve a1b2c3d4e5f6 looks right, ship it
approval-gate deny a1b2c3d4e5f6 wrong recipient

Suggested agent policy

Put something like this in your agent's system prompt or policy file:

Before any outbound or destructive action (send, publish, delete, purchase, deploy), call request_approval and then wait_for_approval. Proceed only if the returned status is exactly approved. Never call decide_approval for your own requests.

State

Everything lives in ~/.approval-gate/ (override with APPROVAL_GATE_DIR): requests/*.json for current state, audit.jsonl for the append-only history.

Why so small?

Because the pattern matters more than the plumbing. In my production systems this same shape (request, out-of-band human decision, fail-closed default, audit trail) sits in front of email, publishing, and deployments, and it has turned entire classes of automation incidents into structural impossibilities. Start small, gate the scary things, and let your incident postmortems tell you what to gate next.

Contributing

Issues and pull requests are welcome. Keep changes small and fail-closed: anything that could turn a "no" into a "yes" needs a test. Run npm test before opening a PR. See CHANGELOG.md for release history.

License

MIT, see LICENSE.


Built by Olufela "Lu" Fagbure · itcustomsolution.com · MIT license

From the server's repository — third-party content, read it before running anything it suggests.

More in Agent infra

Listing from the official MCP Registry · repository facts from GitHub, 1h ago.