DEV Community

Cover image for Build a Paid MCP Server in 5 Minutes (Full Tutorial)
0xAllenDev
0xAllenDev

Posted on • Originally published at dev.to

Build a Paid MCP Server in 5 Minutes (Full Tutorial)

You have an MCP server. It works. Now make it pay you.

This tutorial takes you from pip install to a working paid MCP server in under 5 minutes. We'll build a weather service, put a USDC paywall on it, and test the full buyer-seller flow.

No prior crypto experience needed.


What You'll Need

  • Python 3.10+
  • Two terminal windows
  • 5 minutes
python3 --version
# Python 3.10.x or higher ✓
Enter fullscreen mode Exit fullscreen mode

Step 1: Install (30 seconds)

pip install ag402-core fastmcp
Enter fullscreen mode Exit fullscreen mode

Verify:

ag402 --version
Enter fullscreen mode Exit fullscreen mode

This installs the ag402 CLI (wallet management + reverse proxy), the ag402_core Python SDK (buyer-side auto-payment), and fastmcp (for our demo server).


Step 2: Create Your Wallet (30 seconds)

ag402 init
Enter fullscreen mode Exit fullscreen mode

This generates a Solana keypair and loads it with test USDC for development. Wallet details are stored encrypted at ~/.ag402/wallet.json.

Save your wallet address — you'll need it in Step 4.

In test mode, ag402 mints devnet USDC so you can experiment for free. For production, set X402_MODE=production and fund with real USDC.


Step 3: Build a Simple MCP Server (2 minutes)

mkdir my-paid-mcp && cd my-paid-mcp
Enter fullscreen mode Exit fullscreen mode

Create weather_server.py:

from fastmcp import FastMCP

mcp = FastMCP("Weather Service")

WEATHER_DATA = {
    "san francisco": {"temp_c": 18, "condition": "foggy", "humidity": 75},
    "new york":      {"temp_c": 22, "condition": "sunny", "humidity": 45},
    "tokyo":         {"temp_c": 25, "condition": "cloudy", "humidity": 60},
    "london":        {"temp_c": 15, "condition": "rainy", "humidity": 82},
}

@mcp.tool()
def get_weather(city: str) -> dict:
    """Get current weather for a city."""
    data = WEATHER_DATA.get(city.lower())
    if not data:
        return {"error": f"No data for {city}"}
    return {"city": city, **data}

if __name__ == "__main__":
    # Use HTTP transport so ag402 can proxy requests
    mcp.run(transport="streamable-http", port=3000)
Enter fullscreen mode Exit fullscreen mode

Start in Terminal 1:

python weather_server.py
# Server running on http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

Why not stdio? ag402's reverse proxy needs an HTTP endpoint to sit in front of. The stdio transport communicates via stdin/stdout, which can't be proxied. streamable-http exposes your MCP server as a standard HTTP service. If your MCP server already runs on HTTP (e.g., behind Flask or FastAPI), skip this step and point ag402 at your existing endpoint.


Step 4: Add the Paywall (30 seconds)

Open Terminal 2:

ag402 serve \
  --target http://localhost:3000 \
  --price 0.02 \
  --address <YOUR_WALLET_ADDRESS>
Enter fullscreen mode Exit fullscreen mode
┌─────────────────────────────────────┐
│  🚀 ag402 Payment Proxy            │
│  ─────────────────────────────────  │
│  🎯 Target:  http://localhost:3000  │
│  💵 Price:   0.02 USDC/request     │
│  🔗 Proxy:   http://localhost:4020  │
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Done. Here's what happens on each request:

Agent → :4020 → payment header? ─── No ──→ 402 + price/wallet info
                    │                          ↑
                   Yes                    Agent auto-pays
                    │                     USDC on Solana
                    ▼                          │
              Verify on-chain ←────────────────┘
                    │
                    ▼
         Forward to :3000 (your MCP)
                    │
                    ▼
              Response ✓
Enter fullscreen mode Exit fullscreen mode

Your MCP code: zero changes.


Step 5: Test as a Buyer (1 minute)

Create test_buyer.py:

import ag402_core
import httpx

# One line — patches httpx/requests to auto-pay 402s
ag402_core.enable()

response = httpx.post(
    "http://localhost:4020/mcp",
    json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "tools/call",
        "params": {
            "name": "get_weather",
            "arguments": {"city": "Tokyo"}
        }
    }
)

print(response.json())
Enter fullscreen mode Exit fullscreen mode
python test_buyer.py
Enter fullscreen mode Exit fullscreen mode

Behind the scenes: httpx hits proxy → gets 402 → ag402_core intercepts → auto-pays $0.02 USDC (~0.5s) → retries with proof → weather data ✓

The buyer code has zero payment logic. Even simpler — wrap any existing script:

ag402 run -- python my_existing_agent.py
Enter fullscreen mode Exit fullscreen mode

Bonus: Prepaid Mode (~1ms)

Standard payments take ~0.5s. ag402's prepaid system drops that to ~1ms with zero gas:

One Solana tx → buy N credits → HMAC credential
Each call → credential header → local verify → ~1ms, $0 gas
Enter fullscreen mode Exit fullscreen mode
Package Credits Price Per call Validity
Starter 100 $1.50 $0.015 3 days
Pro 1,000 $8.00 $0.008 30 days
Business 5,000 $35.00 $0.007 365 days

HMAC-SHA256 verified locally — no blockchain calls after the initial purchase. (How prepaid works under the hood)


Bonus: Production

Mainnet:

X402_MODE=production ag402 serve \
  --target http://your-server:3000 \
  --price 0.02 \
  --address <YourMainnetAddress>
Enter fullscreen mode Exit fullscreen mode

Claude Code / Cursor:

ag402 install claude-code   # or: ag402 install cursor
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Problem Fix
ag402 init fails Ensure Python 3.10+ and pip is current
Proxy can't reach target Confirm MCP server is running on the correct port
Payment not going through ag402 init provides test USDC — run again if needed
402 but no auto-pay ag402_core.enable() must be called before HTTP requests
Import errors pip install --upgrade ag402-core

Limitations

  • Buyers need a Solana wallet with USDC — this is real friction for non-crypto developers. Test mode removes this barrier for development, and prepaid reduces on-chain interactions, but production buyers need crypto.
  • Solana network dependency — standard payments require network availability. Prepaid mode (HMAC-based) works independently of the network after the initial purchase.
  • Simple pricing only — ag402 handles per-request pricing. For subscriptions, usage tiers, or invoicing, you'll need additional tooling.

Security Checklist (Before Production)

  • [ ] Private key in environment variable (SOLANA_PRIVATE_KEY), never in code
  • [ ] Tested on devnet before mainnet
  • [ ] Price set slightly above your per-request cost
  • [ ] Reviewed built-in protections: per-tx cap ($5), rate limit, daily cap ($10), circuit breaker, auto-rollback, key redaction
  • [ ] 588+ tests, 4 security audits, MIT licensed → GitHub

What We Built

Step Time Result
Install 30s ag402 + FastMCP ready
Wallet 30s Solana wallet + test USDC
MCP server 2min Weather service on :3000
Paywall 30s Reverse proxy on :4020
Test 1min Auto-pay verified ✓

Your server code: unchanged. Your revenue: non-zero.


Next Steps

→ ⭐ ag402 on GitHub — source, docs, examples
→ 🧪 Colab demo — try in browser, zero install
→ 📖 Why charge? — the business case
→ 📝 Case study — real lessons from a $0.02 paywall

ag402 is open source (MIT). Built by AetherCore on Coinbase x402.

Top comments (0)