What is MPP
The Method Payment Protocol is an IETF-flavoured spec for attaching prices to JSON-RPC methods and MCP tools. Where x402 paywalls HTTP endpoints, MPP paywalls methods. That makes it the natural fit for Model Context Protocol servers and structured RPC services. AlgoVoi is registered in the public MPP services catalogue atmpp.dev and can be discovered programmatically by MPP clients. The live server entry is also indexed on MPPScan.
When to use MPP
Monetised MCP tools
Sell access to a
database.query or web.scrape tool inside an MCP server.JSON-RPC paywalls
Charge per
eth_call shadow on your archive node, per getBlock on your indexer.Method-level pricing
Different prices for
read versus write methods on the same service.Agent-discoverable services
AI agents browsing the MPP registry and paying to use any service that fits.
How MPP differs from x402
| x402 | MPP | |
|---|---|---|
| Granularity | Per HTTP endpoint | Per method (RPC or MCP tool) |
| Discovery | Walk endpoints | Public registry at mpp.dev |
| Auth header | Authorization: Payment … | Authorization: Payment … |
| Challenge format | payment_requirements JSON | Challenge object with method name |
| Best for | REST APIs and content paywalls | RPC services and MCP tools |
Authorization: Payment scheme on the wire. AlgoVoi accepts either on the same gateway.
AgentCash
AgentCash is the reference CLI client for MPP over Tempo mainnet. It holds a USDCe wallet, handles the full challenge-pay-retry loop, and needs no API key or configuration to call any AlgoVoi-hosted MPP resource.Discover and call with one command
Deposit funds
Per-tenant discovery spec
Each tenant that has enabled public MPP access exposes a machine-readable resource list:Keyless public route
AlgoVoi supports a keyless public MPP route — noX-Tenant-Id or X-API-Key required. The payment proof is the auth.
mpp_public_enabled in the dashboard). When a tenant is not enabled or a resource doesn’t exist, the response is a cloaked 404 regardless of the reason.
| Route | Auth |
|---|---|
GET /mpp/{resource_id} | X-Tenant-Id + X-API-Key (server-to-server) |
GET /mpp/{tenant_short_id}/{resource_id} | Authorization: Payment proof only — no API key |
Quickstart
1. Register your service
Define a service entry that points at your MPP-paywalled methods. AlgoVoi can register the entry onmpp.dev for you, or you can self-publish.
Service definitions live in schemas/services.ts upstream. AlgoVoi’s own entry is published there as the canonical reference. See PR #556.
2. Issue a challenge
Client calls a paid method without payment. Server returns a Challenge:3. Pay and present credential
Client pays on-chain, builds aCredential referencing the tx, and retries:
Per-method pricing
A single MPP service can charge different prices for different methods:Chain support
All 7 chains are supported. Each chain maps to a specific MPP method string andmethodDetails shape per the paymentauth.org draft specifications. Configure the chain per-tenant in the dashboard; the gateway emits the correct challenge automatically.
Network reference
| Chain | Network | Method | Spec | methodDetails |
|---|---|---|---|---|
| Tempo | mainnet | tempo | draft-tempo-charge-00 | none — flat request object |
| Solana | mainnet | solana | draft-solana-charge-00 | network: "mainnet", decimals: 6 |
| Solana | devnet | solana | draft-solana-charge-00 | network: "devnet", decimals: 6 |
| Stellar | mainnet | stellar | draft-stellar-charge-00 | network: "stellar:pubnet" |
| Stellar | testnet | stellar | draft-stellar-charge-00 | network: "stellar:testnet" |
| Base | mainnet | evm | draft-evm-charge-00 | chainId: 8453, credentialTypes: ["hash","permit2"] |
| Base | sepolia | evm | draft-evm-charge-00 | chainId: 84532, credentialTypes: ["hash","permit2"] |
| Algorand | mainnet | algorand | AlgoVoi extension | network: "algorand:mainnet" |
| Algorand | testnet | algorand | AlgoVoi extension | network: "algorand:testnet" |
| VOI | mainnet | voi | AlgoVoi extension | network: "voi:mainnet" |
| VOI | testnet | voi | AlgoVoi extension | network: "voi:testnet" |
| Hedera | mainnet | hedera | AlgoVoi extension | network: "hedera:mainnet" |
| Hedera | testnet | hedera | AlgoVoi extension | network: "hedera:testnet" |
stellar (CAIP-2 methodDetails.network, push-mode txId credential).
Challenge example — Solana
request object:
Credential shapes by method
| Method | Push credential | Pull credential |
|---|---|---|
tempo | payload.hash (EVM tx hash) | payload.transaction (RLP signed tx) |
solana | payload.signature (base58 tx sig) | payload.transaction (base64 serialised tx) |
stellar | payload.hash (64-char hex tx hash) | payload.transaction (base64 XDR) |
evm | payload.hash (0x tx hash) or payload permit2 object | payload.transaction (RLP signed tx) |
algorand | payload.txId (base64 tx ID) | — |
voi | payload.txId (base64 tx ID) | — |
hedera | payload.txId (Hedera tx ID) | — |
Subscriptions — intent="subscription"
In addition to per-call charges (intent="charge"), MPP supports subscription intent — a one-time authority tx that grants AlgoVoi standing permission to pull a fixed amount each period.
How it differs from per-call charges
intent="charge" | intent="subscription" | |
|---|---|---|
| Payment per call | Yes — agent pays each time | No — authority is granted once |
| Agent involvement after setup | Every call | None — AlgoVoi pulls autonomously |
| On-chain tx | Payment tx | Authority (approve/allowance) tx |
| Use case | Metered API calls | Periodic tool access, data feeds |
Subscription challenge
When a resource is configured for subscription billing, the gateway returns a402 with subscription fields:
Authorization: Payment. AlgoVoi verifies the authority tx inline and executes the first-period charge on chain before returning (draft-payment-intent-subscription-00 §Activation L396-407). Activation succeeds only when the first pull is broadcast-accepted; the response carries status: "active", a base64url subscriptionId, a first_pull_tx_id, and a Payment-Receipt header. Clients may include an Idempotency-Key header on retries to get the cached response instead of a replay rejection — see Recurring payments — Idempotency.
On successful activation the gateway returns:
subscriptionId is base64url-no-padding per draft-payment-intent-subscription-00 §Subscription Identifier; internally it remains a 16-byte UUID, so it round-trips losslessly. first_pull_tx_id is the on-chain tx that collected the first period; a background finality monitor watches it until per-chain confirmation depth is reached and flips the subscription to status: "revoked" if the tx is orphaned before finality.
If the first-period charge can’t be collected (insufficient allowance, wallet balance, etc.) the gateway returns 402 Payment Required rather than activating — the agent retries with a fresh challenge after resolving the cause. A facilitator-side timeout returns 504.
Subscription routes
| Route | Auth | Purpose |
|---|---|---|
GET /mpp/sub/{resource_id} | X-Tenant-Id + X-API-Key | Server-to-server subscription setup |
GET /mpp/sub/{tenant_short_id}/{resource_id} | Authorization: Payment only | Keyless agent subscription setup |
Lifecycle
active, AlgoVoi’s pull reaper fires every 120 seconds and executes each subsequent period’s pull autonomously (the first period was already charged at activation). The agent receives no further prompts.
See Recurring payments — MPP subscriptions for the full lifecycle, wire format, and resource setup details.
Audit trail & B2 retention
Every MPP payment — regardless of which route or client is used — is recorded in thepayment_ledger table and shipped to Backblaze B2 Object Lock storage. Both paths converge on the same internal function before any response is returned.
| Route | Client | Storage path |
|---|---|---|
GET /mpp/{resource_id} with X-Tenant-Id + X-API-Key | Server-to-server (native code, SDK) | payment_ledger → dashboard Payments tab → B2 |
GET /mpp/{tenant_short_id}/{resource_id} with Authorization: Payment | AgentCash, MPP clients (no API key) | payment_ledger → dashboard Payments tab → B2 |
Hash chain
EachPaymentLedgerEntry row receives three tamper-evidence fields at insert time:
| Field | Description |
|---|---|
chain_position | Monotonically increasing sequence across all MPP payments |
content_hash | SHA-256 of the RFC-8785 canonical JSON of the row’s immutable fields |
prev_hash | content_hash of the previous row (64 zeros for the first row) |
tenant_id, resource_id, tx_id, chain, asset_id, amount_microunits, verified_at, payer_address, and status. These fields cannot be altered post-insert without breaking the chain.
B2 Object Lock shipping
A background reaper (running every ~5 minutes) batches new chained rows and ships them to B2:.ndjson file contains the full canonical payload for every row in the batch, including content_hash and prev_hash, so external auditors can independently recompute and verify the chain. Files are written in COMPLIANCE mode Object Lock — immutable and undeletable for 7 years.
What this means for your integration
- Keyless (AgentCash) payments: the
payer_addressof the AgentCash wallet is captured in the B2 record at the moment of payment. GDPR erasure after 90 days applies to the live database copy; the WORM copy is permanent per UK MLRs Reg 40. - Key-authenticated payments: same guarantee — the calling tenant and the on-chain
tx_idare cryptographically bound to the tenant’stenant_idin the chain. - Dispute resolution: tenants can request the B2 batch files for any time range from
security@algovoi.co.uk. The batch SHA-256 is recorded inaudit_chain_shipmentsfor cross-reference. - Regulatory retention: minimum 5 years per UK MLRs Reg 40; AlgoVoi retains for 7 years (aligned with HMRC standard).
See also
- x402 for HTTP endpoints
- AP2 for Google’s mandate-based agent commerce
- A2A for x402 over the Agent-to-Agent transport
- Tempo chain for USDCe TIP-20 details
- AlgoVoi on MPPScan — live server entry and resource index