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:
- Proxies unprotected traffic straight through.
- Requires MPP payment on matching protected paths.
- Verifies
Authorization: Paymentcredentials with themppxSDK. - Returns MPP-standard
WWW-Authenticate: PaymentandPayment-Receiptheaders. - Issues a 1-hour JWT cookie after a successful payment to avoid repaying on every request.
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/healthcurl -i https://YOUR-WORKER.workers.dev/__mpp/protectedYou 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 loginTell your agent to run:
tempo request -X GET https://YOUR-WORKER.workers.dev/__mpp/protectedThe 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 testing
npm install
echo "JWT_SECRET=$(openssl rand -hex 32)" > .dev.vars
echo "MPP_SECRET_KEY=$(openssl rand -hex 32)" >> .dev.vars
npm run devThen 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_KEYIf 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.
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.
- Client requests a protected route.
- Proxy returns
402 Payment RequiredwithWWW-Authenticate: Payment. - Client retries with
Authorization: Payment. - Proxy verifies the credential with
mppx. - Proxy forwards to the origin and adds
Payment-Receipt. - Proxy also issues an
auth_tokencookie 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/healthcurl -i http://localhost:8787/__mpp/protectedYou should get 402 Payment Required and a WWW-Authenticate: Payment header.
npx mppx account create
npx mppx http://localhost:8787/__mpp/protectedPRIVATE_KEY=0x... npm run test:clientSee 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
- This project uses the Tempo payment method through
mppx. Payment-Receiptis returned on successful paid requests.- Cookies are
HttpOnly,Secure, andSameSite=Strict. - Uncomment
assetsinwrangler.jsonconly if you want the optional landing page served at/.