@ratifia/mcp
v0.5.0
Published
Ratifia MCP server — let an AI agent request a human decision/approval (HITL) mid-task and resume once it's answered. The agent becomes a Ratifia 'engine'.
Downloads
373
Maintainers
Readme
ratifia-mcp
Human-in-the-loop for AI agents. This MCP server lets an agent (Claude Code, Claude Desktop, etc.) pause on a human decision mid-task and resume once it's answered — the agent is the "engine", Ratifia owns the decision, notification, and verdict.
Install
Published on npm as @ratifia/mcp.
Add it to your MCP client — npx fetches and runs it:
{
"mcpServers": {
"ratifia": {
"command": "npx",
"args": ["-y", "@ratifia/mcp"],
"env": {
"RATIFIA_API_KEY": "your-org-worker-api-key",
"RATIFIA_APPROVER_EMAIL": "[email protected]"
}
}
}
}Point separate registrations at different environments by giving each its own RATIFIA_API_URL + key (e.g. ratifia-stg and ratifia-prod).
Local clone (development)
{
"mcpServers": {
"ratifia": {
"command": "node",
"args": ["/absolute/path/to/ratifia-mcp/dist/index.js"],
"env": {
"RATIFIA_API_KEY": "your-org-worker-api-key",
"RATIFIA_APPROVER_EMAIL": "[email protected]"
}
}
}
}Clone, then npm install && npm run build (rebuild after source changes). Use
npx tsx src/index.ts instead of the built file to skip the build step while iterating.
Configuration (env)
| Var | Required | Default | Purpose |
|-----|----------|---------|---------|
| RATIFIA_API_KEY | ✅ | — | Org-scoped worker API key. |
| RATIFIA_API_URL | | https://api.ratifia.com | Ratifia API base. |
| RATIFIA_APP_URL | | https://app.ratifia.com | Dashboard base for decision links. |
| RATIFIA_APPROVER_EMAIL | | — | Who the decision is assigned to / notified. |
| RATIFIA_POLICY | | — | Named policy whose route decides how you're notified (e.g. to your phone). |
Routing (email / SMS / escalation) is decided inside Ratifia by your org's policy — this server is a thin request/verdict bridge.
Tools
| Tool | What it does |
|------|--------------|
| request_decision | Create a decision, notify the human, return a decision_id. |
| check_decision | Poll a decision's status once. |
| await_decision | Block until the verdict lands (or a max wait elapses). |
| list_pending_decisions | The agent's inbox — what's outstanding. |
| cancel_decision | Withdraw a decision the agent no longer needs. |
Decision shapes
request_decision isn't only yes/no. Shape the answer with response_type:
| response_type | The human… | You read the answer from |
|-----------------|-----------|--------------------------|
| approval (default) | approves or rejects | verdict (+ note) |
| select | picks from options you provide (set allow_multiple for many) | response_value.selected (option ids → labels via response_spec.options) |
| text | types a value | response_value.text |
request_decision(
title: "Which environment?",
question: "Where should I deploy?",
response_type: "select",
options: [{ label: "Staging" }, { label: "Production" }]
)Conversational Approvals — propose a draft, get it refined
Pass proposed_output to attach an editable draft (e.g. an email you want to
send). The human refines it in conversation — in the dashboard or by replying in the
Slack thread — and you get their final version back:
request_decision(
title: "Send welcome email",
question: "Review this before I send it.",
proposed_output: { title: "Welcome email", content: "<your draft>" }
)When it resolves, await_decision / check_decision return the final text in
output.content (with a refined flag telling you whether the human changed it).
Act on output.content, not the draft you sent — it may differ.
Gate a specific tool call — show what you'd run
When the decision gates a concrete tool/function call, pass tool_name (and
tool_args). The reviewer sees a structured Tool call panel — the exact
action and arguments — instead of it being buried in free-text context:
request_decision(
title: "Approve refund?",
question: "This exceeds the $5,000 auto-approve floor.",
tool_name: "issue_refund",
tool_args: { amount_cents: 600000, currency: "USD", claim_id: "ACM-2024-00003" }
)tool_args is optional (some tools take none); it's ignored unless tool_name
is set.
How it works
- The agent calls
request_decisionbefore a consequential/irreversible step (deploy, delete, spend, send externally), an ambiguous call it shouldn't guess, or to get a human to pick/refine something. - Ratifia notifies the human (even away from keyboard) per the org's routing.
- The agent
await_decisions (or pollscheck_decision) — readverdict/note, plusresponse_value(select/text) oroutput(a refined draft). - The agent proceeds only on
approved; onrejected/expiredit adapts.
Learn more at ratifia.com.
