Imported from cloudflare/mpp-proxy (
AGENTS.md). Install upstream withnpx skills add cloudflare/mpp-proxy. Copyright stays with the author.
mpp-proxy Setup Guide for AI Agents
Context for AI coding agents helping users set up this MPP payment-gated proxy template.
What is mpp-proxy?
A Cloudflare Worker that adds payment gating to any origin using the Machine Payments Protocol (MPP).
- Protected routes return
402 Payment RequiredwithWWW-Authenticate: Payment - Clients retry with
Authorization: Payment - Successful responses include
Payment-Receipt - The proxy also issues a JWT cookie valid for 1 hour so browsers and agents can reuse access without paying again on every request
With Bot Management Filtering: Requires Bot Management for Enterprise to enable bot filtering. When enabled, humans can pass through free while likely automated traffic must pay. This is optional and enhances the base functionality.
This template is currently wired to the Tempo payment method via mppx.
Interactive Setup Flow
When a user asks for help setting up the proxy, follow this discovery process.
Step 1: Verify Cloudflare Authentication
npx wrangler whoami
If not logged in, guide them to run npx wrangler login.
If they have multiple accounts, note them for Step 2.
Step 2: Select Domain
Ask: "Which domain do you want to add payment gating to?"
If the user has multiple Cloudflare accounts, also ask: "Which account is this domain on?"
Save the domain. It scopes the rest of setup.
Step 3: Check for Bot Management (Optional Enhancement)
Ask: "Do you have Bot Management enabled on {domain}?"
Explain why:
With Bot Management enabled, the proxy can implement a default-closed model for bots: likely human traffic passes free, while likely automated traffic must pay. You can also allow specific bots like Googlebot or verified AI assistants through for free.
Without Bot Management, the proxy still works perfectly. All traffic to protected routes must pay.
| Answer | Effect |
|---|---|
| Yes | Enable Bot Management prompts in Step 4 |
| No | Skip threshold/exception prompts in Step 4 |
Step 4: Configure Protected Paths (Iterative)
Ask: "What path on {domain} do you want to charge for?"
If the user provides multiple paths at once, queue them and configure each in sequence.
For each path, ask:
4.1 Amount
Ask: "What amount should {path} cost?"
Format: 0.01, 0.10, 1.00, etc.
Important: this template stores the value as amount, not price.
4.2 Description
Ask: "What description should users see for {path}?"
Example: Access to premium content for 1 hour
4.3 If Bot Management is enabled
Ask: "What bot score threshold should {path} use?"
Offer exactly these three options:
| Option | Threshold | Meaning |
|---|---|---|
| 1 | 1 | Very strict - only verified humans pass free |
| 2 | 2 | Strict - only clear human traffic passes free |
| 30 (Recommended) | 30 | Balanced - likely automated traffic must pay, humans pass free |
Then ask: "Any bots that should get FREE access to {path}?"
Offer these presets:
| Preset | Bots Included | Use When |
|---|---|---|
| Googlebot + BingBot | Googlebot, BingBot | Allow major crawlers |
| Above + AI assistants | Above + ChatGPT-User, Claude-User, Perplexity-User, Meta-ExternalFetcher | Allow AI assistant citations |
| None | (empty) | All bots must pay |
If the user selects a preset or specific bot names, resolve them using the Bot Registry below and write the resulting IDs to except_detection_ids.
Example:
"except_detection_ids": [
120623194, // Googlebot
117479730 // BingBot
]
4.4 More paths
Ask: "Any more paths on {domain} to protect?"
- If yes, repeat Step 4
- If no, continue
Step 5: Wallet and Tempo Configuration
Ask these together:
- "What wallet address should receive payments (
PAY_TO)?" - "Use Tempo testnet or production?"
Map the answer to config like this:
| User Choice | TEMPO_TESTNET |
|---|---|
| Testnet | true |
| Production | false |
Then ask:
- "Which token address should clients pay in (
PAYMENT_CURRENCY)?"
Recommended default for demos:
0x20c000000000000000000000b9537d11c60e8b50
That is the default PathUSD address used by this template for Tempo testnet demos.
If the user does not have a wallet address yet, they can use the default dead address for smoke testing:
0x000000000000000000000000000000000000dEaD
Deployment Phase
Now that config is complete, discover infrastructure and deploy.
Step 6: Discover Existing Workers and Routes
npx wrangler deployments list
npx wrangler routes list --zone {domain}
This reveals:
- what Workers are already deployed
- whether another Worker already owns routes on the domain
Determine deployment mode:
| Situation | Recommended Mode |
|---|---|
| Origin is a traditional server | Standard Proxy Mode |
| Origin is an external API or service | External Origin Mode |
| Origin is another Worker in the same account | Service Binding Mode |
Existing Worker already owns domain/* |
External Origin Mode or Service Binding Mode |
Step 7: Generate wrangler.jsonc
Write the complete configuration for this MPP template.
Basic example:
{
"routes": [
{ "pattern": "example.com/premium/*", "zone_name": "example.com" },
],
"vars": {
"PAY_TO": "0x000000000000000000000000000000000000dEaD",
"TEMPO_TESTNET": true,
"PAYMENT_CURRENCY": "0x20c000000000000000000000b9537d11c60e8b50",
"PROTECTED_PATTERNS": [
{
"pattern": "/premium/*",
"amount": "0.01",
"description": "Access to premium content for 1 hour",
},
],
},
}
With Bot Management Filtering:
{
"routes": [
{ "pattern": "example.com/content/*", "zone_name": "example.com" },
],
"vars": {
"PAY_TO": "0x000000000000000000000000000000000000dEaD",
"TEMPO_TESTNET": true,
"PAYMENT_CURRENCY": "0x20c000000000000000000000b9537d11c60e8b50",
"PROTECTED_PATTERNS": [
{
"pattern": "/content/*",
"amount": "0.25",
"description": "Content access for 1 hour",
"bot_score_threshold": 30,
"except_detection_ids": [120623194, 117479730],
},
],
},
}
Notes:
- Use
amount, notprice - Do not configure
FACILITATOR_URLorNETWORK; those were x402-era concepts and are not used by this repo anymore - This repo uses Tempo through
mppx
Step 8: Set Secrets
This repo requires two secrets.
Set the JWT secret:
openssl rand -hex 32 | npx wrangler secret put JWT_SECRET
Set the MPP challenge secret:
openssl rand -hex 32 | npx wrangler secret put MPP_SECRET_KEY
If Tempo RPC access requires authentication, also set an authenticated RPC URL so server-side verification and transaction broadcast do not fall back to https://rpc.tempo.xyz/:
printf '%s' 'https://user:pass@rpc.mainnet.tempo.xyz/' | npx wrangler secret put TEMPO_RPC_URL
Step 9: Deploy
npm run deploy
Step 10: Verify
curl https://{domain}/__mpp/health
# Should return: {"status":"ok",...}
curl https://{domain}/__mpp/config
# Should show token, wallet suffix, and protected patterns
For a real payment test, use the MPP CLI:
npx mppx https://{domain}/__mpp/protected
Deployment Modes
Standard Proxy Mode (DNS-based)
- The proxy owns the route, e.g.
api.example.com/* - Protected paths require MPP payment; everything else passes through
- Use when the origin is a traditional server
User -> mpp-proxy -> Origin Server
External Origin Mode
- The proxy owns the route and rewrites requests to
ORIGIN_URL - Use when the origin is another public service or Worker you do not want to modify
"ORIGIN_URL": "https://my-existing-service.example.com"
Service Binding Mode
- The proxy calls the origin Worker through
ORIGIN_SERVICE - Use when the origin is another Worker in the same account and you want the best performance
"services": [{ "binding": "ORIGIN_SERVICE", "service": "my-origin-worker" }]
Bot Management Filtering Reference
Requires Bot Management for Enterprise.
When enabled:
- humans can pass for free
- excepted bots can pass for free
- everyone else must pay
Threshold Reference
| Threshold | Meaning | Use Case |
|---|---|---|
| 1 | Very strict - only verified humans pass free | Maximum monetization |
| 2 | Strict - only clear human traffic passes free | High-value APIs |
| 30 | Balanced - likely automated must pay, humans pass free | Recommended default |
Bot Registry Reference
Use this registry when converting human-readable bot names to detection IDs.
| Bot Name | Detection ID | Notes |
|---|---|---|
| Googlebot | 120623194 | Google Search |
| Google-CloudVertexBot | 133730073 | Google AI training |
Microsoft
| Bot Name | Detection ID | Notes |
|---|---|---|
| BingBot | 117479730 | Microsoft Bing |
OpenAI
| Bot Name | Detection ID | Notes |
|---|---|---|
| GPTBot | 123815556 | OpenAI training |
| ChatGPT-User | 132995013 | ChatGPT browsing mode |
| ChatGPT agent | 129220581 | ChatGPT agents/plugins |
| OAI-SearchBot | 126255384 | OpenAI Search |
Anthropic
| Bot Name | Detection ID |
|---|---|
| ClaudeBot | 33563859 |
| Claude-SearchBot | 33564301 |
| Claude-User | 33564303 |
Perplexity
| Bot Name | Detection ID |
|---|---|
| PerplexityBot | 33563889 |
| Perplexity-User | 33564371 |
Meta
| Bot Name | Detection ID |
|---|---|
| Meta-ExternalAgent | 124581738 |
| Meta-ExternalFetcher | 132272919 |
| FacebookBot | 33563972 |
Configuration Reference
Required vars
| Variable | Description |
|---|---|
PAY_TO |
Wallet address receiving payment |
TEMPO_TESTNET |
Tempo testnet toggle |
PAYMENT_CURRENCY |
Token address clients pay in |
PROTECTED_PATTERNS |
Array of protected path configs |
Required secrets
| Variable | Description |
|---|---|
JWT_SECRET |
Secret for auth cookies |
MPP_SECRET_KEY |
Secret for signing MPP challenges |
TEMPO_RPC_URL |
Optional authenticated Tempo RPC URL |
Protected pattern schema
{
pattern: string
amount: string
description: string
bot_score_threshold?: number
except_detection_ids?: number[]
}
Optional vars
| Variable | Description |
|---|---|
ORIGIN_URL |
External origin URL |
ORIGIN_SERVICE |
Service binding to another Worker |
Debug endpoints
/__mpp/health- health check/__mpp/config- sanitized runtime config/__mpp/protected- built-in paid route for testing
Common Issues
Another Worker already owns the route
Wrangler may fail with a route conflict.
Fix:
- Identify the existing route owner with
npx wrangler routes list --zone <domain> - Remove the route from the old Worker
- Redeploy this proxy
Alternative: keep the old Worker live and point ORIGIN_URL at it.
JWT_SECRET or MPP_SECRET_KEY not set
Protected routes will fail with 500 until both secrets are created.
402 works but content fails
The payment layer is fine; the origin is failing. Test the origin directly.
Homepage shows the built-in demo instead of the origin
This repo ships with public/index.html for demos. If you want the root path to proxy to your origin, comment out or remove the assets block in wrangler.jsonc.
Bot Management Filtering warning about cf.botManagement
This means Bot Management data is not available.
Causes:
- Bot Management for Enterprise is not enabled
- the request is from local development, where bot signals are unavailable
Human traffic still gets 402
Check that:
bot_score_thresholdis set- Bot Management is enabled on the zone
- The score is actually above the threshold
Use npx wrangler tail to inspect request metadata after deployment.
Testing Locally
echo "JWT_SECRET=$(openssl rand -hex 32)" > .dev.vars
echo "MPP_SECRET_KEY=$(openssl rand -hex 32)" >> .dev.vars
npm run dev
curl http://localhost:8787/__mpp/health
curl http://localhost:8787/__mpp/protected
Then try an MPP client flow:
npx mppx http://localhost:8787/__mpp/protected
Pre-Deploy Checklist
Before running npm run deploy, verify:
routesmatches the correct domain and pathPAY_TOis set correctlyPAYMENT_CURRENCYis set correctlyTEMPO_TESTNETmatches testnet vs production intentPROTECTED_PATTERNSusesamount, notpriceJWT_SECRETexistsMPP_SECRET_KEYexistsTEMPO_RPC_URLis set if your Tempo RPC requires authenticationassetsis commented out if you want full proxy behavior at/ORIGIN_SERVICEorORIGIN_URLis configured if DNS-based origin routing is not correct
If using Bot Management Filtering:
- Bot Management is enabled
bot_score_thresholdis set on relevant pathsexcept_detection_idsare resolved correctly