Autonomous x402 payment handling for LLM applications. Available as both an MCP server and a CLI code generator.
Best for: Integrating x402 payments directly into your application's codebase.
Scaffold x402 payment handling code into your project:
npx x402-agent initAutomatically generates:
x402-endpoints.json- Configure your x402 endpointslib/x402/- Payment utilities (logger, config, wallet, types)- Framework-specific API routes (Vite, Next.js, or Express)
Supported frameworks: Vite, Next.js, Express, or framework-agnostic TypeScript utilities.
Best for: Using with Claude Desktop, Claude Code, or other MCP clients.
Add x402 payment capabilities to your MCP-compatible LLM client:
npx x402-agentExposes configured x402 endpoints as MCP tools for autonomous agent access.
- Autonomous Payments: Automatic x402 payment handling using CDP embedded wallets
- Multiple Integration Modes: CLI code generator or MCP server
- Framework Support: Vite, Next.js, Express, or framework-agnostic
- Flexible Configuration: JSON-based endpoint configuration with environment variable support
- Security First: Trust model ensures only approved endpoints can be called
- Multi-Network Support: Works with Base, Base Sepolia, Ethereum, and Sepolia testnets
- Production Ready: Used in production applications with automatic payment retries
- Node.js >= 18.0.0
- A CDP embedded wallet with USDC balance
# Navigate to your project directory
cd my-ai-app
# Run the CLI to scaffold x402 payment handling
npx x402-agent init
# Edit the generated x402-endpoints.json to configure your endpoints
# Add your private key to .env
echo "PRIVATE_KEY=0x..." >> .env
# Install dependencies and start using x402 endpoints!
npm installThe CLI creates the following files in your project:
x402-endpoints.json- Configuration file with example endpointslib/x402/payment-logger.ts- Payment logging utilities with BaseScan linkslib/x402/config.ts- Config loader with environment variable interpolationlib/x402/types.ts- TypeScript type definitionslib/x402/wallet.ts- Wallet setup and x402-fetch wrapper utilities
Vite (+ Vercel Functions):
api/x402/proxy.ts- Generic proxy handler for x402 endpoints
Next.js (App Router):
app/api/x402/[endpoint]/route.ts- Dynamic route handler
Express:
routes/x402.ts- Express router with middleware
None (Framework-agnostic):
- Only the shared utilities above (no API routes)
npx x402-agent init [options]
Options:
-f, --framework <type> Specify framework (vite|nextjs|express|none)
--auto-detect Auto-detect framework from package.json (default)
-o, --output-dir <path> Output directory (default: current directory)
--skip-install Skip automatic dependency installation
-h, --help Display helpnpx x402-agent serve [options]
Options:
-t, --transport <type> Transport type: stdio or sse (default: stdio)
-p, --port <number> Port for SSE transport (default: 8000)
--host <address> Host address for SSE transport (default: 0.0.0.0)
-h, --help Display help
Examples:
npx x402-agent serve # stdio mode (Claude Desktop)
npx x402-agent serve --transport sse # SSE mode on port 8000
npx x402-agent serve --transport sse -p 3000 # SSE mode on port 3000# Auto-detect Vite and generate appropriate files
cd my-vite-app
npx x402-agent init
# Result:
# ✅ x402-endpoints.json
# ✅ lib/x402/*.ts (utilities)
# ✅ api/x402/proxy.ts (Vercel Function handler)Then use in your React components:
// Call x402 endpoint from your frontend
const response = await fetch('/api/x402/proxy', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
endpointId: 'minifetch_extract_metadata',
params: { url: 'https://example.com' }
})
});
const result = await response.json();
console.log('Data:', result.data);
console.log('Transaction:', result.txHash);
console.log('BaseScan:', `https://basescan.org/tx/${result.txHash}`);cd my-nextjs-app
npx x402-agent init --framework nextjs
# Result:
# ✅ x402-endpoints.json
# ✅ lib/x402/*.ts (utilities)
# ✅ app/api/x402/[endpoint]/route.ts (App Router dynamic route)Use in Server Components or API routes:
// app/page.tsx
async function extractMetadata(url: string) {
const response = await fetch('/api/x402/minifetch_extract_metadata', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url })
});
return response.json();
}cd my-express-app
npx x402-agent init --framework express
# Result:
# ✅ x402-endpoints.json
# ✅ lib/x402/*.ts (utilities)
# ✅ routes/x402.ts (Express router)Mount the router in your Express app:
// server.ts
import express from 'express';
import x402Router from './routes/x402.js';
const app = express();
app.use(express.json());
// Mount x402 router
app.use('/api/x402', x402Router);
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
// Now call: POST /api/x402/minifetch_extract_metadataAfter running the CLI, edit x402-endpoints.json to configure your endpoints:
{
"wallet": {
"provider": "cdp-embedded",
"network": "base",
"privateKey": "${PRIVATE_KEY}"
},
"endpoints": [
{
"id": "minifetch_extract_metadata",
"name": "Extract URL Metadata",
"url": "https://minifetch.com/api/v1/x402/extract/url-metadata",
"method": "GET",
"description": "Fetch and extract HTML metadata from a URL",
"parameters": {
"type": "object",
"properties": {
"url": { "type": "string", "description": "URL to extract" }
},
"required": ["url"]
},
"estimatedCost": "$0.01",
"trusted": true
}
]
}Set your private key in .env:
PRIVATE_KEY="0x..."The MCP server supports two transport modes:
- stdio (default) - For local MCP clients like Claude Desktop
- SSE (Server-Sent Events) - For HTTP-based remote MCP clients like OpenAI Responses API, ChatGPT Connectors, and deployed web apps
Run locally for Claude Desktop or other local MCP clients:
npx x402-agent
# or explicitly:
npx x402-agent serve --transport stdioRun as HTTP server for OpenAI, ChatGPT, and remote MCP clients:
npx x402-agent serve --transport sse --port 8000Server will start at http://localhost:8000/sse/
Available endpoints:
/sse- MCP SSE connection endpoint/message- MCP message endpoint/health- Health check/- Server info
Deploy to production:
See examples/vercel-deployment/ for deploying to Vercel, or use any Node.js hosting:
# Replit, Railway, etc.
npx x402-agent serve --transport sse --port 8000 --host 0.0.0.0Then use with OpenAI Responses API:
const response = await openai.responses.create({
model: 'gpt-4o',
input: [{
role: 'user',
content: [{ type: 'input_text', text: 'Extract metadata from example.com' }]
}],
tools: [{
type: 'mcp',
server_url: 'https://your-x402-server.vercel.app/sse/',
allowed_tools: ['minifetch_extract_metadata'],
require_approval: 'never'
}]
});Or add to ChatGPT Connectors:
- Go to ChatGPT Settings → Connectors
- Add new MCP server:
https://your-x402-server.vercel.app/sse/ - ChatGPT will discover your x402 tools automatically
- An MCP-compatible client (Claude Desktop, Claude Code, OpenAI, ChatGPT, etc.)
npm install -g @x402-agent/mcp-servernpx @x402-agent/mcp-servermkdir -p ~/.x402-agentCreate ~/.x402-agent/endpoints.json:
{
"wallet": {
"provider": "cdp-embedded",
"network": "base",
"privateKey": "${PRIVATE_KEY}"
},
"endpoints": [
{
"id": "minifetch_extract_metadata",
"name": "Extract URL Metadata",
"url": "https://minifetch.com/api/v1/x402/extract/url-metadata",
"method": "GET",
"description": "Fetch and extract HTML metadata from a specified URL. Returns all HTML meta tags, Open Graph tags, Twitter tags, headings, image tags, and response headers. Set includeResponseBody=true to return entire response body as a string. Useful for SEO and AI research projects.",
"category": "web-scraping",
"parameters": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The URL from which to extract HTML metadata"
},
"includeResponseBody": {
"type": "string",
"description": "If set to 'true', includes the full HTML response body as a string in the result"
}
},
"required": ["url"]
},
"estimatedCost": "$0.01",
"trusted": true
}
]
}See config/endpoints.example.json for a complete example with multiple endpoints.
Create a .env file or set environment variables:
export PRIVATE_KEY="0x..."
export X402_CONFIG_PATH="~/.x402-agent/endpoints.json" # Optional, defaults to this
export DEBUG="false" # Set to "true" for debug loggingEdit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"x402-agent": {
"command": "npx",
"args": ["-y", "@x402-agent/mcp-server"],
"env": {
"PRIVATE_KEY": "0x...",
"X402_CONFIG_PATH": "~/.x402-agent/endpoints.json"
}
}
}
}Edit ~/.claude/settings.json:
{
"mcp": {
"x402-agent": {
"command": "npx @x402-agent/mcp-server",
"env": {
"PRIVATE_KEY": "0x...",
"X402_CONFIG_PATH": "~/.x402-agent/endpoints.json"
}
}
}
}Edit ~/.codex/config.toml:
[[mcpServers]]
name = "x402-agent"
command = "npx"
args = ["@x402-agent/mcp-server"]
[mcpServers.env]
PRIVATE_KEY = "0x..."
X402_CONFIG_PATH = "~/.x402-agent/endpoints.json"Once configured, your LLM agent can autonomously use the endpoints:
User: "Extract metadata from https://example.com and tell me about the page"
Agent: [Calls minifetch_extract_metadata tool]
[Payment automatically handled via x402]
[Receives metadata and summarizes]
The agent will:
- Discover available tools via
tools/list - Call endpoints via
tools/call - Handle 402 payment responses automatically
- Return results to the user
Install the MCP SDK and integrate the x402 agent into your backend:
npm install @modelcontextprotocol/sdkimport { spawn } from 'child_process';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
// Start MCP server as a child process
const transport = new StdioClientTransport({
command: 'npx',
args: ['@x402-agent/mcp-server'],
env: {
PRIVATE_KEY: process.env.PRIVATE_KEY,
X402_CONFIG_PATH: './x402-endpoints.json'
}
});
const client = new Client({ name: 'my-app', version: '1.0.0' }, {});
await client.connect(transport);
// Call x402-protected endpoints
const result = await client.callTool({
name: 'minifetch_extract_metadata',
arguments: { url: 'https://example.com' }
});
console.log('Result:', result.content);
console.log('Transaction:', result.txHash);
console.log('BaseScan:', `https://basescan.org/tx/${result.txHash}`);The server looks for endpoints.json in the following order:
X402_CONFIG_PATHenvironment variable (explicit path)./x402-endpoints.json(project root)./config/endpoints.json(config folder)~/.x402-agent/endpoints.json(user home, fallback)
When deploying to production:
- Add x402-endpoints.json to your repo (without secrets - use
${PRIVATE_KEY}template) - Set PRIVATE_KEY as environment variable in your deployment platform
- Run the MCP server as a child process from your backend
- Monitor wallet balance and set up alerts for low USDC
- Use separate wallets for dev/staging/prod environments
| Field | Type | Description | Required |
|---|---|---|---|
provider |
string | Wallet provider (only "cdp-embedded" supported) | Yes |
network |
string | Network: "base", "base-sepolia", "ethereum", "sepolia" | Yes |
privateKey |
string | Private key (hex or ${ENV_VAR}) | Yes |
| Field | Type | Description | Required |
|---|---|---|---|
id |
string | Unique identifier (snake_case) | Yes |
name |
string | Human-readable name | Yes |
url |
string | HTTPS URL of x402 endpoint | Yes |
method |
string | HTTP method (GET, POST, PUT, PATCH, DELETE) | Yes |
description |
string | Tool description (min 20 chars) | Yes |
parameters |
object | JSON Schema for parameters | Yes |
trusted |
boolean | Allow autonomous execution | Yes |
category |
string | Endpoint category | No |
estimatedCost |
string | Estimated cost per call | No |
PRIVATE_KEY: Your CDP wallet private key (required)X402_CONFIG_PATH: Path to endpoints.json (default:~/.x402-agent/endpoints.json)DEBUG: Enable debug logging (default:false)
# Clone the repository
git clone https://github.com/yourusername/x402-agent.git
cd x402-agent
# Install dependencies
npm install
# Build
npm run build
# Run in development mode
npm run devx402-agent/
├── src/
│ ├── index.ts # Main entry point
│ ├── server.ts # MCP server setup
│ ├── handlers/
│ │ ├── listTools.ts # tools/list handler
│ │ └── callTool.ts # tools/call handler
│ ├── registry/
│ │ ├── types.ts # TypeScript types
│ │ ├── EndpointRegistry.ts
│ │ └── validator.ts # Config validation
│ ├── payment/
│ │ ├── WalletManager.ts # CDP wallet
│ │ └── PaymentHandler.ts # x402 integration
│ └── utils/
│ ├── errors.ts # Error classes
│ ├── logger.ts # Logging
│ └── retry.ts # Retry logic
├── config/
│ └── endpoints.example.json
└── package.json
- Check that Node.js >= 18.0.0 is installed:
node --version - Verify PRIVATE_KEY is set correctly
- Check configuration file syntax:
cat ~/.x402-agent/endpoints.json | jq
- Restart your MCP client after configuration changes
- Check server logs for errors (set
DEBUG=true) - Verify
trusted: trueis set in endpoint config
- Ensure wallet has sufficient USDC balance
- Check network matches endpoint requirements
- Verify private key has correct format (0x...)
- Validate JSON syntax
- Ensure all required fields are present
- Check endpoint URLs use HTTPS
- Verify parameter schemas are valid JSON Schema
Only endpoints with "trusted": true can be called autonomously. This prevents:
- Unauthorized spending on unknown endpoints
- Malicious endpoint injection
- Unintended payment execution
Review endpoints carefully before setting trusted: true!
✅ DO:
- Use environment variables for private keys (
${PRIVATE_KEY}) - Use separate wallets for dev/staging/prod
- Monitor wallet balance and set up alerts
- Keep private keys in secure secret management systems
- Rotate keys periodically
❌ DON'T:
- Commit private keys to git
- Hardcode private keys in endpoints.json
- Share wallets between different applications
- Use production wallets for testing
- All endpoints must use HTTPS
- Configuration files should have restricted permissions:
chmod 600 ~/.x402-agent/endpoints.json
-
PRIVATE_KEYset as environment variable (not in code) -
endpoints.jsonuses${PRIVATE_KEY}template - Wallet has sufficient USDC balance for expected usage
- Endpoints are marked
trusted: trueonly after verification - Monitor transaction logs for unexpected payments
- Set up alerts for low USDC balance
- Test on testnet (base-sepolia) before production
- Use separate wallets for different environments
Apache-2.0
Contributions are welcome! Please open an issue or pull request.
For issues and questions:
- GitHub Issues: https://github.com/yourusername/x402-agent/issues
- Documentation: https://docs.cdp.coinbase.com/x402/