vet402-check について
vet402-checkは、エージェントが支払う前に、x402やMPPの販売者に関するvet402の公開購入記録を照会します。鍵や支払いを扱わず、読み取り専用の事実と検証結果を返し、その後の判断は呼び出し側に委ねます。
主な機能
- 01販売者の購入・配達記録を照会
- 02署名、Merkle証明、オンチェーン決済を検証
- 03支払先アドレス、金額、アセットを比較
- 04未配達の決済について原因側を診断
- 05fetchフックで署名前に決済を確認
- 06CLI、HTTP照会、MCPツールを提供
活用シーン
- 01支払い前にx402またはMPPの販売者を確認
- 02自動決済にブロックや人間承認のルールを設定
- 03販売者の最新記録とオンチェーン証拠を検証
- 04決済失敗や応答未着の原因を調査
MCP 対応
stdioのMCPサーバーとして、支払い前チェック、記録検証、決済失敗診断の3つの読み取り専用ツールを提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
3掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい | これから支払うリソースの URL |
| asset | string | いいえ | 402 のアセット(ミントまたはトークンアドレス)。vet402 がこの販売者への支払いに使用したアセットと比較します(理由 `asset_unseen`)。 |
| chain | string | いいえ | solana、tempo、base、algorand、または eip155:8453 のような CAIP-2 ID |
| amount | string | いいえ | 402 の金額(最小単位)。vet402 がこの URL に支払った金額と比較します(理由 `price_jump`)。 |
| pay_to | string | いいえ | 手元の 402 にある payTo(受取人) |
| explain | boolean | いいえ | 回答の根拠となる購入記録も、日付と tx を含めて一覧表示します。 |
| verify_newest_record | boolean | いいえ | この販売者の最新の署名済み記録も検証します(署名、Merkle 証明、支払い、オンチェーンへのアンカー)。 |
詳細
@vet402/check(コマンド:vet402-check)
エージェントが支払いを行う前に、vet402 の公開記録で x402 または MPP の販売者を確認します。
このパッケージは、vet402 自身の購入に関する公開記録(vet402-delivery リポジトリ)を読み込みます。vet402 のスコアリング API 用 MCP ツールである @vet402/mcp-server とは別のものです。
vet402 は、Solana、Tempo、Base(および専用ページの Algorand)で自らの資金を使って x402 と MPP の販売者から購入し、各支払いをチェーン上で確認したうえで、返ってきた内容を公開します。公開内容は、ランキング(rank.json)と、日次の Merkle ルートが Solana のメモに書き込まれる署名済み記録です。vet402-check はその記録を読み込みます。返されるのは、vet402 がその販売者から何回購入を試みたか、何回決済されたか、何回応答が返ってきたか、最新の購入とその tx、販売者に対してカウントされる失敗とカウントされない失敗、rank.json に表示されるグレード(購入数が少なすぎる間は measuring)、およびその販売者の署名済み記録といった事実です。vet402 がその販売者から一度も購入したことがない場合、回答は「vet402 has no record of this seller」です。これらの事実をどう扱うかは、呼び出し元に委ねられています。
公開ファイルのみを読み込みます。公開サイト上の rank.json と records/<id>.json、およびこのリポジトリ内の data/records/index.json です。記録の検証時には、公開 RPC も読み込みます。鍵もウォレットも支払いも書き込みもありません。
60 秒で試す
Node 22 以降が必要です。初回実行時に npm からパッケージ(@vet402/check)をダウンロードします。以降はすぐに起動します。
npx -y @vet402/check https://api.xona-agent.com/token/pumpfun-trending
その販売者の最新の署名済み記録も検証します(署名、Merkle プルーフ、チェーン上の支払い、Solana メモのアンカー)。
npx -y @vet402/check https://api.xona-agent.com/token/pumpfun-trending --verify
Claude Code で MCP サーバーとして使う場合(クライアントがサーバーを起動する前にインストールをキャッシュするため、まず上の行を一度実行してください)。
claude mcp add vet402-check -- npx -y @vet402/check --mcp
Node を使わない場合:Python と curl
同じ照会を HTTP 経由で、無料かつ鍵なしで実行できます:GET https://vet402-delivery.vercel.app/v1/check?url=<seller URL>(chain と payTo は任意です)。回答は verdict と why から始まります(判定の意味)。
- Python、標準ライブラリのみ:
examples/python/check_before_paying.py。コマンド、pay_after_check(url, pay)関数、および x402 Python HTTP クライアント用のフック(x402HTTPClientSync(client).on_payment_required(vet402_on_payment_required))が含まれています。このフックは、クライアントが署名する前に、402 が発生するたびに要求された URL を照会します。 - jq を使う場合と使わない場合の curl の各 1 行コマンド:use.html#curl。
コマンドライン
vet402-check <url> [--chain solana|tempo|base|algorand|<CAIP-2>] [--pay-to <address>] [--amount <atomic units>] [--asset <address>] [--explain] [--verify] [--offline] [--json]
vet402-check verify <record id | https URL | file> [--offline] [--json]
vet402-check diagnose <tx signature or hash> --url <seller URL> [--chain solana|base] [--status <http>] [--json]
vet402-check --mcp
--chainは回答を 1 つのチェーンに限定します(eip155:8453は Base、eip155:4217は Tempo です)。--pay-toは、手元にある 402 の payTo と、vet402 がその販売者について記録した payTo アドレスを比較します。--amountと--assetは、402 の金額(x402 が出力する最小単位)とアセットを、vet402 がその販売者に支払った内容と比較します(402 を vet402 の支払いと比較するを参照)。--explainは、回答の根拠となる購入を新しい順に一覧表示します。各購入について、日付、チェーン、結果、HTTP ステータス、tx を示し、販売者の署名済み記録にある支払い(金額、アセット、payTo)も表示します。--jsonは結果全体を出力します:sellers[](販売者が掲載されているページごとに 1 件)、records、payTo、asOf、sources。- 照会後は、見つかったかどうかにかかわらず終了コード 0 を返します。記録の検証に失敗した場合は 1、不正な入力または読み取り不能なデータの場合は 2 を返します。
クローンから実行する場合:npm ci の後に npm run check-before-paying -- <url> を実行します。
MCP ツール
読み取り専用ツールが3つあります(stdio、改行区切りのJSON-RPC)。
| ツール | 入力 | 戻り値 |
|---|---|---|
check_before_paying | url、省略可能な chain、pay_to、amount、asset、explain、verify_newest_record | 上記の事実と該当する理由。テキストおよび structuredContent として返します |
verify_record | record(IDまたはhttps URL)、省略可能な offline | OK、OK_NOT_ANCHORED、OK_OFFLINE、または FAIL。チェックごとに1行で返します |
diagnose_failed_payment | tx、url、省略可能な chain、status | seller_side、facilitator_side、buyer_side、または undetermined と、その理由。seller_side の場合は証拠パックも返します |
Claude Desktop(claude_desktop_config.json):
{ "mcpServers": { "vet402-check": { "command": "npx", "args": ["-y", "@vet402/check", "--mcp"] } } }
支払い時:x402 フェッチフック
x402 クライアントが支払いに使用するフェッチをラップします。すべての402は、クライアントが署名する前に照会されます。
import { wrapFetchWithPayment } from "@x402/fetch";
import { wrapFetchWithCheck } from "@vet402/check"; // npm install @vet402/check
const fetchWithPay = wrapFetchWithPayment(
wrapFetchWithCheck(fetch, {
onCheck: (e) => {
console.log(e.checks.map((c) => c.summary).join("\n"));
// The rule is yours. To stop the payment, throw here:
// if (e.checks.some((c) => c.sellers.some((s) => s.settled > 0 && s.delivered === 0))) throw new Error("not paying");
},
}),
client,
);
このフックは支払いラッパーの内側に配置します。@x402/fetch は渡されたフェッチを呼び出し、そのフェッチが402を返した後にのみ支払いを作成するためです。このフックはクローンを通じて402を読み取ります(本文のx402 accepts または PAYMENT-REQUIRED ヘッダー、ならびにMPPの WWW-Authenticate: Payment チャレンジ)。提示されたチェーンとpayToの組み合わせごとに check_before_paying を実行し、結果を onCheck に渡してから、402を変更せずに返します。キーや署名者を参照することはなく、ヘッダーも変更しません。すでに支払いを含むリクエスト(X-PAYMENT、PAYMENT-SIGNATURE、Authorization: Payment)はクライアントの再試行であり、そのまま通過します。vet402のレコードを読み取れない場合、onCheck には error が設定され、チェックは行われません。
rank.json とレコードのインデックスは一度読み込まれ、10分間メモリに保持されます(new PublicData({ ttlMs }))。そのため、頻繁に動作するエージェントでも、402のたびにダウンロードする必要はありません。金額の比較に読み取る署名済みレコードも、同様に保持されます。
名前付き理由とポリシー
すべての応答には reasons[] が含まれます。各項目には1文の説明と、その根拠となる購入またはレコードが含まれます。これらは判定と併せて示される事実であり、判定が変わることはありません。
| 理由 | 該当する場合 |
|---|---|
paid_not_delivered | vet402が把握している販売者について、vet402が記録した最新の購入で支払いが決済されたものの、応答がありませんでした(支払い決済後のrank.jsonの販売者側ルール)。この理由は、vet402が結果を伝えている販売者に対してのみ示されます。判定で使用する条件と同じです。 |
payto_differs | 402のpayToは、vet402がこの販売者に支払ったことのある宛先と異なります(vet402が少なくとも1件記録している場合)。 |
price_jump | 402の請求額が、同じURL、同じアセットでvet402が支払った最高額の10倍を超えています。ちょうど10倍の場合は price_jump になりません。 |
asset_unseen | 402の請求アセットは、そのチェーン上でvet402がこの販売者に支払ったことのないアセットです。 |
never_bought | vet402はこの販売者からの購入記録を持っていません(指定されたチェーン上)。 |
stale | vet402によるこの販売者からの最新の購入は、7日より前のものです。 |
price_jump と asset_unseen は、販売者の署名済みレコード(そのチェーン上の最新8件。同じURLのレコードを優先)に基づきます。比較対象となるレコードがない場合、どちらの理由も示されません。
フックにポリシーを渡して、理由ごとの対応を決めます。
const fetchWithPay = wrapFetchWithPayment(
wrapFetchWithCheck(fetch, {
policy: { paid_not_delivered: "block", payto_differs: "block", price_jump: "block", asset_unseen: "ask_human", never_bought: "warn" },
askHuman: async (e) => confirmWithPerson(e.reasons), // true pays, anything else stops
}),
client,
);
blockはクライアントの署名前にCheckBlockedErrorをスローします。reasonsには処理を止めた理由が示されます。ask_humanはaskHuman(event)を呼び出し、trueが返された場合にのみ支払います。askHumanがない場合は、CheckBlockedErrorの一種であるCheckNeedsApprovalErrorで停止します。warnとallowは処理を続行します。ポリシーで指定されていない理由はallowとして扱われます。onCheckには、この処理の前にevent.reasonsとevent.decision(理由ごとのアクションと、最も厳しいアクション)が渡されます。policyを指定しない場合、フックの判定と待機の動作は0.1.2とまったく同じです。event.reasonsにはrank.jsonだけに由来する理由が含まれ、署名済みレコードは読み取られないため、price_jumpとasset_unseenは確認されません。- vet402のレコードを読み取れない場合は、
event.errorが設定され、理由はなく、支払いは0.1.2と同様に続行されます。
vet402 が支払った金額との 402 の比較
npx -y @vet402/check https://api.xona-agent.com/token/pumpfun-trending --chain solana --amount 1000000 --asset EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
回答には comparison が追加されます。署名済みレコードの読み取り結果、この販売者に vet402 が支払った資産、この URL に対して vet402 が支払った最高額とそのレコードおよび tx、さらに 402 の金額との比率が含まれます。policy を指定すると、フックは 402 内のすべての x402 オファーについて同じ比較を行います。
支払い後に応答がなかった場合の診断
npx -y @vet402/check diagnose <tx signature or hash> --url <seller URL> --status 500
TypeScript からは diagnose({ tx, url, status }, new PublicData()) を呼び出します。MCP ツールとしては diagnose_failed_payment を使用します。
- パブリック RPC から支払いを読み取ります(Solana または Base。別の RPC を使う場合は
SOLANA_RPC_URLとBASE_RPC_URLで指定します)。決済済みかどうか、payTo、金額、資産、時刻を確認します。署名も送信も行いません。 - vet402 独自の障害ルール(rank.json の生成に使われているものと同じコード)で試行を分類します。
- 同じチェーン上の同じ販売者に対する、支払いから 24 時間以内の vet402 独自の購入を一覧表示します。該当する購入がない場合は、最も近い購入を表示します。rank.json では販売者ごとに最新の購入が保持されるため、古い支払いは対象期間内の購入がない場合があります。
回答の fault は、reasons[] を含みます。
seller_sideになるのは、次の条件をすべて満たす場合に限ります。支払いがオンチェーンで決済済みであること、vet402 がこの販売者への支払いに使った payTo 宛てであること、vet402 がこの販売者への支払いに使った資産であり、金額が vet402 の支払った最低額以上であること、HTTP ステータスが決済後に販売者側の問題として vet402 のルールに定められているものであること(5xx、再度の 402)、rank.json にある販売者の最新購入リストが対象期間の開始時点より前まで遡れること、24 時間以内の販売者からの vet402 独自の購入も決済済みで応答がなく、配信されたものがないこと、さらに該当日付の署名済みレコードに、販売者から配信された購入が記録されていないこと。buyer_sideになるのは、支払いトークンアカウントの残高不足が原因でオンチェーンの支払いに失敗した場合に限ります。facilitator_sideになるのは、オンチェーンの支払いが別の理由で失敗し、かつ対象期間内の販売者への vet402 独自の支払いも決済前に失敗している場合に限ります。- それ以外はすべて
undeterminedです。これには、RPC を読み取れない場合、該当するトランザクションがない場合、ステータスが指定されていない場合、4xx、vet402 が一度も支払ったことのない payTo、vet402 が販売者への支払いに一度も使ったことのない資産、vet402 の支払った最低額を下回る金額、対象期間内に販売者から応答があった場合(rank.json または該当日付の署名済みレコード)、rank.json のリストが対象期間まで遡れない場合、対象期間内に vet402 の購入がない場合が含まれます。すべての条件を満たさない限り、販売者の名前は示されません。
seller_side の場合、evidence には販売者に渡せる資料が JSON と Markdown 形式で含まれます。tx とそのエクスプローラーリンク、payer、payTo、金額と資産、購入者が報告した HTTP ステータス、この支払いについて vet402 のルールが示した内容、対象期間内の vet402 の購入とその tx、該当日付の署名済みレコードが含まれます(vet402 独自の支払いである場合、その支払い自体は除外されます)。資料は表示されるだけで、送信されません。
フレームワークの例
このフォルダーの examples/(npm パッケージには含まれません)には、Coinbase AgentKit、OpenAI Agents SDK、Vercel AI SDK(TypeScript)、LangChain(Python)の例があります。それぞれ、エージェントにポリシー付きの check を通じて、支払いが必要な x402 URL を取得するツールを 1 つ提供します。packages/check/test/examples.test.ts は、フレームワークのツール関数をローカルの代替関数に置き換え、ネットワーク接続なしで各例を実行します。
回答の読み方
- 試行済み/決済完了/回答あり:決済完了後に、本文が空でない 2xx 応答があったことを示します。vet402 は、その回答がリスティングで約束された内容かどうかは確認しません。
- 販売者の責任としてカウントされる失敗:
rank.jsonのmethod.faultRulesにおいて、販売者に責任があるルールです(例:paid_not_deliveredは、vet402 の決済が完了し、販売者が 5xx または無応答だった場合です)。 - 販売者の責任としてカウントされない失敗:vet402 側またはファシリテーター側で発生した失敗と、原因を特定できない失敗です。
- 評価:
rank.jsonに表示される評価です。measuringは、評価を付けるには購入数が少なすぎることを意味します。 - 署名済みレコード:DELIVERED の購入について公開されます。また、その他の判定については、vet402 が販売者に通知した後に公開されます。購入実績があり、否定的なレコードがない販売者でも、
rank.jsonに失敗が記録されている場合があります。 - 基準日:
rank.jsonと読み込まれたレコードの日付です。vet402 はスケジュールに従って再購入するため、最新の購入後に販売者の状況が変わることがあります。
レコードを検証できる理由
各レコードは vet402 の観測鍵で署名されています(EIP-712)。各日のレコードは Merkle ツリーを形成し、そのルートは vet402 のアンカーウォレットによって Solana の memo に書き込まれるため、ルートを変更せずに後からその日のレコードを追加または削除することはできません。verify_record は、バイト列がレコードインデックスに記載されたものかどうか、鍵、署名、判定が記録されたチェック結果に基づいていること、Merkle 証明、Solana、Base または Tempo 上の公開 RPC を通じた支払い、および memo を検証します。scripts/verify-receipt.ts(src/receipt/)と同じコードを使用します。RPC:SOLANA_RPC_URL、BASE_RPC_URL、TEMPO_RPC_URL、または公開エンドポイント。
その他のソース
VET402_CHECK_RANK、VET402_CHECK_RECORDS_INDEX、VET402_CHECK_RECORDS_BASE を設定すると、チェック対象を別のコピー(https URL またはローカルパス)に切り替えられます。たとえば、サイトのローカルビルドを指定できます。
テスト
npm test は、ネットワークを使用せず、packages/check/test/make-fixtures.ts によって公開データから作成されたフィクスチャを使って packages/check/test/check.test.ts を実行します。フィクスチャには、販売者側の失敗と否定的なレコードがある販売者、配信済みの販売者、不明な販売者、チェーンと payTo のフィルター、共有ホスト、成功するレコード検証、および 1 文字だけ変更したレコード、Merkle 証明、別のウォレットからの memo(いずれも検証に失敗)が含まれます。
packages/check/test/v020.test.ts では、diagnose(Solana と Base の固定 RPC 応答:決済完了、チェーン上で失敗、見つからない、RPC がダウン)、402 と vet402 の支払いの比較、理由とフックのポリシーを実際の @x402/fetch およびスパイ署名者とともに検証し、--explain と MCP ツールもテストします。packages/check/test/examples.test.ts はフレームワークのサンプルを実行します。
packages/check/test/no-node.test.ts は、ループバック上で /v1/check 自身のハンドラーに対して、Python のサンプルと、use.html の Python および curl の行を実行します。packages/check/test/package.test.ts は npm パッケージ(scripts/build.mjs)をビルドし、リポジトリ外のフォルダーから実行します。
先行する取り組み:決済ラッパーの下にフックを配置する方法は、別の公開レコード(probe402 のレコード)をチェックする probe402-check に倣っています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。