optional-skills/mcp/mcp-oauth-remote-gateway/references/stripe-mcp-oauth-revocation.md
mcp.stripe.com) — recurring OAuth session revocation, fix with a restricted keyA worked example of pitfall 9/10 in SKILL.md: a provider whose OAuth session dies on a recurring basis, where the durable fix is to drop OAuth for a static API key.
Stripe MCP works for a few days then goes "not connected." Auto-refresh is healthy
in between (the access token is 1h-lived and rotates fine), so it LOOKS like a
refresh-token expiry or a max-session cap — it is neither. Roughly weekly, Stripe
revokes the entire OAuth grant server-side. The next grant_type=refresh_token
POST returns:
HTTP 400 {"error":"invalid_grant","error_description":"Invalid refresh token"}
The whole grant is dead — not just the short-lived access token — so auto-refresh cannot recover it. It requires a fresh interactive browser consent flow, which a headless remote gateway cannot drive. Don't be fooled by a green smoke-test at any given moment: the failure is intermittent revocation, not a permanently broken token.
Per Stripe's OAuth docs (https://docs.stripe.com/stripe-apps/api-authentication/oauth):
So a recurring death cannot be refresh-token expiry (1yr) or "max OAuth session length" (no clean documented cap). It is server-side session revocation. Do NOT loop on refresh.
Stripe's MCP docs (https://docs.stripe.com/mcp) are explicit that for
non-interactive / agent use, OAuth is the wrong tool — mcp.stripe.com accepts a
static restricted key (rk_live_...) as a Bearer token. A restricted key has
no session, no refresh, no expiry — it works until revoked, ending the re-auth
cycle entirely.
config.yaml change (no token files needed — delete the OAuth dance for this server):
mcp_servers:
stripe:
url: https://mcp.stripe.com
headers:
Authorization: *** rk_live_..." # restricted key from Dashboard
# Stripe-Account: "acct_xxx" # only for Connect platform / connected-account calls
Generate the key in Stripe Dashboard → Developers → API keys → Restricted keys. Grant least-privilege scopes for what the bot actually does:
/reload-mcp (full restart only if the breaker is tripped, per pitfall 7).For ANY unattended remote-gateway MCP server that keeps getting its session revoked
(invalid_grant on refresh, or -32002 "Session expired" after a successful refresh),
and whose provider offers a static API key — prefer the static key over OAuth. OAuth's
refresh dance is for interactive clients; it is a liability for a headless gateway.
Stripe (restricted key) and Linear (Personal API key) both fit this rule.