Was macht MPP - Machine Payments Protocol (Maschinenzahlungsprotokoll)?
MPP ist ein offenes Protokoll (unter Mitwirkung von Tempo und Stripe), das HTTP 402 Payment Required für Maschine-zu-Maschine-Zahlungen standardisiert. Clients bezahlen in derselben HTTP-Anfrage - keine Konten, API-Schlüssel oder Checkout-Flüsse erforderlich.
Die Kernprotokollspezifikation wurde bei der IETF als Payment HTTP Authentication Scheme eingereicht.
Der Code in dieser Fähigkeit verwendet Platzhalter-Token-Namen (<USDC_TEMPO_MAINNET>, <PATHUSD_TESTNET>); die echten Adressen befinden sich in der Tempo-Dokumentation und in references/tempo-method.md.
Kernarchitektur
Drei Primitive treiben jede MPP-Zahlung an:
- Challenge - vom Server ausgestellte Zahlungsanforderung (im
WWW-Authenticate: Payment-Header) - Credential - vom Client vorgelegter Zahlungsbeleg (im
Authorization: Payment-Header) - Receipt - Bestätigung des Servers über erfolgreiche Zahlung (im
Payment-Receipt-Header)
Zahlungsmethoden & Intents
MPP ist zahlungsmethodenunabhängig. Jede Methode definiert ihre eigene Abwicklungsschiene:
| Methode | Schiene | SDK-Paket | Status |
|---|---|---|---|
| Tempo | TIP-20 Stablecoins auf der Tempo-Chain | mppx (integriert) | Produktion |
| Stripe | Karten/Wallets (SPT) + On-Chain-Krypto-Einzahlung | mppx (integriert) | Produktion |
| EVM | EIP-3009 Stablecoin-Autorisierungen (x402-exact kompatibel) | mppx (integriert) | Produktion |
| Lightning | Bitcoin über das Lightning Network | @buildonspark/lightning-mpp-sdk | Produktion |
| Stellar | SEP-41-Token auf Stellar, Charge + channel | @stellar/mpp | Produktion (channel-Wire-Spezifikation noch in Arbeit - Änderungen vorbehalten) |
| Solana | Solana-native Charge + Session (SOL, SPL, Token-2022) | @solana/mpp | Produktion |
| Monad | Monad Charge (ERC-3009, Abwicklungsmodi) | @monad-crypto/mpp | Produktion |
| NEAR Intents | Cross-Chain Charge über 1Click-Einzahlungsadressen | @defuse-protocol/nearintents-mpp-sdk | Produktion (nicht vertrauenslos - leitet über ein Abwicklungs-Backend, beworben als methodDetails.settlementBackend: "near-intents" für methodenspezifische Risikorichtlinien) |
| RedotPay | RedotPay-Guthaben (rdt) oder Stablecoin-Nachweis, nur Charge | @redotpay/mpp | Produktion |
| Karte | Verschlüsselte Netzwerk-Token (Visa) | mpp-card | Produktion |
| Benutzerdefiniert | Jede Schiene | Method.from() + Method.toClient/toServer | Erweiterbar |
Tiefergehende Informationen zu den einzelnen Methoden: references/tempo-method.md, references/stripe-method.md, references/lightning-method.md, references/custom-methods.md.
| Intent | Muster | Am besten geeignet für |
|---|---|---|
| charge | Einmalzahlung pro Anfrage | API-Aufrufe, Inhaltszugriff, Festpreis-Endpunkte |
| session | Pay-as-you-go über Zahlungskanäle | LLM-Streaming, verbrauchsabhängige Abrechnung, hochfrequente APIs |
| subscription | Wiederkehrender Zugriff über einen autorisierten Schlüssel (Tempo) - siehe references/subscriptions.md | Pläne/Stufen, bei denen der Zugriff von der Abrechnung pro Anfrage getrennt ist |
Schnellstart: Server (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 erfordert viem >= 2.54.0).
Validiere den fertigen Server Ende-zu-Ende mit npx mppx validate http://localhost:3000.
Schnellstart: Client (TypeScript)
import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'
// Polyfillt globalThis.fetch, um 402 automatisch zu behandeln
Mppx.create({
methods: [tempo({ account: privateKeyToAccount('0x...') })],
})
const res = await fetch('https://api.example.com/paid')
// Die Zahlung erfolgt transparent, wenn der Server 402 zurückgibt
In Browsern hat mppx 0.6.0 den Standard geändert: Der polyfillierte fetch sendet Accept-Payment nur an gleichen Ursprung (Same-Origin)-Endpunkte, daher benötigen Cross-Origin-kostenpflichtige APIs acceptPaymentPolicy ('always' / { origins: [...] }). Client-Fetch wiederholt inkrementelle Challenges bis zu maxPaymentRetries (Standard 3). Für nicht-globale Alternativen (Fetch.from/polyfill/restore, Mppx.restore()) siehe references/typescript-sdk.md.
Schnellstart: Server (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]". Siehe references/python-sdk.md für vollständige Muster.
Schnellstart: Server (Rust)
Installation: cargo add mpp --features tempo,server. Siehe references/rust-sdk.md für vollständige Muster.
Framework-Middleware (TypeScript)
Jedes Framework hat seinen eigenen 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: '...' }))
Siehe references/typescript-sdk.md für Express- und Elysia-Beispiele.
Sessions: Pay-as-You-Go-Streaming
Sessions öffnen einmalig einen Zahlungskanal und verwenden dann Off-Chain-Gutscheine für jede Anfrage - keine Blockchain-Transaktion pro Anfrage. Sub-100ms Latenz, nahezu keine Gebühren pro Anfrage.
Sessions v2 (Standard seit mppx 0.7.0): tempo.session() ist der TIP-1034-Precompile-Kanalablauf; die frühere Escrow-Vertragsimplementierung ist Sessions v1, weiterhin verfügbar als das veraltete tempo.sessionLegacy. Ein v2-erwartender Client lehnt eine v1-Session ab und fällt auf den Charge-Pfad zurück. Halte daher Client und Server auf übereinstimmenden Abläufen. Zwei Client-APIs: tempo.session({ account, maxDeposit }) registriert die Methode mit Mppx.create() (transparente 402-Behandlung über fetch), während tempo.session.manager({ account, maxDeposit }) einen verwalteten Client für die direkte Lebenszyklussteuerung zurückgibt (.sse(), .close()).
// Server - Session-Endpunkt mit automatischer Abrechnung
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, // wiederkehrenden Clients erlauben, ihren Kanal auf dieser Route wiederherzustellen
})],
})
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 mit Abrechnung pro Wort
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 mit automatisch verwaltetem Kanal
Mppx.create({ methods: [tempo({ account, maxDeposit: '1' })] })
const res = await fetch('http://localhost:3000/api/resource')
// 1. Anfrage: öffnet Kanal on-chain; 2. und folgende: Off-Chain-Gutscheine
Sessions streamen auch über WebSocket via Ws.serve(). Siehe references/sessions.md für den vollständigen Lebenszyklus, Abrechnung, Stores, SSE- und WebSocket-Muster und Kanalwiederherstellung.
Multi-Methoden-Unterstützung
Akzeptiere Tempo-Stablecoins, Stripe-Karten und Lightning-Bitcoin an einem einzigen Endpunkt:
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! }),
],
})
Verwende Mppx.compose(), um mehrere Methoden in einer einzigen 402-Antwort mit routenabhängigen Preisen darzustellen. Wende denselben Zweig an der Challenge-Stelle und der Verifizierungsstelle an, sonst bewirbt die 402-Antwort weniger Optionen, als der Server akzeptiert. Siehe references/typescript-sdk.md.
Zahlungslinks (HTML)
Durch Setzen von html: true in einer Zahlungsmethodenkonfiguration wird eine browserfreundliche Zahlungsseite gerendert, wenn ein 402-Endpunkt in einem Browser besucht wird, mit Theming, Multi-Methoden-Compose-Tabs und Solana-Wallet-Unterstützung. Service Worker übernehmen die Übermittlung von Anmeldeinformationen, dann wird die Seite mit der bezahlten Antwort neu geladen.
Anpassbar über mppx/html-Exporte (Config, Text, Theme) und erstelle den Zahlungslink einer benutzerdefinierten Methode mit Html.init(methodName).
Zero-Dollar-Authentifizierung (Beleg-Anmeldeinformationen)
Authentifiziere die Agentenidentität ohne Zahlung. Clients signieren einen EIP-712-Nachweis über die Challenge-ID, anstatt eine Transaktion zu erstellen - kein Gas verbraucht, keine Gelder übertragen.
// Server - Zero-Dollar-Charge mit einem Store für Replay-Schutz
const mppx = Mppx.create({
methods: [tempo.charge({ currency: '<PATHUSD_TESTNET>', recipient: '0x...', store })],
})
const result = await mppx.charge({ amount: '0' })(request)
Seit mppx 0.8.0 sind diese Nachweise an die Zahler-Wallet gebunden: Die EIP-712 Proof typisierten Daten (verfügbar als tempo.Proof) führen ein account-Feld bei Domain-Version 3, sodass ein für ein Konto signierter Nachweis nicht mehr gegen ein anderes verifiziert werden kann.
Anwendungsfälle: Identitätsüberprüfung, Abfrage langlaufender Jobs, kostenpflichtige Freischaltung mit anschließendem kostenlosem Zugriff, mehrstufige Agenten-Pipelines. Siehe mpp.dev/advanced/identity.
Zahlungs-Proxy
Schütze bestehende APIs hinter MPP-Zahlungen:
// import { openai, Proxy } from 'mppx/proxy' - ein Dienst innerhalb von 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` markiert eine kostenlose Route
},
})
Integrierte Voreinstellungen openai(), anthropic(), stripe(), plus custom() für jeden Upstream. Siehe references/discovery-and-proxy.md für Proxy.create(), die bereitgestellten Discovery-Endpunkte und den discovery()-Helfer für Nicht-Proxy-Server.
MCP-Transport
MCP-Toolaufrufe können Zahlungen unter Verwendung des JSON-RPC-Fehlercodes -32042 erfordern (Server können auch -32043 ausgeben):
// Server - importiere tempo von mppx/server, NICHT von mppx/tempo
import { McpServer } from 'mppx/mcp/server'
import { tempo } from 'mppx/server'
const server = McpServer.wrap(baseServer, { methods: [tempo.charge({ /* ... */ })], secretKey })
// Client - Zahlungsbewusster MCP-Client (importiere tempo von 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 werden im selben zahlungsbewussten Fetch abgewickelt, und Transporte sind über Transport.from/http/mcp/mcpSdk auf beiden Seiten steckbar. Siehe references/transports.md.
Privy Server Wallets
createViemAccount von @privy-io/node/viem (erfordert @privy-io/node >= 0.20.0) gibt ein viem Account zurück, das von einem Privy-Server-Wallet unterstützt wird, sodass es in tempo({ account }) überall dort eingesetzt werden kann, wo ein lokales Konto stehen würde.
Serverseitiges Signieren funktioniert mit app-eigenen Server-Wallets; benutzereigene Embedded Wallets erfordern Autorisierungsschlüssel oder Schlüssel-Quoren. Siehe references/typescript-sdk.md für die vollständige Einrichtung und die manuelle toAccount()-Konstruktion.
Testen & CLI
# Ein Konto erstellen (im Keychain gespeichert), dann auf dem Testnetz finanzieren
npx mppx account create
npx mppx account fund --network testnet
# Eine kostenpflichtige Anfrage stellen
npx mppx http://localhost:3000/resource
# Eine Challenge parsen, ohne sie zu signieren
npx mppx sign --dry-run --challenge '<www-authenticate value>'
# Eine Server-Implementierung Ende-zu-Ende validieren
npx mppx validate http://localhost:3000
Die CLI deckt auch init, sessions (auflisten/anschließen/schließen), discover, services, mcp add und skills add ab. Die Konfiguration stammt aus MPPX_CONFIG oder einem expliziten --config - es gibt keine automatische Erkennung aus dem Arbeitsverzeichnis. Vollständige Referenz: references/cli.md.
SDK-Pakete
| Sprache | Paket | Installation |
|---|---|---|
| TypeScript | mppx | npm install mppx |
| Python | pympp | pip install "pympp[tempo]" |
| Rust | mpp | cargo add mpp --features tempo,client,server |
| Ruby | mpp-rb (offiziell, von Stripe) | siehe Repo für Gem-Namen |
| Go | mpp-go (offiziell, von Tempo) | go get github.com/tempoxyz/mpp-go |
| Elixir | mpp (Community) | hex.pm/packages/mpp |
| Swift | mpp-swift (Community) | siehe Repo |
Funktionshinweise, geprüft gegen SDK-Quelle anstelle der Dokumentationsmatrizen (Upstream veröffentlicht zwei, die sich widersprechen):
- Session Intent: Nur TypeScript und Rust.
- Proof Credentials (Zero-Dollar-Authentifizierung): Nur TypeScript
...
[gekürzt für die Übersetzung]