From 75ed7b9a4169d6c57a161d8977962dfdec008e43 Mon Sep 17 00:00:00 2001 From: LIAD Date: Sat, 4 Apr 2026 18:31:05 +0100 Subject: [PATCH] Add recommended security policies for MCP server Three YAML policy presets for use with PolicyLayer Intercept, an open-source MCP proxy that enforces rate limits, spend caps, and access control on tool calls. --- README.md | 22 +++++++++ policies/permissive.yaml | 37 +++++++++++++++ policies/recommended.yaml | 95 +++++++++++++++++++++++++++++++++++++++ policies/strict.yaml | 78 ++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 policies/permissive.yaml create mode 100644 policies/recommended.yaml create mode 100644 policies/strict.yaml diff --git a/README.md b/README.md index 2252aa1f..7d8a13e5 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,28 @@ Tool permissions are controlled by your Restricted API Key (RAK). Create a RAK w See [MCP](/tools/modelcontextprotocol) for more details. +### Policy enforcement (optional) + +The MCP server exposes tools that can move money (`create_refund`, `finalize_invoice`), create live payment URLs (`create_payment_link`), and cancel subscriptions. Restricted API Keys control which tools are available, but not how often or how aggressively an agent uses them. + +You can add rate limits, daily caps, and access control by wrapping the server with [PolicyLayer Intercept](https://github.com/policylayer/intercept), an open-source MCP proxy: + +```sh +npx -y @policylayer/intercept \ + --policy policies/recommended.yaml \ + -- npx -y @stripe/mcp --api-key=YOUR_STRIPE_SECRET_KEY +``` + +Three policy presets are included in [`/policies`](/policies): + +| Policy | Description | +|--------|-------------| +| `recommended.yaml` | Rate limits on writes, daily caps on financial tools, reads allowed freely | +| `strict.yaml` | Default deny — only read tools are allowed unless you explicitly opt in | +| `permissive.yaml` | Everything allowed, rate limits only on financial and destructive operations | + +Policies are YAML files you can edit to match your requirements. See the [Intercept docs](https://github.com/policylayer/intercept) for the full policy reference. + ## Agent toolkit Stripe's Agent Toolkit enables popular agent frameworks including OpenAI's Agent SDK, LangChain, CrewAI, and Vercel's AI SDK to integrate with Stripe APIs through function calling. The library is not exhaustive of the entire Stripe API. It includes support for Python and TypeScript, and is built directly on top of the Stripe [Python][python-sdk] and [Node][node-sdk] SDKs. diff --git a/policies/permissive.yaml b/policies/permissive.yaml new file mode 100644 index 00000000..d0f215aa --- /dev/null +++ b/policies/permissive.yaml @@ -0,0 +1,37 @@ +version: "1" +description: "Stripe MCP — permissive policy. All tools allowed. Rate limits on financial and destructive operations." +default: allow + +tools: + # Financial tools — rate limited even in permissive mode + create_refund: + rules: + - name: "rate-limit" + rate_limit: "10/hour" + on_deny: "Max 10 refunds per hour" + + finalize_invoice: + rules: + - name: "rate-limit" + rate_limit: "20/hour" + on_deny: "Max 20 invoice finalisations per hour" + + create_payment_link: + rules: + - name: "rate-limit" + rate_limit: "20/hour" + on_deny: "Max 20 payment links per hour" + + # Destructive tools — rate limited + cancel_subscription: + rules: + - name: "rate-limit" + rate_limit: "10/hour" + on_deny: "Max 10 subscription cancellations per hour" + + # Global safety net + "*": + rules: + - name: "global-rate-limit" + rate_limit: "120/minute" + on_deny: "Global rate limit — max 120 tool calls per minute" diff --git a/policies/recommended.yaml b/policies/recommended.yaml new file mode 100644 index 00000000..e1061977 --- /dev/null +++ b/policies/recommended.yaml @@ -0,0 +1,95 @@ +version: "1" +description: "Stripe MCP — recommended policy. Rate limits on writes, caps on financial tools, reads allowed freely." +default: allow + +tools: + # Financial tools — highest risk, tightest limits + create_refund: + rules: + - name: "burst-limit" + rate_limit: "3/minute" + on_deny: "Slow down — max 3 refunds per minute" + - name: "daily-cap" + rate_limit: "10/day" + on_deny: "Daily refund limit (10) reached" + + finalize_invoice: + rules: + - name: "burst-limit" + rate_limit: "3/minute" + on_deny: "Slow down — max 3 invoice finalisations per minute" + - name: "daily-cap" + rate_limit: "20/day" + on_deny: "Daily invoice finalisation limit (20) reached — finalised invoices trigger payment collection" + + create_payment_link: + rules: + - name: "rate-limit" + rate_limit: "10/hour" + on_deny: "Max 10 payment links per hour" + + # Destructive tools — require deliberation + cancel_subscription: + rules: + - name: "burst-limit" + rate_limit: "2/minute" + on_deny: "Slow down — max 2 cancellations per minute" + - name: "daily-cap" + rate_limit: "10/day" + on_deny: "Daily subscription cancellation limit (10) reached" + + # Write tools — moderate limits + create_customer: + rules: + - name: "rate-limit" + rate_limit: "30/hour" + on_deny: "Max 30 customer creations per hour" + + create_product: + rules: + - name: "rate-limit" + rate_limit: "30/hour" + on_deny: "Max 30 product creations per hour" + + create_price: + rules: + - name: "rate-limit" + rate_limit: "30/hour" + on_deny: "Max 30 price creations per hour" + + create_coupon: + rules: + - name: "rate-limit" + rate_limit: "20/hour" + on_deny: "Max 20 coupon creations per hour" + + create_invoice: + rules: + - name: "rate-limit" + rate_limit: "20/hour" + on_deny: "Max 20 invoice creations per hour" + + create_invoice_item: + rules: + - name: "rate-limit" + rate_limit: "30/hour" + on_deny: "Max 30 invoice item creations per hour" + + update_subscription: + rules: + - name: "rate-limit" + rate_limit: "20/hour" + on_deny: "Max 20 subscription updates per hour" + + update_dispute: + rules: + - name: "rate-limit" + rate_limit: "10/hour" + on_deny: "Max 10 dispute updates per hour" + + # Global safety net + "*": + rules: + - name: "global-rate-limit" + rate_limit: "60/minute" + on_deny: "Global rate limit — max 60 tool calls per minute across all Stripe tools" diff --git a/policies/strict.yaml b/policies/strict.yaml new file mode 100644 index 00000000..f1490901 --- /dev/null +++ b/policies/strict.yaml @@ -0,0 +1,78 @@ +version: "1" +description: "Stripe MCP — strict policy. Default deny. Only explicitly allowed tools are accessible." +default: deny + +tools: + # Read-only tools — explicitly allowed + list_customers: + rules: + - action: allow + rate_limit: "30/minute" + + list_products: + rules: + - action: allow + rate_limit: "30/minute" + + list_prices: + rules: + - action: allow + rate_limit: "30/minute" + + list_invoices: + rules: + - action: allow + rate_limit: "30/minute" + + list_subscriptions: + rules: + - action: allow + rate_limit: "30/minute" + + list_payment_intents: + rules: + - action: allow + rate_limit: "30/minute" + + list_charges: + rules: + - action: allow + rate_limit: "30/minute" + + list_disputes: + rules: + - action: allow + rate_limit: "30/minute" + + list_coupons: + rules: + - action: allow + rate_limit: "30/minute" + + retrieve_balance: + rules: + - action: allow + rate_limit: "10/minute" + + get_stripe_account_info: + rules: + - action: allow + rate_limit: "10/minute" + + search_stripe_resources: + rules: + - action: allow + rate_limit: "30/minute" + + fetch_stripe_resources: + rules: + - action: allow + rate_limit: "30/minute" + + search_stripe_documentation: + rules: + - action: allow + rate_limit: "30/minute" + + # Everything else blocked by default: deny + # To allow writes, copy rules from recommended.yaml