mpp

July 11, 2026 ยท View on GitHub



Machine Payments Protocol



mpp

Rust SDK for the Machine Payments Protocol

Website Docs Crates.io License

MPP (the Machine Payments Protocol) is an open standard for machine-to-machine payments, co-authored by Tempo and Stripe. Paying for a resource over HTTP typically requires API keys, billing accounts, or checkout flows set up ahead of time. MPP lets any client, including an AI agent, an app, or a person, pay as part of the HTTP exchange using the native 402 Payment Required response.

This crate is the Rust SDK for MPP. It supports developers building either side of a paid HTTP exchange: servers that charge for access with Tempo or Stripe, and clients that automatically handle 402 payment challenges. Typical scenarios include gating an API behind per-call payments or building an agent that pays for tools or data as it works. See the quickstart for server and client patterns.

MPP SDKs

MPP has official SDKs in multiple languages:

LanguageRepository
Rustmpp-rs (this repository)
Gotempoxyz/mpp-go
Pythontempoxyz/pympp
TypeScriptwevm/mppx
Rubystripe/mpp-rb

Install

cargo add mpp

Quick Start

Server (Tempo)

use mpp::server::{Mpp, tempo, TempoConfig};

let mpp = Mpp::create(tempo(TempoConfig {
    recipient: "0x742d35Cc6634C0532925a3b844Bc9e7595f1B0F2",
}))?;

let challenge = mpp.charge("1")?;
let receipt = mpp.verify_credential(&credential).await?;

Server (Stripe)

use mpp::server::{Mpp, stripe, StripeConfig};

let mpp = Mpp::create_stripe(stripe(StripeConfig {
    secret_key: "sk_test_...",
    network_id: "internal",
    payment_method_types: &["card"],
    currency: "usd",
    decimals: 2,
}))?;

let challenge = mpp.stripe_charge("1")?;
let receipt = mpp.verify_credential(&credential).await?;

Client (Tempo)

use mpp::client::{PaymentMiddleware, TempoProvider};
use reqwest_middleware::ClientBuilder;

let provider = TempoProvider::new(signer, "https://rpc.moderato.tempo.xyz")?;
let client = ClientBuilder::new(reqwest::Client::new())
    .with(PaymentMiddleware::new(provider))
    .build();

// Requests now handle 402 automatically
let resp = client.get("https://mpp.dev/api/ping/paid").send().await?;

Client (Stripe)

use mpp::client::{Fetch, StripeProvider};
use mpp::protocol::methods::stripe::CreateTokenResult;

let provider = StripeProvider::new(|params| {
    Box::pin(async move {
        // Proxy SPT creation through your backend (requires Stripe secret key)
        let resp = reqwest::Client::new()
            .post("https://my-server.com/api/create-spt")
            .json(&params)
            .send().await?.json::<serde_json::Value>().await?;
        Ok(CreateTokenResult::from(resp["spt"].as_str().unwrap().to_string()))
    })
});

let resp = reqwest::Client::new()
    .get("https://api.example.com/paid")
    .send_with_payment(&provider)
    .await?;

WebSocket

use mpp::server::ws::{WsMessage, WsResponse};

// Server: parse incoming WS message, send challenge/receipt
let msg: WsMessage = serde_json::from_str(&text)?;
if let WsMessage::Credential { credential } = msg {
    let parsed = mpp::parse_authorization(&credential)?;
    let receipt = mpp.verify_credential(&parsed).await?;
    let resp = WsResponse::Receipt {
        receipt: serde_json::to_value(&receipt)?,
    };
    socket.send(resp.to_text()).await;
}

// Client: detect challenge, send credential
let msg: mpp::client::ws::WsServerMessage = serde_json::from_str(&text)?;
if let WsServerMessage::Challenge { challenge, .. } = msg {
    let cred_msg = serde_json::json!({
        "type": "credential",
        "credential": auth_string,
    });
    ws.send(cred_msg.to_string()).await;
}

WSS (WebSocket Secure) is handled at the connection layer. The transport itself is protocol-agnostic. On the server, terminate TLS via a reverse proxy (nginx, Cloudflare) or use axum-server with rustls. On the client, tokio-tungstenite supports wss:// URLs via its native-tls or rustls features:

tokio-tungstenite = { version = "0.26", features = ["rustls-tls-webpki-roots"] }

Feature Flags

FeatureDescription
clientClient-side payment providers (PaymentProvider trait, Fetch extension)
serverServer-side payment verification (ChargeMethod trait)
tempoTempo blockchain support (includes evm)
stripeStripe payment support via SPTs
evmShared EVM utilities (Address, U256, parsing)
middlewarereqwest-middleware support with PaymentMiddleware (implies client)
towerTower middleware for server-side integration
axumAxum extractor support for server-side convenience
wsWebSocket transport for bidirectional session payments
utilsHex/random utilities for development and testing

Payment Methods

MPP supports multiple payment methods through one protocol: Tempo, Stripe, Lightning, Card, and custom methods. The server advertises which methods it accepts, and the client chooses which one to pay with. This SDK implements Tempo (charge and session intents) and Stripe (charge intent via Shared Payment Tokens).

Protocol

Built on the "Payment" HTTP Authentication Scheme. The source specifications are maintained in tempoxyz/mpp-specs. See mpp.dev/protocol for the protocol overview or paymentauth.org for the wire format.

Contributing

git clone https://github.com/tempoxyz/mpp-rs
cd mpp-rs
cargo test

Security

See SECURITY.md for reporting vulnerabilities.

License

Licensed under either of Apache License, Version 2.0 or MIT License at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.