> ## Documentation Index
> Fetch the complete documentation index at: https://docs.algovoi.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# MPP (Method Payment Protocol)

> MPP charges per call for MCP tools and JSON-RPC methods. AlgoVoi is a registered multi-chain MPP service issuing per method, offline verifiable receipts.

## What is MPP

The [Method Payment Protocol](https://mpp.dev) 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](https://modelcontextprotocol.io) servers and structured RPC services.

AlgoVoi is registered in the public MPP services catalogue at [`mpp.dev`](https://mpp.dev) and can be discovered programmatically by MPP clients. The live server entry is also indexed on [MPPScan](https://www.mppscan.com/server/eb10b2d7fb1e2fcbea7a4c5b031e339daacc7cf37d1fb569c58849287c121633).

## Verifiable receipts for MPP

Every MPP method call AlgoVoi prices produces a deterministic, offline-verifiable per-method receipt
on the shared [JCS canonicalisation substrate](/canonicalisation-substrate): a categorical ALLOW /
REFER / DENY [compliance receipt](/compliance-receipt) at admission and a settlement attestation
on-chain, bound by the [`action_ref`](/canonicalisation-substrate) primitive. Anyone can recompute the
canonical bytes and verify the signature years later with the open [receipt verifier](/receipt-verifier),
with no live call to AlgoVoi and no customer PII.

See [Agentic Payment Receipts](/agentic-payment-receipts) for how this works across x402, AP2, A2A and
MPP.

## When to use MPP

<CardGroup cols={2}>
  <Card title="Monetised MCP tools">
    Sell access to a `database.query` or `web.scrape` tool inside an MCP server.
  </Card>

  <Card title="JSON-RPC paywalls">
    Charge per `eth_call` shadow on your archive node, per `getBlock` on your indexer.
  </Card>

  <Card title="Method-level pricing">
    Different prices for `read` versus `write` methods on the same service.
  </Card>

  <Card title="Agent-discoverable services">
    AI agents browsing the MPP registry and paying to use any service that fits.
  </Card>
</CardGroup>

## 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          |

Both protocols speak the same `Authorization: Payment` scheme on the wire. AlgoVoi accepts either on the same gateway.

## AgentCash

[AgentCash](https://agentcash.dev) 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

```bash theme={null}
# Discover what's available at the gateway
npx agentcash try https://api.algovoi.co.uk

# Pay a specific tenant resource (no API key needed)
npx agentcash fetch https://api.algovoi.co.uk/mpp/{tenant_short_id}/{resource_id} -m GET
```

### Deposit funds

```bash theme={null}
npx agentcash deposit
# Deposits USDCe to your AgentCash wallet address on Tempo mainnet
```

A successful payment returns a signed JWT receipt in the response body:

```json theme={null}
{
  "verified": true,
  "resource_id": "mpp-test-tempo",
  "access_token": "eyJhbGci...",
  "network": "tempo"
}
```

### Per-tenant discovery spec

Each tenant that has enabled public MPP access exposes a machine-readable resource list:

```
GET https://api.algovoi.co.uk/openapi-mpp/{tenant_short_id}.json
```

AgentCash and MPPScan can use this to enumerate all payable resources for that merchant.

## Keyless public route

AlgoVoi supports a **keyless public MPP route** — no `X-Tenant-Id` or `X-API-Key` required. The payment proof is the auth.

```
GET /mpp/{tenant_short_id}/{resource_id}
```

Tenants must opt in to this route (operators set `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 on `mpp.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](https://github.com/tempoxyz/mpp/pull/556).

### 2. Issue a challenge

Client calls a paid method without payment. Server returns a Challenge:

```json theme={null}
{
  "version": 1,
  "method": "database.query",
  "credentials": [
    {
      "scheme": "exact",
      "network": "base:mainnet",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "amount": "5000",
      "payTo": "0xMerchant…",
      "validUntil": 1777200300
    }
  ]
}
```

### 3. Pay and present credential

Client pays on-chain, builds a `Credential` referencing the tx, and retries:

```http theme={null}
POST /jsonrpc HTTP/1.1
Authorization: Payment <base64-credential>
Content-Type: application/json

{ "jsonrpc": "2.0", "method": "database.query", "params": {...}, "id": 1 }
```

AlgoVoi verifies the credential, marks the payment consumed, and forwards the call.

## Per-method pricing

A single MPP service can charge different prices for different methods:

```json theme={null}
{
  "id": "your-service",
  "methods": {
    "data.read":  { "price_microunits": "100",   "asset": "USDC" },
    "data.write": { "price_microunits": "10000", "asset": "USDC" }
  }
}
```

## Chain support

All 7 chains are supported. Each chain maps to a specific MPP method string and `methodDetails` shape per the [paymentauth.org](https://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](https://paymentauth.org/draft-tempo-charge-00)     | none — flat request object                              |
| Solana   | mainnet | `solana`   | [draft-solana-charge-00](https://paymentauth.org/draft-solana-charge-00)   | `network: "mainnet"`, `decimals: 6`                     |
| Solana   | devnet  | `solana`   | [draft-solana-charge-00](https://paymentauth.org/draft-solana-charge-00)   | `network: "devnet"`, `decimals: 6`                      |
| Stellar  | mainnet | `stellar`  | [draft-stellar-charge-00](https://paymentauth.org/draft-stellar-charge-00) | `network: "stellar:pubnet"`                             |
| Stellar  | testnet | `stellar`  | [draft-stellar-charge-00](https://paymentauth.org/draft-stellar-charge-00) | `network: "stellar:testnet"`                            |
| Base     | mainnet | `evm`      | [draft-evm-charge-00](https://paymentauth.org/draft-evm-charge-00)         | `chainId: 8453`, `credentialTypes: ["hash","permit2"]`  |
| Base     | sepolia | `evm`      | [draft-evm-charge-00](https://paymentauth.org/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"`                             |

Algorand, VOI, and Hedera are not yet in the paymentauth.org catalogue. AlgoVoi implements custom methods for each, following the same request/credential shape as `stellar` (CAIP-2 `methodDetails.network`, push-mode `txId` credential).

### Challenge example — Solana

```http theme={null}
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment realm="api.algovoi.co.uk", id="...", method="solana",
  intent="charge", expires="...", request="<base64url>"
```

Decoded `request` object:

```json theme={null}
{
  "amount": "1000000",
  "currency": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
  "recipient": "<payout_wallet>",
  "methodDetails": {
    "network": "mainnet",
    "decimals": 6
  }
}
```

### 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)                           | —                                            |

For AgentCash (Tempo mainnet), the CLI handles the full challenge-pay-retry loop automatically — see [AgentCash](#agentcash) above.

## 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 a `402` with subscription fields:

```http theme={null}
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment realm="api.algovoi.co.uk" method="algorand"
  intent="subscription"
  periodCount="1" periodUnit="month"
  subscriptionExpires="2027-05-12T00:00:00Z"
  amount="5000000" asset="31566704"
  receiver="ALGOVOI_WALLET"
  nonce="..." expires="..." request="<base64url>"
```

The agent signs an on-chain authority tx, then re-submits with `Authorization: Payment`. AlgoVoi verifies the authority tx inline **and executes the first-period charge on chain before returning** ([draft-payment-intent-subscription-00 §Activation](https://github.com/tempoxyz/mpp-specs/pull/230) 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](/concepts/recurring#idempotency).

On successful activation the gateway returns:

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private
Payment-Receipt: subscriptionId="gIom4-F_S4qDyD7Hq9EFjw", intent="subscription",
                 periodCount="1", periodUnit="month"

{
  "subscriptionId": "gIom4-F_S4qDyD7Hq9EFjw",
  "status": "active",
  "periodCount": 1,
  "periodUnit": "month",
  "nextDueAt": "2026-06-12T12:00:00Z",
  "expiresAt": "2027-05-12T00:00:00Z",
  "first_pull_tx_id": "0xabc..."
}
```

The `subscriptionId` is base64url-no-padding per [draft-payment-intent-subscription-00 §Subscription Identifier](https://github.com/tempoxyz/mpp-specs/pull/230); 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

```
(synchronous activation, atomic with first-period charge)
  authority verify  →  first-pull broadcast-accepted  →  active
                                                       →  402 (pull failed)

(post-activation, async)
  active  →  revoked   (first-pull dropped pre-finality)
          →  cancelled (operator or agent request)
          →  expired   (sub_expires_at reached)
```

Once `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](/concepts/recurring#mpp-subscriptions-agent-native-standing-authority) 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 the `payment_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

Each `PaymentLedgerEntry` 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)      |

The canonical payload locked into each hash includes: `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:

```
payment_ledger/000000001-000000250-<batch-sha256>.ndjson
```

Each `.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_address` of 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_id` are cryptographically bound to the tenant's `tenant_id` in 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 in `audit_chain_shipments` for cross-reference.
* **Regulatory retention**: minimum 5 years per UK MLRs Reg 40; AlgoVoi retains for 7 years (aligned with HMRC standard).

## See also

* [x402](/protocols/x402) for HTTP endpoints
* [AP2](/protocols/ap2) for Google's mandate-based agent commerce
* [A2A](/protocols/a2a) for x402 over the Agent-to-Agent transport
* [Tempo chain](/chains/tempo) for USDCe TIP-20 details
* [AlgoVoi on MPPScan](https://www.mppscan.com/server/eb10b2d7fb1e2fcbea7a4c5b031e339daacc7cf37d1fb569c58849287c121633) — live server entry and resource index
