Public beta · the BotShield app is live on the web.
Console

BotShield MCP Tools.

Five tools your agents call to put a person behind the actions that can’t be undone. None of the five can say yes. The proof carries the person’s intent, never the model’s guess. That is the shape of the surface, not a policy.

The five tools · over MCP · REST · the SDK

An agent connects with its key and gets five tools.

Bind to a human. Check the binding. Propose an action. Check the decision. Cancel. Anything a person approves comes back as a signed Proof of Resolution — verified by your code, not by the model, before anything executes.

The model asks · your code enforces

How it works.

Invocation over MCP is model-mediated, so asking is cooperative. Enforcement is on your side: your executor verifies the Proof of Resolution and refuses without it. Five tools, in the order an agent calls them.

Tool
You send
You get
bind_session
display_name (optional)
A short code and a link (app.botshield.ai/bind?code=…), with an expiry. The person enters or scans it in the BotShield app and confirms with a passkey. If this agent is already bound to them, the opaque id comes back at once — binding happens once, not per conversation.
check_binding
code · wait_seconds (up to 25)
pending · bound with an opaque_id · expired · revoked. Store the opaque id. It is the only way this agent can name a human.
propose_resolution
request_id (your UUID — the idempotency key) · summary_title · category · detail · opaque_id
queued. The card lands in their Agents Ask inbox with a TTL between 60 seconds and 24 hours. A category outside the agent’s allowed set is refused (403).
check_resolution_status
request_id · wait_seconds (up to 25)
confirmed · denied · expired · cancelled — with resolved_at, the ceremony id, and on a terminal outcome the signed Proof of Resolution.
cancel_resolution
request_id · reason (optional, kept in the audit log)
cancelled. A no-op once the request has reached a terminal state.

The proof.

An ES256 JWT with a kid in the header. Claims: iss · sub · aud (your agent id) · iat · exp · jti (your request id) · the verdict · the action. It attests that the person’s signed-in session answered this request; the passkey does not sign the action itself. Verify it against BotShield’s public JWKS in your own code before you execute. A model cannot verify a signature. Your executor can.

Who the agent can name.

Only an opaque id from the binding. The email field was removed from the tool surface on 9 August 2026: a deprecation note in a description does not stop a model, so the wrong call was made impossible rather than discouraged.

Auth and transport.

OAuth 2.0 client credentials at /token, discovery at /.well-known/oauth-authorization-server, the MCP endpoint at /mcp over Streamable HTTP. One key per agent, registered in the BotShield Console. Any MCP-capable harness, any model.

How to require a person’s yes  →

Common questions

BotShield MCP Tools FAQ

Can the agent confirm on the person’s behalf?
No. There is no confirm tool. The five tools can bind, propose, check and cancel; none of them can say yes. The shape of the surface enforces it, not a handler.
What forces the agent to ask?
Nothing in MCP. Invocation is model-mediated, so asking is cooperative. What is enforced sits on your side: your executor refuses to run without a valid Proof of Resolution. The model asks, your code enforces.
How is the human identified?
Only by the opaque id returned from the binding. The email field was removed from the tool surface on 9 August 2026, so the wrong call cannot be made. The agent never holds a name, an email or a device.
What is in the proof, and how do I verify it?
An ES256 JWT issued by api.botshield.ai, with a kid in the header. Claims: iss · sub · aud (your agent id) · iat · exp · jti (your request id) · the verdict · the action. It attests that the person’s signed-in session answered this request; the passkey does not sign the action itself. Verify it against BotShield’s public JWKS in deterministic code before you execute. A model cannot verify a signature.
Can a proof be replayed?
jti is your request id and exp bounds its life to 24 hours. Your executor’s idempotency on the request id closes the rest: one request id, one execution.
How do verifiers learn a new signing key?
From the JWKS. Each proof names its key by kid, and the signer already carries additional kids so keys can rotate without a break.