AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Mpp

skill-tenequm-skills-mpp · by tenequm

Build with MPP (Machine Payments Protocol) - the open protocol for machine-to-machine payments over HTTP 402. Use when developing paid APIs, payment-gated content, AI agent payment flows, MCP tool payments, pay-per-token streaming, or any service using HTTP 402 Payment Required. Covers the mppx TypeScript SDK with Hono/Express/Next.js/Elysia middleware, pympp Python SDK, and mpp Rust SDK. Support…

No reviews yet
0 installs
49 views
0.0% view→install

Install

$ agentstack add skill-tenequm-skills-mpp

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-tenequm-skills-mpp)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Mpp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

MPP - Machine Payments Protocol

MPP is an open protocol (co-authored by Tempo and Stripe) that standardizes HTTP 402 Payment Required for machine-to-machine payments. Clients pay in the same HTTP request - no accounts, API keys, or checkout flows needed.

The core protocol spec is submitted to the IETF as the Payment HTTP Authentication Scheme.

Tempo token addresses

Public Tempo token addresses referenced throughout this skill. Use the placeholder names in code; full addresses are in the Tempo documentation.

| Token | Network | Placeholder | |--------------------|----------|----------------------| | USDC.e (mainnet) | mainnet | ` | | pathUSD (testnet) | testnet | ` |

When to Use

  • Building a paid API that charges per request
  • Adding a paywall to endpoints or content
  • Enabling AI agents to pay for services autonomously
  • MCP tool calls that require payment
  • Pay-per-token streaming (LLM inference, content generation)
  • Session-based metered billing (pay-as-you-go)
  • Accepting stablecoins (Tempo), cards (Stripe), or Bitcoin (Lightning) for API access
  • Building a payments proxy to gate existing APIs (OpenAI, Anthropic, etc.)

Core Architecture

Three primitives power every MPP payment:

  1. Challenge - server-issued payment requirement (in WWW-Authenticate: Payment header)
  2. Credential - client-submitted payment proof (in Authorization: Payment header)
  3. Receipt - server confirmation of successful payment (in Payment-Receipt header)
Client                                          Server
  │  (1) GET /resource                            │
  ├──────────────────────────────────────────────>│
  │         (2) 402 + WWW-Authenticate: Payment   │
  ││
  │         (5) Verify + settle                   │
  │         (6) 200 OK + Payment-Receipt          │
  │', // 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: '...' }))
}

Install: npm install mppx viem

Quick Start: Client (TypeScript)

import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'

// Polyfills globalThis.fetch to handle 402 automatically
Mppx.create({
  methods: [tempo({ account: privateKeyToAccount('0x...') })],
})

const res = await fetch('https://api.example.com/paid')
// Payment happens transparently when server returns 402

In browsers, mppx 0.6.0 changed the default: polyfilled fetch only sends Accept-Payment to same-origin endpoints. For cross-origin paid APIs set acceptPaymentPolicy ('always' / { origins: [...] }). See references/typescript-sdk.md.

Quick Start: Server (Python)

from fastapi import FastAPI, Request
from mpp.server import Mpp
from mpp.methods.tempo import tempo, ChargeIntent

app = FastAPI()
mpp = Mpp.create(method=tempo(
    currency="",
    recipient="0xYourAddress", intents={"charge": ChargeIntent()},
))

@app.get("/resource")
async def get_resource(request: Request):
    result = await mpp.charge(authorization=request.headers.get("Authorization"), amount="0.50")
    if isinstance(result, Challenge):
        return JSONResponse(status_code=402, content={"error": "Payment required"},
            headers={"WWW-Authenticate": result.to_www_authenticate(mpp.realm)})
    return {"data": "paid content"}

Install: pip install "pympp[tempo]". See references/python-sdk.md for full patterns.

Quick Start: Server (Rust)

Install: cargo add mpp --features tempo,server. See references/rust-sdk.md for full patterns.

Framework Middleware (TypeScript)

Each framework has its own import (mppx/nextjs, mppx/hono, mppx/express, mppx/elysia):

