███╗ ███╗ ██████╗ ██████╗
████╗ ████║ ██╔══██╗██╔══██╗
██╔████╔██║ ██████╔╝██████╔╝
██║╚██╔╝██║ ██╔═══╝ ██╔═══╝
██║ ╚═╝ ██║ ██║ ██║ ██╗███╗ ██╗███████╗██████╗ ███████╗ ██████╗████████╗ ██████╗ ██████╗
╚═╝ ╚═╝ ╚═╝ ╚═╝ ██║████╗ ██║██╔════╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗
██║██╔██╗ ██║███████╗██████╔╝█████╗ ██║ ██║ ██║ ██║██████╔╝
██║██║╚██╗██║╚════██║██╔═══╝ ██╔══╝ ██║ ██║ ██║ ██║██╔══██╗
██║██║ ╚████║███████║██║ ███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║
╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
Postman for HTTP 402 — the missing devtool for the Machine Payments Protocol
MPP Inspector is a lightweight CLI toolkit that speaks the Machine Payments Protocol natively. It intercepts 402 Payment Required responses, parses WWW-Authenticate: Payment challenge headers per the IETF Payment HTTP Authentication Scheme, and supports all 6 MPP payment methods — all from your terminal.
No browser. No GUI. No friction. Just raw protocol inspection.
GET /v1/data HTTP/1.1
Host: api.example.com
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment id="qB3wErTyU7iOpAsD9fGhJk",
realm="mpp.dev",
method="tempo",
intent="charge",
expires="2025-01-15T12:05:00Z",
request="eyJhbW91bnQiOiIxMDAwIiwiY3VycmVuY3kiOiJ1c2QifQ"
MPP Inspector catches that. Decodes the request payload. Verifies the fields. Drives it.
| Command | What it does | Status |
|---|---|---|
inspect <url> |
Dissect a 402 challenge — decode request base64url payload, verify fields, show payment method |
Stable |
flow <url> |
Run the full 402 -> sign -> pay -> receipt cycle end-to-end |
Preview |
validate [input] |
Decode and verify a base64-encoded MPP receipt or credential (--credential) |
Stable |
scan <domain> |
Discover endpoints via /.well-known/mpp.json and /llms.txt |
Stable |
compare <urls...> |
Side-by-side pricing diff across multiple MPP services, grouped by payment method | Stable |
benchmark <url> |
Load-test an MPP endpoint with configurable concurrency | Preview |
session <url> |
Test payment-channel / streaming session lifecycle | Preview |
Every command supports --json for machine-readable output and --timeout <ms>.
MPP Inspector understands all 6 payment methods defined by the protocol:
| Method | Status | What MPP Inspector does |
|---|---|---|
| Tempo | Full support | Decodes request payload, validates recipient address, resolves chain (42431/42432), identifies pathUSD token |
| Stripe | Parsed | Decodes request payload, identifies SPT-based card payment, skips blockchain-specific validation |
| Lightning | Parsed | Decodes request payload, identifies BOLT11 invoice fields |
| Solana | Parsed | Decodes request payload, identifies SOL/SPL token fields |
| Card | Parsed | Decodes request payload, identifies encrypted network token fields |
| Custom | Parsed | Decodes any request payload, displays raw fields |
The parser is method-aware: blockchain methods (Tempo, Lightning, Solana) get address validation; non-blockchain methods (Stripe, Card) skip it. Unknown methods are displayed without errors.
The MPP protocol is well-specified. The SDKs exist for building. But there are no official devtools for inspecting, debugging, or exploring the protocol at the wire level. That's the exact gap this fills.
When a developer is implementing MPP on either side (client or server), they need to see the raw challenge fields: is the WWW-Authenticate: Payment header well-formed? Is the request payload decodable? Is the payment method correct? Is the expiry sane? The official SDKs abstract this away by design — great for production, terrible for debugging. inspect is the equivalent of Chrome DevTools' Network tab, but specifically for MPP's 402 flow.
The protocol defines /.well-known/mpp.json and mentions llms.txt, but there's no official tool to discover what a domain supports. As the agent economy grows, developers building autonomous agents need to programmatically discover which endpoints accept payments, what they charge, and what payment methods they support. This is nmap for the MPP surface.
As competing services emerge — multiple LLM providers, multiple data APIs, all accepting MPP — developers and agents need to compare pricing across providers. No official tool does side-by-side pricing diffs, grouped by payment method. This becomes increasingly valuable as the ecosystem scales.
When a payment flow breaks, you need to decode and verify receipts and credentials outside your application code. The protocol has specific structures for both, and being able to validate them from the terminal is essential for debugging production issues. Use --credential to parse the credential format (challenge + source + payload).
The full 402 -> parse -> sign -> pay -> retry -> 200 cycle, step by step, with timing. This is the best way to verify whether an MPP integration actually works before shipping to production. The --dry-run mode is particularly valuable — it validates everything without spending real money.
MPP adds a multi-step flow on top of normal HTTP. How does an MPP server perform under concurrent load? What are the p50/p95/p99 latencies of the full payment cycle? No other tool measures this.
The @mpp-inspector/mock-server package lets anyone develop MPP clients locally without needing a Tempo testnet wallet, real tokens, or a live MPP service. It returns spec-compliant 402 challenges with id, realm, method, request (base64url), supports multiple payment methods (Tempo + Stripe), and returns receipts — all locally.
Official MPP SDKs MPP Inspector You
+------------------+ +------------------+ +------------------+
| Build servers | | Inspect, debug | | Ship with |
| Build clients | ---> | Discover, scan | ---> | confidence |
| Handle payments | | Compare, bench | | |
+------------------+ | Mock & test | +------------------+
+------------------+
# install globally
npm install -g mpp-inspector
# ...or run without installing
npx mpp-inspector <command>The official MPP docs provide a live test endpoint at https://mpp.dev/api/ping/paid:
# inspect a real 402 challenge from mpp.dev
mpp-inspector inspect https://mpp.dev/api/ping/paid
# scan mpp.dev for endpoints
mpp-inspector scan mpp.dev
# dry-run the full payment flow
mpp-inspector flow https://mpp.dev/api/ping/paid --dry-runNo live MPP endpoint needed — spin up the built-in mock server and start inspecting:
# terminal 1: start the mock server
npx @mpp-inspector/mock-server
# terminal 2: inspect a Tempo endpoint
mpp-inspector inspect http://localhost:3402/v1/query
# inspect a Stripe endpoint
mpp-inspector inspect http://localhost:3402/v1/premium
# discover all endpoints
mpp-inspector scan localhost:3402
# compare pricing across payment methods
mpp-inspector compare http://localhost:3402/v1/query http://localhost:3402/v1/search http://localhost:3402/v1/premium
# dry-run payment flow
mpp-inspector flow http://localhost:3402/v1/query --dry-rungit clone https://github.com/amgb20/MPP-Inspector.git
cd mpp-inspector && npm install
# build everything
npm run build # build CLI
cd packages/mock-server && npx tsup && cd ../.. # build mock server
# link CLI globally for easy access
cd packages/cli && npm link && cd ../..
# start mock server
node packages/mock-server/dist/bin/mpp-mock-server.js
# in another terminal, test commands
mpp-inspector inspect http://localhost:3402/v1/query
mpp-inspector scan localhost:3402| Task | curl |
mpp-inspector |
|---|---|---|
| Hit an endpoint and see the 402 | curl -sI https://api.example.com/v1/query |
mpp-inspector inspect https://api.example.com/v1/query |
Decode the request base64url payload |
Copy request param, base64-decode, JSON-parse manually |
Decoded automatically, shown in "Request Params" section |
| Identify the payment method | Read method= from header, look up what "tempo" or "stripe" means |
Shown as "Tempo" / "Stripe" with description |
| Check if the challenge has expired | Copy expires, compare ISO 8601 string to now |
Expiry in future shown in verification section |
| Identify the token being charged | Decode request, find currency, look up address |
Resolved to USD / pathUSD from built-in registry |
| Verify the recipient is valid | Decode request, copy address, validate hex format and checksum |
Recipient valid via viem |
| Discover all paid endpoints | Check /.well-known/mpp.json, parse JSON manually, then probe paths with HEAD |
mpp-inspector scan domain.com --probe |
| Compare pricing across services | Repeat curl N times, manually align the amounts | mpp-inspector compare url1 url2 url3 |
| Machine-readable output | curl ... | jq and hope the structure is consistent |
--json flag on every command |
The core interaction model MPP Inspector drives:
Client MPP Server Tempo Chain
| | |
| GET /v1/data | |
|-------------------------------->| |
| | |
| 402 Payment Required | |
| WWW-Authenticate: Payment | |
| id="..", method="tempo", | |
| request="<base64url>" | |
|<--------------------------------| |
| | |
| +------------------+ | |
| | mpp-inspector | | |
| | decodes request | | |
| | verifies fields | | |
| | signs payment | | |
| +------------------+ | |
| | |
| On-chain payment | |
|---------------------------------+----------------------------->|
| | |
| GET /v1/data | tx confirmed |
| Authorization: Payment <cred> |<-----------------------------|
|-------------------------------->| |
| | |
| 200 OK { data } | |
|<--------------------------------| |
| | |
inspect — Dissect a real 402 challenge
$ mpp-inspector inspect https://mpp.dev/api/ping/paid
+--------------------------------------+
| MPP Challenge Inspection |
| URL: https://mpp.dev/api/ping/paid |
+--------------------------------------+
Status: 402 Payment Required
Protocol: MPP (Payment HTTP Authentication Scheme)
-- Challenge Details --
Challenge ID: nVAXFzJOH0jx...
Realm: mpp.sh
Method: Tempo
Intent: charge (one-time payment)
Amount: 100000.00 ($100000)
Currency: 0x20c0...0000
Recipient: 0xf39F...2266
Chain: Tempo Mainnet (42431)
Expires: 2026-03-26T23:02:55.506Z (5m 01s remaining)
-- Request Params (decoded) --
amount: 100000
currency: 0x20c0000000000000000000000000000000000000
methodDetails: { chainId: 42431, feePayer: true }
recipient: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
chainId: 42431
-- Verification --
? Challenge signature valid (unverifiable)
v Expiry in future
v Payment method known (Tempo)
v Amount parseable
v Recipient valid
v Currency recognized# machine-readable output
$ mpp-inspector inspect https://mpp.dev/api/ping/paid --json | jq .challenge.requestDecoded.amount
"100000"flow — Execute the full payment lifecycle
# dry-run (no actual tx)
$ mpp-inspector flow https://mpp.dev/api/ping/paid --dry-run
Step 1: Request resource v 402 received 97ms
Step 2: Parse challenge v Tempo / charge 1ms
Step 3: Sign transaction - skipped (dry run) --
Step 4: Retry with cred - skipped (dry run) --
Step 5: Verify receipt - skipped (dry run) --
# live execution against testnet
$ MPP_PRIVATE_KEY=0x... mpp-inspector flow https://api.example.com/v1/query --testnetscan — Discover MPP endpoints on a domain
$ mpp-inspector scan localhost:3402
Scanning localhost:3402 for MPP endpoints...
v Checking /.well-known/mpp.json v Found
v Checking /llms.txt v Found
v Checking /health v 200 OK
Discovered 4 MPP-enabled endpoints:
+------------------+-------+--------+---------------------------------+
| Endpoint | Price | Method | Description |
+------------------+-------+--------+---------------------------------+
| GET /v1/query | $1000 | Tempo | Financial data query |
| POST /v1/search | $5000 | Tempo | Full-text search across datasets|
| GET /v1/stream | $100 | Tempo | Real-time data streaming channel|
| GET /v1/premium | $500 | Stripe | Premium API endpoint (Stripe) |
+------------------+-------+--------+---------------------------------+compare — Price diff across providers and methods
$ mpp-inspector compare \
http://localhost:3402/v1/query \
http://localhost:3402/v1/search \
http://localhost:3402/v1/premium
+------------+-------+--------+--------+----------+---------------+
| Service | Price | Method | Intent | Currency | Chain |
+------------+-------+--------+--------+----------+---------------+
| localhost | $1000 | Tempo | charge | USD | Tempo Mainnet |
| localhost | $5000 | Tempo | charge | USD | Tempo Mainnet |
| localhost | $500 | Stripe | charge | USD | unknown |
+------------+-------+--------+--------+----------+---------------+
Cheapest: localhost ($500/query via Stripe)
Payment methods available:
Tempo: localhost, localhost
Stripe: localhostvalidate — Verify receipts and credentials
# validate a receipt
$ mpp-inspector validate eyJjaGFsbGVuZ2VJZCI6...
-- Receipt Validation --
Challenge ID: qB3wErTyU7iOpAsD9fGhJk
Method: Tempo
Reference: 0xtx789abc...
Status: success
Timestamp: 2025-01-15T12:00:00Z
Settlement: 1000 USD
v Base64 decoding valid
v JSON structure valid
v Required fields present
v Timestamp not in future
# validate a credential
$ mpp-inspector validate eyJjaGFsbGVuZ2UiOi... --credential
-- Credential Validation --
Source: 0x1234...5678
Challenge ID: qB3wErTyU7iOpAsD9fGhJk
Method: Tempo
Intent: charge
Payload: { signature: "0x..." }
v Structure valid
v Challenge object present
v Source field present
v Payload object presentbenchmark — Load test MPP endpoints
$ mpp-inspector benchmark https://api.example.com/v1/query -c 10 -n 100
-- Benchmark Results --
Total requests: 100
Successful: 98
Failed: 2
Throughput: 47.3 req/s
-- Latency --
p50: 42ms p95: 118ms p99: 203ms
avg: 51ms min: 18ms max: 312msmpp-inspector/
+-- packages/
| +-- cli/ # published npm package
| | +-- bin/
| | | +-- mpp-inspector.ts # node shebang entry
| | +-- src/
| | | +-- commands/
| | | | +-- inspect.ts # 402 challenge dissector
| | | | +-- flow.ts # challenge -> sign -> pay -> receipt
| | | | +-- validate.ts # receipt + credential decoder
| | | | +-- scan.ts # .well-known/mpp.json + /llms.txt
| | | | +-- compare.ts # multi-endpoint price diff
| | | | +-- benchmark.ts # concurrent load testing
| | | | +-- session.ts # payment channel lifecycle
| | | +-- display/
| | | | +-- challenge.ts # boxen + chalk terminal output
| | | | +-- receipt.ts # receipt + credential formatting
| | | | +-- flow.ts # step-by-step flow rendering
| | | | +-- table.ts # cli-table3 endpoint tables
| | | +-- utils/
| | | | +-- parser.ts # RFC 7235 auth-param + base64url decoder
| | | | +-- http.ts # fetch wrapper with timeout
| | | | +-- crypto.ts # method-aware field validation
| | | | +-- wallet.ts # viem wallet + public client
| | | | +-- chains.ts # chain registry + payment method info
| | | | +-- format.ts # address truncation, formatting
| | | +-- types.ts # MppChallenge, MppReceipt, MppCredential
| | | +-- index.ts # commander + barrel re-exports
| | +-- tsup.config.ts # dual entry build (bin + lib)
| | +-- vitest.config.ts # test runner config
| +-- mock-server/ # mock MPP server for demos & testing
| | +-- bin/
| | | +-- mpp-mock-server.ts # CLI entry point
| | +-- src/
| | +-- server.ts # Node http server (zero deps)
| | +-- fixtures.ts # spec-compliant challenge builder
| | +-- index.ts # public API
| +-- plugin/ # Claude Code plugin + MCP server
| +-- .claude-plugin/
| | +-- plugin.json # plugin manifest
| +-- skills/
| | +-- mpp-protocol/
| | +-- SKILL.md # MPP protocol knowledge skill
| +-- hooks/
| | +-- hooks.json # SessionStart project detection
| +-- .mcp.json # MCP server config
| +-- src/
| +-- index.ts # MCP server entry (stdio)
| +-- tools/ # mpp_inspect, mpp_scan, etc.
| +-- hooks/
| +-- session-check.ts # MPP project detector
+-- package.json # npm workspaces root
Challenge Parser — spec-compliant with backward compatibility
The parser handles both the spec-compliant format (used by real MPP servers like mpp.dev) and the legacy format for backward compatibility:
Spec-compliant format:
WWW-Authenticate: Payment id="qB3wErTyU7iOpAsD9fGhJk",
realm="mpp.dev",
method="tempo",
intent="charge",
expires="2025-01-15T12:05:00Z",
request="eyJhbW91bnQiOiIxMDAwIiwiY3VycmVuY3kiOiJ1c2QifQ"
Where request is a base64url-encoded JSON containing method-specific payment details (amount, currency, recipient, chainId, etc.).
Parsed into a typed MppChallenge:
interface MppChallenge {
id: string; // unique challenge identifier
realm: string; // domain scope (e.g. "mpp.dev")
method: string; // payment method: "tempo" | "stripe" | "lightning" | "solana" | "card" | "custom"
intent: string; // "charge" | "session"
expires: string; // ISO 8601 expiry timestamp
request: string; // base64url-encoded JSON payload
requestDecoded: MppRequestParams; // decoded: { amount, currency, recipient, chainId, ... }
extra: Record<string, string>; // forward-compat for new fields
raw: string; // original header value
}Legacy format (auto-detected and mapped):
WWW-Authenticate: Payment challengeId="c_abc", amount="0.01", currency="0x...", recipient="0x...", chainId="4217"
Legacy fields are automatically mapped: challengeId -> id, top-level amount/currency/recipient/chainId are synthesized into requestDecoded.
Verification Engine — method-aware challenge validation
Each parsed challenge runs through a method-aware verification pipeline:
+-----------------------------------------------------+
| Verification Pipeline |
+-----------------------------------------------------+
| v methodKnown -> KNOWN_PAYMENT_METHODS set |
| v expiryValid -> ISO 8601 parse + compare |
| v amountParseable -> requestDecoded.amount |
| v recipientValid -> viem.isAddress() (blockchain |
| methods only) |
| v currencyKnown -> currency registry lookup |
| ? signatureValid -> method-specific (planned) |
+-----------------------------------------------------+
Blockchain methods (Tempo, Lightning, Solana) get full address validation. Non-blockchain methods (Stripe, Card) skip address checks.
Chain & Payment Method Registry
// Chain support
CHAINS = {
42431: { name: "Tempo Mainnet", rpc: "https://rpc.tempo.xyz", testnet: false },
42432: { name: "Tempo Testnet", rpc: "https://rpc-testnet.tempo.xyz", testnet: true },
1: { name: "Ethereum Mainnet", rpc: "https://eth.llamarpc.com", testnet: false },
}
// Payment method registry
PAYMENT_METHODS = {
tempo: { name: "Tempo", blockchain: true, desc: "Tempo blockchain stablecoin payments" },
stripe: { name: "Stripe", blockchain: false, desc: "SPT-based card payments via Stripe" },
lightning: { name: "Lightning", blockchain: true, desc: "Bitcoin via Lightning Network (BOLT11)" },
solana: { name: "Solana", blockchain: true, desc: "SOL + SPL token payments" },
card: { name: "Card", blockchain: false, desc: "Encrypted network tokens (Visa)" },
custom: { name: "Custom", blockchain: false, desc: "Custom payment rail" },
}MPP Inspector ships as a Claude Code plugin with an MCP server that works in Claude Code, Cursor, and any MCP-compatible client.
# register the MCP server
claude mcp add --transport stdio mpp-inspector node ./packages/plugin/dist/index.jsThe plugin provides 5 MCP tools, an MPP protocol knowledge skill, and a session-start hook that detects MPP projects automatically.
Add to your MCP configuration (.cursor/mcp.json, mcp.json, or IDE settings):
{
"mcpServers": {
"mpp-inspector": {
"command": "npx",
"args": ["-y", "@mpp-inspector/plugin"]
}
}
}npx @modelcontextprotocol/inspector node packages/plugin/dist/index.jsOpens a web UI where you can interactively call each tool and see JSON responses.
| Tool | What it does |
|---|---|
mpp_inspect |
Send a request to a URL, parse the 402 challenge, decode request payload, verify fields |
mpp_scan |
Discover MPP endpoints on a domain via .well-known/mpp.json, /llms.txt, and path probing |
mpp_compare |
Compare pricing across 2+ MPP endpoints side by side, grouped by payment method |
mpp_validate |
Decode and verify a base64-encoded MPP receipt |
mpp_flow |
Dry-run the full payment flow (request -> parse -> verify) without real transactions |
Example prompts in Claude Code or Cursor:
"Inspect https://mpp.dev/api/ping/paid and tell me what payment method it uses"
"Scan mpp.dev for MPP endpoints"
"Compare pricing between these three MPP APIs: url1, url2, url3"
| Layer | Technology | Why |
|---|---|---|
| Runtime | Node.js 18+ (ESM) | Native fetch, top-level await |
| CLI Framework | Commander v13 | Declarative command/option tree |
| Chain Interaction | viem | Type-safe Ethereum client, wallet ops, address validation |
| Terminal UI | chalk + boxen + ora + cli-table3 | Styled output, spinners, tables |
| Build | tsup | Dual-entry ESM bundles with shebang banner |
| Tests | Vitest | Fast unit tests with native ESM support |
| Types | TypeScript 5.x | Strict, readonly interfaces throughout |
| Variable | Scope | Description |
|---|---|---|
MPP_PRIVATE_KEY |
flow benchmark session |
Wallet private key for signing transactions. Overridden by -w flag. |
+--------------------+---------+----------+----------------------------------+
| Chain | ID | Type | RPC |
+--------------------+---------+----------+----------------------------------+
| Tempo Mainnet | 42431 | prod | https://rpc.tempo.xyz |
| Tempo Testnet | 42432 | testnet | https://rpc-testnet.tempo.xyz |
| Ethereum Mainnet | 1 | prod | https://eth.llamarpc.com |
+--------------------+---------+----------+----------------------------------+
Legacy chain IDs 4217 / 4218 are also recognized for backward compatibility.
Use --testnet for testnet. Use --rpc <url> to override.
git clone https://github.com/amgb20/MPP-Inspector.git
cd mpp-inspector && npm install
npm run build # compile CLI
npm run dev # watch mode (rebuild on change)
npm run test # run test suite
npm run lint # type-check (tsc --noEmit)
npm run check # lint + test + build (all gates)
# build and start mock server
cd packages/mock-server && npx tsup && cd ../..
node packages/mock-server/dist/bin/mpp-mock-server.js
# link CLI globally (optional, for convenience)
cd packages/cli && npm link && cd ../..
mpp-inspector inspect http://localhost:3402/v1/queryDone
- Spec-compliant challenge parser (
id,realm,method,requestbase64url) - All 6 payment methods parsed (Tempo, Stripe, Lightning, Solana, Card, Custom)
- Method-aware verification (blockchain vs non-blockchain)
- Receipt and credential validation (
--credentialflag) - Real Tempo chain ID (42431/42432) with legacy fallback
- Spec-compliant mock server with multiple payment methods
- Claude Code plugin + MCP server (
packages/plugin) - Tested against live
https://mpp.dev/api/ping/paidendpoint
Next
- Complete
flowcommand with real testnet payments - Signature verification (method-specific)
-
/llms.txtparsing into structured endpoints - MCP transport support (JSON-RPC error codes +
_metafields for AI agent tool calls)
Planned
- Receipt persistence and history
- GitHub Actions integration —
mpp-inspector scanas a CI step - Web dashboard (React + Vite) as
packages/web
Future
- Plugin system for custom payment flows
- Additional chain support (Solana, Ethereum L2s)
MIT — build whatever you want.
Built for the Machine Payments Protocol ecosystem on Tempo