Skip to main content

x402 Payment Protocol

KnowledgeFlowDB uses the x402 payment protocol for per-call pricing on MCP tool calls. Payments use USDC on Base chain with EIP-3009 TransferWithAuthorization.

How It Works

  1. Client calls an MCP tool endpoint
  2. Server responds with 402 Payment Required and payment requirements
  3. Client signs a USDC TransferWithAuthorization (EIP-712)
  4. Client retries the request with the signed payment in the X-PAYMENT header
  5. Server verifies the payment via the facilitator and executes the tool
Client                    Gateway                   Facilitator
|--- POST /tool -------->| |
|<-- 402 + requirements --| |
| | |
| (sign EIP-712) | |
| | |
|--- POST /tool --------->| |
| X-PAYMENT: <signed> |--- verify payment ---------->|
| |<-- payment valid ------------|
|<-- 200 + result --------| |

Pricing

ItemCost
Default tool call$0.0005
Payment tokenUSDC
ChainBase mainnet (chain ID 8453)
Gas cost to userNone (gasless via EIP-3009)

Server operators can set custom per-server pricing.

SpendingWallet (SDK)

The rickydata SDK provides a SpendingWallet class for safe, isolated payment signing with built-in spending limits and circuit breakers.

Creating a SpendingWallet

import { SpendingWallet } from '@nickydata/sdk';

// From a BIP-39 seed phrase (recommended)
const wallet = await SpendingWallet.fromSeedPhrase(
'your seed phrase words...',
0, // HD derivation index
{
maxPerCall: 0.01, // Max $0.01 per call
maxPerDay: 5.0, // Max $5/day
maxPerWeek: 20.0, // Max $20/week
maxPerSession: 10.0, // Max $10/session
}
);

// From a private key
const wallet = await SpendingWallet.fromPrivateKey(
'0xPRIVATE_KEY',
{ maxPerDay: 5.0 }
);

Safety Features

The SpendingWallet provides defense-in-depth:

  • Spending limits: Per-call, daily, weekly, and session limits
  • Circuit breaker: Stops payments after consecutive failures
  • Event emission: payment:signed, payment:rejected, balance:low, spending:warning
  • Isolated key: Separate from your main wallet
  • Memory cleanup: wallet.destroy() clears private key material

Monitoring Spending

// Check current balance
const balance = await wallet.getBalance();
console.log(`USDC: ${balance.usdc}, ETH: ${balance.eth}`);

// Get spending summary
const spending = wallet.getSpending();
console.log(`Total spent: $${spending.totalUsd}`);

// Get remaining budget
const remaining = wallet.getRemainingBudget('day');
console.log(`Remaining today: $${remaining}`);

// Payment history
const history = wallet.getHistory({ limit: 10 });

Events

wallet.on('payment:signed', (receipt) => {
console.log(`Paid $${receipt.amountUsd} for ${receipt.toolName}`);
});

wallet.on('balance:low', ({ balance, threshold }) => {
console.warn(`Low balance: ${balance} USDC (threshold: ${threshold})`);
});

wallet.on('spending:warning', ({ period, percentUsed }) => {
console.warn(`${period} spending at ${percentUsed.toFixed(0)}% of limit`);
});

wallet.on('circuit-breaker:tripped', ({ failureCount }) => {
console.error(`Circuit breaker tripped after ${failureCount} failures`);
});

Operator Bypass

Certain wallet addresses (configured as operator bypass addresses) can call tools without x402 payment. This is used for gateway operators and internal services.

Authenticated Bypass

When enabled on the gateway, any wallet with a valid Bearer token (JWT or mcpwt_) can call tools without x402 payment. Usage is logged for future billing. This enables clients like Claude Code that cannot sign x402 payments to use tools with just wallet authentication.