tenequm/mpp

Construisez avec MPP (Machine Payments Protocol), un protocole ouvert de paiement machine-à-machine via HTTP 402. Utilisez-le pour des API payantes, des points d'accès avec barrière de paiement, des flux de paiement pour agents, des paiements d'outils MCP ou de la facturation à l'usage. Couvre les SDK mppx (TS), pympp et mpp Rust.

Qu'est-ce que mpp ?

MPP (Machine Payments Protocol) est un protocole ouvert, co-écrit par Tempo et Stripe, qui standardise le code HTTP `402 Payment Required` pour les paiements machine-à-machine. Le client paie dans la même requête HTTP, sans avoir besoin de comptes, de clés API ou de processus de paiement classiques. Ce skill vous permet d'utiliser MPP avec des SDK en TypeScript (mppx), Python (pympp) et Rust (mpp). Il couvre les architectures de base (Challenge, Credential, Receipt), les modes de paiement (paiement unique, session, abonnement), l'intégration avec des frameworks web (Next.js, Hono, etc.), le transport MCP (Model Context Protocol) pour les outils d'IA, et un proxy de paiement pour protéger des API existantes. Il prend en charge de nombreux réseaux de règlement (Tempo, Stripe, EVM, Lightning, Solana, Monad, Stellar, etc.) et des fonctionnalités avancées comme l'authentification à coût zéro (Proof Credentials), les sessions de streaming avec paiement à l'utilisation, et un client CLI pour les tests.

Compatible avec✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/tenequm/skills/tree/HEAD/archive/mpp

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

MPP - Protocole de Paiement Machine

MPP est un protocole ouvert (co-écrit par Tempo et Stripe) qui standardise le code HTTP 402 Payment Required pour les paiements machine-à-machine. Les clients paient dans la même requête HTTP - pas besoin de comptes, de clés API ou de processus de paiement.

La spécification de base du protocole est soumise à l'IETF en tant que Schéma d'Authentification HTTP de Paiement.

Le code de ce skill utilise des noms de jetons fictifs (<USDC_TEMPO_MAINNET>, <PATHUSD_TESTNET>) ; les vraies adresses se trouvent dans la documentation Tempo et dans references/tempo-method.md.

Architecture de Base

Trois primitives alimentent chaque paiement MPP :

  1. Challenge - exigence de paiement émise par le serveur (dans l'en-tête WWW-Authenticate: Payment)
  2. Credential - preuve de paiement soumise par le client (dans l'en-tête Authorization: Payment)
  3. Receipt - confirmation par le serveur d'un paiement réussi (dans l'en-tête Payment-Receipt)

Méthodes de Paiement et Intentions

MPP est indépendant de la méthode de paiement. Chaque méthode définit son propre rail de règlement :

MéthodeRailPaquet SDKStatut
TempoStablecoins TIP-20 sur la chaîne Tempomppx (intégré)Production
StripeCartes/portefeuilles (SPT) + dépôt crypto on-chainmppx (intégré)Production
EVMAutorisations de stablecoins EIP-3009 (compatible x402-exact)mppx (intégré)Production
LightningBitcoin via le réseau Lightning@buildonspark/lightning-mpp-sdkProduction
StellarJetons SEP-41 sur Stellar, charge + channel@stellar/mppProduction (spécification du câble channel encore en cours d'élaboration - sujette à modification)
SolanaCharge + session natives Solana (SOL, SPL, Token-2022)@solana/mppProduction
MonadCharge Monad (ERC-3009, modes de règlement)@monad-crypto/mppProduction
NEAR IntentsCharge inter-chaînes via des adresses de dépôt 1Click@defuse-protocol/nearintents-mpp-sdkProduction (non sans confiance - transite par un backend de règlement, annoncé comme methodDetails.settlementBackend: "near-intents" pour une politique de risque par méthode)
RedotPaySolde RedotPay (rdt) ou preuve de stablecoin, charge uniquement@redotpay/mppProduction
CarteJetons réseau cryptés (Visa)mpp-cardProduction
PersonnaliséeN'importe quel railMethod.from() + Method.toClient/toServerExtensible

Analyses approfondies par méthode : references/tempo-method.md, references/stripe-method.md, references/lightning-method.md, references/custom-methods.md.

IntentionModèleIdéal Pour
chargePaiement unique par requêteAppels API, accès à du contenu, endpoints à prix fixe
sessionPaiement à l'usage via des canaux de paiementStreaming LLM, facturation à l'usage, API à haute fréquence
subscriptionAccès récurrent via une clé autorisée (Tempo) - voir references/subscriptions.mdPlans/niveaux où l'accès est séparé de la facturation par requête

Démarrage Rapide : Serveur (TypeScript)

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: '...' }))
}

