Stripe — your agent’s Stripe access, with limits
An agent with a Stripe key can do whatever the key can: refund every payment of the week, create a 100 % coupon, send a payment link, write off an invoice. Stripe’s own controls judge one action at a time. Regent sits in front of Stripe and judges each action against what this agent already did: today, this month and for this customer. Then it calls Stripe with a key the agent never holds and closes the decision from Stripe’s own webhook, with a receipt anyone can verify.
| Stripe alone | Stripe behind Regent | |
|---|---|---|
| Where the key is | in the agent’s config or environment | in Regent’s vault; injected after the decision |
| Limit on one action | approval rules: one threshold per action | per-transaction cap in the mandate |
| Limit over time | none | daily and monthly budget, per agent |
| Limit per customer | none | e.g. at most 100 refunded to one customer a month |
| Coupons, payment links, invoice void | not gated | decided like money; a percent_off coupon by a rule |
| A person decides | in the Stripe dashboard | passkey, in the console or the chat the agent runs in |
| Record | Stripe’s request log | a signed receipt, settled from Stripe’s own webhook |
One line: Stripe’s own tools, through Regent
If your agent already uses Stripe’s MCP server, change its URL. Regent offers the same five tools under the same names and arguments, so no prompt and no code learns anything new:
| Tool | What it does through Regent |
|---|---|
stripe_api_search | finds an operation (PostRefunds, GetCustomersCustomer, …) by intent and resource |
stripe_api_details | lists its path, query and body parameters |
stripe_api_read | runs any GET; nothing changes, no money moves |
stripe_api_write | runs any POST or DELETE; Regent decides first whenever it moves money |
get_stripe_account_info | the account Regent holds the key for |
Beside them: my_budget, approval_status, receipt, request_budget and
budget_request_status, the same as on the main endpoint.
Connect Stripe once (a person)
Console → Connect → Gateway → paste a restricted key (rk_…). Regent registers its
settlement webhook on your account and creates the stripe tool
(details). Grant the key what the agent’s role needs:
Refunds for a support agent, Invoices and Payment Links for billing, Coupons for retention.
The key’s permissions remain the outer wall: Regent never does more than the key may.
Give the agent its limits
Console → Spend limits → New mandate → Start from a Stripe role fills them in (roles below). The person who grants them signs with a passkey.
Point the agent at Regent
Replace https://mcp.stripe.com with https://gw.regentprotocol.org/gw/mcp/stripe.
{
"mcpServers": {
"stripe": {
"type": "http",
"url": "https://gw.regentprotocol.org/gw/mcp/stripe"
}
}
}claude mcp add --transport http stripe https://gw.regentprotocol.org/gw/mcp/stripe
codex mcp add stripe --url https://gw.regentprotocol.org/gw/mcp/stripeThe client signs in with OAuth the first time (/mcp in Claude Code); a client without OAuth
sends the agent’s bound Regent credential as Authorization: Bearer …. Remove the Stripe key
from the agent’s environment: it no longer needs one.
Stripe’s MCP server stops accepting full secret keys and restricted keys without the Agent tag on 30 November 2026. The Regent endpoint calls Stripe’s API directly and is not affected: the restricted key you vaulted keeps working.
What Regent decides on
stripe_api_write turns the operation ID into Stripe’s method and path, then the gateway’s
Stripe map says what that call does with money. The full table is in the
Tool Catalog; in short:
| Kind | Stripe operations | How it is decided |
|---|---|---|
| charge | payment intents, charges, Checkout, invoice pay and finalize, quote accept, subscriptions | on the amount (prices looked up), payee = the customer |
| refund | refunds, credit notes, dispute close | on the amount, payee = the customer of the payment |
| credit | customer balance credits | on the amount, payee = the customer |
| discount | coupons | amount_off as money; percent_off and duration by a rule |
| offer | payment links, quotes | on the total of their line items |
| transfer, payout | transfers, payouts | on the amount, payee = the destination |
| cancel, dispute | voids, cancellations, write-offs, evidence | no money; a rule can refuse them |
An operation the map does not know and that could move money is refused rather than guessed (Treasury v2 and subscription schedules today). Reads pass without a budget.
What the agent sees:
| Answer | Meaning | What the agent should do |
|---|---|---|
Stripe’s object + regent_decision_id | allowed, Stripe ran it | show the receipt once it settles |
ESCALATION_REQUIRED | above the allowance: parked for the owner | tell the owner, poll approval_status, repeat the same call with the same idempotency_key |
PROVIDER_APPROVAL_PENDING | Stripe’s own approval rule paused it | tell the owner; never repeat: Stripe runs it after approval |
MANDATE_LIMIT_EXCEEDED and others | refused | explain; my_budget says what is left |
Roles
Four starting points. Each is a set of limits (the mandate) and one rule (the organization’s policy): the limits bound how much, the rule bounds what. A 100 % coupon moves no money, so only a rule can stop it. The console adds the rule for one agent or for all under Behavior policies → Stripe role rules; these are the same texts.
Support: refunds
Up to 50 per refund, 500 a day, 2 000 a month, 100 per customer a month (a seller cap
*, counted per customer). Only refunds; reads are free.
@id("stripe-support-refunds-only")
forbid (principal == Agent::"<agent id>", action, resource == Tool::"stripe")
when { !(context.action like "GET *") && context.op != "refund" };Billing: invoices and links
Up to 2 000 per document, 10 000 a day, 50 000 a month, 5 000 per customer a month. It never gives money back:
@id("stripe-billing-no-money-back")
forbid (principal == Agent::"<agent id>", action, resource == Tool::"stripe")
when { ["refund", "credit", "discount", "transfer", "payout"].contains(context.op) };Retention: coupons
Up to 20 per amount_off coupon, 200 a day, 1 000 a month. One-time coupons up to 20 % pass;
above 20 %, or a repeating coupon, goes to the owner (an @id with “escalate” asks a person
instead of refusing):
@id("stripe-retention-coupons-only")
forbid (principal == Agent::"<agent id>", action, resource == Tool::"stripe")
when { !(context.action like "GET *") && context.op != "discount" };
@id("stripe-retention-coupon-escalate")
forbid (principal == Agent::"<agent id>", action, resource == Tool::"stripe")
when { context.op == "discount" &&
(context.percent_off.greaterThan(decimal("20.0000")) ||
(context.duration != "" && context.duration != "once")) };Analyst: read only
No mandate at all (without one, every payment is refused) and one rule for the writes that move no money:
@id("stripe-read-only")
forbid (principal == Agent::"<agent id>", action, resource == Tool::"stripe")
when { !(context.action like "GET *") };Replace principal == Agent::"<agent id>" with principal to apply a rule to every agent of
the organization, and "stripe" with your tool’s name if you named it otherwise.
Together with Stripe’s approval rules
Keep them. Regent decides first, so nothing reaches Stripe that Regent refused; a rule in Stripe is then a second line for the actions it covers. How the two interact, including what happens when a reviewer rejects, is in the gateway overview.
Check an agent’s Stripe access
pip install regent-control
regent-control scanReads the MCP configs of Claude Code, Claude Desktop, Cursor, VS Code, Codex and Hermes on
this machine and reports where an agent reaches Stripe, with which kind of key (masked), and
what that means: a live secret key in a file the agent reads, a key Stripe MCP will stop
accepting on 30 November 2026. With --stripe-key-env NAME (or --use-found-key) it also
counts the key’s refunds, coupons, payment links, credit notes and payouts of the last 30
days, by GET requests to api.stripe.com and nowhere else. It writes nothing; --json and
--fail-on high fit a CI step.
When you do not need Regent for Stripe
- The agent only reads (reports, reconciliation): a read-only restricted key is enough.
- A person already approves every write in the Stripe dashboard and the volume is small.
- The only risk you care about is one large action: a Stripe approval rule on that action covers it.
Regent earns its place when an agent writes on its own, many times a day: refunds, credits, coupons, links; when one customer must not get more than a set amount; when you need a record a third party can verify; or when the same agent also pays on other rails (Agentcard, x402) under one budget.