Skip to main content

Add x402 payments to your MCP server in one line

Project description

VAULLS

Value-Wall Monetisation Layer for MCP Tools

Add x402 payments to your MCP server in one line.

VAULLS is a Python package that lets MCP server developers monetise their tools using the x402 payment protocol and USDC on Base. It's a value wall, not a paywall — your tools are worth paying for, and agents pay because the value is real. Like adding a payment plugin to a WordPress site — you own the server, you set the prices, agents pay to use your tools.

Tests Mainnet Verified

                          Your MCP Server
                    ┌────────────────────────┐
                    │                        │
                    │  @paywall(price="0.05") │
                    │  def my_tool(args):     │
                    │      return result      │
                    │                        │
                    │  VAULLS handles:        │
                    │  ├─ 402 responses       │
                    │  ├─ payment verify      │
                    │  ├─ settlement logging  │
                    │  └─ pricing discovery   │
                    └───────────┬────────────┘
                                │
                    Agent calls tool, pays via x402
                                │
                    ┌───────────┴────────────┐
                    │  AI Agent              │
                    │  (Claude, Cursor, etc.) │
                    │  + Coinbase Smart      │
                    │    Wallet with USDC    │
                    └────────────────────────┘

Quickstart

1. Install

pip install "vaulls[fastapi,cdp]"

The [cdp] extra pulls in PyJWT[crypto], which VAULLS uses to sign the Authorization: Bearer JWT that the Coinbase CDP facilitator requires. This is needed for both testnet (Base Sepolia) and mainnet (Base).

2. Configure

export VAULLS_PAY_TO=0xYourBaseWalletAddress
export VAULLS_CDP_API_KEY_ID=your_key_id
export VAULLS_CDP_API_KEY_SECRET=your_key_secret

Get CDP API keys at portal.cdp.coinbase.com. The secret may be either a PEM-encoded EC P-256 key (signed as ES256) or a base64-encoded 64-byte Ed25519 key (signed as EdDSA) — VAULLS auto-detects which one you have.

3. Decorate

from fastapi import FastAPI
from vaulls import configure, paywall
from vaulls.integrations.fastapi import vaulls_middleware

app = FastAPI()
configure(pay_to="0xYourWallet")

# Free tool — no change needed
@app.post("/tools/free-lookup")
def free_lookup(data: dict):
    return {"result": "free"}

# Paid tool — one line added
@app.post("/tools/premium-analysis")
@paywall(price="0.10")
def premium_analysis(data: dict):
    return {"analysis": "detailed result", "confidence": 0.95}

# Freemium — first 5 calls free, then paid
@app.post("/tools/quick-check")
@paywall(price="0.02", free_calls=5)
def quick_check(data: dict):
    return {"valid": True}

vaulls_middleware(app)

That's it. Run your server and agents can discover prices at GET /vaulls/pricing.

How It Works

Agent calls tool ──► 402 Payment Required
                         (x402 payment details in header)
                              │
Agent signs payment ◄─────────┘
with smart wallet
                              │
Agent retries with ───────────┘
X-PAYMENT header
        │
        ▼
Server verifies via facilitator ──► Tool executes ──► Result returned
                                         │
                                    Settlement logged
  1. You own an MCP server with tools you've built
  2. You pip install vaulls and add @paywall to the tools you want to monetise
  3. Agents connect to your MCP server as normal
  4. When an agent calls a paywalled tool, it gets a 402 with payment requirements
  5. The agent's x402 client signs a USDC payment and retries — your tool executes
  6. Settlement happens on Base via the Coinbase CDP facilitator

The agent doesn't need to know about VAULLS. It just sees standard x402 payment requirements and responds with a signed payment. Any x402-compatible agent wallet works.

API Reference

@paywall decorator

from vaulls import paywall

@paywall(
    price="0.05",                          # price in USD
    asset="USDC",                          # payment asset (default: USDC)
    network="base-sepolia",                # or "base" for mainnet
    network=["base", "base-sepolia"],      # accept multiple networks
    description="My premium tool",         # shown in pricing endpoint
    free_calls=10,                         # first N calls free per caller
)
def my_tool(args):
    return result

configure()

import vaulls

