Stripe Mpp
Security Notice
This extension includes AI agent skills that can modify AI assistant behavior. Review the skill files before installing.
Stripe Machine Payments Protocol (MPP) — agent buyer (probe/mint/pay over HTTP-402 Payment auth), consumer buyer (grant a Shared Payment Token from a Link wallet via link-cli, spend by reference), and full seller API (challenge/verify/charge/receipt/reconcile/refund) for fiat Shared Payment Tokens, built on mppx and the Stripe preview SDK
2026.10.25.10
- Repo-wide republish; no functional change.
Global Arguments
| Argument | Type | Description |
|---|---|---|
| secretKey | string | Stripe secret key (sk_test_... / sk_live_...). Use a vault reference: |
| serverSecret? | string | Seller-side HMAC secret (>=32 chars) binding challenge ids |
| networkId? | string | Stripe Business Network Profile id (profile_test_... / profile_...). |
| realm? | string | Protection-space identifier advertised in seller challenges (RFC 9110). |
| stripeVersion? | string | Stripe-Version header. SPT endpoints need the preview channel. |
| testMode? | boolean | Gates test helpers (createTestGrantedToken). Must match the key mode. |
| allowInsecure? | boolean | Test-fixture escape: permit plain http:// to loopback, allow private/ |
| timeoutMs? | number | Per-request timeout for resource fetches and Stripe calls. |
| paymentMethodTypes? | array | Payment method types advertised in seller challenges. |
| linkCliPath? | string | ABSOLUTE path to the installed @stripe/link-cli binary (a non-writable |
| linkCliVersion? | string | Pinned link-cli version. The MCP initialize serverInfo.version is |
| allowLiveGrants? | boolean | Consumer-grant live-money opt-in. Default false forces link-cli test |
| Argument | Type | Description |
|---|---|---|
| paymentMethodId | string | Existing payment method (pm_...). Raw-PAN creation is PCI-gated in |
| maxAmount | string | Usage-limit ceiling, minor units string. |
| currency | string | Usage-limit currency (ISO, lowercase). |
| expiresAt? | number | Unix timestamp for usage_limits.expires_at. |
| sellerNetworkId? | string | Seller network profile the token is granted to (defaults to networkId). |
| externalId? | string | Correlation id; also drives the Idempotency-Key. |
| Argument | Type | Description |
|---|---|---|
| sptId | string | Shared Payment Token (spt_...) to present. |
| maxAmount | string | Spend ceiling, minor units string. The challenge amount must not |
| currency | string | Expected challenge currency. Mismatch blocks the payment. |
| expectedNetworkId? | string | Pin the payee: the Stripe Business Network Profile (profile_...) the |
| expectedRealm? | string | Pin the challenge realm (issuing authority); mismatch blocks the payment. |
| externalId? | string | Correlation id. |
| Argument | Type | Description |
|---|---|---|
| sptId | string | Shared Payment Token id (spt_...). |
| Argument | Type | Description |
|---|---|---|
| sptId | string | Shared Payment Token id (spt_...). |
| Argument | Type | Description |
|---|---|---|
| amount | string | Amount demanded, minor units string. |
| currency | string | Currency (ISO, lowercase). |
| description? | string | |
| externalId? | string | |
| expiresInSeconds? | number | Challenge validity window; recommended to keep challenges short-lived. |
| networkId? | string | Override the global networkId. |
| scope? | string | Bind the challenge to a specific resource/route. Carried inside the |
| Argument | Type | Description |
|---|---|---|
| authorizationHeader | string | The received Authorization value ("Payment <base64url>"). |
| expectedAmount? | string | |
| expectedCurrency? | string | |
| expectedScope? | string | Require the credential's challenge `opaque` to equal this route scope |
| Argument | Type | Description |
|---|---|---|
| sptId? | string | Granted token to settle (or pass authorizationHeader). |
| amount? | string | Minor units string. |
| currency? | string | |
| authorizationHeader? | string | Full received credential; verified (HMAC + expiry) before settling. |
| expectedScope? | string | When settling from an authorizationHeader, require the challenge |
| description? | string | |
| externalId? | string |
| Argument | Type | Description |
|---|---|---|
| chargeId | string | Settled PaymentIntent id (pi_...). |
| externalId? | string |
| Argument | Type | Description |
|---|---|---|
| chargeId | string | PaymentIntent id (pi_...). |
| Argument | Type | Description |
|---|---|---|
| externalId? | string | Filter by metadata externalId (uses /v1/payment_intents/search). |
| createdGte? | number | Unix lower bound. |
| createdLte? | number | Unix upper bound. |
| maxResults? | number | |
| pageSize? | number |
| Argument | Type | Description |
|---|---|---|
| chargeId | string | PaymentIntent id (pi_...) to refund. |
| amount | string | Refund amount, minor units string. Must not exceed the remaining |
| reason? | enum | |
| externalId? | string |
| Argument | Type | Description |
|---|---|---|
| sptId | string | Shared Payment Token id (spt_...). |
| Argument | Type | Description |
|---|---|---|
| maxAmount | string | Usage-limit ceiling, minor units string. |
| currency | string | Usage-limit currency. |
| paymentMethodId? | string | Payment method the fabricated granted token draws on (required by the |
| expiresAt? | number |
| Argument | Type | Description |
|---|---|---|
| id | string | Spend request id (lsrq_...). |
| Argument | Type | Description |
|---|---|---|
| id | string | Spend request id (lsrq_...). |
| Argument | Type | Description |
|---|---|---|
| amount | string | Amount to authorise, minor-units STRING (e.g. "500" = $5.00). |
| currency? | string | Currency (ISO, lowercase). US-only Link; default usd. |
| context | string | Purchase description + rationale the consumer READS when approving. |
| networkId? | string | Payee Business Network Profile (profile_...). Defaults to the global |
| paymentMethodId? | string | Consumer Link payment method (csmrpd_...). Omit to let the consumer pick |
| externalId? | string | Correlation id; also anchors the deterministic intent key persisted on |
| Argument | Type | Description |
|---|---|---|
| id | string | Approved spend request id (lsrq_...) to spend. |
| maxAmount | string | ADVISORY pre-flight ceiling (minor units). NOTE: the binding cap is the |
| currency | string | Expected challenge currency (advisory). |
| expectedNetworkId? | string | Advisory payee pin for the pre-flight challenge. |
| expectedRealm? | string | Advisory realm pin. |
| externalId? | string | Correlation id. |
Resources
2026.10.25.2
Fixed
- Consumer-buyer methods were broken against link-cli 0.19.1+ (including the
pinned 0.28.0). link-cli's stdio MCP server (built on
incur) uses progressive tool discovery:tools/listreturns onlysearch_tools,get_tool_details,call_read_toolandcall_write_tool, and a directtools/callofspend-request_create(or any other inner tool) fails with JSON-RPC -32602 "Tool … not found".lib/link_cli.tsnow reaches every inner tool ascall_write_tool { name, arguments }. The reads go throughcall_write_tooltoo: link-cli 0.28.0 annotates no toolreadOnlyHint, andcall_read_toolrefuses such tools ("Tool is not read-only"). The routing is a pinned per-tool table; the strictlinkCliVersioncheck still guards it. - Streamed results are unwrapped.
spend-request_create,spend-request_retrieveandmpp_payare generator commands, so their result is a JSON array of chunks; the model now uses the last chunk. An empty array is a failure: incur drops a generator'sc.error(for example NOT_FOUND, POLLING_TIMEOUT or a duplicate spend request) and returns[]. - Error results are unwrapped to their message (the wrapper's
{"error": …}, an inner validation error'scode: message, or plain text), and the call-to-action text incur appends after a success result is stripped before parsing. paySpendRequestrecordspay-failedwhenmpp_payreturns the paid request's HTTP response with a status of 400 or above (link-cli reports that as a successful tool result), and sendsdomain, which link-cli'sreportschema requires.
Method names, arguments and resource schemas are unchanged.
2026.10.25.1
Dependency bump for the upstream release drift tracked in #231:
mppx@0.9.3 → 0.13.5, stripe@22.7.0-beta.1 → 23.1.0-beta.1, and the
linkCliVersion drift-detection default 0.19.1 → 0.28.0. No source change was
needed. Contract (stripe_mpp_test.ts) and adversarial/tamper
(stripe_mpp_adversarial_test.ts) suites pass unmodified apart from the pin
strings.
- mppx (0.10.0 … 0.13.5, read release notes for every version):
- The Stripe SPT rail is byte-identical.
dist/Challenge.js,dist/Credential.js,dist/PaymentRequest.js,dist/Expires.jsanddist/stripe/server/Charge.jsmatch 0.9.3 exactly, so the HMAC challenge-id binding, the codec and the per-currencycanOfferminimums are unchanged. The crypto primitives in the regenerated lock are unchanged too:@noble/hashes@1.8.0,@noble/curves@1.9.1,@scure/base@1.2.6,@scure/bip32@1.7.0and@scure/bip39@1.6.0. Receiptgains an optionalfundingCurrencyfield. The change is additive.- Since 0.13.4, server-issued challenges carry an HMAC-bound random issuance
nonce in
opaque(_mppx_nonce). Route scope still lives inrequest.methodDetails.metadata.scope, soexpectedScopechecks are unaffected. A swamp-runtime smoke test (createChallenge, thenverifyCredential) confirmed that an in-scope credential is accepted and a cross-scope one is rejected. - Breaking changes in the range only affect surfaces this model does not use:
Tempo, EVM, x402, sessions,
stripe.create()'s new shared-store requirement, and the CLI. - Peer
viemfloor is now 2.57.1 (locked at 2.57.10). The directzodfloor is now ^4.6.5, but zod stays externalized and shared with swamp. mppx uses only basiczod/miniAPIs.
- The Stripe SPT rail is byte-identical.
- stripe (
public-previewchannel): the model pins its own API version (2026-04-22.preview), so the SDK's new pinned API version does not change the wire format. No changes in the range touch the endpoints this model uses: SharedPayment issued/granted tokens, PaymentIntents, Refunds andrawRequest. From the 23.0.0 GA notes: incomplete response bodies now throwStripeConnectionErrorinstead ofStripeAPIError. Only the message is surfaced, and it is redacted. - link-cli: the inputs of the six MCP tools this model calls
(
spend-request_create/_retrieve/_cancel,payment-methods_list,mpp_pay,report) were compared between 0.19.1 and 0.28.0 viaget_tool_details. Changes are additive only (useApprovalPolicy,approvedChallenge, recurring fields),currencybecame optional (this model always sends it), and the removedexecutionMethodfield was never sent. Hosts must upgrade thelink-clibinary to 0.28.0, because the version check is fatal. - README: setup now stores secrets with a prompting
swamp vault put <vault> <key>instead of passing the value on the command line.
2026.10.15.9
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.8
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.6
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.5
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.4
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.3
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.2
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.15.1
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.10.14.2
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
Security
- Bump the bundle-resolution pin
@modelcontextprotocol/sdk1.30.0 → 1.32.1 to clear GHSA-6qxp-vccf-f47h (HIGH), which blocked the dependency-trust gate.
2026.09.19.2
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
idemKey's NUL-byte domain separator is now written as the literal\x00escape instead of a raw embedded NUL byte in the source. Source-representation change only: the hashed string, SHA-256 digests and idempotency keys are byte-identical before and after (verified against fixed inputs).stripe_mpp.tsis now ordinary UTF-8 text — see docs/MAINTAINING.md.
2026.09.19.1
Dependency bump: mppx@0.8.14 → 0.9.3 (minor, preview channel, bundled runtime
dep) + stripe@22.4.0-beta.1 → 22.7.0-beta.1 (public-preview dist-tag
moved) + linkCliVersion drift-detection default 0.10.1 → 0.19.1. Required a
real source change, not just version strings — see below.
- mppx: NO-OP on the fiat/SPT wire contract, confirmed on durable evidence.
The crypto primitives are byte-identical in the regenerated lock
(
@noble/hashes@1.8.0backs the HMAC-SHA256 id-binding,@noble/curves@1.9.1,@scure/base@1.2.6,@scure/bip32@1.7.0,@scure/bip39@1.6.0all unmoved), and the upstream release notes for every intervening version (0.8.15, 0.8.17..0.8.19, 0.9.0..0.9.3) show no change to the HMAC challenge-id binding, key derivation, domain separators, or the Challenge/Credential/Receipt codec.stripe_mpp_test.ts's golden vectors andstripe_mpp_adversarial_test.tsboth pass UNMODIFIED. 0.9.0's breaking removal of the machineUSD charge/session flows does not apply — this model only imports the Stripe rail (stripeServer.charge()); nomachineUSD, Tempo, x402, or EVM usage anywhere in the extension.- Behavioural change (not wire format) required a source fix: 0.8.17 added
a
canOffergate in mppx's Stripe rail (dist/stripe/server/Charge.js,minimumChargeAmountByCurrency) that refuses to offer a charge below Stripe's per-currency minimum, surfacing as a bare"No payment offers are available for this request"from inside the library. Extended the model's ownMIN_CHARGEtable (usdonly until now) to mirror all 32 currencies mppx enforces, and added a pre-flight check increateChallenge(immediately after the existingisCanonicalMinorUnitsguard) so a sub-minimum request fails closed with a clear, model-level error naming the amount, currency, and floor — before a consumer is ever prompted — instead of the opaque library error. Raised the amount floor instripe_mpp_flow_property_test.ts's andstripe_mpp_invariant_property_test.ts's amount arbitraries (1n → 50n) to stop generating amounts Stripe itself would never have accepted; this is correcting the property domain, not weakening it. - New drift guard: mppx's
minimumChargeAmountByCurrencyis module-local and not exported, soMIN_CHARGEis a hand-maintained copy that can silently diverge from upstream. Added 5 contract tests (stripe_mpp_test.ts) that probe mppx's REALcanOfferbehaviour at the boundary — refuses atfloor - 1, offers atfloor— for a representative currency spread (usd,gbp,huf,czk,jpy: the two Link-relevant currencies, the two highest floors in the table, and a zero-decimal currency) rather than comparing the constant to itself, so a future upstream table change reddens this suite instead of the two copies quietly drifting apart.
- Behavioural change (not wire format) required a source fix: 0.8.17 added
a
- stripe:
public-previewdist-tag genuinely moved (npm view stripe dist-tags). No SDK-surface changes this model depends on. - link-cli:
@stripe/link-clidrift-detection default re-pinned0.10.1 → 0.19.1on maintainer instruction (nine minors, release-notes evidence only — Link is still US-only, not live-verified). Runtime consequence:lib/link_cli.ts's version check is FATAL, not advisory — it throws and aborts the call if the real binary's reported version differs fromlinkCliVersion. Any host still running alink-cliolder than 0.19.1 will now hard-fail every consumer-grant call until the binary is upgraded. Updated the three fixture literals (stripe_mpp_methods_test.ts,stripe_mpp_live_test.ts,lib/link_cli.test.ts) alongside the default. - Transitive drift from the lockfile regeneration:
viem 2.55.10 → 2.56.8,oxgains a0.14.45peer variant,@stripe/stripe-js 9.9.0 → 9.13.0, peerzod 4.4.3 → 4.5.4(this package's ownzodimport already floats onnpm:zod@4).stripe's andmppx's deps all keep sha512 integrity hashes; no stalemppx@0.8.14specifier remains. - Re-bundle republishes with
0.9.3/22.7.0-beta.1inlined. Full offline suite: 126 passed, 0 failed, 1 ignored (stripe_mpp_live_test.ts, requires real Link test-mode secrets, not run). 10000-run property soak: 28 passed, 0 failed. Contract (stripe_mpp_test.ts) and adversarial/tamper (stripe_mpp_adversarial_test.ts) suites pass UNMODIFIED aside from the pin string and, in the contract suite, the new drift-guard tests appended at the end (no existing test body touched).
2026.09.17.1
Changed
- Repo-wide maintenance release: version bump to republish the current source. No schema change.
2026.09.01.1
Re-release of 2026.08.19.1 (beta), whose publish never reached the registry —
the repo-wide 2026.08.19.1 bump's extension-publish job did not complete for
this package, and that job only fires on a version bump. Content is unchanged
from 2026.08.19.1; its notes are carried forward below.
- Version bump and smoke test
2026.08.01.1
Dependency bump: mppx@0.8.12 → 0.8.14 (patch, preview channel, bundled runtime
dep) + linkCliVersion drift-detection default 0.9.0 → 0.10.1
(fixture/default only, no bundle impact).
- mppx: NO-OP on the fiat/SPT wire contract, confirmed on durable evidence.
deno task checkstayed clean (no method signature the model calls moved) and the full offline suite (121 tests) + the 10000-run property soak pass UNMODIFIED, including the byte-exactstripe_mpp_test.tsgolden-vector test — the Challenge / Credential / Receipt codec, HMAC challenge-id binding, key derivation, and domain separators are unchanged. The 0.8.13/0.8.14 deltas are Tempo/SQLite/stablecoin patch changes plus additive APIs this fiat/SPT model does not import.- Watch item: 0.8.14 marks the legacy combined payment-verification hooks DEPRECATED (not removed, not yet used by this model) — a future mppx major that removes them will need re-verification, not just a version bump.
- link-cli:
@stripe/link-clire-pinned0.9.0 → 0.10.1on release-notes evidence only (additive/security changes, no documented stdio-MCP contract change) — not live-verified, Link is still US-only and the maintainer's account is EU (stripe_mpp_live_test.tsstaysignored). The bump is required regardless: the drift-detection preflight (lib/link_cli.ts) rejects a real 0.10.1 binary unlesslinkCliVersionis bumped to match. Updated the three fixture literals (lib/link_cli.test.ts,stripe_mpp_methods_test.ts,stripe_mpp_live_test.ts) alongside the default; thempp_pay/paySpendRequestspend-by-reference path stays on the same watch list as the rest of the consumer-buyer surface for the next real observation. - Transitive drift from the lockfile regeneration:
viem 2.55.4 → 2.55.10,oxgains a0.14.33peer variant alongside the existing0.14.30(mppx/viem resolve different ox ranges),mppxpicks up the matchingviem@2.55.10peer combination.stripestays22.4.0-beta.1and@stripe/stripe-jsstays9.9.0(both unchanged); the crypto primitives are byte-identical in the regenerated lock (@noble/hashes@1.8.0,@noble/curves@1.9.1,@scure/base@1.2.6,@scure/bip32@1.7.0,@scure/bip39@1.6.0) and every dep keeps its sha512 integrity hash. - Re-bundle republishes with
0.8.14inlined (extension deps are bundled at build time). All fixtures stay synthetic (RFC 2606 hosts,_test_fixture_ids) — no vectors were re-derived, since the golden test passed unmodified.
2026.07.21.2
Dependency bump: mppx@0.8.6 → 0.8.12 (patch, preview channel). No breaking
changes to the Challenge / Credential / Receipt codecs or the Mppx / Stripe
server APIs.
- Wire format unchanged, on durable evidence: the crypto primitives are
byte-identical in the regenerated lock (
@noble/hashes@1.8.0backs the HMAC-SHA256 id-binding,@noble/curves@1.9.1,@scure/*all unmoved), and the upstream review of the0.8.6..0.8.12releases (0.8.7, 0.8.8, 0.8.9, 0.8.11, 0.8.12 — 0.8.10 was never published) found no change to the HMAC challenge-id binding, key derivation, domain separators, or the challenge/credential/receipt serialization. The 0.8.7..0.8.12 deltas are Celo/Tempo/session-voucher andmppx validate-command code this fiat/SPT model does not import. - Transitive drift from the lockfile regeneration:
viem 2.54.2 → 2.55.4,ox 0.14.29 → 0.14.30,@stripe/stripe-js 9.8.0 → 9.9.0, and a prerelease inversion@modelcontextprotocol/server 2.0.0-beta.2 → 2.0.0-alpha.4(pulled viaincur, off the crypto/wire path), plus test-only dedupes.stripestays22.4.0-beta.1(unchanged — still the current public-preview dist-tag); every dep keeps its sha512 integrity hash. - Re-bundle republishes with
0.8.12inlined (extension deps are bundled at build time). Regression coverage: the full suite (120 offline tests) + the 10000-run property soak re-run green against0.8.12, and the spec-fixture contract (stripe_mpp_test.ts) and adversarial/tamper (stripe_mpp_adversarial_test.ts) suites pass UNMODIFIED.
2026.07.21.1
Consumer buyer (Link grant): a human WITHOUT a Stripe account can now fund agent
payments from their Link wallet. Five methods behind a new lib/link_cli.ts
anti-corruption layer that drives Stripe's link-cli as an MCP server over
stdio (link-cli --mcp) — deliberately NOT its HTTP serve mode, which
binds all interfaces with Access-Control-Allow-Origin: * and no auth (see
SPIKE-link-cli.md).
listConsumerPaymentMethods,createSpendRequest,getSpendRequest,cancelSpendRequest,paySpendRequest.- The grant is spent BY REFERENCE (
mpp_pay --spendRequestId); the model never holds a rawspt_(persistslsrq_only, strictObject resources). No Link token custody — link-cli owns its device-flow session on disk; the subprocess is spawnedclearEnv. createSpendRequestis the PRIMARY binding guard (anchored payee, amount cap≤500000+$0.50USD floor,context≥100, response-echo) before the consumer is prompted;paySpendRequest's pre-flight is advisory only.- New non-secret globals:
linkCliPath(absolute, fail-closed),linkCliVersion(drift-detection preflight),allowLiveGrants(default false → test mode). - Extracted
pay's spend-guard into the sharedchallengeGuardViolation()helper (behaviour-preserving). - US-only (Stripe Link) and inert without an authenticated co-located link-cli session; the four consumer methods fail closed, the existing 14 are unaffected. Not live-verified (Link is US-only; the maintainer is EU) — built on the observed v0.9.0 tool contract, pinned by fixtures.
Modified 1 behaviors. Modified 1 skills
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented1/1earned
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit2/2earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License1/2partial
no SPDX license declared
- Verified public repository2/2earned