Best for
- Use when building paid APIs, payment-gated content or endpoints, AI agent payment flows, MCP tool payments, pay-per-token streaming, or metered pay-as-you-go billing.
tenequm/skills/skills/mpp/SKILL.md
Build with MPP (Machine Payments Protocol) - the open protocol for machine-to-machine payments over HTTP 402. Use when building paid APIs, payment-gated content or endpoints, AI agent payment flows, MCP tool payments, pay-per-token streaming, or metered pay-as-you-go billing. Covers the mppx TypeScript SDK (Hono/Express/Next.js/Elysia middleware), pympp Python SDK, and mpp Rust SDK, with Tempo stablecoins, Stripe cards, Lightning Bitcoin, and custom payment rails.
Decision brief
MPP is an open protocol (co-authored by Tempo and Stripe) that standardizes HTTP 402 Payment Required for machine-to-machine payments. Clients pay in the same HTTP request - no accounts, API keys, or checkout flows needed.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/tenequm/skills --skill "skills/mpp"Inspect the Agent Skill "mpp" from https://github.com/tenequm/skills/blob/9b9fb5a29c103ed207dc255d753939e4e2ed29f5/skills/mpp/SKILL.md at commit 9b9fb5a29c103ed207dc255d753939e4e2ed29f5. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Install: npm install mppx viem (mppx 0.8.15 requires viem = 2.54.0).
In browsers, mppx 0.6.0 changed the default: polyfilled fetch only sends Accept-Payment to same-origin endpoints, so cross-origin paid APIs need acceptPaymentPolicy ('always' / { origins: [...] }). Client fetch retries incremental challenges up to maxPaymentRetries (default 3).…
Install: pip install "pympp[tempo]". See references/python-sdk.md for full patterns.
Install: cargo add mpp --features tempo,server. See references/rust-sdk.md for full patterns.
const accessKey = { expiry: Expiry.days(7), limits: [{ token: usdc, limit: numberToHex(parseUnits('10', 6)), period: 86400 }], // 10 USDC/day scopes: [Scopes.tip20(usdc).transfer({ recipients: [recipientAddress] })], } // Authorize: provider.request({ method: 'walletconnect', pa…
Permission review
The documentation includes network, browsing, or remote request actions.
MPP is an open protocol (co-authored by Tempo and Stripe) that standardizes HTTP `402 Payment Required` for machine-to-machine payments. Clients pay in the same HTTP request - no accounts, API keys, or checkout flows needed.The documentation includes network, browsing, or remote request actions.
| **charge** | One-time payment per request | API calls, content access, fixed-price endpoints |The documentation asks the agent to run terminal commands or scripts.
npx mppx account createThe documentation asks the agent to run terminal commands or scripts.
npx mppx account fund --network testnetEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 96/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 35 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
MPP is an open protocol (co-authored by Tempo and Stripe) that standardizes HTTP 402 Payment Required for machine-to-machine payments. Clients pay in the same HTTP request - no accounts, API keys, or checkout flows needed.
The core protocol spec is submitted to the IETF as the Payment HTTP Authentication Scheme.
Code in this skill uses placeholder token names (<USDC_TEMPO_MAINNET>, <PATHUSD_TESTNET>); the real addresses live in the Tempo documentation and references/tempo-method.md.
Three primitives power every MPP payment:
WWW-Authenticate: Payment header)Authorization: Payment header)Payment-Receipt header)MPP is payment-method agnostic. Each method defines its own settlement rail:
| Method | Rail | SDK Package | Status |
|---|---|---|---|
| Tempo | TIP-20 stablecoins on Tempo chain | mppx (built-in) | Production |
| Stripe | Cards/wallets (SPT) + on-chain crypto deposit | mppx (built-in) | Production |
| EVM | EIP-3009 stablecoin authorizations (x402-exact compatible) | mppx (built-in) | Production |
| Lightning | Bitcoin over Lightning Network | @buildonspark/lightning-mpp-sdk | Production |
| Stellar | SEP-41 tokens on Stellar, charge + channel | @stellar/mpp | Production (channel wire spec still being drafted - subject to change) |
| Solana | Solana-native charge + session (SOL, SPL, Token-2022) | @solana/mpp | Production |
| Monad | Monad charge (ERC-3009, settlement modes) | @monad-crypto/mpp | Production |
| NEAR Intents | Cross-chain charge via 1Click deposit addresses | @defuse-protocol/nearintents-mpp-sdk | Production (not trustless - routes through a settlement backend, advertised as methodDetails.settlementBackend: "near-intents" for per-method risk policy) |
| RedotPay | RedotPay balance (rdt) or stablecoin proof, charge only | @redotpay/mpp | Production |
| Card | Encrypted network tokens (Visa) | mpp-card | Production |
| Custom | Any rail | Method.from() + Method.toClient/toServer | Extensible |
Per-method deep dives: references/tempo-method.md, references/stripe-method.md, references/lightning-method.md, references/custom-methods.md.
| Intent | Pattern | Best For |
|---|---|---|
| charge | One-time payment per request | API calls, content access, fixed-price endpoints |
| session | Pay-as-you-go over payment channels | LLM streaming, metered billing, high-frequency APIs |
| subscription | Recurring access via an authorized key (Tempo) - see references/subscriptions.md | Plans/tiers where access is separated from per-request billing |
import { Mppx, tempo } from 'mppx/server'
const mppx = Mppx.create({
methods: [tempo({
currency: '<PATHUSD_TESTNET>', // pathUSD testnet
recipient: '0xYourAddress',
})],
})
export async function handler(request: Request) {
const result = await mppx.charge({ amount: '0.01' })(request)
if (result.status === 402) return result.challenge
return result.withReceipt(Response.json({ data: '...' }))
}
Install: npm install mppx viem (mppx 0.8.15 requires viem >= 2.54.0).
Validate the finished server end-to-end with npx mppx validate http://localhost:3000.
import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'
// Polyfills globalThis.fetch to handle 402 automatically
Mppx.create({
methods: [tempo({ account: privateKeyToAccount('0x...') })],
})
const res = await fetch('https://api.example.com/paid')
// Payment happens transparently when server returns 402
In browsers, mppx 0.6.0 changed the default: polyfilled fetch only sends Accept-Payment to same-origin endpoints, so cross-origin paid APIs need acceptPaymentPolicy ('always' / { origins: [...] }). Client fetch retries incremental challenges up to maxPaymentRetries (default 3). For non-global alternatives (Fetch.from/polyfill/restore, Mppx.restore()), see references/typescript-sdk.md.
from fastapi import FastAPI
from mpp import Credential, Receipt
from mpp.server import Mpp
from mpp.methods.tempo import tempo, ChargeIntent
app = FastAPI()
server = Mpp.create(method=tempo(
currency="<PATHUSD_TESTNET>",
recipient="0xYourAddress", intents={"charge": ChargeIntent()},
))
@app.get("/resource")
@server.pay(amount="0.50")
async def get_resource(request, credential: Credential, receipt: Receipt):
return {"data": "paid content", "payer": credential.source}
Install: pip install "pympp[tempo]". See references/python-sdk.md for full patterns.
Install: cargo add mpp --features tempo,server. See references/rust-sdk.md for full patterns.
Each framework has its own import (mppx/nextjs, mppx/hono, mppx/express, mppx/elysia):
// Next.js
import { Mppx, tempo } from 'mppx/nextjs'
const mppx = Mppx.create({ methods: [tempo({ currency: '<PATHUSD_TESTNET>', recipient: '0x...' })] })
export const GET = mppx.charge({ amount: '0.1' })(() => Response.json({ data: '...' }))
// Hono
import { Mppx, tempo } from 'mppx/hono'
app.get('/resource', mppx.charge({ amount: '0.1' }), (c) => c.json({ data: '...' }))
See references/typescript-sdk.md for Express and Elysia examples.
Sessions open a payment channel once, then use off-chain vouchers for each request - no blockchain transaction per request. Sub-100ms latency, near-zero per-request fees.
Sessions v2 (default since mppx 0.7.0): tempo.session() is the TIP-1034 precompile channel flow; the earlier escrow-contract implementation is Sessions v1, still available as the deprecated tempo.sessionLegacy. A v2-expecting client rejects a v1 session and falls back to the charge path, so keep client and server on matching flows. Two client APIs: tempo.session({ account, maxDeposit }) registers the method with Mppx.create() (transparent 402 handling via fetch), while tempo.session.manager({ account, maxDeposit }) returns a managed client for direct lifecycle control (.sse(), .close()).
// Server - session endpoint with automatic settlement
const mppx = Mppx.create({
methods: [tempo.session({
currency: '<PATHUSD_TESTNET>', recipient: '0x...',
store: Store.redis(redis),
settlementSchedule: { amount: '1.00', intervalMs: 300_000 },
bootstrap: true, // let returning clients recover their channel on this route
})],
})
const result = await mppx.session({ amount: '0.001', unitType: 'token' })(request)
if (result.status === 402) return result.challenge
return result.withReceipt(Response.json({ data: '...' }))
// Server - SSE streaming with per-word billing
export const GET = mppx.session({ amount: '0.001', unitType: 'word' })(
async () => async function* (stream) {
for (const word of ['hello', 'world']) {
await stream.charge()
yield word
}
}
)
// Client - session with auto-managed channel
Mppx.create({ methods: [tempo({ account, maxDeposit: '1' })] })
const res = await fetch('http://localhost:3000/api/resource')
// 1st request: opens channel on-chain; 2nd+: off-chain vouchers
Sessions also stream over WebSocket via Ws.serve(). See references/sessions.md for the full lifecycle, settlement, stores, SSE and WebSocket patterns, and channel recovery.
Accept Tempo stablecoins, Stripe cards, and Lightning Bitcoin on a single endpoint:
const mppx = Mppx.create({
methods: [
tempo({ currency: '<PATHUSD_TESTNET>', recipient: '0x...' }),
stripe.charge({ client: new Stripe(key), networkId: 'profile_...', paymentMethodTypes: ['card'] }),
spark.charge({ mnemonic: process.env.MNEMONIC! }),
],
})
Use Mppx.compose() to present multiple methods in a single 402 response with per-route pricing. Apply the same branch at the challenge site and the verification site, or the 402 advertises fewer options than the server accepts. See references/typescript-sdk.md.
Setting html: true on a payment method config renders a browser-friendly payment page when a 402 endpoint is visited in a browser, with theming, multi-method compose tabs, and Solana wallet support. Service workers handle credential submission, then the page reloads with the paid response.
Customize via mppx/html exports (Config, Text, Theme), and build a custom method's payment link with Html.init(methodName).
Authenticate agent identity without payment. Clients sign an EIP-712 proof over the challenge ID instead of creating a transaction - no gas burned, no funds transferred.
// Server - zero-dollar charge, with a store for replay protection
const mppx = Mppx.create({
methods: [tempo.charge({ currency: '<PATHUSD_TESTNET>', recipient: '0x...', store })],
})
const result = await mppx.charge({ amount: '0' })(request)
Since mppx 0.8.0 these proofs are bound to the payer wallet: the EIP-712 Proof typed data (exposed as tempo.Proof) carries an account field at domain version 3, so a proof signed for one account no longer verifies against another.
Use cases: identity verification, long-running job polling, paid unlock with free subsequent access, multi-step agent pipelines. See mpp.dev/advanced/identity.
Gate existing APIs behind MPP payments:
// import { openai, Proxy } from 'mppx/proxy' - a service inside Proxy.create({ services: [...] })
openai({
apiKey: process.env.OPENAI_API_KEY,
routes: {
'POST /v1/chat/completions': mppx.charge({ amount: '0.05' }),
'GET /v1/models': true, // literal `true` marks a free route
},
})
Built-in presets openai(), anthropic(), stripe(), plus custom() for any upstream. See references/discovery-and-proxy.md for Proxy.create(), the discovery endpoints it serves, and the discovery() helper for non-proxy servers.
MCP tool calls can require payment using JSON-RPC error code -32042 (servers may also issue -32043):
// Server - import tempo from mppx/server, NOT mppx/tempo
import { McpServer } from 'mppx/mcp/server'
import { tempo } from 'mppx/server'
const server = McpServer.wrap(baseServer, { methods: [tempo.charge({ /* ... */ })], secretKey })
// Client - payment-aware MCP client (import tempo from mppx/client)
import { McpClient } from 'mppx/mcp/client'
import { tempo } from 'mppx/client'
const mcp = McpClient.wrap(client, { methods: [tempo({ account })] })
const result = await mcp.callTool({ name: 'premium_tool', arguments: {} })
MCP-over-HTTP challenges settle in the same payment-aware fetch, and transports are pluggable via Transport.from/http/mcp/mcpSdk on both sides. See references/transports.md.
createViemAccount from @privy-io/node/viem (needs @privy-io/node >= 0.20.0) returns a viem Account backed by a Privy server wallet, so it drops into tempo({ account }) wherever a local account would go.
Server-side signing works with app-owned server wallets; user-owned embedded wallets require authorization keys or key quorums. See references/typescript-sdk.md for the full setup and the manual toAccount() construction.
# Create an account (stored in keychain), then fund it on testnet
npx mppx account create
npx mppx account fund --network testnet
# Make a paid request
npx mppx http://localhost:3000/resource
# Parse a challenge without signing it
npx mppx sign --dry-run --challenge '<www-authenticate value>'
# Validate a server implementation end-to-end
npx mppx validate http://localhost:3000
The CLI also covers init, sessions (list/view/close), discover, services, mcp add, and skills add. Config comes from MPPX_CONFIG or an explicit --config - there is no auto-discovery from the working directory. Full reference: references/cli.md.
| Language | Package | Install |
|---|---|---|
| TypeScript | mppx | npm install mppx |
| Python | pympp | pip install "pympp[tempo]" |
| Rust | mpp | cargo add mpp --features tempo,client,server |
| Ruby | mpp-rb (official, by Stripe) | see repo for gem name |
| Go | mpp-go (official, by Tempo) | go get github.com/tempoxyz/mpp-go |
| Elixir | mpp (community) | hex.pm/packages/mpp |
| Swift | mpp-swift (community) | see repo |
Capability notes, checked against SDK source rather than the docs matrices (upstream publishes two that disagree):
hash and transaction payload types.mpp-go, which ships client/server/charge/fee-sponsorship/proof with net/http, Gin, Echo, and Chi middleware. A separate community Go mppx (cp0x) also exists.Go and Ruby have first-class SDK doc pages at mpp.dev/sdk/go and mpp.dev/sdk/ruby.
Always import Mppx and tempo from the subpath matching your context (mppx/server, mppx/client, or the framework subpath). Note: Mppx and tempo are NOT exported from mppx/tempo - that subpath only exports Session and Ws. The authoritative subpath table is in references/typescript-sdk.md.
references/protocol-spec.mdexpectedRecipients). See references/tempo-method.mdmaxInFlightReservations / maxInFlightTotalFeetempo.charge({ relay })tempo.charge({ expectedChainId }) rejects challenges for the wrong Tempo networkchannelStore to persist and reuse payer session channels across processesevm.charge({ x402: { facilitator } }) serves native MPP and x402 "exact" challenges from one route; the client prefers Payment-auth challengesMethod.from(). See references/custom-methods.mdAttach logging, metrics, or tracing without touching the handler. Register on the object returned by Mppx.create(); each registration returns an unsubscribe function.
mppx/server): onChallengeCreated, onPaymentSuccess, onPaymentFailed, onSessionSettlement, on('*')mppx/client): onChallengeReceived, onCredentialCreated, onPaymentResponse, onPaymentFailedServer handlers are awaited inline on the request path - keep them fast. onPaymentFailed is the practical way to see the real error behind an opaque 402. See references/typescript-sdk.md and mpp.dev/advanced/payment-hooks.
Bound an agent's payment authority with Tempo access keys - delegated signing keys with built-in spend controls, their own expiry, and a revocation path.
import { Expiry } from 'accounts'
import { numberToHex, parseUnits } from 'viem'
import { Scopes } from 'viem/tempo'
const accessKey = {
expiry: Expiry.days(7),
limits: [{ token: usdc, limit: numberToHex(parseUnits('10', 6)), period: 86_400 }], // 10 USDC/day
scopes: [Scopes.tip20(usdc).transfer({ recipients: [recipientAddress] })],
}
// Authorize: provider.request({ method: 'wallet_connect', params: [{ capabilities: { authorizeAccessKey: accessKey } }] })
Mppx.create({
methods: [tempo({
account: provider.getAccount(),
...provider.getMppxParameters({ accessKey: accessKeyAddress }),
})],
})
Spend limits are hex-encoded - pass numberToHex(parseUnits(...)), not a raw bigint. Separate keys per app/tool/deployment keep delegated runtimes isolated. See mpp.dev/guides/managing-agent-spend and Tempo access keys.
The failure modes that cost the most time. Full detail in references/production-gotchas.md:
feeToken or call setUserToken, or transactions fail with gas_limit: 0. "Fund with ETH" errors mean "fund with the stablecoin fee token"settlementSchedule or run your own tempo.settle() / tempo.settleBatch() sweep, paired with a close policy for idle channels - otherwise revenue accrues as unredeemed vouchers and channels stay open holding payer depositsvalidateCredential then broadcastCredential when payment should depend on the work succeeding. Challenges expire after 5 minutes by defaultStore.memory() in production. Lost channel state means deposits stay reserved indefinitelyrealm explicitly. Env vars outrank the per-request hostname, and Kubernetes HOSTNAME rotates every deploy, breaking mppscan attributionclose, and topUp credentials are bodyless POSTs, so a body validator running before mppx.session() rejects them with a spurious 400. Clone the request before reading its body, or mppx sees an empty one and returns 402| File | Content |
|---|---|
references/protocol-spec.md | Challenge/Credential/Receipt, status codes, security |
references/typescript-sdk.md | mppx: server, client, middleware, transports, stores |
references/cli.md | mppx CLI: requests, validate, sign, accounts, config |
references/production-gotchas.md | Field-tested failure modes and their fixes |
references/sessions.md | Channels, vouchers, settlement, SSE/WS, recovery |
references/subscriptions.md | Subscription intent: activation, renewal, cancellation |
references/tempo-method.md | Tempo: fees, relays, push/pull, splits, sessions |
references/stripe-method.md | Stripe: SPT fiat flow, crypto deposit, Elements |
references/discovery-and-proxy.md | Proxy services, discovery documents, registries |
references/transports.md | HTTP, MCP, and WebSocket transport bindings |
references/python-sdk.md | pympp: @server.pay, async client, charge intent |
references/rust-sdk.md | mpp Rust: server/client, features, sessions |
references/lightning-method.md | Lightning: BOLT11 charge, bearer sessions, Spark |
references/custom-methods.md | Method.from, toClient, toServer patterns |
claude mcp add --transport http mpp https://mpp.dev/api/mcp (8 tools: list_pages, read_page, search_docs, search_source, list_sources, list_source_files, read_source_file, get_file_tree). Services MCP: mpp.dev/mcp/servicesmpp.dev/.well-known/agent-skills/mppx/SKILL.md; install via npx skills add tempoxyz/mpp -g or mppx skills addFrequently asked questions
MPP is an open protocol (co-authored by Tempo and Stripe) that standardizes HTTP 402 Payment Required for machine-to-machine payments. Clients pay in the same HTTP request - no accounts, API keys, or checkout flows needed.
The source record exposes this install command: npx skills add https://github.com/tenequm/skills --skill "skills/mpp". Inspect the command and pinned source before running it.
Static rules flagged network, exec-script in the source; the page lists the matching lines and excerpts.
Alternatives
alirezarezvani/claude-skills
Reverse-engineer any codebase into a complete Product Requirements Document (PRD). Analyzes routes, components, state management, API integrations, and user interactions to produce business-readable documentation detailed enough for engineers or AI agents to fully reconstruct every page and endpoint. Works with frontend frameworks (React, Vue, Angular, Svelte, Next.js, Nuxt), backend frameworks (NestJS, Django, Express, FastAPI), and fullstack applications. Use when users mention: generate PRD,
alirezarezvani/claude-skills
Fullstack development toolkit with project scaffolding for Next.js, FastAPI, MERN, and Django stacks, code quality analysis with security and complexity scoring, and stack selection guidance. Use when the user asks to "scaffold a new project", "create a Next.js app", "set up FastAPI with React", "analyze code quality", "audit my codebase", "what stack should I use", "generate project boilerplate", or mentions fullstack development, project setup, or tech stack comparison.
hookdeck/webhook-skills
Receive and verify Scrapfly webhooks. Use when setting up Scrapfly webhook handlers for async scrape, extraction, screenshot, or crawler jobs, debugging X-Scrapfly-Webhook-Signature verification, or routing on X-Scrapfly-Webhook-Resource-Type.
mem0ai/mem0
Mem0 provider for Vercel AI SDK (@mem0/vercel-ai-provider). TRIGGER when: user mentions "vercel ai sdk", "@mem0/vercel-ai-provider", "createMem0", "retrieveMemories", "addMemories", "getMemories", "searchMemories", "mem0 vercel", "AI SDK provider", "AI SDK memory", or is using generateText/streamText with mem0. Also triggers for Next.js apps needing memory-augmented AI. DO NOT TRIGGER when: user asks about direct Python/TS SDK calls without Vercel (use mem0 skill), or CLI terminal commands (use