The Stripe MCP server control model, explained
The Stripe MCP server is where this series stops being hypothetical: the tools move money. First-party, remote at https://mcp.stripe.com (OAuth) and local via npx -y @stripe/mcp (part of the agent-toolkit family), with an official Claude Code plugin (stripe@claude-plugins-official) and one-click installs for Cursor, VS Code, and Codex. It also has the single best native control in the ten servers we’ve surveyed — and the docs that most explicitly hand the hard part back to you. Sources: the official MCP docs and restricted-key docs.
This page covers the server’s own controls. For the cross-server picture, see the MCP server controls comparison; for what a control layer adds on top, the coverage matrix.
What’s at stake on this surface
Every other server in this series can lose you data or code. This one can lose you money, and some of it irreversibly: create_refund is a first-class tool — a completed refund is not clawed back — and the stripe_api_write meta-tool reaches subscription cancellation, invoice finalization and voiding, coupon deletion, payment-link creation, and webhook-endpoint creation (a standing-configuration write: an agent that can add a webhook endpoint has changed where your payment events flow). The read surface covers customers, charges, payouts, issuing cards, and balance history — customer PII and financial records, the exact material an injection wants exfiltrated. This is the highest-anxiety surface in the series and it deserves to be.
Auth: OAuth remote, key local — and sessions you can actually see
The remote server authenticates via OAuth per the MCP spec: a consent form on connect, then a session that appears in your Dashboard user settings, revocable per-client. Admins can view and revoke any team member’s MCP sessions (“Revoke all” included) and enable or disable MCP access for the account outright, separately for sandbox and live mode. That is more session visibility than any other server here offers — a named, listable, killable grant per client, at the vendor.
For clients without OAuth, and explicitly for autonomous agents, the docs take a bearer key in the Authorization header — and here Stripe says the load-bearing sentence itself: “We strongly recommend using restricted API keys to limit your agent’s access to exactly the functionality it requires.” The local server takes the same decision as --api-key. Which key you mint is the whole control model, so:
Restricted keys: the only scoping in this series the agent can’t edit past
Every other server on the comparison table enforces its scoping in or before the server process — flags and env vars in a client config that lives in the workspace, readable and usually writable by the agent it constrains. GitHub’s read-only mode is a filter the server applies to itself; Supabase’s read-only role is set by a launch flag. Stripe’s restricted API keys are different in kind: per-resource read/write permissions, minted in the Dashboard, checked by Stripe’s API servers on every call. A key with Refunds set to none cannot create a refund — not because a tool was hidden, but because the vendor refuses the request. No prompt injection, no config edit, no jailbroken argument changes that. The key is the policy, and it’s held at Stripe.
This is the standard the rest of the ecosystem should meet. GitHub’s fine-grained PATs come close; Supabase’s account-wide PATs don’t try. If MCP servers are going to front real systems, “the credential’s scope is enforced by the vendor and the agent can’t widen it” should be table stakes — Stripe is the one server here where it actually is.
Now the grain. Restricted-key permissions are binary per resource: Refunds read or write, Subscriptions read or write. Write means all writes at any size. There is no key that can refund up to $50, refund at most three times an hour, or cancel subscriptions only below a given MRR. The strongest enforcement in the series is also the coarsest vocabulary for the surface where fine grain matters most.
Tool selection: two meta-tools carry the write surface
The remote server’s tool list is short and deliberate: named tools like create_refund, get_stripe_account_info, and search_stripe_documentation, plus four API meta-tools — stripe_api_search, stripe_api_details, stripe_api_read, stripe_api_write — through which a hundred-plus supported API methods flow without bloating the context window. Clever engineering, with a control consequence: client-side tool filtering mostly collapses. Allow stripe_api_write and you’ve allowed subscription cancellation, invoice voiding, coupon deletion, and webhook creation in one name; deny it and you’ve denied harmless writes too. Any control keyed on tool names sees one tool where the risk lives in the arguments. The local server’s --tools flag (documented as --tools=all, with the key carrying the real permissions) narrows the older per-action surface, but on the remote server the meaningful grain is the key — again.
Sandboxes: rehearsal with real walls
Stripe’s test environments are the best rehearsal story in the series: keys are per-environment, so a sandbox key structurally cannot touch live money, and MCP access is managed separately between sandbox and live mode. Compare Supabase’s branching, where the sandbox and the merge tools sit on the same surface: here the wall is at the credential, vendor-enforced. The limit is the usual one — rehearsal is not a runtime boundary. The day the agent gets the live key, nothing about having rehearsed constrains what it does with it.
The missing pieces: amounts, velocity, approvals
Three policies matter more on this surface than any other, and none is expressible natively:
- Amounts. “Never refund more than $X” does not exist. A key that can refund can refund any amount on any charge.
- Velocity. The docs mention no MCP-level rate or amount limits; the fiftieth refund in an hour is processed like the first. Money surfaces are where runaway loops get expensive fastest.
- Approvals. No call can be held for a human by the server. Stripe’s docs say it directly: “We recommend enabling human confirmation of tools and exercising caution when using the Stripe MCP with other servers to avoid prompt injection attacks.” Both clauses matter. The first delegates the approval step to your MCP client — a client-side courtesy, and the first thing gone in yolo mode. The second names the read-untrusted-then-act pattern and hands you caution rather than a control.
The Dashboard’s API logs deserve their category stated precisely: every API call the server makes lands in Stripe’s request logs, which is a real forensic record — better than the nothing most servers leave (the general MCP audit gap). But it’s forensics, not control: not agent-attributed, not MCP-aware (a stripe_api_write call logs as the underlying API request), and it tells you what happened after the refund cleared.
Where the native model ends
Credit where due, precisely: vendor-enforced key scoping, revocable named sessions, admin kill switches, environment walls at the credential. That’s the strongest ownership story in this series — the one server whose boundary survives anything the agent does to its own config. And the seam runs exactly where the money does:
- The key’s vocabulary is binary. Read or write, per resource. No amounts, no velocity, no conditions — the policies that distinguish a correct refund from an incident are not expressible in the strongest control the model has.
- Nothing is per-call. The key decides once, at mint time. One
create_refundis indistinguishable from another to every native mechanism. - The approval is homeless. Stripe recommends human confirmation and ships no mechanism for it; it lives wherever your client puts it, at whatever autonomy setting the client is in.
- The record is downstream. Request logs tell you which calls happened, not which agent made them, under which posture, or why.
The practical posture: mint a restricted key with exactly the writes the task needs (the floor, and here it’s a real floor), rehearse in a sandbox, keep OAuth sessions pruned, leave client confirmation on — and put the amount thresholds, the velocity limits, the approval that survives autonomy, and the agent-attributed record in a layer that stands between the agent and the key. Stripe built the strongest wall in the series; the policies that matter most on this surface live in the gate it doesn’t have.