← Back to Blog

How to Stop Your AI Agent Draining Your Stripe Account

Your AI support agent just issued 200 refunds in three minutes. It misread a batch of customer complaints, decided every order from the past week deserved a full refund, and processed them all before anyone noticed. Your Stripe balance is negative, and the charges are real.

This is not hypothetical. The Stripe MCP server exposes 27 tools to any AI agent that connects to it — and several of those tools move money.

What the Stripe MCP server exposes

Stripe’s official stripe/agent-toolkit MCP server gives agents access to everything from harmless read operations to financially destructive actions. The dangerous ones:

  • create_refund — issues refunds against existing charges
  • create_invoice and finalize_invoice — creates and locks invoices that get sent to customers (finalised invoices cannot be edited)
  • create_payment_link — generates live payment URLs
  • cancel_subscription — cancels recurring revenue
  • create_customer, create_product, create_price, create_coupon — bulk creation tools that can pollute your account with junk data

Read tools like list_charges, retrieve_balance, and search_stripe_resources are relatively safe. But the write and financial tools need constraints — and MCP does not provide any.

Why prompt guardrails don’t work

You could add “never issue more than 5 refunds per hour” to your system prompt. The agent will follow that instruction right up until it doesn’t. Prompts are suggestions, not enforcement. A sufficiently long context window, an unexpected edge case, or a prompt injection can override any instruction. As we covered in MCP Security: Beyond Guardrails, the only reliable control is one that operates outside the model’s decision loop — at the transport layer, deterministically.

The fix: rate limits on financial operations

Intercept sits between your agent and the Stripe MCP server. Every tools/call is evaluated against a YAML policy before it reaches Stripe. Violating calls are blocked and the agent receives a clear denial message.

Here is the financial tools section from the Stripe policy:

version: "1"
description: "Policy for stripe/agent-toolkit"
default: "allow"
tools:
    create_refund:
        rules:
          - name: "refund-rate-limit"
            rate_limit: "10/hour"
            on_deny: "Rate limit: max 10 refunds per hour — review refund activity before retrying"

    create_invoice:
        rules:
          - name: "invoice-creation-rate-limit"
            rate_limit: "10/hour"
            on_deny: "Rate limit: max 10 invoice creations per hour"

    finalize_invoice:
        rules:
          - name: "invoice-finalise-rate-limit"
            rate_limit: "10/hour"
            on_deny: "Rate limit: max 10 invoice finalisations per hour — finalised invoices cannot be edited"

    create_payment_link:
        rules:
          - name: "payment-link-rate-limit"
            rate_limit: "10/hour"
            on_deny: "Rate limit: max 10 payment links per hour"

    cancel_subscription:
        rules:
          - name: "subscription-cancel-rate-limit"
            rate_limit: "10/hour"
            on_deny: "Rate limit: max 10 subscription cancellations per hour — review before retrying"

Financial tools are capped at 10 per hour. Write tools like create_customer and create_product get a higher limit of 30 per hour — enough for legitimate bulk operations, tight enough to stop a runaway loop.

A global rate limit catches anything else:

    "*":
        rules:
          - name: "global-rate-limit"
            rate_limit: "60/minute"
            on_deny: "Global rate limit: max 60 tool calls per minute across all Stripe tools"

The rate_limit shorthand expands internally to a stateful counter that tracks calls and resets at the start of each window. When the agent hits the limit, it receives the on_deny message as the tool response — no silent failures, no retries slipping through. For more on how this mechanism works, see Rate Limiting MCP Tool Calls.

The default: "allow" posture means read tools like list_customers and retrieve_balance pass through without restriction. If you want a stricter setup, switch to default: "deny" and explicitly allowlist every tool — an approach we walk through in Spending Controls for MCP Agents.

Getting started

Install Intercept and point it at the Stripe MCP server:

npm install -g @policylayer/intercept

Then run it with the Stripe policy:

intercept -c stripe.yaml -- npx -y @stripe/mcp --tools=all

Every tool call from your agent now passes through the policy engine. Refund number 11 in an hour gets blocked. The 61st tool call in a minute gets blocked. Your Stripe balance stays intact.

Adjust the limits to match your operations. A high-volume support team might raise create_refund to 50/hour. A solo founder might drop it to 3. The point is that the limit is deterministic, transport-level, and impossible for the model to override.

Full Stripe policy →

Ready to secure your AI agents?

Get spending controls for autonomous agents in 5 minutes.

Get Started