Installation : npm install mppx viem (mppx 0.8.15 nécessite viem >= 2.54.0).

Validez que le serveur finalisé fonctionne de bout en bout avec npx mppx validate http://localhost:3000.

Démarrage Rapide : Client (TypeScript)

import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'

// Polyfill globalThis.fetch pour gérer automatiquement les codes 402
Mppx.create({
  methods: [tempo({ account: privateKeyToAccount('0x...') })],
})

const res = await fetch('https://api.example.com/paid')
// Le paiement s'effectue de manière transparente lorsque le serveur renvoie un code 402

Dans les navigateurs, mppx 0.6.0 a changé le comportement par défaut : le fetch polyfillé n'envoie Accept-Payment qu'aux endpoints de même origine, donc les API payantes cross-origin nécessitent acceptPaymentPolicy ('always' / { origins: [...] }). Le fetch client réessaie les challenges incrémentaux jusqu'à maxPaymentRetries (par défaut 3). Pour les alternatives non globales (Fetch.from/polyfill/restore, Mppx.restore()), voir references/typescript-sdk.md.

Démarrage Rapide : Serveur (Python)

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}

Installation : pip install "pympp[tempo]". Voir references/python-sdk.md pour les schémas complets.

Démarrage Rapide : Serveur (Rust)

Installation : cargo add mpp --features tempo,server. Voir references/rust-sdk.md pour les schémas complets.

Middleware de Framework (TypeScript)

Chaque framework a sa propre importation (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: '...' }))

Voir references/typescript-sdk.md pour les exemples avec Express et Elysia.

Sessions : Streaming à l'Utilisation (Pay-as-You-Go)

Les sessions ouvrent un canal de paiement une seule fois, puis utilisent des justificatifs hors chaîne pour chaque requête - pas de transaction blockchain par requête. Latence inférieure à 100 ms, frais par requête quasi nuls.

Sessions v2 (par défaut depuis mppx 0.7.0) : tempo.session() est le flux de canal précompilé TIP-1034 ; l'implémentation précédente par contrat de dépôt est la Sessions v1, toujours disponible via tempo.sessionLegacy (obsolète). Un client qui attend la v2 rejette une session v1 et retombe sur le chemin de charge, alors gardez le client et le serveur sur des flux correspondants. Deux API client : tempo.session({ account, maxDeposit }) enregistre la méthode avec Mppx.create() (gestion transparente du 402 via fetch), tandis que tempo.session.manager({ account, maxDeposit }) retourne un client géré pour un contrôle direct du cycle de vie (.sse(), .close()).

// Serveur - endpoint de session avec règlement automatique
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, // permet aux clients de retour de récupérer leur canal sur cette 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: '...' }))
// Serveur - streaming SSE avec facturation par mot
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 avec canal auto-géré
Mppx.create({ methods: [tempo({ account, maxDeposit: '1' })] })
const res = await fetch('http://localhost:3000/api/resource')
// 1ère requête : ouvre le canal on-chain ; 2ème et suivantes : justificatifs hors chaîne

Les sessions diffusent également en continu via WebSocket via Ws.serve(). Voir references/sessions.md pour le cycle de vie complet, le règlement, les magasins, les schémas SSE et WebSocket, et la récupération de canal.

Prise en Charge Multi-Méthodes

Acceptez les stablecoins Tempo, les cartes Stripe et le Bitcoin Lightning sur un seul 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! }),
  ],
})

Utilisez Mppx.compose() pour présenter plusieurs méthodes dans une seule réponse 402 avec une tarification par route. Appliquez la même branche sur le site du challenge et le site de vérification, ou le 402 annonce moins d'options que le serveur n'en accepte. Voir references/typescript-sdk.md.

Liens de Paiement (HTML)

En définissant html: true sur une configuration de méthode de paiement, une page de paiement compatible navigateur s'affiche lorsqu'un endpoint 402 est visité dans un navigateur, avec des thèmes, des onglets de composition multi-méthodes et la prise en charge du portefeuille Solana. Les service workers gèrent la soumission des credentials, puis la page se recharge avec la réponse payée.

Personnalisez via les exports mppx/html (Config, Text, Theme), et construisez le lien de paiement d'une méthode personnalisée avec Html.init(methodName).

Authentification Zéro-Dollar (Preuve de Credential)

