Approval Gate
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Approval GateDraft an email approving a $40 refund for Jane and ask for my approval before sending."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Approval Gate — an MCP App
A human approval gate for AI agents, built as an MCP App. Before an agent does something consequential — send an email, issue a refund, publish a post, delete data — it calls a tool that renders an interactive card inline in the chat. A human clicks Approve, Edit, or Reject, and only then does the agent proceed.
It runs in any MCP Apps host: Claude (web/desktop), ChatGPT, VS Code, Goose, and others.
Why this and not a dashboard? The highest-leverage use of MCP Apps in real workflows isn't a fancy chart — it's the confirmation gate that stops an agent acting on a misread "yes". The artifact changes per client; the pattern doesn't.
How it works
MCP Apps extend MCP with one idea: a tool can declare a UI resource. When the tool is called, the host fetches that resource and renders it in a sandboxed iframe, then relays messages between the UI and your server.
This project wires up that pattern for an approval gate using three tools and one UI resource:
┌─────────────────────────────────────────────┐
agent calls │ request_approval (declares the UI resource)│
request_approval ───▶│ → creates a pending ApprovalRequest │
│ → host renders ui://approval-gate card │
└───────────────────────┬─────────────────────┘
│ card shows the artifact
▼
human clicks Approve / Edit / Reject
│
┌───────────────────────▼─────────────────────┐
the card calls │ submit_approval_decision │
(via the host) ─────▶│ → records the decision (once only) │
│ → returns the outcome to the agent │
└───────────────────────┬─────────────────────┘
│ "APPROVED" / "…WITH EDITS" / "REJECTED"
▼
agent proceeds with the action — or doesn't
list_approvals → read-only audit trail of every gate and its decisionThe agent's contract is simple: call request_approval, then wait. It must not perform the real action until submit_approval_decision reports approved or edited. On edited, it uses the reviewer's corrected values; on rejected, it stops.
Related MCP server: LoopIn MCP Server
Project structure
mcp-approval-gate/
├── server.ts # MCP server: registers the 3 tools + the UI resource
├── main.ts # Entry point: stdio (--stdio) or Streamable HTTP
├── mcp-app.html # View shell (Vite bundles the React app into it)
├── src/
│ ├── types.ts # Shared, type-only model (ApprovalRequest, …)
│ ├── schemas.ts # Zod input schemas for the tools
│ ├── store.ts # In-memory store + audit trail (swap for a DB in prod)
│ └── ui/
│ ├── main.tsx # React entry
│ ├── useApprovalApp.ts# Hook around the ext-apps `App` class (connect/receive/submit/theme)
│ ├── ApprovalCard.tsx # The card: view / edit / reject / outcome states
│ └── styles.css # Theme-adaptive styling (matches host light/dark)
├── vite.config.ts # Bundles the View into a single self-contained HTML file
├── tsconfig.json # Typecheck for the View
├── tsconfig.server.json # Typecheck for the server
└── test-smoke.mjs # End-to-end runtime test over stdioPrerequisites
Node.js 20.19+ or 22+
An MCP Apps-capable host to see the UI (Claude Desktop, ChatGPT, VS Code, Goose, …), or the
basic-hostfrom the ext-apps repo for local testing.
Setup
npm install
npm run build # typechecks, then bundles the View into dist/mcp-app.htmlThe server serves dist/mcp-app.html as the UI resource, so you must build before running.
Run
Streamable HTTP (default, on http://localhost:3001/mcp):
npm startstdio (for Claude Desktop and other local hosts):
npm run start:stdioDuring development, npm run dev rebuilds the View on change and restarts the server.
Use it in Claude Desktop
Build first (npm run build), then add this to your claude_desktop_config.json (use an absolute path):
{
"mcpServers": {
"approval-gate": {
"command": "npx",
"args": ["-y", "tsx", "/ABSOLUTE/PATH/TO/mcp-approval-gate/main.ts", "--stdio"]
}
}
}Restart Claude Desktop, then try a prompt like:
Draft a reply to Jane approving her $40 refund, and ask me to approve it before sending.
The agent calls request_approval, the card appears inline, and your click decides what happens next.
Try it locally with basic-host
The ext-apps repo ships a reference host you can run against this server over HTTP:
# terminal 1 — this project
npm start
# terminal 2 — the reference host
git clone https://github.com/modelcontextprotocol/ext-apps.git
cd ext-apps && npm install && cd examples/basic-host && npm start
# open http://localhost:8080, point it at http://localhost:3001/mcp,
# call request_approval, and interact with the cardTest
test-smoke.mjs boots the server over stdio and drives the full flow — initialize, list tools, call request_approval, read the UI resource, submit an edited decision, verify the one-decision-only guard, and check the audit trail:
npm run build && node test-smoke.mjsAdapting it
Change the artifact, keep the gate.
request_approvaltakes a genericfields: [{ label, value, multiline? }]list, so the same card reviews an email, a refund, a social post, or a config change. Only the calling agent's prompt changes.Make it durable. The store in
src/store.tsis an in-memoryMap— fine for a demo or single instance, lost on restart and not shared across replicas. Back it with Postgres or Redis for production; the function signatures (createRequest,recordDecision,listRequests) are the seam to replace.Add structured output. Each tool currently returns text. Define an
outputSchemaand returnstructuredContentif your host consumes structured tool results.
Tech
TypeScript · React 19 · Vite (single-file bundle) · @modelcontextprotocol/ext-apps · @modelcontextprotocol/sdk. Built against the MCP Apps spec version 2026-01-26.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Preventive human-approval write-gate for AI agents: writes commit only after a human approves.
Human-in-the-loop approval for agent actions, with verifiable action-bound receipts.
Supervised API-write gateway for AI agents with policy, human approval and execution receipts.
Runtime permission, approval, and audit layer for AI agent tool execution.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceHuman-in-the-Loop authorization gateway for AI Agents. Securely pause MCP workflows and route high-risk actions to human approvers via Slack or Email.40 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to pause execution at critical decision points and request human review before proceeding. Provides tools for creating interrupts, polling for decisions, and managing approvals through a simple REST API interface.4 npmMIT
- AlicenseAqualityDmaintenanceHuman-in-the-loop approval gate for AI agents. Your agent calls submit_approval before any irreversible action; a human reviews on a branded page; a signed webhook fires back with the decision.11MIT
- AlicenseNot gradedqualityCmaintenancePauses AI agent execution and routes approval requests to humans via Slack or email, with cryptographically signed proof of the human's decision.18 npmMIT