vaulls.configure(
    pay_to="0xYourWallet",                # your Base wallet address
    network="base-sepolia",               # default network
    cdp_api_key_id="your_key_id",         # CDP API key ID
    cdp_api_key_secret="your_key_secret", # CDP API key secret
)

Warning: Never set pay_to to the zero address (0x000...000). It passes validation but any USDC that settles will be permanently burned. Always use a real wallet address you control.

</code></pre>
<p>Or use environment variables  no code needed:</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>VAULLS_PAY_TO</code></td>
<td>Your wallet address</td>
<td><em>(required)</em></td>
</tr>
<tr>
<td><code>VAULLS_CDP_API_KEY_ID</code></td>
<td>CDP API key ID</td>
<td><em>(required)</em></td>
</tr>
<tr>
<td><code>VAULLS_CDP_API_KEY_SECRET</code></td>
<td>CDP API key secret</td>
<td><em>(required)</em></td>
</tr>
<tr>
<td><code>VAULLS_NETWORK</code></td>
<td><code>"base-sepolia"</code> or <code>"base"</code></td>
<td><code>base-sepolia</code></td>
</tr>
<tr>
<td><code>VAULLS_FACILITATOR_URL</code></td>
<td>x402 facilitator URL</td>
<td>Coinbase CDP</td>
</tr>
</tbody>
</table>
<h3><code>enable_settlement_log()</code></h3>
<pre lang="python"><code>from vaulls import enable_settlement_log

# Log to JSONL file
enable_settlement_log("settlements.jsonl")

# Log via callback (send to your own DB, webhook, etc.)
enable_settlement_log(callback=lambda entry: print(entry))

# Both
enable_settlement_log("settlements.jsonl", callback=my_logger)

Each settlement entry contains:

{
  "timestamp": "2026-03-19T04:00:00.000Z",
  "tool": "POST /tools/premium-analysis",
  "price": "$0.10",
  "payer": "0xAgentWalletAddress",
  "tx_hash": "0x...",
  "network": "eip155:84532",
  "latency_ms": 1.8
}

Pricing Discovery

VAULLS automatically adds GET /vaulls/pricing to your FastAPI app:

{
  "server": "My Tool Server",
  "tools": [
    {
      "path": "/tools/premium-analysis",
      "methods": ["POST"],
      "price": "0.10",
      "asset": "USDC",
      "networks": ["base-sepolia"],
      "pay_to": "0xYourWallet",
      "protocol": "x402",
      "description": "Premium data analysis"
    },
    {
      "path": "/tools/quick-check",
      "methods": ["POST"],
      "price": "0.02",
      "asset": "USDC",
      "networks": ["base-sepolia"],
      "pay_to": "0xYourWallet",
      "protocol": "x402",
      "free_calls": 5
    }
  ],
  "payment_protocol": "x402",
  "facilitator": "https://api.cdp.coinbase.com/platform/v2/x402"
}

Agents can query this endpoint to discover tool costs before calling anything.

Integrations

Compatibility matrix

Framework Transport Enforcement Discovery
FastAPI HTTP ✅ Full x402 enforcement GET /vaulls/pricing
FastMCP HTTP (uvicorn) ✅ Full x402 enforcement ✅ Tool descriptions
FastMCP stdio ❌ Not applicable ✅ Tool descriptions

Enforcement means the server returns 402 Payment Required and verifies payment before executing the tool. Discovery means agents can see pricing before calling.

FastAPI

The primary integration. Adds x402 middleware to gate @paywall-decorated routes.

from vaulls.integrations.fastapi import vaulls_middleware
vaulls_middleware(app)

MCP Python SDK (FastMCP) — HTTP enforcement

Full x402 payment enforcement over FastMCP's HTTP transport. Use vaulls_mcp_enforcement_app instead of mcp.run():

import uvicorn
from mcp.server.fastmcp import FastMCP
from vaulls import configure, paywall
from vaulls.integrations.mcp import vaulls_mcp_enforcement_app

mcp = FastMCP("my-tools")
configure(pay_to="0xYourWallet")

@mcp.tool()
@paywall(price="0.05")
def my_tool(query: str) -> str:
    return "result"

app = vaulls_mcp_enforcement_app(mcp)
uvicorn.run(app, host="0.0.0.0", port=8080)

Agents calling tools/call on paywalled tools will receive a 402 Payment Required response with x402 payment details. initialize, tools/list, and unpaywalled tools pass through untouched.

