x402 Micro Tollgate について
x402 Micro Tollgateは、APIやMCPツールの前段に置くセルフホスト可能な決済ゲートウェイで、呼び出し単位で課金したい提供者を対象とします。HTTP 402で価格を示し、支払い後にリクエストを上流へ中継します。標準設定ではCoinbase CDPを通じてBase上のUSDCで決済します。
主な機能
- 01USDCまたは設定したUSDTで従量課金
- 02HTTP 402で支払い要件を提示
- 03支払い後に上流へリクエストを中継
- 04MCPペイウォールと有料コンテンツ経路
- 05購入クライアントの支出上限と再試行
活用シーン
- 01有料APIをリクエスト単位で課金
- 02MCPツールへのアクセス前に支払いを要求
- 03予算内でエージェントに自動決済と再試行を実行
- 04有料ウェブコンテンツをMarkdownとして提供
MCP 対応
有料MCPサービスのゲートウェイとして利用でき、HTTP 402の支払いフローで保護されたツールエンドポイントをMCPクライアントに公開します。READMEにはHTTPおよびstdioでの接続設定も記載されています。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y x402-micro-tollgateCDP_API_KEY_IDシークレットCoinbase CDP API key ID for the x402 facilitatorCDP_API_KEY_SECRETシークレットCoinbase CDP API key secret for the x402 facilitatorX402_PAY_TOEVM address that receives USDC settlementsUPSTREAM_URLUpstream HTTP API to proxy after payment (omit for built-in mock)PRICEDollar price per paid call, e.g. $0.001NETWORKCAIP-2 network id (eip155:84532 Base Sepolia or eip155:8453 Base)X402_ENVIRONMENTdevelopment or productionローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
x402-micro-tollgate
カードを持てない AI エージェントのための Visa。
エージェントのトラフィック向けの秒単位の決済ブリッジ — USDC の少額決済を処理し、**0.1%**を徴収する Web3 版の料金所です。
支払い能力のない数千万の AI エージェントに秒単位のブリッジ決済を提供し、0.1%を徴収する Web3 版 Visa 料金所
Coinbase CDP によって支えられたセキュリティ。 お客様のキーに触れることも、独自の暗号技術で支払いを決済することもありません。EIP-3009 の認可ノンスは CDP ファシリテーター(オンチェーンでの一意性の信頼できる情報源)で一度だけ使用できます。このゲートウェイは、購入者と販売者の間にある4つの信頼境界を強化します。支払い証明のリプレイ/競合、URL 取得時の SSRF、上流のバイパス(共有シークレットの信頼ヘッダー)、および Base の混雑/決済遅延(保留中の場合は同じ証明で再試行してください。HTTP タイムアウトだけで「支払い失敗」と判断しないでください)。
概要
API または MCP ツールの手前に設置する、薄いセルフホスト可能な料金所です。エージェントが有料ルートを呼び出すと、価格表示として HTTP 402が返されます(アクセスを完全に拒否するわけではありません)。エージェントが少額の USDC(または設定した USDT)を支払うと、サービスを提供します。デフォルトの決済は、Coinbase CDP経由の Base + USDCです。複数ネットワークでの受け入れは環境変数で設定します(下のマトリックスを参照)。人間は引き続き無料の経路を利用でき、エージェントは料金所で支払いに切り替えます。
セルフホストは無料です(MIT)。リポジトリ:github.com/kevin2003050666-coder/x402-micro-tollgate · お問い合わせ:[email protected]
Coinbase の公式製品ではありません。完全なエージェントマーケットプレイスではありません。請求 SaaS ではありません。Visa 方式のシンプルな料金所です。法定通貨のカストディは行いません。
開発の背景:MANIFESTO.md — 課題、エンジニアリング、オンチェーンの証明、MIT。
ネットワーク × アセットのマトリックス
デフォルトのデプロイプロファイル:Base USDC のみ(開発環境:Base Sepolia)。NETWORKS + ASSETS、または ACCEPTS_JSON / X402_* エイリアスで複数の受け入れを有効にできます。複数の受け入れが設定されている場合、ブラウザーの HTML 402 にチェーン + アセットの選択欄が表示されます。
| ネットワーク | CAIP-2 | USDC | USDT | ステータス | ファシリテーター/備考 |
|---|---|---|---|---|---|
| Base | eip155:8453 | Circle ネイティブ | ブリッジ版 | 稼働中 | CDP exact。FeeSplitterFactory 稼働中(deployments/base.json) |
| Base Sepolia | eip155:84532 | テスト用 USDC | — | 稼働中 | CDP テストネット |
| Optimism | eip155:10 | ネイティブ | ブリッジ版 | 設定対応済み | アドレス設定済み。現在の CDP マトリックスには含まれていません |
| Arbitrum One | eip155:42161 | ネイティブ | ブリッジ版 | 稼働中 | CDP exact。ファクトリーはスタブ |
| Polygon PoS | eip155:137 | ネイティブ(USDC.e ではありません) | PoS USDT | 稼働中 | CDP exact。ファクトリーはスタブ |
| BNB Smart Chain | eip155:56 | ペッグ、18 桁 | ペッグ、18 桁 | 設定対応済み | CDP リストには含まれていません |
| Ethereum | eip155:1 | ネイティブ | Tether | 設定対応済み | ファシリテーターに依存 |
| Avalanche C-Chain | eip155:43114 | ネイティブ | USDT | 設定対応済み | @x402/evm のデフォルトに含まれています |
| Celo / Sei | eip155:42220 / 1329 | USDC | — | 設定対応済み | カタログの追加項目 |
| Solana | solana:5eykt… | SPL USDC | SPL USDT | 実験的 | CDP は Solana を掲載しています。ゲートウェイのスタブと、オプションの SVM ペイウォール(SOLANA_PAY_TO)があります |
| TRON | tron:mainnet | — | TRC-20 | 予定 | 依存関係にスキームがないため、accepts[] には絶対に含まれません |
EVM 上の USDT は通常、EIP-3009 ではなく extra.assetTransferMethod: "permit2" を使用します。FeeSplitter の本番経路は引き続き Base + USDCです。その他のチェーンは、contracts/deployments/ にある設定用スタブです。
ブラウザーウォレット
| ウォレット | 役割 |
|---|---|
| Coinbase Smart Wallet(Passkey) | 主な CTA |
| MetaMask | wagmi の注入ターゲット経由 |
| Injected | その他のブラウザーウォレット |
| WalletConnect | WALLETCONNECT_PROJECT_ID が設定されている場合 |
| Solana ペイウォール | 実験的。Solana の受け入れ設定/PAYWALL_SVM が必要 |
| TronLink | 提供していません(TRON は予定のみ) |
対象ユーザー
- API 販売者:課金コンソールを構築したり、月額シートを販売したりせずに、エージェントに呼び出しごとの料金を支払わせたい方
- ツール開発者:Cursor / Claude 向けに有料 MCP エンドポイントを提供する方
- 運用担当者:ホスティング料金ではなく、Visa のような手数料率(0.1%)を求める方
収益の仕組み
- 料金提示 — 未払いのトラフィックには、支払額を示す HTTP 402 を返します(拒否ではなく、コンバージョンを促します)
- 支払い — エージェントは Coinbase CDP 経由で、数秒で USDC のマイクロペイメントを決済します
- 利用開始 — トールゲートがアップストリームにプロキシし、約 99.9% を受け取り、プロトコル手数料は 0.1% です
プロトコルの月額料金はありません。収益化は通行料によって行います。カードネットワークのインターチェンジ手数料のようなものです。
1 分でできるクイックスタート
Node.js 22 以降が必要です。
git clone https://github.com/kevin2003050666-coder/x402-micro-tollgate
cd x402-micro-tollgate && cp .env.example .env
# set CDP_API_KEY_ID, CDP_API_KEY_SECRET, X402_PAY_TO (optional: PUBLIC_BASE_URL, UPSTREAM_URL)
npm i && npm start
# curl http://127.0.0.1:8402/health → 200
# curl http://127.0.0.1:8402/x402/discover → 200 (free agent yellow pages)
# curl http://127.0.0.1:8402/v1/quote → 402
# curl "http://127.0.0.1:8402/v1/fetch-md?url=https://example.com" → 402 (paid HTML→Markdown demo)
npx のワンライナー(クローン不要):
npx [email protected]
npx [email protected] --seller 0xYourReceivingAddress --stdio
--seller / -s は起動前に X402_PAY_TO を設定します(環境変数も引き続き使用できます)。--stdio を指定しない場合、デフォルトでは HTTP とポート 8402 の /mcp が使用されます。
エージェント / クローラー向けドキュメント:llms.txt(GET /llms.txt および GET /.well-known/llms.txt からも取得できます) · OpenAPI 3.1:docs/openapi.yaml · well-known:GET /.well-known/x402.json、GET /.well-known/agent-card.json
別のワンライナー:docker compose up --build
CDP キーがない場合、プロセスはデモモードで実行されます(プロトコル形式の 402 / MCP PaymentRequired を返し、オンチェーン決済は行いません)。
Cursor の mcp.json:
{
"mcpServers": {
"x402-micro-tollgate": {
"url": "http://127.0.0.1:8402/mcp"
}
}
}
Stdio:
{
"mcpServers": {
"x402-micro-tollgate": {
"command": "npx",
"args": [
"[email protected]",
"--seller",
"0xYourReceivingAddress",
"--stdio"
],
"env": {
"CDP_API_KEY_ID": "...",
"CDP_API_KEY_SECRET": "...",
"PUBLIC_BASE_URL": "https://your.public.host"
}
}
}
}
(--seller を省略した場合も、env 内の X402_PAY_TO は引き続き使用できます。)
ライブラリへの組み込み(パーミッションレスな販売者)
import express from "express";
import { x402Tollgate } from "x402-micro-tollgate";
const app = express();
app.use("/v1", await x402Tollgate({ seller: process.env.SELLER! }));
または、.env に SELLER / X402_SELLER を設定して npm start を実行します。$10 のしきい値、ファクトリーアドレス、手数料のリリースの詳細については、環境変数を参照してください。
購入者 / エージェントのクライアント
公式の @x402/fetch と @x402/evm の ExactEvmScheme をラップする、軽量な TypeScript ヘルパーです。HTTP 402 を受け取ると、PAYMENT-REQUIRED を解析し、予算を確認して、EIP-3009 に一度だけ署名し、PAYMENT-SIGNATURE を付けて一度だけ再試行します(ループはしません)。
npm i [email protected]
import { createX402Fetch } from "x402-micro-tollgate/client";
const fetch402 = createX402Fetch({ privateKey: process.env.BUYER_KEY as `0x${string}` });
const res = await fetch402("https://x402-micro-tollgate.onrender.com/v1/quote");
デフォルト値:maxSingleSpendUsdc = 0.05、maxTotalSpendUsdc = 1.00(上限を超えると明確な Error が発生します)。サーキットブレーカー(署名前):ローリング 60 秒あたりの有料 402 は最大 10 件 / 0.05 USDC。さらに、フィンガープリントによるデッドループ停止機能もあります(maxPaidRequestsPerMinute、maxSpendUsdcPerMinute、enableFingerprintBreaker)。**ホットウォレットに関する警告:**署名キーには約 $5~$10 USDC だけを保持してください。資金庫ではなく、エージェントが支出するための蛇口として扱ってください。
人間が委任するエージェントのクレジット(CLI)
シンプルな PoC:人間が B_max を設定 → エージェントが有料 URL に対して createX402Fetch をループ実行します(402 を自動検出 → 一度支払い → 再試行)。Chrome / Telegram / Session Key / Passkey の UI は今後の実装予定です。
# SAFETY: fund BUYER_PRIVATE_KEY with ≤ $5–$10 USDC only. Never commit keys.
export BUYER_PRIVATE_KEY=0xYourHotWalletKey
# optional: TARGET_URL MAX_SINGLE_USDC MAX_TOTAL_USDC ROUNDS
npm run poc:buyer-agent
# or: npx tsx scripts/buyer-agent-poc.ts
| 環境変数 | デフォルト値 | 備考 |
|---|---|---|
BUYER_PRIVATE_KEY | (必須) | EIP-3009 の署名に使う 0x… の EOA |
TARGET_URL | https://x402-micro-tollgate.onrender.com/v1/quote | 呼び出す有料ルート |
MAX_SINGLE_USDC | 0.05 | 呼び出しごとの上限(maxSingleSpendUsdc) |
MAX_TOTAL_USDC | 1.00 | セッションの上限 / 人間が設定する B_max |
ROUNDS | 3 | N 回呼び出した後、または予算を使い切った時点で停止します |
スクリプトはローカルのクライアント(../src/client)をインポートするため、リポジトリの CI で稼働中のチェーンへの支払いは必要ありません。公開済みパッケージでライブデモを行うには、インポートを x402-micro-tollgate/client に差し替えてください(0.3.2+ と同じ API です)。各ラウンドでは status、autoPaid、sessionSpendUsdc が stdout に出力され、安全性に関するバナーは stderr に出力されます。
デプロイ
render.yaml を使用します。Node 22、npm start、ヘルスチェック /health、環境変数名は .env.example に記載されています。ライブ決済を有効にするには、ダッシュボードで CDP_API_KEY_ID、CDP_API_KEY_SECRET、X402_PAY_TO を設定します。Bazaar 用に PUBLIC_BASE_URL を https://….onrender.com のオリジンに設定してください。
運用上の更新:discover と well-known を再デプロイ(Render の GitHub 自動デプロイを強制し、本番環境で GET /x402/discover、GET /.well-known/x402.json、GET /.well-known/agent-card.json、および MCP の fetch_md が利用できるようにします)。これが main に反映されてから数分経っても自動デプロイが実行されない場合は、Render ダッシュボードから「Manual Deploy」→「Deploy latest commit」を選択してください。
本番環境をセルフホストする場合: Docker — docker compose up --build(Dockerfile/docker-compose.yml を参照)。
環境
| 変数 | デフォルト | 備考 |
|---|---|---|
PORT | 8402 | HTTP リッスンポート |
UPSTREAM_URL | (未設定 → モック) | API のオリジン |
UPSTREAM_SHARED_SECRET / X402_UPSTREAM_SECRET | — | 任意。決済後、tollgate は X-Tollgate-Secret + X-Tollgate-Paid(HMAC)を挿入します。アップストリームはこれらを必須とし、(mTLS でない)公開からの直接アクセスを拒否する必要があります |
X402_PAY_TO | — | EVM の受取アドレス(ライブモードの SDK 初期化) |
SELLER / X402_SELLER | — | パーミッションレスの販売者 EOA(EIP-55 検証済み。無効な場合は起動に失敗) |
FACTORY_ADDRESS | — | 金額がしきい値以上の場合に CREATE2 の予測に使用する、運用者が設定した FeeSplitterFactory(Base のライブアドレスは contracts/deployments/base.json を参照。シークレットをハードコードしないでください) |
FEE_FREE_BELOW_USDC / X402_FEE_FREE_BELOW_USDC | 10000000 | 最小単位の USDC(小数点以下 6 桁)。$10 未満 → payTo=seller、$10 以上 → FeeSplitter |
CDP_API_KEY_ID / CDP_API_KEY_SECRET | — | CDP ファシリテーター(+ Onramp セッショントークン) |
CDP_CLIENT_API_KEY | — | ブラウザーの Smart Wallet ペイウォール用の公開 CDP クライアントキー(フロントエンドで安全に使用可能)。別名:CDP_CLIENT_KEY |
X402_FACILITATOR_URL / CDP_FACILITATOR_URL | CDP のデフォルト | MCP 用の代替ファシリテーターのベース URL(createCdpFacilitatorClient({ baseUrl }))。単一ベンダー方式で、複数ファシリテーターへのルーティングにはまだ対応していません |
PRICE | $0.001 | ネットワークのデフォルト USDC/USDT 価格タグ |
NETWORK / X402_NETWORK | eip155:84532 / 8453 | プライマリ CAIP-2(別名:base、optimism、…) |
NETWORKS / X402_NETWORKS | (プライマリのみ) | 複数の支払い受付に対応するネットワークのカンマ区切り/JSON リスト |
ASSETS / X402_ASSETS | USDC | NETWORKS との組み合わせで受付対象を決定します(USDC、USDT) |
ACCEPTS_JSON / X402_ACCEPTS_JSON | — | 明示的な受付配列(NETWORKS×ASSETS を上書き) |
FACTORY_ADDRESSES | — | caip2 → FeeSplitterFactory の JSON マップ(Base はライブ対応、その他は任意) |
SOLANA_PAY_TO | — | 実験的な Solana 受付用の Base58 payTo |
PAYWALL_SVM | false | @x402/paywall の SVM UI を強制します(受付対象に Solana が含まれる場合も自動的に有効化) |
WALLETCONNECT_PROJECT_ID | — | ブラウザーのペイウォールで WalletConnect を有効化します |
X402_MIN_PRICE_USDC | — | 任意の静的な受付最小額(最小単位の USDC)。実効価格 = max(PRICE、この値、ガス下限) |
X402_DYNAMIC_MIN_ENABLED | false | true の場合、ガスが支払い額を過度に消費する場合に、Base の基本手数料オラクルが受付最小額/feeFreeBelow を引き上げることがあります |
X402_GAS_COST_MAX_FRACTION | 0.5 | 推定ガス代(USD)が支払い額に対してこの割合を超えると引き上げます |
X402_GAS_ORACLE_TTL_MS | 30000 | baseFee キャッシュの TTL(15~60 秒に制限) |
X402_GAS_RPC_URL / BASE_RPC_URL | 公開 Base RPC | baseFee 取得用の eth_getBlockByNumber JSON-RPC |
X402_GAS_USED_ESTIMATE | 100000 | 決済コストの推定に使用する、おおよその L2 ガス単位 |
X402_ETH_USD | 4000 | 保守的な ETH/USD 下限(リアルタイムの為替レートは不要) |
X402_ENVIRONMENT | development | または production |
GATED_PREFIX | /v1 | 支払いが必要な HTTP パス |
PUBLIC_BASE_URL | http://127.0.0.1:$PORT | Bazaar リソース URL 用の公開 https:// オリジン |
CONTACT_EMAIL | [email protected] | ランディングページの連絡先 mailto(SaaS の CTA ではありません) |
FEE_BPS | 10 | 文書化された運用者手数料(0.1%)。ライブ決済では、release() まで引き続き 100% が payTo に支払われます |
FEE_COLLECTOR | 0xa922…7e30E | FeeSplitter.release() 後に 0.1% 分を受け取る固定運用者ウォレット |
MERCHANTS_JSON | — | 任意のホスト型マルチテナントレジストリ(SELLER が設定されている場合は不要) |
MERCHANTS_FILE | merchants.json | ファイルパス。販売者がいない場合は merchants.example.json/組み込みデモにフォールバックします |
DEFAULT_MERCHANT | demo | ?merchant=/x-merchant-id が省略された場合に使用します — エージェントは常に merchant id を送信する必要があります |
REQUIRE_MERCHANT | false | true の場合、ゲート対象のパスでは merchant id がないリクエストを 400 {error:"merchant_required"} で拒否します(デモへのフォールバックなし) |
PAYMENT_DEDUPE_TTL_MS | 600000 | メモリ内の支払い証明冪等性ウィンドウ(10 分)。正本は引き続き CDP ファシリテーターの nonce です |
PAYMENT_DEDUPE_MAX_ENTRIES | 10000 | ゲートウェイの PaymentDedupeStore LRU に保存できる最大キー数(Redis は使用しません。インターフェースは Redis 対応可能です) |
X402_VERIFY_TIMEOUT_MS | 15000 | 文書化された検証フェーズの予算(ローカル/ファシリテーターでの検証) |
X402_SETTLE_TIMEOUT_MS | 180000 | 202 payment_pending を返す前に、ファシリテーター/オンチェーン決済を待機する時間(デフォルト 3 分 — Base の混雑時) |
KEEPER_ENABLED | false | 任意の FeeSplitter release() キーパー — デフォルトでは決して有効になりません |
KEEPER_DRY_RUN | (備考を参照) | true の場合、トランザクションを送信せずに keeper_would_release をログに記録します |
KEEPER_PRIVATE_KEY | — | ライブの release() のみに使用する EVM キー(絶対にコミットしないでください) |
KEEPER_RPC_URL | 公開 Base RPC | 残高確認とリリース用の JSON-RPC エンドポイント |
KEEPER_INTERVAL_MS | 3600000 | ポーリング間隔(1 時間) |
KEEPER_MIN_USDC | 1000000 | release() 前に必要な USDC 残高の最小値(最小単位)— デフォルトは $1 |
許可不要の販売者+10ドルのしきい値(0.3.0)
0.3.0:SELLER を設定するか(または x402Tollgate({ seller }) を使用し)、10ドル以上の CREATE2 ルーティング用に FACTORY_ADDRESS を設定します。MERCHANTS_JSON は不要です。
| 金額(USDC の最小単位、6 桁の小数) | accepts[].payTo |
|---|---|
< 10_000_000(10ドル) | 販売者の EOA — プロトコル手数料 0 |
≥ 10_000_000(10ドル) | その販売者向けに CREATE2 で予測された FeeSplitter |
x402 exact と EIP-3009 が行うのは payTo への入金だけです。FeeSplitter/ファクトリーのコードは実行されず、同じトランザクション内で分割されることもありません。10ドル以上の場合は、オペレーターがデプロイしたファクトリーを FACTORY_ADDRESS に設定し(Base のリファレンス:contracts/deployments/base.json)、その金額で初めて決済する前に getOrCreate(seller) を呼び出してから、後で release() を呼び出します(99.9%/0.1%)。アドレスの入力ミスは資金を誤った宛先に送ります。ゲートウェイは起動時に SELLER のチェックサムを検証します。ソースに秘密鍵やオペレーターのシークレットをハードコードしないでください。
マーチャントレジストリ(任意のホステッド型マルチテナント)
オペレーターの FEE_COLLECTOR は固定です:0xa922F38041B5ee227c96A547F106F1330447e30E。各マーチャントには専用の FeeSplitter が割り当てられます(seller = マーチャントのウォレット、feeCollector = オペレーター、feeBps = 10)。レジストリは merchantId → スプリッターアドレス(payTo)と表示用の販売者を対応付けます。SELLER が設定されている場合、レジストリは任意です。MERCHANTS_JSON を指定すれば、引き続き ?merchant= を使用できます。
マーチャントを登録する:
seller= マーチャントのウォレット、feeCollector=0xa922F38041B5ee227c96A547F106F1330447e30E、feeBps= 10、asset= チェーンのネイティブ USDC としてFeeSplitterをデプロイします。MERCHANTS_JSONにエントリを追加します(またはmerchants.jsonを使用するか、merchants.example.jsonをコピーします)。{ "acme": { "seller": "0xMerchantWallet…", "payTo": "0xDeployedFeeSplitter…", "label": "Acme API" } }?merchant=acmeまたはヘッダーx-merchant-id: acme(大文字と小文字は区別されません)を指定して、ゲートされた API を呼び出します。エージェントは常にマーチャント ID を送信する必要があります。 省略すると、ゲートウェイはDEFAULT_MERCHANT(demo)にフォールバックします。つまり、トラフィック(および USDC)が気付かないうちにデモ用FeeSplitterに送られる可能性があります。REQUIRE_MERCHANT=trueを設定すると、マーチャントが指定されていないリクエストは400 { "error": "merchant_required" }で拒否されます。ゲートされたパスで不明なマーチャントを指定した場合 →400{ "error": "unknown_merchant" }。- 無料の一覧:
GET /merchants(/v1/merchantsも使用できます)。 - エージェント向けイエローページ:
GET /x402/discover(別名GET /discover)— 同じレジストリ/SELLER/デモから生成される安定した JSON カタログです。JSON 設定は引き続きサポートされます。このリリースには、オンチェーンのRegistry.solによる5ドルのステークはありません。
注: Base のデモ用スプリッターでは、seller と feeCollector の両方にオペレーターが設定されています。デモには適しています。実際のマーチャントには、自身のウォレットを seller に設定した専用スプリッターが必要です。
CDP の createX402Server は、SDK の初期化に単一のグローバルな payTo(X402_PAY_TO またはデフォルトのマーチャントスプリッター)を使用します。リクエストごとのマーチャントルーティングでは、解決された FeeSplitter に合わせて PAYMENT-REQUIRED の accepts[].payTo を書き換えます(https の resource.url を書き換える場合と同じパターンです)。
X402_PAY_TO が引き続き EOA で、マーチャントが1つだけの場合は、動作はシンプルなままです。マルチマーチャントの本番環境では、レジストリ内の各 payTo がデプロイ済みスプリッターを指すようにしてください。x402/exact は EIP-3009 を介してそのスプリッターに入金します。その後、release() を呼び出して(手動または任意のキーパー経由で)99.9%/0.1% を送金します。Base/Arbitrum/Polygon で同じコントラクトを使用します。マルチチェーン FeeSplitter の一覧を参照してください。これは受け取り後に release() を呼び出す方式であり、同じトランザクション内でのアトミックな分割でも、OpenZeppelin の PaymentSplitter でもありません。
ディスカバリー(稼働中)+流動性ロードマップ(計画中)
現在提供中 — ディスカバリーのみ。 無料ルート GET /x402/discover(エイリアス /discover)は、既存のソース(MERCHANTS_JSON/merchants ファイル/SELLER/組み込みデモ)と PUBLIC_BASE_URL から、エージェントが読み取れるイエローページを返します。402 は発生しません。レスポンスの例:
{
"version": 1,
"network": "eip155:8453",
"updatedAt": "2026-09-03T00:00:00.000Z",
"source": "merchants",
"services": [{
"id": "demo",
"label": "demo (operator is also seller)",
"endpoint": "https://your-host/v1/quote?merchant=demo",
"mcp": "https://your-host/mcp",
"capabilities": ["quote", "proxy", "fetch-md"],
"price": "$0.001",
"asset": "USDC",
"payTo": "0x…",
"seller": "0x…",
"status": "demo"
}]
}
status はヘルス状態を正確に反映します。CDP ファシリテーターの認証情報と payTo が設定されている場合のみ live となり、それ以外は demo(accepts が非稼働の場合は config)となります。これはオンチェーンのエージェントレジストリではありません。
計画中(文書化のみ — 提供済みとして扱わないでください):
| トラック | 現時点で実施しない理由 |
|---|---|
| フラッシュ流動性プール(チェーン間で 0 確認の立替) | 多額の資本が必要です。個人の創業者が複数チェーンにわたる USDC の資金を保有することはできません。0 確認の立替は信用リスクを伴います。ホットウォレットの残高が不足した場合に備えて、サーキットブレーカーが必要です。Superchain/AggLayer が 1 秒未満のネイティブ相互運用性を実現すれば、クロスチェーンの摩擦 (S_{cross}) は 0 に近づき、このトラックは縮小する可能性があります。 |
| リバース懸賞金(エージェントに報酬を支払い、呼び出してもらう) | セラーが呼び出しを補助すると、Sybil 攻撃によって資金が枯渇します。claimBounty を実装する前に、レート制限/エージェントごとの ID/IP とフィンガープリントによる制限が必要です。現在の約 20 ドルの Discord/X 懸賞金は、引き続きオペレーターによる手動支払いであり、オンチェーンで請求するものではありません。 |
詳細は docs/ROADMAP-LIQUIDITY.md をご覧ください。このリリースでは FeeSplitter に depositBounty/claimBounty を追加せず、クロスチェーン清算が「稼働中」であるかのような虚偽の主張もしません。
ディスカバリー層は稼働中です(
GET /x402/discover)。フラッシュ流動性プールとリバース懸賞金は計画段階に限られます。ロードマップをご覧ください。
ガス代とマイクロペイメントの下限(任意)
マイクロペイメント(0.001~0.01 ドル)は、Base の低い手数料を前提としています。L2 のガス代が急騰すると、決済コストの推定額が少額決済の大部分を占める場合があります。X402_DYNAMIC_MIN_ENABLED=true を設定すると、この機能が有効になります。キャッシュされた Base の baseFee オラクル(TTL 15~60 秒、RPC への過剰なリクエストなし)がガス代の USD 換算額(gasUsedEstimate * baseFee * X402_ETH_USD)を推定し、その額が決済額の X402_GAS_COST_MAX_FRACTION(デフォルト 50%)を超える場合、表示および適用される最小受け入れ額を引き上げます。また、より高額になるまで FeeSplitter と release() を使用しないよう、feeFreeBelow を引き上げることがあります。通常の条件でデモの $0.001 が引き続き機能するよう、デフォルトでは無効です。オペレーターは静的な X402_MIN_PRICE_USDC を設定することもできます。現在有効な最小額は GET /health → gasFloor で確認できます。
セキュリティ(ゲートウェイの強化)
購入者とセラーが把握しておくべき 4 つの防御策:
- 支払い署名のリプレイ/競合 — 冪等性キーには SHA-256(
PAYMENT-SIGNATURE)を使用します。プロセス内ミューテックスとPaymentDedupeStore(現在はメモリ上の実装ですが、Redis に対応できるインターフェース)が、上流へのリクエスト前に「未設定の場合のみ設定」を行います。競合に負けたリクエストには409 { "error": "payment_already_used" }が返されます。永続的な記録は決済成功後にのみ行われます。検証に失敗した場合は保留中の予約が解放されるため、正当なリトライが妨げられることはありません。 /v1/fetch-mdの SSRF —http/httpsのみを許可します。DNS 解決では、プライベート/ボゴン/リンクローカル/メタデータの各アドレスを拒否します。フェッチ前にも DNS を再確認し(DNS リバインディング対策)、リダイレクトは無効にします。- 上流のバイパス — 任意の
UPSTREAM_SHARED_SECRETを設定できます。支払い後、プロキシはX-Tollgate-Secret/X-Tollgate-Paid/X-Tollgate-Timestampを挿入します。上流側ではこれらを必須にする必要があります(以下のスニペットを参照)。これは共有シークレットを使う MVP であり、mTLS ではありません。 - Base の混雑/決済の遅延 —
X402_SETTLE_TIMEOUT_MS(デフォルト 3 分)は、短い検証タイムアウトとは別です。待機中にタイムアウトすると202 { "error": "payment_pending", "retry_with_same_proof": true }が返されます。HTTP がタイムアウトしたという理由だけで、新しい支払いを作成したり、購入者が失敗したと判断したりしないでください。同じ証明を使ってリトライしてください。ゲートウェイは二重決済を行わずに処理を再開します。
デフォルトでは、CDP ファシリテーターは単一ベンダーへの決済依存先です。利用可能になった場合に別のファシリテーターを指定する X402_FACILITATOR_URL については SECURITY.md を参照してください。ファシリテーター間のルーティングには、まだ対応していません。
Payment proof idempotency + settle pending
CDP x402 exact と EIP-3009 オーソリは、ファシリテーターで一度しか使用できません(nonce)。ゲートウェイではさらに、各支払い証明のフィンガープリントを pending → settled → consumed として追跡します。
| Store state | Client sees |
|---|---|
pending(決済処理中/決済待ちタイムアウト後) | 202 payment_pending + retry_with_same_proof: true |
settled(支払い済み。上流への配信はまだ) | 再決済を省略し、プロキシ経由で一度だけ転送して、consumed に設定 |
consumed | 409 payment_already_used |
デフォルトではプロセス内のみで管理されます(再起動するとクリアされます)。オンチェーンの nonce の一意性については、引き続きファシリテーターが正とします。
上流の信頼ヘッダー(Express の例)
import { createHmac, timingSafeEqual } from "node:crypto";
import type { RequestHandler } from "express";
const SECRET = process.env.UPSTREAM_SHARED_SECRET!;
export const requireTollgate: RequestHandler = (req, res, next) => {
const secret = req.header("x-tollgate-secret") ?? "";
const paid = req.header("x-tollgate-paid") ?? "";
const ts = req.header("x-tollgate-timestamp") ?? "";
const expected = createHmac("sha256", SECRET)
.update(`${ts}.${req.method.toUpperCase()}.${req.path}`, "utf8")
.digest("hex");
const okSecret =
secret.length === SECRET.length &&
timingSafeEqual(Buffer.from(secret), Buffer.from(SECRET));
const okPaid =
paid.length === expected.length &&
timingSafeEqual(Buffer.from(paid), Buffer.from(expected));
if (!okSecret || !okPaid) {
res.status(401).json({ error: "tollgate_required" });
return;
}
next();
};
// app.use(requireTollgate); // reject public direct hits
または、上流プロセスで x402-micro-tollgate の verifyUpstreamTrustHeaders をインポートしてください。
オプションの FeeSplitter リリースキーパー
src/keeper.ts にスキャフォールドがあります。デフォルトでは無効です(KEEPER_ENABLED が未設定または false)。有効にすると、KEEPER_INTERVAL_MS ごと(デフォルトは 1 時間)に、レジストリ内の payTo FeeSplitter アドレスの USDC 残高を確認し、残高が KEEPER_MIN_USDC(デフォルトは $1)以上の場合に release() を呼び出します。
警告: 少額の支払いでは、release() のガス代がオペレーター手数料の 0.1% を上回ることがあります。そのため、最低残高の条件を設けています。Render ではデフォルトで有効にしないでください。実際の KEEPER_PRIVATE_KEY を使用する前に、KEEPER_DRY_RUN=true を設定することをおすすめします(keeper_would_release がログに記録されます)。キーは絶対にコミットしないでください。
Bazaar での検出(エージェントが販売者を見つける)
Bazaar は x402 のディスカバリーカタログです。
- HTTP:
createX402Serverは Bazaar を自動的に挿入します。これをdiscoverable: true、説明、入出力スキーマ(GET /v1/quoteと、支払いが必要なプレフィックスプロキシ)で上書きします。 - MCP:
x402ResourceServerは Bazaar を自動宣言しません。bazaarResourceServerExtensionを登録し、get_quote/proxy_request/fetch_mdでdeclareDiscoveryExtension({ toolName, inputSchema, … })を渡します。リソース URL はPUBLIC_BASE_URL/mcpです(表示名ではなく、実際の http(s) URL)。 - Origin の well-known:
GET /.well-known/x402.json(別名/.well-known/x402)は、discover を反映し、ファシリテーターに依存しないクローラー向けに、稼働中の有料 HTTP/MCP リソースを一覧表示します。
Bazaar に掲載するには:
PUBLIC_BASE_URLに公開 https オリジンを設定します(localhost の掲載情報は実際のクローラーには利用されません)。- 有効な CDP 認証情報と
X402_PAY_TOを設定して実行します。 - CDP ファシリテーター経由で決済を 1 回成功させます(支払いが必要なルートへの空の本文のプローブは 400 ではなく 402 を返します)。
公開のヒント:最初の決済後に、Discord の #x402 で /mcp または /v1/quote の URL を共有してください。
ブラウザーで支払う(Smart Wallet)
ブラウザーが支払いの必要なルートにアクセスすると(Accept: text/html + Mozilla UA)、ゲートウェイは JSON の代わりに簡易 HTML ペイウォールを返します。エージェント/MCP/curl には、引き続き JSON の 402 本文が返されます。
利用できる機能
- 公式の
@x402/paywallEVM UI を使って、Coinbase Smart Wallet を接続/作成します(Coinbase Wallet コネクター — Passkey Smart Wallet、MetaMask は不要)。 - Base(開発時は Base Sepolia)で x402
exactEIP-3009 支払いに署名し、PAYMENT-SIGNATUREを付けて再試行します。 - USDC を入手します(任意)。サーバーに CDP キーが設定されている場合、ペイウォールに Get USDC ボタンが表示されます。このボタンは
POST /x402/session-tokenを呼び出し、Coinbase Onramp を開きます。Apple Pay/カードが表示されるのは、Onramp がそのドメインでサポートしている場合のみです。このリポジトリは Onramp 以外で Apple Pay を装うことはなく、Portal の本番アクセスなしに「Apple Pay で 10 秒」と保証することもありません。
セットアップ(購入者 UX)
# .env — server secrets stay on the host
CDP_API_KEY_ID=…
CDP_API_KEY_SECRET=…
X402_PAY_TO=0x… # or SELLER=0x…
# Public client key only (browser-safe)
CDP_CLIENT_API_KEY=… # from portal.cdp.coinbase.com
# Optional but recommended for live demo / Bazaar
PUBLIC_BASE_URL=https://your.host
X402_ENVIRONMENT=development # Base Sepolia (eip155:84532)
# X402_ENVIRONMENT=production # Base mainnet (eip155:8453)
| 項目 | 役割 |
|---|---|
CDP_CLIENT_API_KEY | ペイウォールの HTML に window.x402.cdpClientKey として挿入されます |
CDP_API_KEY_ID + CDP_API_KEY_SECRET | ファシリテーターの決済確定 および POST /x402/session-token(Onramp JWT) |
POST /x402/session-token | 無料パス。リクエスト本文 { "addresses": [{ "address": "0x…", "blockchains": ["base"] }], "assets": ["USDC"] } → { token } |
正直な説明/本番環境に関する注意事項
- MVP ネットワーク: Base Sepolia(
development)および Base mainnet(production/NETWORK=eip155:8453)。 - Onramp の本番利用: CDP Portal で Onramp を有効にし、ドメインを許可リストに登録して、Coinbase が必要とする Apple Pay のドメイン認証を完了してください。それまでは Smart Wallet での支払い、署名、再試行は引き続き機能しますが、Get USDC でエラーが発生したり、カード決済の選択肢が表示されなかったりすることがあります。
- CSP: ペイウォールにはインラインスクリプトが含まれます(上流の
@x402/paywallと同じです)。402 HTML レスポンスに nonce を設定せずに厳格なscript-srcを設定することは避けてください。 - セキュリティ: ウォレットの秘密鍵がフロントエンドに渡ることはありません。埋め込まれるのは公開クライアントキーのみです。セッショントークンはサーバー側で発行されます。
試すには、上記のキーを設定してから、Chrome で https://your-host/v1/quote を開いてください。
概要
Agents / clients
├─ HTTP /v1/* → x402 402 JSON (agents) or Smart Wallet HTML paywall (browsers)
├─ GET /v1/fetch-md → paid HTML→Markdown demo (same x402 gate)
├─ GET /x402/discover → free agent yellow pages (alias /discover; from merchants JSON)
├─ GET /.well-known/x402.json → free Bazaar-friendly origin manifest (alias /.well-known/x402)
├─ GET /.well-known/agent-card.json → free agent card (alias /.well-known/agent.json)
├─ GET /llms.txt → free AI-crawler summary (alias /.well-known/llms.txt)
├─ GET /openapi.yaml → free OpenAPI 3.1 (alias /docs/openapi.yaml)
├─ POST /x402/session-token → free Onramp session token (when CDP server keys set)
├─ GET /merchants → free merchant registry (id, label, seller, payTo)
├─ GET /health → free (+ paywall config flags)
├─ GET / → developer landing (EN / 中文)
└─ MCP /mcp → server_info (free), get_quote + proxy_request + fetch_md (paid + bazaar)
| 対象 | 技術スタック |
|---|---|
| HTTP | createX402Server + paymentMiddlewareFromHTTPServer + @x402/paywall(ブラウザー) |
| MCP | x402ResourceServer + createCdpFacilitatorClient + createPaymentWrapper + Bazaar 拡張機能 |
CLI:npx [email protected] | --seller 0x…/-s | --stdio | --port N
エージェント向け SEO:llms.txt · docs/openapi.yaml
公開
パッケージの識別情報(同期を保つ必要があります):
package.jsonのmcpName=io.github.kevin2003050666-coder/x402-micro-tollgateserver.jsonのname= 同じ文字列
手順(この VM ではなく、トークンを利用できるマシンで実施してください):
- GitHub に公開ミラー
kevin2003050666-coder/x402-micro-tollgateを作成します npm publish(またはタグv*を付ける →.github/workflows/publish-mcp.yml)mcp-publisher publish(OIDC)→ 公式 MCP Registry- PulseMCP は公式レジストリから自動取り込みします。PulseMCP に直接登録 しないでください
リモートを公開する前に、server.json の remotes[0].url を実際に公開する /mcp URL に更新してください。
テスト
npm test
CDP の有効な認証情報は必要ありません。
ライセンス
MIT · CONTRIBUTING.md を参照 · SECURITY.md
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。