A Cloudflare Worker that acts as a transparent reverse proxy with payment-gated access using the Machine Payments Protocol and stateless cookie-based authentication.
This proxy sits in front of any origin and:
Authorization: Payment credentials with the mppx SDK.WWW-Authenticate: Payment and Payment-Receipt headers.The repo ships with production defaults: Tempo production, USDC at 0x20c000000000000000000000b9537d11c60e8b50, and the dead address 0x000000000000000000000000000000000000dEaD as PAY_TO. Update with your wallet address if you want payments to go to that wallet.
The Deploy to Cloudflare button above creates a Worker for you. Once deployed, you can test the payment flow with an AI agent or the tempo CLI.
curl https://YOUR-WORKER.workers.dev/__mpp/health
curl -i https://YOUR-WORKER.workers.dev/__mpp/protected
You should get 402 Payment Required with a WWW-Authenticate: Payment header. That confirms the paywall is active.
curl -fsSL tempo.xyz/install | bash
tempo wallet login
Tell your agent to run:
tempo request -X GET https://YOUR-WORKER.workers.dev/__mpp/protected
The client handles the 402 automatically — it pays and returns the protected content with a Payment-Receipt header.
/__mpp/health - public health check/__mpp/config - sanitized runtime config/__mpp/protected - built-in paid route for testingnpm install
echo "JWT_SECRET=$(openssl rand -hex 32)" > .dev.vars
echo "MPP_SECRET_KEY=$(openssl rand -hex 32)" >> .dev.vars
npm run dev
Then hit http://localhost:8787/__mpp/health or http://localhost:8787/__mpp/protected.
For local testnet development, set TEMPO_TESTNET to true and PAYMENT_CURRENCY to 0x20c0000000000000000000000000000000000000 in wrangler.jsonc. See TUTORIAL.md for a full local walkthrough.
If you want the optional landing page at /, uncomment the assets block in wrangler.jsonc.
The proxy is configured in wrangler.jsonc. The checked-in defaults keep routes disabled and use production-safe payment values until you swap in your own domain, wallet, and token.
| Variable | Description |
|---|---|
PAY_TO | Recipient wallet address |
PAYMENT_CURRENCY | Token address clients pay with |
TEMPO_TESTNET | false for production, true for testnet |
PROTECTED_PATTERNS | Paid paths and their amounts |
| Secret | Description |
|---|---|
JWT_SECRET | Signs the auth cookie |
MPP_SECRET_KEY | Signs MPP challenges for stateless verification |
| Secret | Description |
|---|---|
TEMPO_RPC_URL | Authenticated Tempo RPC URL for server-side verification |
Set secrets for production with:
npx wrangler secret put JWT_SECRET
npx wrangler secret put MPP_SECRET_KEY
If your Tempo RPC requires authentication, also set TEMPO_RPC_URL.
Use TEMPO_RPC_URL when Tempo RPC access requires authentication, for example:
https://user:pass@rpc.mainnet.tempo.xyz/
Without this override, mppx falls back to the default Tempo RPC URLs for server-side verification.
"PROTECTED_PATTERNS": [
{
"pattern": "/premium/*",
"amount": "0.01",
"description": "Access to premium content for 1 hour"
}
]
Bot Management filtering is still supported with bot_score_threshold and except_detection_ids.
The built-in paid test route at /__mpp/protected always exists, even if you change or remove PROTECTED_PATTERNS.
402 Payment Required with WWW-Authenticate: Payment.Authorization: Payment.mppx.Payment-Receipt.auth_token cookie valid for 1 hour.That means MPP-native clients get standards-compliant receipts, while browsers and agents can reuse the cookie for repeated access during the valid period.
Leave ORIGIN_URL unset and route traffic to an origin already defined in Cloudflare DNS.
Set:
"ORIGIN_URL": "https://my-backend.example.com"
If the origin is another Worker in your account:
"services": [
{ "binding": "ORIGIN_SERVICE", "service": "my-origin-worker" }
]
curl http://localhost:8787/__mpp/health
curl -i http://localhost:8787/__mpp/protected
You should get 402 Payment Required and a WWW-Authenticate: Payment header.
npx mppx account create
npx mppx http://localhost:8787/__mpp/protected
PRIVATE_KEY=0x... npm run test:client
See TESTING.md for details.
src/index.ts Main proxy entrypoint
src/auth.ts Cookie + MPP payment middleware
src/jwt.ts JWT utilities
src/bot-management/ Optional Bot Management filtering
public/index.html Optional landing page
test-client.ts End-to-end MPP client test
wrangler.jsonc Worker configuration
mppx.Payment-Receipt is returned on successful paid requests.HttpOnly, Secure, and SameSite=Strict.assets in wrangler.jsonc only if you want the optional landing page served at /.TypeScript
67.6%
HTML
29.7%
JavaScript
2.8%
A Cloudflare Worker that acts as a transparent reverse proxy with payment-gated access using the Machine Payments Protocol and stateless cookie-based authentication.
This proxy sits in front of any origin and:
Authorization: Payment credentials with the mppx SDK.WWW-Authenticate: Payment and Payment-Receipt headers.The repo ships with production defaults: Tempo production, USDC at 0x20c000000000000000000000b9537d11c60e8b50, and the dead address 0x000000000000000000000000000000000000dEaD as PAY_TO. Update with your wallet address if you want payments to go to that wallet.
The Deploy to Cloudflare button above creates a Worker for you. Once deployed, you can test the payment flow with an AI agent or the tempo CLI.
curl https://YOUR-WORKER.workers.dev/__mpp/health
curl -i https://YOUR-WORKER.workers.dev/__mpp/protected
You should get 402 Payment Required with a WWW-Authenticate: Payment header. That confirms the paywall is active.
curl -fsSL tempo.xyz/install | bash
tempo wallet login
Tell your agent to run:
tempo request -X GET https://YOUR-WORKER.workers.dev/__mpp/protected
The client handles the 402 automatically — it pays and returns the protected content with a Payment-Receipt header.
/__mpp/health - public health check/__mpp/config - sanitized runtime config/__mpp/protected - built-in paid route for testingnpm install
echo "JWT_SECRET=$(openssl rand -hex 32)" > .dev.vars
echo "MPP_SECRET_KEY=$(openssl rand -hex 32)" >> .dev.vars
npm run dev
Then hit http://localhost:8787/__mpp/health or http://localhost:8787/__mpp/protected.
For local testnet development, set TEMPO_TESTNET to true and PAYMENT_CURRENCY to 0x20c0000000000000000000000000000000000000 in wrangler.jsonc. See TUTORIAL.md for a full local walkthrough.
If you want the optional landing page at /, uncomment the assets block in wrangler.jsonc.
The proxy is configured in wrangler.jsonc. The checked-in defaults keep routes disabled and use production-safe payment values until you swap in your own domain, wallet, and token.
| Variable | Description |
|---|---|
PAY_TO | Recipient wallet address |
PAYMENT_CURRENCY | Token address clients pay with |
TEMPO_TESTNET | false for production, true for testnet |
PROTECTED_PATTERNS | Paid paths and their amounts |
| Secret | Description |
|---|---|
JWT_SECRET | Signs the auth cookie |
MPP_SECRET_KEY | Signs MPP challenges for stateless verification |
| Secret | Description |
|---|---|
TEMPO_RPC_URL | Authenticated Tempo RPC URL for server-side verification |
Set secrets for production with:
npx wrangler secret put JWT_SECRET
npx wrangler secret put MPP_SECRET_KEY
If your Tempo RPC requires authentication, also set TEMPO_RPC_URL.
Use TEMPO_RPC_URL when Tempo RPC access requires authentication, for example:
https://user:pass@rpc.mainnet.tempo.xyz/
Without this override, mppx falls back to the default Tempo RPC URLs for server-side verification.
"PROTECTED_PATTERNS": [
{
"pattern": "/premium/*",
"amount": "0.01",
"description": "Access to premium content for 1 hour"
}
]
Bot Management filtering is still supported with bot_score_threshold and except_detection_ids.
The built-in paid test route at /__mpp/protected always exists, even if you change or remove PROTECTED_PATTERNS.
402 Payment Required with WWW-Authenticate: Payment.Authorization: Payment.mppx.Payment-Receipt.auth_token cookie valid for 1 hour.That means MPP-native clients get standards-compliant receipts, while browsers and agents can reuse the cookie for repeated access during the valid period.
Leave ORIGIN_URL unset and route traffic to an origin already defined in Cloudflare DNS.
Set:
"ORIGIN_URL": "https://my-backend.example.com"
If the origin is another Worker in your account:
"services": [
{ "binding": "ORIGIN_SERVICE", "service": "my-origin-worker" }
]
curl http://localhost:8787/__mpp/health
curl -i http://localhost:8787/__mpp/protected
You should get 402 Payment Required and a WWW-Authenticate: Payment header.
npx mppx account create
npx mppx http://localhost:8787/__mpp/protected
PRIVATE_KEY=0x... npm run test:client
See TESTING.md for details.
src/index.ts Main proxy entrypoint
src/auth.ts Cookie + MPP payment middleware
src/jwt.ts JWT utilities
src/bot-management/ Optional Bot Management filtering
public/index.html Optional landing page
test-client.ts End-to-end MPP client test
wrangler.jsonc Worker configuration
mppx.Payment-Receipt is returned on successful paid requests.HttpOnly, Secure, and SameSite=Strict.assets in wrangler.jsonc only if you want the optional landing page served at /.TypeScript
67.6%
HTML
29.7%
JavaScript
2.8%