// Next.js
import { Mppx, tempo } from 'mppx/nextjs'
const mppx = Mppx.create({ methods: [tempo({ currency: '0x20c0...', 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: '...' }))

See references/typescript-sdk.md for Express and Elysia examples.

Sessions: Pay-as-You-Go Streaming

Sessions open a payment channel once, then use off-chain vouchers for each request - no blockchain transaction per request. Sub-100ms latency, near-zero per-request fees.

// Server - session endpoint
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 with per-word billing
const mppx = Mppx.create({
  methods: [tempo({ currency: '0x20c0...', recipient: '0x...', sse: true })],
})
export const GET = mppx.session({ amount: '0.001', unitType: 'word' })(
  async () => {
    const words = ['hello', 'world']
    return async function* (stream) {
      for (const word of words) {
        await stream.charge()
        yield word
      }
    }
  }
)

// Client - session with auto-managed channel
import { Mppx, tempo } from 'mppx/client'
Mppx.create({
  methods: [tempo({ account, maxDeposit: '1' })], // Lock up to 1 pathUSD
})
const res = await fetch('http://localhost:3000/api/resource')
// 1st request: opens channel on-chain
// 2nd+ requests: off-chain vouchers (no on-chain tx)

WebSocket transport: Sessions also support WebSocket streaming via Ws.serve(). The WebSocket protocol uses typed messages (mpp: 'authorization', mpp: 'message', mpp: 'payment-close-request', etc.) for payment negotiation alongside data delivery. See references/sessions.md for the full session lifecycle, escrow contracts, SSE patterns, and WebSocket integration.

Multi-Method Support

Accept Tempo stablecoins, Stripe cards, and Lightning Bitcoin on a single endpoint:

import Stripe from 'stripe'
import { Mppx, tempo, stripe } from 'mppx/server'
import { spark } from '@buildonspark/lightning-mpp-sdk/server'

const mppx = Mppx.create({
  methods: [
    tempo({ currency: '0x20c0...', recipient: '0x...' }),
    stripe.charge({ client: new Stripe(key), networkId: 'internal', paymentMethodTypes: ['card'] }),
    spark.charge({ mnemonic: process.env.MNEMONIC! }),
  ],
})

Use compose() to present multiple methods in a single 402 response with per-route pricing. See references/typescript-sdk.md for compose patterns.

Payment Links (HTML)

Payment links render a browser-friendly payment UI when a 402 endpoint is visited in a browser. Set html: true on the payment method config. Supports theming, multi-method compose (Tempo + Stripe tabs), and Solana wallets.

import { Mppx, tempo } from 'mppx/nextjs'

const mppx = Mppx.create({
  methods: [tempo.charge({
    currency: '0x20c0...', recipient: '0x...',
    html: true, // auto-renders payment page for browsers
  })],
})
export const GET = mppx.charge({ amount: '0.1' })(() => Response.json({ data: '...' }))

Customize via mppx/html exports (Config, Text, Theme). Service workers handle credential submission - the page reloads with the paid response. For multi-method compose, tabs auto-switch between payment options.

Zero-Dollar Auth (Proof Credentials)

Authenticate agent identity without payment. Clients sign an EIP-712 proof over the challenge ID instead of creating a transaction - no gas burned, no funds transferred.

// Server - zero-dollar charge (amount: '0')
const result = await mppx.charge({ amount: '0' })(request)

// Enable replay protection (makes each proof single-use)
const mppx = Mppx.create({
  methods: [tempo.charge({ currency: '0x20c0...', recipient: '0x...', store: Store.memory() })],
})

Use cases: identity verification, long-running job polling (prove identity once, poll freely), paid unlock with free subsequent access, multi-step agent pipelines. See mpp.dev/advanced/identity for full patterns.

Payments Proxy

Gate existing APIs behind MPP payments:

import { openai, Proxy } from 'mppx/proxy'
import { Mppx, tempo } from 'mppx/server'

const mppx = Mppx.create({ methods: [tempo()] })
const proxy = Proxy.create({
  title: 'My API Gateway',
  description: 'Paid access to AI APIs',
  services: [
    openai({
      apiKey: 'sk-...', // pragma: allowlist secret
      routes: {
        'POST /v1/chat/completions': mppx.charge({ amount: '0.05' }),
        'GET /v1/models': mppx.free(), // mppx.free() marks a route as free (no payment)
      },
    }),
  ],
})
// Discovery: GET /openapi.json (x-payment-info document), plus live /discover, /discover/all, /llms.txt

MCP Transport

MCP tool calls can require payment using JSON-RPC error code -32042 (servers may also issue -32043):

// Server - MCP with payment (import tempo from mppx/server, NOT mppx/tempo)
import { McpServer } from 'mppx/mcp-sdk/server'
import { tempo } from 'mppx/server'
const server = McpServer.wrap(baseServer, {
  methods: [tempo.charge({ ... })],
  secretKey: '...',
})

// Client - payment-aware MCP client (import tempo from mppx/client)
import { McpClient } from 'mppx/mcp-sdk/client'
import { tempo } from 'mppx/client'
const mcp = McpClient.wrap(client, { methods: [tempo({ account })] })
const result = await mcp.callTool({ name: 'premium_tool', arguments: {} })

See references/transports.md for the full MCP encoding (challenge in error.data.challenges, credential in _meta).

Privy Server Wallets

Use Privy server wallets as MPP signers for agentic payment flows. The pattern: create a custom viem Account via toAccount() that delegates signMessage, signTransaction, and signTypedData to Privy's API (@privy-io/node), then pass it to tempo({ account }). Tempo's custom serializer requires using signSecp256k1 (raw hash signing) for transactions instead of Privy's higher-level signTransaction.

Install: npm install @privy-io/node mppx viem. See references/typescript-sdk.md for the full implementation, Privy agentic wallets docs, and the demo app.

Testing & CLI

# Create an account (stored in keychain, auto-funded on testnet)
npx mppx account create

# Make a paid request
npx mppx http://localhost:3000/resource

# Inspect challenge without paying
npx mppx --inspect http://localhost:3000/resource

CLI config file: Extend the CLI with custom payment methods via mppx.config.(js|mjs|ts):

// mppx.config.ts
import { defineConfig } from 'mppx/cli'
export default defineConfig({ plugins: [myCustomMethod()] })

SDK Packages

| Language | Package | Install | |----------|---------|---------| | TypeScript | mppx | npm install mppx | | Python | pympp | pip install pympp or pip install "pympp[tempo]" | | Rust | mpp | cargo add mpp --features tempo,client,server | | Ruby | mpp-rb (official, by Stripe) | see repo for gem name | | Go | mppx (community) | go get github.com/cp0x-org/mppx | | Elixir | mpp (community) | mix deps / hex.pm/packages/mpp |

Per the official SDK capability matrix, the session intent is implemented in TypeScript and Rust only; Python/Ruby/Go cover the charge intent (plus Stripe and fee sponsorship). Stellar uses @stellar/mpp (repo).

TypeScript subpath exports (mppx 0.6.30):

  • Server: mppx/server (generic), mppx/hono, mppx/express, mppx/nextjs, mppx/elysia (framework middleware)
  • Client: mppx/client
  • Proxy: mppx/proxy
  • Built-in methods: mppx/stripe (+ /client, /server), mppx/evm (+ /client, /server)
  • x402 interop: mppx/x402
  • MCP: mppx/mcp-sdk/server, mppx/mcp-sdk/client
  • HTML: mppx/html (exports Config, Text, Theme types and init() for payment link customization)
  • Discovery: mppx/discovery (OpenAPI-first discovery tooling)
  • CLI: mppx/cli, mppx/cli/plugins
  • SSE utilities: mppx/tempo (exports Session with Session.Sse.iterateData for SSE stream parsing)

Always import Mppx and tempo from the appropriate subpath for your context (e.g. mppx/hono for Hono, mppx/server for generic/MCP server, mppx/client for client). Note: Mppx and tempo are NOT exported from mppx/tempo - that subpath only exports Session.

Key Concepts

  • Challenge/Credential/Receipt: The three protocol primitives. Challenge IDs are HMAC-SHA256 bound to prevent tampering. See references/protocol-spec.md
  • Payment methods: Tempo (stablecoins), Stripe (cards), Lightning (Bitcoin), Card (network tokens), or custom. See method-specific references
  • Intents: charge (one-time) and session (streaming). See references/sessions.md for session details
  • Payment links: Browser-rendered 402 payment pages with html: true. Supports theming and multi-method compose tabs
  • Zero-dollar auth: proof credential type for identity without payment. Amount '0' triggers EIP-712 proof signing. Add store for replay protection
  • Split payments: Distribute a charge across multiple recipients in a single transaction (Tempo charge, 0.4.12+)
  • Subscriptions: Recurring access on Tempo via an authorized key - activation collects the first period, later requests reuse the key (no per-request payment), the server renews in the background (needs a durable store), and access is cancelled/revoked server-side. mppx.tempo.subscription (+ dev_second test periods)
  • Refunds: MPP defines no refund protocol. For charge, refund out-of-protocol by sending funds back to the payer's address. For session, refund by closing the channel - unspent escrow returns to the client
  • Transports: HTTP (headers), MCP (JSON-RPC), and WebSocket (streaming). See references/transports.md
  • Tempo gas model: Tempo has no native gas token (no ETH equivalent). All transaction fees are paid in stablecoins (USDC, pathUSD) via the feeToken transaction field. Accounts must either set feeToken per-transaction or call setUserToken on the FeeManager precompile to set a default. Without this, transactions fail with gas_limit: 0. See references/tempo-method.md
  • Fee sponsorship: Server pays gas fees on behalf of clients (Tempo). See references/tempo-method.md
  • Push/pull modes: Client broadcasts tx (push) or server broadcasts (pull). See references/tempo-method.md
  • Custom methods: Implement any payment rail with Method.from(). See references/custom-methods.md

Production Gotchas

Tempo Gas (CRITICAL)

Tempo has no native gas token. Unlike Ethereum (ETH for gas) or Solana (SOL for fees), Tempo charges transaction fees in stablecoins. Every transaction must specify which stablecoin pays for gas. There are two ways:

  1. Per-transaction feeToken - set in the transaction itself:
const prepared = await prepareTransactionRequest(client, {
  account,
  calls: [{ to, data }],
  feeToken: '', // USDC mainnet (see Tempo token addresses table)
} as never)
  1. Account-level default via setUserToken - one-time setup, applies to all future transactions:
import { setUserToken } from 'viem/tempo'
await client.fee.setUserTokenSync({
  token: '', // USDC mainnet
})

**Without either, transactions fai

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.