This release is a pre-release and may not be stable for production use.
stripe-blade-mcp
⚠️ Phase 0 scaffold — pre-alpha (
0.1.0a1). All 45 tools currently raiseNotImplementedError. The scaffold exists to validate the/build-blade-mcpskill conventions (security, privacy, token-efficiency, devops baseline) end-to-end. Production implementation of Phases A–E is gated on a real Stallari build trigger perBUILD_PLAN.md. Do not install for production use. Use@stripe/mcpfor direct Claude Desktop / Cursor Stripe access in the meantime.
Stripe MCP server for Stallari workloads. Token-efficient, Restricted-Key-only, per-resource write-gated. Closes the gaps in Stripe's own
@stripe/mcpfor Stallari pack-workload integration.
Dual-contract blade implementing both billing-v1 (subscriptions, products, prices, invoices) and payments-v1 (PaymentIntents, refunds, disputes, webhooks). First blade where one repo cleanly implements both Stallari payment contracts end-to-end.
Why another Stripe MCP?
Stripe ships @stripe/mcp. It covers 23 tools across 11 resource categories and works well for direct Claude Desktop / Cursor use. This blade exists because:
- Missing
payments-v1Required ops.@stripe/mcpshipslist_payment_intents+create_refundonly — missingpayment_intent_create/capture/cancel/get,refund_get/list, and the fullwebhook_verify+webhook_subscription_*block that Stallari'spayments-v1contract requires. - HTTP-only transport —
@stripe/mcpis HTTP only; DD-242 requires stdio when launched by Stallari. - Raw JSON responses —
@stripe/mcpreturns standard MCP JSON-RPC payloads. This blade emits pipe-delimited summaries on list ops (~16× token reduction measured on equivalent paddle-blade ops), with field selection and null-omit on detail views. - Advisory-only write-gating —
@stripe/mcprecommends human confirmation but doesn't enforce. This blade enforces per-resourceSTRIPE_WRITE_*env gates AND aconfirm=trueparameter on destructive ops.
If you only need basic Stripe access in Claude Desktop, use @stripe/mcp. If you're running Stallari pack workloads, use this blade.
Comparison
| Capability | stripe-blade-mcp |
@stripe/mcp |
|---|---|---|
| Tool count | ~45 (full billing-v1 + payments-v1) |
23 (partial coverage) |
payments-v1 Required ops |
8/8 | 2/8 |
billing-v1 Required ops |
6/6 | 3/6 |
| Webhook HMAC verification | Built-in stripe_webhook_verify |
Not present |
| Webhook subscription management | 4-op block (list/create/delete/replay) | Not present |
| Token-efficient responses | Pipe-delimited, field selection, null-omit, money-formatted | Raw JSON |
| Write gating | Per-op env var, fail-closed | Advisory only |
| Destructive op confirmation | confirm=true enforced |
None enforced |
| Sandbox/live isolation | Mandatory STRIPE_ENV, fail-closed |
Yes (per-env access) |
| API key security | Env var only, credential scrubbing | Env var OR --api-key CLI arg (ps leak) |
| Restricted-Key enforcement | Startup check + scope coherence warn | None |
| Stdio when harness-launched | Yes (DD-242) | No — HTTP only |
| Money formatting | Human-readable ($29.00 USD) |
Raw cents |
| Field selection | fields= parameter |
Not available |
| Pagination hints | Cursor + "N more" | Standard has_more only |
| Idempotency-key auto-attach | Yes (stallari-... prefix) |
Unclear |
| Connect (multi-tenant) | Out of scope v1 — explicit refuse | Possibly available |
| Runtime | Python (uv) | TypeScript (npm) |
Token efficiency: before and after
Raw Stripe API (≈ @stripe/mcp shape) — 1 page of 25 subscriptions:
{
"object": "list",
"url": "/v1/subscriptions",
"has_more": true,
"data": [
{
"id": "sub_1NkVJ8...",
"object": "subscription",
"application": null,
"application_fee_percent": null,
"automatic_tax": {"enabled": false, "liability": null},
"billing_cycle_anchor": 1715000000,
"billing_thresholds": null,
"cancel_at": null,
"cancel_at_period_end": false,
"canceled_at": null,
"cancellation_details": {"comment": null, "feedback": null, "reason": null},
"collection_method": "charge_automatically",
"created": 1715000000,
... ~50 more fields per subscription
},
... 24 more
]
}
~12,000 tokens for the page.
stripe-blade-mcp pipe-delimited:
[env=test]
sub_1NkVJ8 | acme inc. | active | $29.00 USD / month | 3 days ago
sub_1NkVK2 | beta corp | active | $99.00 USD / month | 7 days ago
sub_1NkVL5 | trial co. | trialing | $0.00 USD / month | 1 day ago
... 22 more (pass starting_after=sub_1NkVL5 to continue)
~280 tokens. ≈ 40× reduction.
Need a single field? Call stripe_subscription_get with fields=["id", "status", "current_period_end"] to project exactly what you need.
Installation
As a Stallari blade
stripe-blade-mcp installs as a Stallari pack. The blade resolves credentials
through the Stallari CredentialStore (DD-186) at launch — never commit secrets.
stallari pack install groupthink-dev/stripe-blade-mcp
Standalone (Claude Desktop, Cursor, etc.)
uv tool install stripe-blade-mcp
Claude Desktop MCP config:
{
"mcpServers": {
"stripe": {
"command": "stripe-blade-mcp",
"env": {
"STRIPE_ENV": "test",
"STRIPE_API_KEY": "rk_test_..."
}
}
}
}
Quickstart
- Create a Restricted Key at https://dashboard.stripe.com/apikeys/create — Standard Keys are rejected
- Enable the resources your workload needs (Payments / Subscriptions / Refunds)
- Configure the env:
export STRIPE_ENV=test # or 'live' for production
export STRIPE_API_KEY=rk_test_... # restricted key only
export STRIPE_WRITE_PAYMENTS=1 # only enable writes you need
- Validate:
stripe-blade-mcpthen invokestripe_account_info
Usage examples
# List recent subscriptions (pipe-delimited)
await stripe_subscription_list(after=None, limit=10)
# Get one with field selection
await stripe_subscription_get(id="sub_1NkVJ8", fields=["id", "status", "current_period_end"])
# Create a PaymentIntent (gated — requires STRIPE_WRITE_PAYMENTS=1)
await stripe_payment_intent_create(
payload={"amount": 2900, "currency": "usd", "customer": "cus_QABCDEF", "confirm": True}
)
# Verify a Stripe webhook
await stripe_webhook_verify(
body=raw_request_body,
signature_header=req.headers["Stripe-Signature"],
secret=os.environ["STRIPE_WEBHOOK_SECRET"]
)
# → {"verified": True, "event_type": "payment_intent.succeeded", "event_id": "evt_...", "age_seconds": 2}
Security posture
- Mandatory sandbox/live env isolation. Refuses to start without
STRIPE_ENV=test|live. - Restricted Keys only.
sk_live_*Standard Keys rejected at startup; onlyrk_*accepted in live mode. - Per-resource write gates. Read is always permitted; write requires opt-in per-resource (
STRIPE_WRITE_PAYMENTS=1, etc.). Defaults to all off. - Confirm gates on destructive ops.
cancel,void,deleterequireconfirm=trueparameter. - Credential scrubbing. Every error path (incl. exception cause chain) is scrubbed of
rk_*,sk_*,whsec_*, and genericapi_key-named fields. - PCI allowlist. Card data projected to
last_4+brand+exp_*+fingerprintonly (DD-179). Rawpayment_method/cardobjects never reach the response. - Idempotency. Auto-attached
stallari-<date>T<run_id>-<uuid>key on every mutation; caller override always wins. - Stdio transport when harness-launched (DD-242). HTTP transport opt-in is loopback-only with mandatory bearer token.
- No telemetry, no phone-home (convention #19).
- Mesh exposure denied — blade tools never advertised on daemon
:9847/mcp(DD-240 invariant #8).
Sandbox vs production
| Env | STRIPE_ENV |
Key prefix | Notes |
|---|---|---|---|
| Test | test |
rk_test_* or sk_test_* |
Stripe test mode — no real money. Use freely. |
| Live | live |
rk_live_* (only) |
Real-money production. sk_live_* rejected. |
The blade echoes _env: test or _env: live on every response so misconfig is visible immediately.
Tool inventory
Required (billing-v1 + payments-v1 conformance)
| Tool | Wraps | Contract op |
|---|---|---|
stripe_product_list / stripe_product_get |
Products | billing-v1 products / product |
stripe_price_list |
Prices | billing-v1 prices |
stripe_customer_list / stripe_customer_get |
Customers | billing-v1 customers + payments-v1 customer_* |
stripe_subscription_list / stripe_subscription_get |
Subscriptions | billing-v1 subscriptions / subscription |
stripe_transaction_list |
Invoices | billing-v1 transactions |
stripe_payment_intent_create / _capture / _cancel / _get / _list |
PaymentIntents | payments-v1 payment_* |
stripe_refund_create / _get / _list |
Refunds | payments-v1 refund_* |
stripe_webhook_verify |
(local HMAC) | payments-v1 webhook_verify |
Recommended (~14 tools)
stripe_customer_create / _update · stripe_subscription_update / _cancel · stripe_invoice_list / _get · stripe_adjustment_list / _create · stripe_discount_list / _apply · stripe_event_list · stripe_credit_balance_get · stripe_payment_method_list · stripe_dispute_list
Optional / target-specific
stripe_preview_transaction · stripe_notification_list · stripe_simulate · stripe_payout_list / _get · stripe_balance_get · stripe_dispute_get / _evidence_submit · stripe_webhook_endpoint_list / _create / _delete · stripe_replay_notification · stripe_webhook_event_types · stripe_account_info
Out of scope for v1
Stripe Connect · Stripe Issuing · Stripe Treasury · Stripe Climate · Stripe Identity. Each refused upfront at the server boundary with a pointer to a future DD.
Webhook verification
from stripe_blade_mcp.tools import stripe_webhook_verify
result = await stripe_webhook_verify(
config,
body=raw_request_body, # bytes or str
signature_header=req.headers["Stripe-Signature"],
secret=webhook_endpoint_secret,
tolerance_seconds=300, # default 5min replay window
)
# → {
# "verified": True,
# "event_type": "payment_intent.succeeded",
# "event_id": "evt_1NkVJ8...",
# "created_at": "2026-05-11T15:32:00+10:00",
# "age_seconds": 4,
# "data": {...} # parsed event payload
# }
The HMAC scheme follows Stripe's canonical format: t={timestamp},v1={hmac}. The blade enforces the timestamp tolerance to defeat replay attacks.
Rate limits + retry policy
| Mode | Global | Per endpoint |
|---|---|---|
| Live | 100 req/s | 25 req/s |
| Test | 25 req/s | 25 req/s |
Plus: PaymentIntent updates ≤ 1000/hour, Search ≤ 20 req/s.
On 429, the blade surfaces RateLimited verbatim with the Stripe-Rate-Limited-Reason header (global-rate / endpoint-rate / global-concurrency / resource-specific). No internal retry beyond 2 attempts — configure token-bucket throttling at the Stallari workload layer if you need it.
Development
git clone https://github.com/groupthink-dev/stripe-blade-mcp
cd stripe-blade-mcp
uv sync --group test --group dev
make test
make lint
make typecheck
The build plan lives in BUILD_PLAN.md. Each phase is a fresh PR.
Contributing
This is a first-party Groupthink blade. Issues + PRs welcome via github.com/groupthink-dev/stripe-blade-mcp/issues.
For Stallari pack development conventions, see the Stallari developer docs.
License
MIT. See LICENSE.
Metadata
Release files for stripe-blade-mcp 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| stripe_blade_mcp-0.1.0a1.tar.gz | 132.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| stripe_blade_mcp-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 185.1 kB
Release files / stripe_blade_mcp-0.1.0a1.tar.gz
| Download URL | stripe_blade_mcp-0.1.0a1.tar.gz |
|---|---|
| Size | 132.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4f2efacacd90d60cc7fc0c52242c280f4928feeb0940157738cb5673a4ac31e3
|
|
BLAKE2b-256 checksum How to use checksums |
f984a81a66022cce6140f6ed4ad9d70533a1bb25fe08bd49efd3e244daaf3856
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 11, 2026.
Transparency logRelease files / stripe_blade_mcp-0.1.0a1-py3-none-any.whl
| Download URL | stripe_blade_mcp-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 52.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e2ac8a5f5fdf5c3505340dd82b813d85d3faff6207efe1fc45f7c167f24f6d40
|
|
BLAKE2b-256 checksum How to use checksums |
2124db76673655638c17d61f4e4dea9ae86e6d3f71a65b9bbdeeaee86c257ed7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 11, 2026.
Transparency log