final-approval
# FinalApproval MCP Server
Standalone [Model Context Protocol](https://modelcontextprotocol.io) server for [FinalApproval](https://www.finalapproval.ai) — **gate AI agent actions behind a human approval**.
Your agent calls `submit_approval`; a human reviews on a branded page in your FinalApproval dashboard; the channel's configured webhook fires back when the human decides.
This is the **stdio** variant intended for local / headless / CI / directory-indexed (Glama) use. If you want the hosted OAuth-gated Streamable-HTTP server instead, point MCP clients at `https://www.finalapproval.ai/mcp`.
## Scope
v0.1 exposes one tool:
| Tool | Status | Notes |
| ----------------- | -------- | ----------------------------------------------------------------- |
| `submit_approval` | ✅ shipped | Creates a pending approval. Webhook fires on resolution. |
| `wait_for_resolution` | planned | Blocked on public `GET /api/v1/approvals/:id`. Use webhook today. |
| `list_pending` | planned | Blocked on public `GET /api/v1/approvals`. |
| `get_approval` | planned | Blocked on public `GET /api/v1/approvals/:id`. |
For the full tool surface today, use the hosted endpoint at `https://www.finalapproval.ai/mcp` (OAuth 2.1, scope `approvals:write`).
## Setup
1. Sign in at [finalapproval.ai](https://www.finalapproval.ai) and create a channel. Copy its API key (starts with `fa_`) and configure a webhook URL.
2. Run the MCP server with the API key in `FINALAPPROVAL_API_KEY`.
### Claude Code / Cursor (Node)
```bash
npx -y @finalapproval/mcp-server
```
Config snippet (Claude Code `~/.claude.json`):
```json
{
"mcpServers": {
"finalapproval": {
"command": "npx",
"args": ["-y", "@finalapproval/mcp-server"],
"env": {
"FINALAPPROVAL_API_KEY": "fa_..."
}
}
}
}
```
### Docker
```bash
docker run --rm -i \
-e FINALAPPROVAL_API_KEY=fa_xxx \
ghcr.io/finalapproval/final-approval-mcp:latest
```
(Published image coming; you can also build locally: `docker build -t finalapproval-mcp .`.)
## Environment variables
| Var | Required | Default | Purpose |
| ------------------------ | -------- | --------------------------------- | ----------------------------------- |
| `FINALAPPROVAL_API_KEY` | yes | — | Channel API key (starts with `fa_`) |
| `FINALAPPROVAL_URL` | no | `https://www.finalapproval.ai` | Override for self-hosted / dev |
## Closing the loop
`submit_approval` returns immediately with a pending approval ID. The actual decision arrives **via the channel's webhook**, not back through MCP. Your host application (the agent's server) must implement a webhook receiver that verifies the HMAC signature and executes the gated action on `approved` or logs on `denied`. See the [FinalApproval docs](https://www.finalapproval.ai/docs) for webhook payload schema.
## Development
```bash
npm install
npm run build
FINALAPPROVAL_API_KEY=fa_... npm start
```
## License
MIT
TDQS
Scored across 1 tool
With only one tool, there is no possibility of ambiguity or overlap between tools. The single tool has a clear and distinct purpose for submitting approvals.
The tool name 'submit_approval' follows a clear verb_noun pattern. Since there is only one tool, consistency is inherently perfect with no deviations or mixed conventions.
A single tool is too few for most practical server purposes, as it severely limits functionality and scope. While it might serve a narrow use case, it feels thin and incomplete for typical agent workflows.
The server's domain appears to be approval workflows, but with only a submit tool, there are significant gaps. Missing operations likely include checking approval status, listing pending approvals, or handling approvals programmatically, which could cause agent failures.