MCP Python SDK (FastMCP) — stdio (pricing discovery only)

For stdio transport, VAULLS enriches tool descriptions with pricing metadata so agents see costs in tool listings. Enforcement is not applicable over stdio — use HTTP transport if you need payment gating.

from mcp.server.fastmcp import FastMCP
from vaulls import paywall
from vaulls.integrations.mcp import vaulls_mcp_setup

mcp = FastMCP("my-tools")

@mcp.tool()
@paywall(price="0.05")
def my_tool(query: str) -> str:
    return "result"

vaulls_mcp_setup(mcp)  # adds pricing to tool descriptions
mcp.run()              # stdio

Examples

Working examples in the examples/ directory:

  • fastapi_server.py — FastAPI server with free, paid, and freemium tools. The canonical confirmed-working enforcement reference.
  • fastmcp_server.py — FastMCP server. Run with --http for full enforcement, or without for stdio pricing-discovery mode.
  • smoke_test.py — End-to-end payment flow test against a live server.

Run the FastAPI example:

export VAULLS_PAY_TO=0xYourWallet
export VAULLS_CDP_API_KEY_ID=your_key_id
export VAULLS_CDP_API_KEY_SECRET=your_key_secret
uvicorn examples.fastapi_server:app --reload
# Visit http://localhost:8000/vaulls/pricing

Run the FastMCP example with HTTP enforcement:

export VAULLS_PAY_TO=0xYourWallet
export VAULLS_CDP_API_KEY_ID=your_key_id
export VAULLS_CDP_API_KEY_SECRET=your_key_secret
python examples/fastmcp_server.py --http
# Agents connect to http://localhost:8080/mcp

Why VAULLS?

The problem: MCP servers give AI agents access to powerful tools, but there's no standard way for tool developers to get paid. The x402 protocol solves the payment mechanics, but integrating it requires understanding EIP-712 signatures, facilitator APIs, and middleware patterns.

The solution: VAULLS wraps all that complexity into a single decorator. You set a price, VAULLS handles the rest. Your tools, your server, your wallet, your revenue.

The analogy: x402 is the payment protocol (like credit card networks). VAULLS is the developer SDK (like Stripe). You don't need to understand the protocol — you just set a price.

Related Projects

  • x402 — The payment protocol VAULLS builds on
  • Carbon-Contractors — A Human-as-a-Service MCP with x402 baked in (by the same team)
  • MCP — Model Context Protocol specification

Stack

  • Payment: x402 protocol (EIP-712 signatures)
  • Settlement: USDC on Base
  • Facilitator: Coinbase CDP
  • Integrations: FastAPI, MCP Python SDK (FastMCP)
  • License: MIT

Contributing

VAULLS is open source under the MIT license. Issues and PRs welcome at github.com/North-Metro-Tech/vaulls.

Built by North Metro Tech.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vaulls-0.3.0.tar.gz (30.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vaulls-0.3.0-py3-none-any.whl (32.0 kB view details)

Uploaded Python 3

File details

Details for the file vaulls-0.3.0.tar.gz.

File metadata

  • Download URL: vaulls-0.3.0.tar.gz
  • Upload date:
  • Size: 30.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vaulls-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9c6e27e521e1196b030cedcd0c085e37b50cae435e113132eb954814d59d9ac8
MD5 d7c0b2460c932fccc9a0b65eb5070a0b
BLAKE2b-256 41e6abd35d466d017a63a24852357ec1cdaa5d8dde775356aeb43d1fba81935f

See more details on using hashes here.

Provenance

The following attestation bundles were made for vaulls-0.3.0.tar.gz:

Publisher: publish.yml on North-Metro-Tech/vaulls

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vaulls-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: vaulls-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 32.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vaulls-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec907011df975d74b54b9c7a02e6982b60f7f68a53325fb36eb2c8ece0ced6c0
MD5 5e7c91c4769d957293316bf3d3402bfd
BLAKE2b-256 f783f7b748344a58b07fcf5ea2887f9b4e58bc8cd3e8aba421cba163d2ea4405

See more details on using hashes here.

Provenance

The following attestation bundles were made for vaulls-0.3.0-py3-none-any.whl:

Publisher: publish.yml on North-Metro-Tech/vaulls

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page