MPP Integration (Machine Payments Protocol)
March 30, 2026 · View on GitHub
What is MPP?
MPP (Machine Payments Protocol) is the open standard for machine-to-machine payments, co-authored by Stripe and Tempo. It standardizes HTTP 402 for automated agent-to-service payments.
Partners: Anthropic, OpenAI, DoorDash, Mastercard, Nubank, Revolut, Shopify, Standard Chartered, Visa, Ramp, Lightspark.
MPP and OpenAgentPay are complementary — MPP defines the wire protocol, OpenAgentPay adds the developer toolkit (policy engine, receipts, MCP adapter, multi-method support).
How MPP Works
MPP uses a Challenge-Credential-Receipt pattern over HTTP 402:
Agent → GET /api/data
Server → 402 + Challenge { challengeId, amount, networks: ['tempo', 'stripe'] }
Agent → Pays on selected network
Agent → GET /api/data + Authorization: <Credential>
Server → 200 + Receipt
Payment Networks
MPP supports multiple payment rails:
- Tempo — stablecoin payments on the Tempo blockchain (backed by Stripe + Paradigm)
- Stripe — card payments via Shared Payment Tokens (SPTs)
- Lightning — Bitcoin micropayments via BOLT11 invoices (via Lightspark)
Installation
pnpm add @openagentpay/adapter-mpp @openagentpay/core
Server: Accept MPP Payments
import { createPaywall } from '@openagentpay/server-express';
import { mpp } from '@openagentpay/adapter-mpp';
const paywall = createPaywall({
recipient: '0xYourAddress',
adapters: [mpp({
networks: ['tempo', 'stripe'],
secretKey: process.env.MPP_SECRET_KEY,
})],
});
app.get('/api/data', paywall({ price: '0.01' }), handler);
The adapter issues MPP Challenges in the 402 response and verifies Credentials on retry.
Client: Agent Pays via MPP
import { withPayment } from '@openagentpay/client';
import { mppWallet } from '@openagentpay/adapter-mpp';
const paidFetch = withPayment(fetch, {
wallet: mppWallet({
network: 'tempo',
privateKey: process.env.AGENT_WALLET_KEY,
}),
policy: { maxPerRequest: '1.00', maxPerDay: '50.00' },
});
const data = await paidFetch('https://api.example.com/data').then(r => r.json());
MPP Sessions — "OAuth for Money"
Sessions are MPP's key innovation. Instead of paying per-call, the agent authorizes a spending limit upfront. Thousands of micro-transactions are aggregated into a single settlement.
import { MPPSessionManager } from '@openagentpay/adapter-mpp';
const sessions = new MPPSessionManager({
network: 'tempo',
privateKey: process.env.AGENT_WALLET_KEY,
});
// Agent authorizes \$10 for this session
const session = await sessions.createSession({
maxAmount: '10.00',
currency: 'USD',
network: 'tempo',
recipient: '0xAPIProvider',
duration: '1h',
});
// Per-call charges against the session (no per-call auth)
await sessions.chargeSession(session.sessionId, '0.01');
await sessions.chargeSession(session.sessionId, '0.01');
// ...repeat thousands of times...
// Close session, refund unused balance
await sessions.closeSession(session.sessionId);
Streaming Payments
For long-running requests (LLM token generation, data processing), streaming payments charge incrementally against a session:
import { mpp, MPPAdapter } from '@openagentpay/adapter-mpp';
const adapter = mpp({
networks: ['tempo', 'stripe'],
sessionsSupported: true,
streamingSupported: true,
});
// Start a stream against an active session
const stream = await adapter.startStream({
sessionId: session.sessionId,
amountPerChunk: '0.0001',
currency: 'USD',
});
// Charge per chunk/token
for await (const chunk of generateTokens()) {
await adapter.chargeStreamChunk(stream.streamId, '0.0001');
yield chunk;
}
// End the stream
const meter = await adapter.endStream(stream.streamId);
// meter.chunksCharged, meter.totalCharged
IETF Payment Auth Scheme
OpenAgentPay's MPP adapter supports the IETF Payment HTTP auth scheme per draft-ryan-httpauth-payment:
// Server generates WWW-Authenticate header
const wwwAuth = adapter.buildWWWAuthenticate({
recipient: '0x...',
amount: '0.01',
currency: 'USD',
resource: '/api/data',
});
// → "Payment realm="0x...", challenge="base64...", networks="tempo,stripe", sessions=true, streaming=true"
// Receipt in response header
const receiptHeader = MPPAdapter.buildReceiptHeader({
id: 'mpp_receipt_123',
amount: '0.01',
currency: 'USD',
network: 'tempo',
status: 'settled',
ref: '0xabc...',
});
// → "Payment base64..."
Session-First Wallet
The MPP wallet can prefer sessions over per-call payments when available:
import { mppWallet } from '@openagentpay/adapter-mpp';
const wallet = mppWallet({
network: 'tempo',
tempoPrivateKey: process.env.KEY,
preferSessions: true, // auto-create sessions when available
defaultSessionBudget: '10.00', // \$10 per session
defaultSessionDuration: '1h', // 1 hour sessions
});
// When paying, wallet automatically creates/reuses sessions
// Falls back to per-call payment if sessions unavailable
MPP + OpenAgentPay Advantages
Using MPP through OpenAgentPay gives you:
- Policy engine — spend limits, domain rules, approval thresholds (MPP alone has none)
- Receipts — structured audit trail with query/export (MPP receipts are minimal)
- Multi-method — fall back to x402, credits, Stripe, PayPal if MPP isn't available
- MCP adapter — paid MCP tools work with MPP payments
- Subscriptions — OpenAgentPay's subscription system works alongside MPP sessions
Combining with Other Adapters
const paywall = createPaywall({
recipient: '0x...',
adapters: [
mpp({ networks: ['tempo', 'stripe'] }), // try MPP first
x402({ network: 'base' }), // fallback to x402
credits({ store }), // fallback to credits
],
});
The 402 response advertises all available methods. The agent picks the best one.