Skip to main content
Glama
agentlabbusiness

raposa-mcp

Official

raposa-mcp

Raposa Aval — human approval MCP on mcprush

Raposa Aval is a human-approval MCP server by DC ESCRYPT (https://raposa.group). It gives an agent one honest capability: before a high-stakes action runs, a named human must explicitly approve it. The API is served from EU infrastructure; approvals are sealed in a hash-chained audit log that can be exported for an auditor.

https://dcescrypt.com · Documentation · Get a sandbox key

1 · Why fail-closed approval matters

request_human_approval(action, context, risk) returns:

{approved: true|false, decided_by, decided_at, comment, status, …}

approved is true only when an authorised human pressed Approve. Every other outcome — a rejection, an expiry, a timeout — returns approved: false. Silence is never consent:

Outcome

approved

Meaning

approved

true

A named human approved within the deadline

rejected

false

A named human rejected — do not proceed

expired

false

The TTL elapsed with no decision — do not proceed; no decision will arrive for the id

timeout

false

Nobody answered within wait_sec — the request stays open until its TTL; check later with get_approval

The agent must branch on approved; the tool result never leaks a key or a secret. A decided approval is final: a second decision on the same id is refused with HTTP 409. Every decision lands in the hash-chained audit log (/v1/audit/verify, /v1/audit/export).

Related MCP server: gotoHuman MCP Server

2 · Architecture

Agent ──tool call──▶ MCP server (raposa-mcp) ──HTTPS, Bearer RAPOSA_API_KEY──▶ Raposa Aval API
                                                                             │
                                                          approval created (status: pending)
                                                                             │
                     human sees it: e-mail link · web console · Slack · Telegram
                                                                             │
     agent ◀── polls get_approval / webhook callback ◀── decision (approve|reject)
  • The MCP server holds only the client API key. It reads RAPOSA_API_KEY from its environment and never includes it in tool inputs or outputs.

  • Approvals are scoped per API key: one customer can never read or decide another customer's requests — foreign ids answer 404 Approval not found, and only an operator key can decide.

  • Decisions carry the approver identity and a comment; re-deciding is refused.

3 · Getting an API key

  1. Register a free sandbox at https://raposa.group/start/ (100 approvals a month).

  2. An e-mail titled “Raposa — your sandbox key” arrives with a one-time claim link, valid 24 hours. The link shows the key once and cannot be reused; an expired or used link refuses with 410 gone.

  3. The claim link is itself the credential: whoever opens it first within 24 h owns the key. Treat that mail as a secret — do not forward it or paste the link into tickets and chats. If the link may have leaked before you opened it, write to contact@raposa.group: an unclaimed link self-expires in 24 h and a claimed key can be revoked and reissued from the account page or by support.

  4. Put the key into the MCP server’s environment (below).

No production data is needed for the sandbox; the same flow issues paid-plan keys automatically after checkout.

4 · Install (secure, step by step)

The server is a stdio MCP server, one command: uvx raposa-mcp (pin raposa-mcp==0.1.2 to freeze a published release).

4.1 The key never travels through a command line

Do not write RAPOSA_API_KEY=<value> into a chat, a shell command, a screenshot or a repository. Two supported ways to bring the secret to the MCP process:

Secret-manager export (1Password CLI, any similar tool works the same way):

# ~/.zshrc or ~/.bash_profile — resolved at login from your own vault
export RAPOSA_API_KEY="$(op read 'op://Dev-API/<your-item>/key')"

The expansion happens inside the shell that starts your MCP client; the key never appears as a literal argument (it would otherwise show in ps, in the shell history and in crash logs).

Plain-environment alternative: keep the value in a file with restrictive permissions and source it from your shell profile. Whatever the source, the constant rule is: the MCP process must inherit the variable from its parent environment, not receive it as an argument.

4.2 Claude Code

Claude Code supports ${VAR} expansion in MCP configuration — the placeholder is stored in the config file, resolved from the environment when the server starts (MCP docs):

claude mcp add raposa -e RAPOSA_API_KEY='${RAPOSA_API_KEY}' -- uvx raposa-mcp
claude mcp get raposa    # shows the ${...} reference — never the secret itself

Single quotes matter: without them the shell resolves the placeholder before Claude Code stores it. claude mcp get raposa is the check that no secret landed in the configuration.

4.3 Generic MCP stdio config (.mcp.json, other clients)

{
  "mcpServers": {
    "raposa": {
      "command": "uvx",
      "args": ["raposa-mcp"],
      "env": { "RAPOSA_API_KEY": "${RAPOSA_API_KEY}" }
    }
  }
}

4.4 Check it without spending the secret

# 1 · the stored placeholder is a reference, never the value:
claude mcp get raposa | grep -F '${RAPOSA_API_KEY}'     # prints the line — good
claude mcp get raposa | grep -F '<the key>'             # prints nothing — good
# 2 · end to end: list the tools (the server only runs when it can read the key):
#     three tools — create_approval, get_approval, request_human_approval
# 3 · a controlled read of a non-existent id must answer a 404 "Approval not
#     found", never a missing-environment error — that proves the key arrived

5 · Tools reference

All three tools take exactly these arguments (limits enforced client- and server-side):

create_approval

Create an approval request and return its id immediately (no waiting). Use with a webhook_url, or poll with get_approval.

Parameter

Type

Required

Notes

action

string

yes

≤ 200 chars

context

string

yes

≤ 4000 chars

risk

string

yes

low | medium | high

requested_by

string

no

≤ 200 chars, default mcp-agent

expires_in_sec

integer

no

60–2592000 (default 86400 = 24 h)

webhook_url

string (URL)

no

where the signed decision callback is POSTed

Returns {"id": "…", "status": "pending"}.

get_approval

Parameter

Type

Required

approval_id

string (UUID)

yes

Returns the same shape for every terminal state:

{"id": "…", "status": "approved|rejected|expired|pending", "approved": true|false,
 "decided_by": "…", "decided_at": "…", "comment": "…", "message": "…"}

approved is true only when status == "approved".

request_human_approval

Same parameters as create_approval (no webhook_url), plus:

Parameter

Type

Required

Notes

wait_sec

integer

no

how long to poll (5 s cadence), default 600

On a human decision returns the same shape as get_approval. On the deadline it returns {"status": "timeout", "approved": false, "id": "…", "message": "Not approved — nobody answered in Ns. The request is still open; check later with get_approval."} — and it really stays open until its TTL: decide late via your console or get_approval later.

6 · Worked examples

Real outputs (sandbox, uvx raposa-mcp==0.1.2):

create_approval → returns immediately:

{"id": "79d647c1-…", "status": "pending"}

get_approval while pending:

{"id": "79d647c1-…", "status": "pending", "approved": false,
 "decided_by": null, "comment": null, "message": "Still waiting for a human."}

a human approved (via e-mail link or console):

{"id": "79d647c1-…", "status": "approved", "approved": true,
 "decided_by": "<approver>", "decided_at": "2026-10-20T…", "comment": "owner mcp e2e approve",
 "message": "Approved by a human — proceed."}

a human rejected:

{"status": "rejected", "approved": false, "message": "Rejected by a human — do not proceed."}

TTL elapsed, nobody decided:

{"status": "expired", "approved": false,
 "message": "Not approved — the request expired before anyone decided."}

request_human_approval with wait_sec=8 and nobody answering:

{"id": "ed2e963e-…", "status": "timeout", "approved": false, "decided_by": null,
 "message": "Not approved — nobody answered in 8s. The request is still open; check later with get_approval."}

Error shapes you will actually see:

get_approval on a foreign or unknown id — existence is never confirmed to a foreign key:

Raposa API 404 on GET /v1/approvals/<id>: {"detail":"Approval not found"}

a decided approval does not flip: the second decision is refused by the API:

Raposa API 409 on POST /v1/approvals/<id>/decision

7 · Who holds which power

Role

Capability

Scope

client (the MCP key)

create, read, poll, receive webhooks for its own approvals

exactly its own approvals; foreign ids are 404

operator (human decision path)

decide, list, verify the audit chain, export the audit

scoped to one customer or house-wide, by key configuration

owner

internal plan: unlimited monthly approvals, key management for its own account

unlimited quota, not unlimited privileges: the same rate limits, isolation and audit apply

Nothing here makes an MCP client key an administrative credential. The administrative surface (operator console) is a separate, credentialed place — not reachable with an MCP key.

8 · MCP Rush hosted listing

The same server is published on MCP Rush hosted infrastructure: darius-ceponas/raposa-aval-human-approval-mcp — release 0.1.1, three tools, scanned and verified (trust score 96/100, grade A). The gateway is live and refuses calls that carry no buyer token.

Honest status: the hosted release answers, but an end-to-end gateway call with real buyer credentials has not been verified yet — the marketplace’s Access page (where a buyer mints the required gateway key) was unreachable at the time of writing, and the publisher has reported it to MCP Rush support. Until that lands, the direct uvx install in § 4 is the supported way; this README makes no gateway end-to-end claim.

9 · Troubleshooting

Symptom

Cause

Fix

RAPOSA_API_KEY is not set. Get a free sandbox key at …

the variable did not reach the MCP process

export it in the shell that starts the client; check claude mcp add used the ${VAR} placeholder, not an empty value

HTTP 401 Invalid API key on a direct API call

key revoked or mistyped

re-read the value from your vault; rotate from the account page

404 Approval not found on the right id

another key’s approval, or the id is mis-typed

approvals are tenant-scoped; use the key that created it

429 … Rate limit exceeded (60/min for your plan)

per-key per-minute rate limit (abuse guard, stays on every plan)

honour Retry-After; batch agent work

409 on a second decision

the approval already reached a terminal state

terminal decisions are final and immutable

timeout with nobody awake

wait_sec elapsed at 5-second polling

the request stays open until TTL; ask the human, then get_approval

client hangs ~1 min on first call

cold start of a hosted/gateway server or package cache

retry; the second call is fast

claim link says 410 gone

the one-time link was already opened or expired (24 h)

the key was already shown once; register again to receive a new link

10 · Development

This repository — the MCP package itself:

pip install -e ".[test]" && pytest -q

11 contract tests run against a mocked transport: tools are listed with their schemas; approve / reject / timeout / expiry all read back fail-closed; create returns an id without waiting; API errors are reported, not swallowed; an unknown risk never reaches the API; a missing key is a clear error while the tool listing still works.

The backend API (quotas, key rotation, one-time claim links, tenant isolation, panel scopes, rate limiting, webhooks, Stripe, Slack/Telegram channels, audit chain) is a separate repository with its own suite; these pytest runs do not exercise it.

Raposa Aval is a DC ESCRYPT product.

Available Tools

3 tools
create_approvalB

Create an approval request and return its id immediately (no waiting). Use with a webhook_url, or poll with get_approval. risk: low | medium | high.

NameRequiredDescriptionDefault
riskYes
actionYes
contextYes
webhook_urlNo
requested_byNomcp-agent
expires_in_secNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the disclosure burden. It does reveal the non-blocking, asynchronous behavior ('no waiting') and the webhook/poll follow-up pattern, which is valuable. But it omits what happens after creation, whether approval may be automatic, or any side effects or permission requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler; the core behavior is front-loaded and the usage follow-up is compact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite an output schema, the description lacks meaning for four of six parameters and fails to contrast with request_human_approval. It captures the creation flow but is incomplete for correct invocation in all cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain parameters. It explains risk's allowed values (low|medium|high) and hints at webhook_url's role, but leaves action, context, requested_by, and expires_in_sec without any semantic guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific operation ('Create an approval request') and the key outcome ('return its id immediately'), so the core purpose is unmistakable. It explicitly references get_approval for polling, distinguishing it from that sibling, but it does not differentiate from request_human_approval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives two concrete usage modes: supply a webhook_url, or poll with get_approval. However, it never says when create_approval should be chosen over request_human_approval, and provides no when-not conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_approvalA

Read an approval by id. Look at approved — it is true only when a human approved.

NameRequiredDescriptionDefault
approval_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the disclosure burden. It correctly indicates a read operation and adds useful field-level behavior: 'approved' is true only when a human approved. This goes beyond a generic 'get by id' and clarifies an important semantic detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two tight sentences with no filler. The core operation is front-loaded, and the second sentence adds a valuable semantic nuance about the 'approved' field.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with an output schema available, the description is mostly complete. It states the purpose, the lookup key, and the key field semantics. The only small gap is not explicitly documenting the approval_id parameter beyond 'by id,' but the input schema already makes that required parameter visible.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description only implicitly references the parameter through 'by id.' It does not directly explain that approval_id is the approval's unique identifier or provide any format expectations, leaving the agent to infer the mapping.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and object: 'Read an approval by id.' This clearly identifies the operation and resource, and it is easy to distinguish from the sibling tools create_approval and request_human_approval, which are write/request operations rather than reads.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: use this tool when you need to read an approval by its id. It does not explicitly name alternatives or state when not to use them, but the read-versus-create/request distinction is clear enough from the sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

request_human_approvalA

Ask an authorised human to approve an action and wait for the answer. Returns {approved: bool, status, decided_by, ...}. Proceed ONLY if approved is true — a timeout, an expiry or a rejection means do not proceed. risk: low | medium | high.

NameRequiredDescriptionDefault
riskYes
actionYes
contextYes
wait_secNo
requested_byNomcp-agent
expires_in_secNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It does this well by explaining that the tool waits, returns a structured result, and that only approved=true means proceed, while timeout, expiry, or rejection means do not proceed. It also enumerates acceptable risk values, giving the agent actionable safety semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded, with every sentence providing necessary information: the action, the return shape, the proceed condition, and the risk vocabulary. There is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description gives strong core semantics and the output schema likely covers return values, but it leaves gaps around parameter meanings and does not explain when to prefer this over the sibling create_approval/get_approval tools. For a 6-parameter tool with no input schema descriptions and no annotations, more guidance is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for missing parameter documentation. It only clarifies the risk parameter by listing low | medium | high. The important parameters action, context, wait_sec, requested_by, and expires_in_sec are left to be inferred from their names, which is insufficient for reliable invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the action: 'Ask an authorised human to approve an action and wait for the answer.' It identifies both the verb and the resource, and the waiting/returning behavior distinguishes it from siblings like create_approval and get_approval without needing to read their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool: when human approval is needed and you can wait for the decision. However, it does not explicitly contrast with the sibling tools create_approval or get_approval, so the agent is left to infer which one to pick for asynchronous creation or later retrieval.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.1
    • First observedcreate_approval
    • First observedget_approval
    • First observedrequest_human_approval

TDQS

A3.9/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: create_approval is fire-and-forget async, get_approval is read-only polling, and request_human_approval is synchronous waiting. The descriptions explicitly differentiate the workflows, leaving no ambiguity.

Naming Consistency4/5

create_approval and get_approval follow a clean verb_noun pattern, while request_human_approval deviates slightly by inserting 'human' into the noun phrase. Still, the overall pattern remains readable and predictable.

Tool Count5/5

Three tools is well-scoped for a focused human-approval server. Each tool fulfills a necessary role: async creation, status lookup, and synchronous approval waiting. No redundant tools exist.

Completeness4/5

The core approval lifecycle (create, read, wait) is covered with no dead ends for the primary use cases. A list or cancel operation would be a minor gap, but the three tools support the main workflow effectively.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Pauses AI agent execution and routes approval requests to humans via Slack or email, with cryptographically signed proof of the human's decision.
    17 npm
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Human-in-the-loop approval gateway for agent tool calls: agents request, policies decide, humans approve via Slack/Discord/web — with an OWASP-LLM-Top-10-tagged audit trail. Self-hostable.
    10
    18 npm
    33
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Human-in-the-loop approval inbox for AI agents: an agent proposes an action (send email, post comment, run a command), a human approves, rejects, or edits it from a web, mobile, or Slack/Discord/Telegram inbox, and the agent only runs on approval. Full audit trail, self-hostable (MIT).
    8
    6
    MIT