[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is a protocol for passing context between LLMs and other AI agents. This page shows how to use the x402 payment protocol with MCP to ma
What is this integration?
This guide walks you through running an MCP server that can access paid APIs using the x402 protocol. The MCP server acts as a bridge between Claude Desktop (or any MCP-compatible client) and a paid API (such as the sample weather API in the x402 repo). When Claude (or another agent) calls a tool, the MCP server will:
Detect if the API requires payment (via HTTP 402 with PAYMENT-REQUIRED header)
Automatically handle the payment using your wallet via the registered x402 scheme
Return the paid data to the client (e.g., Claude)
This lets you (or your agent) access paid APIs programmatically, with no manual payment steps.
# Clone the x402 repositorygitclonehttps://github.com/coinbase/x402.gitcdx402/examples/typescript# Install dependencies and build packagespnpminstall&&pnpmbuild# Navigate to the MCP client examplecdclients/mcp
2. Configure Claude Desktop
Add the MCP server to your Claude Desktop configuration:
3. Start the x402 Server
Make sure your x402-compatible server is running at the URL specified in RESOURCE_SERVER_URL:
4. Restart Claude Desktop
Restart Claude Desktop to load the new MCP server, then ask Claude to use the get-data-from-resource-server tool.
Environment Variables
Variable
Description
Required
EVM_PRIVATE_KEY
Your EVM wallet's private key (0x prefixed)
One of EVM or SVM required
SVM_PRIVATE_KEY
Your Solana wallet's private key (base58 encoded)
One of EVM or SVM required
RESOURCE_SERVER_URL
The base URL of the paid API
Yes
ENDPOINT_PATH
The specific endpoint path (e.g., /weather)
Yes
Implementation
The MCP server uses @x402/axios to wrap axios with automatic payment handling:
How It Works
The MCP server exposes a tool that, when called, fetches data from a paid API endpoint. If the endpoint requires payment, the x402 axios wrapper automatically handles the payment handshake:
402 Response: The server returns HTTP 402 with PAYMENT-REQUIRED header
Parse Requirements: The wrapper extracts payment requirements from the header
Create Payment: Uses the registered scheme (EVM or SVM) to create a payment payload
Retry Request: Sends the original request with the PAYMENT-SIGNATURE header
Return Data: Once payment is verified, the data is returned to Claude
Multi-Network Support
The example supports both EVM (Base, Ethereum) and Solana networks. The x402 client automatically selects the appropriate scheme based on the payment requirements:
When the server returns a 402 response, the client checks the network field in the payment requirements:
eip155:* networks use the EVM scheme
solana:* networks use the SVM scheme
Response Handling
Payment Required (402)
When a payment is required, the client receives:
The wrapper automatically:
Parses the payment requirements
Creates and signs a payment using the appropriate scheme
Retries the request with the PAYMENT-SIGNATURE header
Successful Response
After payment is processed, the MCP server returns:
Architecture Diagram
Dependencies
The example uses these x402 v2 packages:
How the Pieces Fit Together
x402-compatible server: Hosts the paid API (e.g., weather data). Responds with HTTP 402 and PAYMENT-REQUIRED header if payment is required.
MCP server (this implementation): Acts as a bridge, handling payment via @x402/axios and exposing tools to MCP clients.
Claude Desktop: Calls the MCP tool, receives the paid data, and displays it to the user.
{
"mcpServers": {
"demo": {
"command": "pnpm",
"args": [
"--silent",
"-C",
"<absolute path to this repo>/examples/typescript/clients/mcp",
"dev"
],
"env": {
"EVM_PRIVATE_KEY": "<private key of a wallet with USDC on Base Sepolia>",
"SVM_PRIVATE_KEY": "<base58-encoded private key of a Solana wallet with USDC on Devnet>",
"RESOURCE_SERVER_URL": "http://localhost:4021",
"ENDPOINT_PATH": "/weather"
}
}
}
}
# In another terminal, from the examples/typescript directory
cd servers/express
pnpm dev
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import axios from "axios";
import { x402Client, wrapAxiosWithPayment } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { registerExactSvmScheme } from "@x402/svm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { base58 } from "@scure/base";
import { config } from "dotenv";
config();
const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`;
const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string;
const baseURL = process.env.RESOURCE_SERVER_URL || "http://localhost:4021";
const endpointPath = process.env.ENDPOINT_PATH || "/weather";
if (!evmPrivateKey && !svmPrivateKey) {
throw new Error("At least one of EVM_PRIVATE_KEY or SVM_PRIVATE_KEY must be provided");
}
/**
* Creates an axios client configured with x402 payment support for EVM and/or SVM.
*/
async function createClient() {
const client = new x402Client();
// Register EVM scheme if private key is provided
if (evmPrivateKey) {
const evmSigner = privateKeyToAccount(evmPrivateKey);
registerExactEvmScheme(client, { signer: evmSigner });
}
// Register SVM scheme if private key is provided
if (svmPrivateKey) {
const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey));
registerExactSvmScheme(client, { signer: svmSigner });
}
return wrapAxiosWithPayment(axios.create({ baseURL }), client);
}
async function main() {
const api = await createClient();
// Create an MCP server
const server = new McpServer({
name: "x402 MCP Client Demo",
version: "2.0.0",
});
// Add a tool that calls the paid API
server.tool(
"get-data-from-resource-server",
"Get data from the resource server (in this example, the weather)",
{},
async () => {
const res = await api.get(endpointPath);
return {
content: [{ type: "text", text: JSON.stringify(res.data) }],
};
},
);
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch(error => {
console.error(error);
process.exit(1);
});
import { x402Client, wrapAxiosWithPayment } from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { registerExactSvmScheme } from "@x402/svm/exact/client";
const client = new x402Client();
// Register EVM scheme for Base/Ethereum payments
registerExactEvmScheme(client, { signer: evmSigner });
// Register SVM scheme for Solana payments
registerExactSvmScheme(client, { signer: svmSigner });
// Now handles both EVM and Solana networks automatically
const httpClient = wrapAxiosWithPayment(axios.create({ baseURL }), client);