x402 Universal Payer
io.github.nirholas/x402-bridge · 231 stars · JavaScript · Apache-2.0
MCP server Pay any x402 endpoint on the open web: auto-paying bridge with Bazaar discovery and spend caps.
Install
The repo has no one-line install. Follow its README.
Published as
- npm
@three-ws/mcp-bridgestdio
From the server's entry in the official MCP Registry.
Configuration
| Name | Set as | What it is |
|---|---|---|
MCP_BRIDGE_EVM_PRIVATE_KEYOptional · Secret | Env var | 0x-prefixed 32-byte hex private key that funds USDC payments on EVM chains (Base, Arbitrum, …). At least one of the EVM/SVM keys is required. Treat like cash — use a dedicated low-balance wallet. |
MCP_BRIDGE_SVM_PRIVATE_KEYOptional · Secret | Env var | Solana secret key that funds USDC payments: base58 64-byte secret key (Phantom / solana-keygen format) or a JSON array of 64 integers. At least one of the EVM/SVM keys is required. Treat like cash. |
MCP_BRIDGE_MAX_PRICE_PER_CALL_ATOMICOptional | Env var | Per-call spending cap in atomic units (USDC has 6 decimals). Payments above this abort with a clear reason. |
MCP_BRIDGE_MAX_TOTAL_ATOMICOptional | Env var | Cumulative session spending ceiling in atomic units. Once total spend would exceed it, further payments abort until restart. |
MCP_BRIDGE_ALLOWED_PAYTOOptional | Env var | Comma-separated payee allowlist. When set, any payment whose payTo address is not listed is refused. |
MCP_BRIDGE_ALLOWED_HOSTSOptional | Env var | Comma-separated hostname allowlist for outbound paid requests. When set, any other host is refused before a request is signed. |
MCP_BRIDGE_ALLOW_HTTPOptional | Env var | Set to 1 to allow http:// targets (local development only). https is enforced otherwise. |
MCP_BRIDGE_DISCOVER_LIMITOptional | Env var | Max number of x402 Bazaar resources to register as dynamic tools at startup. Set 0 to disable discovery. |
MCP_BRIDGE_BAZAAR_URLOptional | Env var | x402 Bazaar discovery endpoint. Override to point at a self-hosted or alternative bazaar. |
MCP_BRIDGE_BATCH_DEPOSIT_MULTIPLIEROptional | Env var | How many request-amounts to deposit at once when opening an EVM batch-settlement channel. |
MCP_BRIDGE_MAX_DEPOSIT_ATOMICOptional | Env var | Hard cap in atomic units on a single batch-settlement channel deposit or top-up. |
X402_MCP_BRIDGE_CHANNELS_DIROptional | Env var | Directory for persisted batch-settlement channel state (survives client restarts). |
RPC_URL_8453Optional | Env var | Per-chain RPC override, one variable per chain id (RPC_URL_<chainId>, e.g. RPC_URL_8453 for Base). Defaults to viem's public RPC for that chain. |
Files
@three-ws/mcp-bridge
One MCP server that can pay any x402-paid endpoint on the open web — the universal x402 payer for AI agents.
Quick start · Security · Tools · Environment · three.ws
A Model Context Protocol server that can pay any x402-paid endpoint on the open web. Point your agent at a URL that answers
402 Payment Required; the bridge signs, pays, retries, and hands back the response plus the settlement receipt — EVM exact, EVM batch-settlement, and Solana exact, all behind hard spending caps. It also pre-loads a tool per service discovered on the Coinbase x402 Bazaar, so the entire paid-API economy shows up in your tool list.
Quick start
Claude Code:
claude mcp add x402-bridge -e MCP_BRIDGE_SVM_PRIVATE_KEY=... -- npx -y @three-ws/mcp-bridge
Use -e MCP_BRIDGE_EVM_PRIVATE_KEY=0x... instead (or as well) to pay on Base and other EVM chains. At least one key is required.
Claude Desktop (claude_desktop_config.json) or Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"x402-bridge": {
"command": "npx",
"args": ["-y", "@three-ws/mcp-bridge"],
"env": {
"MCP_BRIDGE_EVM_PRIVATE_KEY": "0x…buyer key…",
"MCP_BRIDGE_SVM_PRIVATE_KEY": "…base58 64-byte secret key…",
"MCP_BRIDGE_MAX_PRICE_PER_CALL_ATOMIC": "100000",
"MCP_BRIDGE_DISCOVER_LIMIT": "20"
}
}
}
}
Restart the client and ask for something like "pay $0.01 on Base for a weather report" — the model picks a matching Bazaar tool (or call_paid_endpoint), and the bridge auto-pays via x402.
Security and spending controls
This server holds private keys and spends real USDC. Read this section before configuring it.
- Use a dedicated, low-balance wallet.
MCP_BRIDGE_EVM_PRIVATE_KEY/MCP_BRIDGE_SVM_PRIVATE_KEYshould never be a main wallet. Fund it with only what you are willing to let an agent spend. - Per-call cap. Any payment above
MCP_BRIDGE_MAX_PRICE_PER_CALL_ATOMIC(default100000= $0.10 USDC) is refused before a payload is signed, with an error naming the network, asset, and cap. - Session ceiling. Cumulative spend per process is capped by
MCP_BRIDGE_MAX_TOTAL_ATOMIC(default1000000= $1.00 USDC). This bounds the damage of a looping or prompt-injected agent: once the ceiling is reached, every further payment aborts until restart. The accumulator reserves atomically, so concurrent calls cannot jointly overshoot it. - Payee allowlist. Set
MCP_BRIDGE_ALLOWED_PAYTO(comma-separated addresses) to refuse payment to any recipient you have not explicitly trusted. - SSRF guard. Every outbound payable URL — whether supplied by the model or by a Bazaar listing — passes one chokepoint that enforces an https-only scheme policy, resolves the hostname, and rejects the request if any resolved address is private, loopback, link-local (including
169.254.169.254cloud metadata), CGNAT, ULA, or unspecified. Literal-IP hosts are checked directly; redirects are never followed (a public host cannot 3xx the bridge into internal infrastructure).http://is available only behind the explicitMCP_BRIDGE_ALLOW_HTTP=1dev opt-in. - Host allowlist. Set
MCP_BRIDGE_ALLOWED_HOSTS(comma-separated hostnames) for strict mode: only listed hosts can be paid at all. - Deposit caps. Batch-settlement channel deposits are bounded by
MCP_BRIDGE_MAX_DEPOSIT_ATOMIC(default $5.00) regardless of what a server requests. - Honest annotations. Every paying tool is annotated
readOnlyHint: false,idempotentHint: false,openWorldHint: true, so MCP hosts apply their strictest confirmation policy. Retrying a paid call is a new charge.
What it exposes
On startup the bridge registers:
| Tool | What it does |
|---|---|
call_paid_endpoint |
Universal fallback: hit any URL, auto-pay if it returns 402. Returns the response + parsed settlement. |
list_bazaar_tools |
Returns the cached list of Bazaar-discovered tools (name, resource, accepted payment terms). Free. |
refresh_bazaar |
Re-queries the x402 Bazaar and re-registers dynamic tools without restarting. Free. |
paid_<derived> … |
One tool per discovered Bazaar resource (up to MCP_BRIDGE_DISCOVER_LIMIT), with that endpoint's schema. |
Tools whose prices all exceed the per-call cap are filtered out at discovery time, so the model never sees a tool it cannot afford.
Tool annotations
Every tool carries MCP ToolAnnotations so hosts can apply the right confirmation policy:
call_paid_endpointand every dynamicpaid_*tool:readOnlyHint: false,destructiveHint: false,idempotentHint: false,openWorldHint: true. These spend real USDC — each call settles a payment (capped byMCP_BRIDGE_MAX_PRICE_PER_CALL_ATOMIC), and retrying is a new charge. They never delete or overwrite caller state, hence not destructive.list_bazaar_tools:readOnlyHint: true,idempotentHint: true,openWorldHint: false. Pure in-process cache read; free, no network.refresh_bazaar:readOnlyHint: false,destructiveHint: false,idempotentHint: false,openWorldHint: true. Free (no payment), but it mutates the registered tool set from the live Bazaar feed, so repeat calls can differ.
Tool results that are plain objects are returned as both a JSON text block (backward compatible) and structuredContent for typed clients.
Payment schemes
Payment paths registered on the buyer client:
eip155:*→BatchSettlementEvmScheme(preferred when the server advertises it; voucher-based, no per-call gas)eip155:*→ExactEvmScheme(used when the server advertisesscheme: "exact")solana:*→ExactSvmScheme(USDC SPL transfer co-signed by the advertised fee payer)
Batch-settlement channel state is persisted to ~/.x402-mcp-bridge/channels/client/ so client restarts do not re-deposit on the next call.
Environment
| Variable | Required | Default | Notes |
|---|---|---|---|
MCP_BRIDGE_EVM_PRIVATE_KEY |
one of EVM/SVM required | — | 0x-prefixed 32-byte hex. Funds USDC payments on Base, Arbitrum, etc. |
MCP_BRIDGE_SVM_PRIVATE_KEY |
one of EVM/SVM required | — | base58 64-byte secret key (Phantom/solana-keygen format) or 64-int JSON array. |
MCP_BRIDGE_MAX_PRICE_PER_CALL_ATOMIC |
no | 100000 (= $0.10 USDC at 6 decimals) |
Per-call spending cap. Payment aborts above this with a clear reason. |
MCP_BRIDGE_MAX_TOTAL_ATOMIC |
no | 1000000 (= $1.00 USDC) |
Cumulative session spending ceiling. Aborts further payments once reached. |
MCP_BRIDGE_ALLOWED_PAYTO |
no | — (any payee) | Comma-separated payee allowlist. When set, unlisted payTo addresses are refused. |
MCP_BRIDGE_ALLOWED_HOSTS |
no | — (any public host) | Comma-separated hostname allowlist for outbound paid requests. |
MCP_BRIDGE_ALLOW_HTTP |
no | 0 |
Set 1 to allow http:// targets. Local development only. |
MCP_BRIDGE_DISCOVER_LIMIT |
no | 20 |
Max number of Bazaar tools to register dynamically. Set 0 to disable discovery. |
MCP_BRIDGE_BAZAAR_URL |
no | https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources |
Override to point at a self-hosted or alternative bazaar. |
MCP_BRIDGE_BATCH_DEPOSIT_MULTIPLIER |
no | 5 |
How many request-amounts to deposit at once when opening a batch channel. |
MCP_BRIDGE_MAX_DEPOSIT_ATOMIC |
no | 5000000 (= $5.00 USDC) |
Hard cap on the deposit amount per channel open / top-up. |
X402_MCP_BRIDGE_CHANNELS_DIR |
no | ~/.x402-mcp-bridge/channels |
Override the directory used by FileClientChannelStorage. |
RPC_URL_<chainId> |
no | viem default public RPC | Per-chain RPC override. Example: RPC_URL_8453=https://mainnet.base.org. |
MCP_BRIDGE_* key vars also fall back to EVM_PRIVATE_KEY / SVM_PRIVATE_KEY if you already have those set.
Spending cap behavior
The pre-payment hook inspects the selected accepts entry and aborts payload creation if the amount exceeds the per-call cap, the payee is outside the allowlist, or the session ceiling would be crossed. The tool result then carries a clear error message naming the network, asset, and the limit that was hit — useful for the model to decide whether to ask you to raise it.
Inspecting without a client
MCP_BRIDGE_SVM_PRIVATE_KEY=... npx -y @modelcontextprotocol/inspector npx -y @three-ws/mcp-bridge
The inspector connects over stdio and lists the static tools (call_paid_endpoint, list_bazaar_tools, refresh_bazaar) plus one dynamic tool per discovered Bazaar entry.
Programmatic use
Any Node module can consume an x402 endpoint through the same buyer client:
import { buildBuyerAxios } from '@three-ws/mcp-bridge/src/x402-axios-client.js';
const { api } = await buildBuyerAxios();
const res = await api.get('https://api.example.com/some-paid-resource');
The same spending caps, SSRF guard, and channel-storage rules apply. Idle batch channels can be refunded out-of-band with the @x402 SDK's client.refund(resourceUrl, { amount }).
Tests
npm test # hermetic: url-guard SSRF policy, spending-cap hook, tool naming, stdio boot npm run test:smoke # live: boots against the real Bazaar and asserts the cap blocks a real paid call
The hermetic suite generates throwaway keypairs in-process; no real keys or funds are ever involved.
License
All rights reserved. See LICENSE.
Facts
- Kind
- MCP server
- Group
- Uncategorized
- Stars
- 231
- License
- Apache-2.0
- Language
- JavaScript
- Last push
- 2026-10-12
- Forks
- 63
- MCP Registry
- io.github.nirholas/x402-bridge
- Homepage
- three.ws
- Topics
- animation, avatar, gltf, llm, mcp, webgl, 3d-generation, ai-agents, digital-human, generative-ai, glb, image-to-3d, mcp-server, model-context-protocol, solana, text-to-3d, threejs, web-components, webxr, x402
- 1REAio.github.morluto/reaReverse engineer anything from your terminal or agent with one CLI and MCP server.125.3k
- 2com.browser-use/browser-usecom.browser-use/browser-useControl a real Chrome browser to complete any task: fill forms, extract data, book flights.117.7k
- 3World Monitorapp.worldmonitor/mcpLive markets, conflicts, country risk, chokepoints, energy, and China decision signals. 93 tools.88.3k
- 4Scrapling MCP Serverd4vinci/scrapling🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scraplingdev86.9k
- 5Everythingmodelcontextprotocol/serversThis MCP server attempts to exercise all the features of the MCP protocol. It is not intended to be a useful server, but rather a test server for builders of MCP clients. It implements prompts, tools, resources, sampling, and more to showcase MCP capabilities.85.8k
- 6Fetchmodelcontextprotocol/serversA Model Context Protocol server that provides web content fetching capabilities. This server enables LLMs to retrieve and process content from web pages, converting HTML to markdown for easier consumption.85.8k