Enable MCP
Setmcp: true in your SellerConfig. The Express router automatically mounts all MCP routes alongside the existing A2A and x402 HTTP endpoints.
Routes
The integration mounts four routes on the Express router:Tools
The MCP server exposes two tools:discover_plans
Takes no arguments. Returns the full plan catalog as JSON:request_access
TakesplanId (required) and resourceId (optional, defaults to "default").
When called without payment, it returns a PaymentRequired response. When called with a valid x402 payment, it settles on-chain and returns an access grant.
Payment Flow
There are two paths to complete a payment, depending on the client’s capabilities.- Path A: HTTP x402 (Current Clients)
- Path B: Native x402 MCP (Future Clients)
This is the path used by current MCP clients like Claude Desktop, Claude Code, and Cursor. The agent uses a companion payment tool (such as Coinbase’s
payments-mcp) to settle via HTTP.Step-by-step:- Agent calls
discover_plansto get the catalog - Agent calls
request_access({ planId: "basic" })with no payment attached - Server returns
isError: truewith a PaymentRequired response containingx402PaymentUrlandpaymentInstructions - Agent calls
make_http_request_with_x402(frompayments-mcp) to POST to thex402PaymentUrl payments-mcpsigns an EIP-3009 authorization off-chain and sends it as aPAYMENT-SIGNATUREheader- The
/x402/accessendpoint settles the payment on-chain and returns an AccessGrant with a JWT
The
content[0].text field contains x402PaymentUrl and human-readable paymentInstructions so that LLM agents can parse the next step even without structured content support.Error Handling
Already-redeemed transactions return the original AccessGrant. The
requestId is derived deterministically from the payment signature, so retries with the same payment always resolve to the same challenge.Connecting from Claude Code
Add your MCP server to.mcp.json in your project root:
discover_plans and request_access tools automatically.
Testing with curl
List available tools:discover_plans:
Why Stateless?
The MCP transport creates a freshMcpServer and StreamableHTTPServerTransport for every request. This is intentional:
- Tools are pure request/response. There is no streaming, subscriptions, or server-initiated messages.
- All state lives in external stores. ChallengeStore and SeenTxStore (Redis or Postgres) hold challenge state and double-spend records.
- Horizontal scaling. No sticky sessions, no in-memory state, no affinity requirements. Put it behind any load balancer.
- No memory leaks. Each server instance is created, used, and closed within a single request lifecycle.