Authentifiez l'identité d'un agent sans paiement. Les clients signent une preuve EIP-712 sur l'ID du challenge au lieu de créer une transaction - pas de gaz brûlé, pas de transfert de fonds.

// Serveur - charge zéro-dollar, avec un magasin pour la protection contre les rejeux
const mppx = Mppx.create({
  methods: [tempo.charge({ currency: '<PATHUSD_TESTNET>', recipient: '0x...', store })],
})
const result = await mppx.charge({ amount: '0' })(request)

Depuis mppx 0.8.0, ces preuves sont liées au portefeuille du payeur : les données typées EIP-712 Proof (exposées sous tempo.Proof) portent un champ account à la version de domaine 3, donc une preuve signée pour un compte ne se vérifie plus contre un autre.

Cas d'usage : vérification d'identité, interrogation de tâches de longue durée, déverrouillage payé avec accès gratuit ultérieur, pipelines d'agents multi-étapes. Voir mpp.dev/advanced/identity.

Proxy de Paiement

Protégez des API existantes derrière des paiements MPP :

// import { openai, Proxy } from 'mppx/proxy' - un service dans Proxy.create({ services: [...] })
openai({
  apiKey: process.env.OPENAI_API_KEY,
  routes: {
    'POST /v1/chat/completions': mppx.charge({ amount: '0.05' }),
    'GET /v1/models': true, // `true` littéral marque une route gratuite
  },
})

Préréglages intégrés openai(), anthropic(), stripe(), plus custom() pour n'importe quel service en amont. Voir references/discovery-and-proxy.md pour Proxy.create(), les endpoints de découverte qu'il sert, et l'assistant discovery() pour les serveurs non proxy.

Transport MCP

Les appels d'outils MCP peuvent exiger un paiement en utilisant le code d'erreur JSON-RPC -32042 (les serveurs peuvent également émettre -32043) :

// Serveur - importer tempo depuis mppx/server, PAS mppx/tempo
import { McpServer } from 'mppx/mcp/server'
import { tempo } from 'mppx/server'
const server = McpServer.wrap(baseServer, { methods: [tempo.charge({ /* ... */ })], secretKey })

// Client - client MCP compatible paiement (importer tempo depuis 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: {} })

Les challenges MCP-over-HTTP sont réglés dans le même fetch compatible paiement, et les transports sont enfichables via Transport.from/http/mcp/mcpSdk des deux côtés. Voir references/transports.md.

Portefeuilles Serveur Privy

createViemAccount depuis @privy-io/node/viem (nécessite @privy-io/node >= 0.20.0) retourne un Account viem soutenu par un portefeuille serveur Privy, donc il s'intègre dans tempo({ account }) partout où un compte local irait.

La signature côté serveur fonctionne avec des portefeuilles serveur appartenant à l'application ; les portefeuilles intégrés appartenant à l'utilisateur nécessitent des clés d'autorisation ou des quorums de clés. Voir references/typescript-sdk.md pour la configuration complète et la construction manuelle de toAccount().

Tests & CLI

# Créer un compte (stocké dans le trousseau de clés), puis l'alimenter sur le testnet
npx mppx account create
npx mppx account fund --network testnet

# Effectuer une requête payante
npx mppx http://localhost:3000/resource

# Analyser un challenge sans le signer
npx mppx sign --dry-run --challenge '<valeur www-authenticate>'

# Valider une implémentation de serveur de bout en bout
npx mppx validate http://localhost:3000

La CLI couvre également init, sessions (lister/voir/fermer), discover, services, mcp add et skills add. La configuration provient de MPPX_CONFIG ou d'un --config explicite - il n'y a pas de découverte automatique depuis le répertoire de travail. Référence complète : references/cli.md.

Paquets SDK

LangagePaquetInstallation
TypeScriptmppxnpm install mppx
Pythonpympppip install "pympp[tempo]"
Rustmppcargo add mpp --features tempo,client,server
Rubympp-rb (officiel, par Stripe)voir le dépôt pour le nom de la gem
Gompp-go (officiel, par Tempo)go get github.com/tempoxyz/mpp-go
Elixirmpp (communauté)hex.pm/packages/mpp
Swiftmpp-swift (communauté)voir le dépôt

Notes sur les capacités, vérifiées par rapport à la source du SDK plutôt qu'aux matrices de documentation (l'éditeur en publie deux qui se contredisent) :

  • Intention Session : TypeScript et Rust uniquement.
  • Preuves de Credential (authentification zéro-dollar) : TypeScript

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Skills associés