Skip to content

feat: x402 payment protocol support#11

Draft
MQ37 wants to merge 5 commits intomainfrom
feat/x402
Draft

feat: x402 payment protocol support#11
MQ37 wants to merge 5 commits intomainfrom
feat/x402

Conversation

@MQ37
Copy link
Collaborator

@MQ37 MQ37 commented Feb 28, 2026

Summary

Add x402 payment protocol support — automatic USDC payments for paid MCP tools on Base/Base Sepolia.

  • mcpc x402 init|import|info|remove|sign for wallet management
  • --x402 flag enables auto-payment on both direct and session connections
  • Two signing paths: proactive (bridge reads _meta.x402 from tools list) and 402 fallback (retry on HTTP 402)
  • Single wallet in ~/.mcpc/wallets.json (versioned format, 0600 perms)
  • viem for EIP-3009 signing, custom fetch wrapper via SDK transport
  • Bridge receives wallet via IPC, never as CLI args

Tested e2e against local x402 demo server (direct + bridge, paid + free tools). All existing tests pass except pre-existing flaky bridge-resilience (parallel test pollution causes INVARIANT VIOLATION — unrelated to x402).

MQ37 added 5 commits February 28, 2026 11:05
Adds mcpc x402 subcommands: init, import, list, remove, sign.
Wallets stored in ~/.mcpc/wallets.json. Signing parses PAYMENT-REQUIRED
headers and produces PAYMENT-SIGNATURE for x402 payment protocol.
Implement automatic x402 payment signing when calling paid MCP tools.
The --x402 global flag enables auto-payment using the default wallet.

Architecture:
- Shared signer module (src/lib/x402/signer.ts) for EIP-3009 typed data signing
- Fetch middleware (src/lib/x402/fetch-middleware.ts) wraps SDK's fetch with:
  - Proactive signing: reads _meta.x402 from cached tools list, signs before request
  - 402 fallback: if server returns HTTP 402, parses PAYMENT-REQUIRED header, signs, retries once
- Bridge receives wallet credentials via IPC (set-x402-wallet message type)
- Bridge maintains its own tools cache for proactive signing (populated on connect,
  updated via listChanged notifications)
- Direct connections (withMcpClient) only support 402 fallback (no persistent tools cache)
- customFetch option threaded through transports.ts -> factory.ts -> SDK transport

Known issues and TODOs:
- --x402 is currently a boolean flag (always uses 'default' wallet). Supporting
  --x402 [wallet-name] with optional value is blocked by Commander.js not being
  able to disambiguate optional option values from subcommands. Options considered:
  (a) pre-process args to convert '--x402 name' to '--x402=name' before Commander,
  (b) use separate --x402-wallet <name> option, (c) strip --x402 from Commander
  args and re-inject via closure. All approaches were prototyped but add significant
  complexity. For now --x402 uses the default wallet; named wallets can wait.
- No unit tests yet for signer.ts and fetch-middleware.ts
- No E2E test with the demo x402 server
- Interactive shell does not support --x402 (only direct commands and sessions)
- Direct connections don't have proactive signing (no tools cache), only 402 fallback
- Pre-existing flaky test: sessions/bridge-resilience occasionally fails (unrelated)
Drop multi-wallet support (named wallets, --name options, defaultWallet)
in favor of a single wallet stored in ~/.mcpc/wallets.json with a
versioned format { version: 1, wallet?: WalletData }.

- Remove wallet names from WalletData, X402WalletCredentials, SessionData
- Replace SessionData.walletName with x402 boolean flag
- Simplify wallets.ts CRUD to operate on single wallet
- Rename 'list' command to 'info', remove --name from all x402 commands
- Update bridge IPC: --wallet <name> arg becomes --x402 boolean flag
- Update all callsites (bridge-manager, sessions, helpers, parser, CLI)

This avoids Commander.js optional-arg parsing complexity for --x402
[wallet-name] and matches the actual use case (one wallet per user).
Multi-wallet can be added later with --x402-wallet <name> if needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant