capacity-attest について
capacity-attestは、x402の容量取引後に署名付きの事実ベースの納品記録を残すMCPサーバーです。購入側のエージェントは取引前に販売者の記録を確認できますが、評価や紛争の裁定は行いません。
主な機能
- 01署名付き納品記録の登録
- 02記録ハッシュと署名の検証
- 03販売者記録の時系列取得
- 04関連記録の欠落チェック
- 05独立ソースからの記録発見
活用シーン
- 01支払い後のGPU時間やストレージ納品の記録
- 02支払い前の販売者履歴の確認
- 03複数ソースから集めた記録の比較
MCP 対応
納品記録の登録と販売者履歴の取得に使うツールをMCPクライアントに公開します。記録内容と購入者の署名を検証してから台帳に追記します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
3掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| claimId | string | はい | コンテンツアドレス型 ID:この請求の内容フィールドを正規化した JSON の sha256。computeClaimId() を参照してください。 |
| measured | object | いいえ | 約束された量と測定量の任意の定量記録です。フィールドの有無がバージョンマーカーとなり、「未測定」を示す唯一の方法はフィールドを省略することです。 |
| measured.unit | enum | はい | 以下の数量の単位。この assetType に対応する UNITS_BY_ASSET_TYPE の項目に含まれている必要があります。gpu-second | byte | byte-second | call | token | credit |
| measured.basis | enum | はい | この数値が、販売者が利用可能にした量(`supplied`)を数えるのか、購入者が実際に引き出した量(`consumed`)を数えるのかを示します。supplied | consumed |
| measured.method | object | はい | 数値の取得方法です。 |
| measured.method.instrument | string | はい | 測定機器に関する自由記述です。例:"nvidia-smi accounting, 10s polling" |
| measured.method.attribution | enum | はい | 数値を生成した主体です。出所のみを示し、品質や信頼性の指標ではありません。buyer | seller | third-party | undisclosed |
| measured.method.readingsHash | string | いいえ | 生のメーターダンプの sha256。ダンプ自体は保存されません。配達の証拠に関する evidenceHash とは別のものです。 |
| measured.period | object | はい | この測定が対象とする、終了済みの期間です。 |
| measured.period.end | string | はい | 終了済みの測定期間の終了時刻。正規形式の UTC 時刻です。 |
| measured.period.start | string | はい | 終了済みの測定期間の開始時刻。正規形式の UTC 時刻です。 |
| measured.promisedAmount | string | はい | 約束された金額。正規化された十進文字列で指定 |
| measured.deliveredAmount | string | はい | 測定された金額。正規化された十進文字列で指定 |
| assetType | enum | はい | この請求が対象とする容量の種類gpu-hours | storage | api-credits | bandwidth |
| delivered | enum | はい | 約束された内容が実際に届いたかどうかyes | no | partial |
| signature | string | はい | claimId に対する買い手の EIP-191 personal-sign 署名 |
| timestamp | string | はい | この請求が作成された日時の ISO-8601 タイムスタンプ |
| buyerAddress | string | はい | 支払いを行うエージェントの 0x アドレス。`signature` から復元されたアドレスと一致する必要があります |
| evidenceHash | string | はい | この請求の証拠(ログ、応答ペイロードなど)の sha256 16 進ダイジェスト。証拠自体はここに保存されません |
| externalRefs | object | いいえ | 他のエージェント経済インフラ(アイデンティティ、権限、意図、紛争)を指す、任意の未検証ポインターです。Tokenizen はこれらを解決も信頼もしません。検証済みの事実ではなく、参照情報です |
| externalRefs.intentRef | string | いいえ | 外部で発行された署名済み意図オブジェクト(例:AP2 IntentMandate)への未検証ポインター。買い手のプリンシパルが当初依頼した内容を記述します |
| externalRefs.mandateRef | string | いいえ | 外部で発行された権限/委任オブジェクト(例:AP2 Payment/Cart Mandate)への未検証ポインターです。買い手はこれが今回の納品を対象としていると主張します。Tokenizen はこれに照らして範囲、予算、有効性を確認しません |
| externalRefs.buyerAgentRef | string | いいえ | 買い手の外部エージェント ID レコードへの未検証ポインターです。Tokenizen はこれを解決も検証もしません |
| externalRefs.disputeContext | object | いいえ | 決済時に買い手と売り手が外部紛争条件にすでに合意していた場合にのみ存在します。delivered:no の請求を、その外部プロトコルでの証拠として使用可能にし、Tokenizen 自身は裁定しません |
| externalRefs.disputeContext.protocol | string | はい | この請求を証拠として使用できる外部紛争/責任プロトコルの短いラベル。例:"LCP" |
| externalRefs.disputeContext.termsHash | string | はい | 決済時に双方が受諾した適用条件の sha256。条件自体はここに保存されません |
| externalRefs.disputeContext.resolutionRef | string | いいえ | `protocol` で指定された外部プロトコルに解決/ケースレコードが存在する場合、そのレコードへの任意のポインター |
| externalRefs.sellerAgentRef | string | いいえ | 売り手の外部エージェント ID レコード(例:ERC-8004 agent id または DID)への未検証ポインターです。Tokenizen はこれを解決も検証もしません |
| externalRefs.mandateIssuerDid | string | いいえ | `mandateRef` が参照する委任を発行したとされるプリンシパルの DID。委任自体との照合検証は行われません |
| priorClaimId | string | いいえ | 任意のチェーンリンク:この買い手が同じ sellerAddress について直前に行った請求の claimId。買い手がその売り手に初めて請求する場合は省略します。読者がホストによる中間請求の隠蔽を検出できます。analyzeCompleteness および DECISIONS.md D-006 を参照 |
| promisedSpec | any | はい | 売り手が納品を約束した内容。自由形式のテキストまたは構造化オブジェクト |
| sellerAddress | string | はい | 支払いを受け、履行する予定だったエージェント/サービスの 0x アドレス |
| settlementRef | string | はい | この申し立ての対象となる決済の x402 支払い参照情報、またはオンチェーントランザクションハッシュ |
詳細
capacity-attest
AI エージェント間の x402 キャパシティ取引における納品証明のための MCP サーバーです。
ステータス:MVP。npm(
npm install capacity-attest)および公式 MCP レジストリ(io.github.holistis/capacity-attest)で公開されています。
主張だけでなく、第三者が独立して確認済み
以下のこのプロジェクトに関する記述は、すべてクリックして独立に検証できます。こちらの言葉をそのまま信じる必要はありません。
| 内容 | 誰が | ステータス |
|---|---|---|
実際の依存関係として [email protected] を使用し、独自のコードを通じて claim digest/claimId/署名を検証 | YE-YI7/asm-spec#18 | マージ済み |
| 同じコンテンツアドレス方式の claim 形式を使用する BSV レールアダプター | YE-YI7/asm-spec#19(作成者:EmbryoSpace) | マージ済み |
| 当プロジェクトの境界に関する主張(「発見可能性 ≠ 完全性」)は、何も鵜呑みにせず、第三者によってオンチェーンで独立に検証済み | x402-foundation/x402#3379 | 公開中、継続中 |
| Base メインネット上のライブ納品 claim は、誰でもデコードできるオンチェーン証明として記録 | delivered=yes · delivered=no | 稼働中 |
| 2 番目および 3 番目のチェーン(WP2)でも同様に稼働中。EAS ソースが Base だけでなく、複数のデプロイ環境で動作することを証明 | Optimism · Ethereum mainnet | 稼働中 |
ERC-8004 Reputation Registry に対する実際の giveFeedback() 呼び出し、Base メインネット | tx 0x2217...efc0 | 稼働中 |
| 他のプロジェクトのエージェント仕様に、購入者側の追加機能として提案 | omworldprotocol/om-world#18 | レビュー中、未マージ |
| 独立して再実装された標準ライブラリのみの Python 検証ツール(独自の secp256k1/EIP-191/canonical JSON 実装を使用し、コードを共有せず)、偽造署名と改ざん済み claim の両方のネガティブコントロールを含む、当プロジェクト独自のテストベクトルすべてで 7/7 一致。現在は別途独立して公開されたプロジェクトの恒久的な回帰テスト | x402-foundation/x402#2887 (comment)、作成者:goun7。Tamga(pip install tamga-protocol)に統合済み | 他のプロジェクトに恒久的に統合済み |
ドラフト版 ERC-8004 grounded-feedback 規約において、計測された納品の信頼できる情報源として measured ブロックを引用。当リポジトリの特定のコミットに固定され、2 つの独立した検証ツール(Node と Python)が 5 件の署名済みテストベクトルすべてで合格 | erc-8004/erc-8004-contracts#99、スキーマのドキュメント:predgeAI/erc8004-outcome-validator | ドラフト v0、公開中、コミットハッシュで参照 |
以下の表とは誠実に分けて記載します。これは第三者によるレビューではないためです。 ブロックチェーンへの書き込みを実際に行う最初のバージョンである 0.6.0 より前に、当プロジェクト独自で敵対的セキュリティレビューを実施しました。9 件の指摘はすべて修正済みです。うち 7 件は専用の回帰テストで解決を確認し、1 件は単体テストではなくパッケージングチェック(npm pack --dry-run)で検証し、1 件はドキュメントのみの修正でした。外部組織による独立監査ではありません。完全版の検証可能なレポートはこちらです:docs/SECURITY-REVIEW-2026-09-11.md。
これが必要な理由
AI エージェントが別のエージェントやサービスからキャパシティ(GPU 時間、ストレージ、API/推論クレジット、帯域幅)を x402 protocol 経由で購入しても、支払い後に、約束されたものが実際に提供されたことを示す証拠はありません。購入したエージェント自身はそれを把握しています(出力を確認した、あるいは確認できなかったため)が、セッションが終了した瞬間に、その知識は失われます。同じ販売者と取引しようとする次のエージェントは、また何も知らない状態から始めることになります。
capacity-attest は、この特定の問題を解消します。決済後、支払いを行ったエージェントは、暗号学的に署名された事実に基づく主張(delivered: yes/no/partial +証拠のハッシュ)を残します。他のエージェントは、同じ販売者と取引する前にその履歴を取得できます。
評価はしません。評判スコアもありません。「判定」もありません。署名付きの受領証と主張だけです。実物の荷物を受け取るときに、配送伝票を受け取るのと同じです。
これは意図的に何ではないか
これは、意図的かつ恒久的に、以下のものではありません。
- 評判スコアや評価ではありません。
get_delivery_historyは、主張を時系列順に並べた生のリストを返します。平均値や割合、「信頼スコア」は返しません。それらを単一の数値に要約することは暗黙の評価にあたり、このプロジェクトの設計段階で明確に却下されました。 - 金融商品ではありません。 利息、支払いの時間割引、台帳残高への利回り(残高はなく、エスクローでもありません)、貸付、担保、請求書の融資/ファクタリングはありません。
assetTypeはキャパシティの種類(gpu-hours、storage、api-credits、bandwidth)を示す閉じた列挙型であり、金融商品に類するものは意図的に含めていません。 - 独自のトークンやコインではありません。 支払いには通常どおり x402/USDC を使用します。このプロジェクトは、別の場所で既に行われた決済の受領を記録するだけです。
- 信用供与ではありません。 主張は、完了した支払いの後にのみ作成されます。このプロジェクトは何も融資せず、既に完了したイジャーラ(賃貸/サービス)取引を記録するものです。
- 独自のアイデンティティ、権限、紛争解決レイヤーではありません。
externalRefs(以下を参照)は、他者のシステム(ERC-8004、AP2、Legal Context Protocol など)への参照にすぎません。このプロジェクト自体が、その参照を解決、検証、判定することはありません。これが独自のプロトコルにならなかった理由については、DECISIONS.md の D-007 から D-013 を参照してください。
これは、意図的に正式なレビューを経て選択された設計方針であり、偶発的なスコープの制限ではありません。ここに何かを追加することを検討している場合は、プロジェクト概要のガードレールのセクションを参照してください。あるフィールドや関数がこの境界に触れるかどうか迷った場合は、追加しないでください。
意図的に先送りされた機能(アンカリング、中間ステータス、正式な適合性ベクトル)と、それでも実装に着手する正確な条件については、DECISIONS.md を参照してください。
さらに詳しく知るには、上記の D-014/D-018 を公開解説した配送の主張を偽装する9つの方法と、どれも完全にはうまくいかなかった理由をご覧ください。
仕組み
1. record_delivery
支払いを行ったエージェント(購入者)は、x402 の決済後、約束されたものが届いたかどうかが判明した時点で、この処理を呼び出します。申し立てには次の項目が含まれます。
| フィールド | 意味 |
|---|---|
sellerAddress | 支払いを受けた当事者の 0x アドレス |
buyerAddress | 支払いを行ったエージェントの 0x アドレス。signature から復元されるアドレスと一致している必要があります |
assetType | gpu-hours | storage | api-credits | bandwidth |
promisedSpec | 約束された内容。自由記述テキストまたは構造化オブジェクト |
delivered | yes | no | partial |
evidenceHash | 裏付けとなる証拠(ログ、レスポンスペイロードなど)の sha256 16 進数値。証拠自体は保存されません |
settlementRef | x402 の支払い参照、または基となる支払いのオンチェーントランザクションハッシュ |
timestamp | ISO-8601 タイムスタンプ |
claimId | 上記すべてのフィールドのコンテンツアドレス指定 sha256 ハッシュ。src/schema.ts の computeClaimId() を参照してください |
signature | claimId に対する購入者の EIP-191 personal-sign 署名 |
externalRefs | (0.3.0 以降では省略可能) 他のエージェントエコノミーインフラストラクチャへの未検証の参照:sellerAgentRef/buyerAgentRef(例:ERC-8004 エージェント ID や DID)、mandateRef+mandateIssuerDid(外部発行の AP2/AAE マンデート)、intentRef(外部 AP2 IntentMandate)、disputeContext(protocol+termsHash+省略可能なresolutionRef。例:Legal Context Protocol の参照)。DECISIONS.md の D-007 から D-013 を参照してください |
priorClaimId | (0.4.0 以降では省略可能) 同じsellerAddressについて以前に行った申し立てのclaimId。これにより、その販売者に関する申し立てが連鎖します。販売者に関する最初の申し立てでは省略します。署名対象のコンテンツの一部であるため、ホストが削除することはできません。ホストが途中の申し立てを隠していることを、読み手が検出できるようにします。DECISIONS.md の D-006 を参照してください |
offerReceiptHash | (0.8.0 以降では省略可能) この申し立てが回答する、販売者署名済みの x402 offer-receipt の sha256 16 進数値。送信されたとおりのレシートアーティファクトを対象とします。レシートはサービスが提供されたという販売者の表明であり、この申し立ては実際に届いたものについての購入者の表明です。この2つをリンクすることで、利害関係者だけの一方的な説明ではなく、紛争の双方の見解を提示できます。署名対象のコンテンツの一部であるため、署名後に参照を差し替えたり削除したりすることはできません。両方の要素と実際の署名を含む使用例: examples/offer-receipt-link-testvector.json |
サーバーはまずスキーマを検証し、次にclaimIdが実際にコンテンツのハッシュであるか、続いてsignatureから復元されるアドレスが実際にbuyerAddressと一致するかを検証します。検証に成功した場合に限り、追記専用の台帳(data/claims.jsonl)に申し立てが追加されます。無効な署名、またはすでに保存されている申し立て(同じclaimId)は拒否されます。
2. get_delivery_history
sellerAddressを指定すると、このインストール環境でその販売者に対して記録されているすべての請求を、古い順に返します。要約した件数ではなく、事実のみを返します。購入エージェントは支払いの前にこれを呼び出し、販売者候補の生の配送履歴を確認して、自ら判断できます。
レスポンスには、sellerAddress、count、claimsに加えて、scope(常に"local-ledger")と、この結果がこのインストール環境のローカル台帳のみを反映していることを説明する固定の事実文noteが含まれます。履歴が空、または短いからといって、その販売者に問題のない記録があるとは限りません。ここではまだ請求が記録されていないだけの場合もあります。
0.4.0以降、レスポンスには、まさにこの結果セット内の購入者ごとのチェーン(priorClaimId)を分析するcompletenessも含まれます。ここに表示された請求が、結果セットに含まれていない請求を参照している場合、その情報はpossibleOmissionsに表示されます。漠然とした疑いではなく、ホストが途中の請求を隠している可能性を示す、具体的で検証可能なシグナルです。
ただし、最も重要な点に注意してください。このcompletenessフィールドは、請求を返すサーバーと同じサーバーが計算しています。そのサーバーを信頼できないなら、このフィールドも信頼しないでください。不誠実なホストは、いくらでも「すべて完全」と設定できます。本当の保証は、請求そのものに含まれる署名済みのpriorClaimIdにあります。ホストはこれを偽造したり削除したりできません。そこで、返された請求を使って、自分でチェックを再計算してください。
// recompute-completeness.mjs
import { verifyClaim } from "capacity-attest/dist/signing.js";
import { analyzeCompleteness } from "capacity-attest/dist/completeness.js";
// `claims` = the array from the get_delivery_history response.
const allSigned = claims.every((c) => verifyClaim(c).ok); // is every claim genuine?
const report = analyzeCompleteness(claims); // recompute yourself, don't trust the host field
console.log({ allSigned, chainConsistent: report.chainConsistent, possibleOmissions: report.possibleOmissions });
正直なところ、自分で再計算しても、最後の請求が隠されている場合や、購入者全体が隠されている場合は検出できません。どちらの場合も、手掛かりとなるリンクがないためです。また、前の請求への参照が見つからないからといって、必ずしも不正行為とは限りません。前の請求が別のインストール環境に記録されているだけかもしれません(D-005のケース)。本当に確信を得るには、外部の証拠が必要です。上記の自分で保管したコピーと、オンチェーンの支払い(settlementRef)です。DECISIONS.mdのD-006を参照してください。
ホストが隠蔽を試みるケースをシミュレートした、公開済みで自分で検証可能な例と、意図的に壊したテストケースが、docs/COMPLETENESS-FIXTURE.mdにあります。npm run fixtureで実行できます。同じチェックはテストとしてプッシュごとに実行されます。したがって、私たちの言葉をうのみにせず、自分で主張を検証できます。
他のインストール環境からのクレームの発見(D-005)
get_delivery_history は定義上ローカルの機能です。購入者 B は、別のインストール環境で購入者 A が同じ販売者について記録した内容を確認できません。すべてのクレームは自己検証可能なため、発見に信頼できるインデックスは必要ありません。discoverDeliveryHistory(seller, sources)(src/discovery.ts を参照)は、複数の独立した信頼できないソース(ローカルの台帳と、読み取りたいホストに依存しない基盤など)から販売者のクレームを読み込み、重複を排除し、すべてのクレームを再検証し、他の販売者のものを除外したうえで、結合したデータセットに対して完全性チェックを実行します。偽のデータを注入するソースは拒否されます。不足があるソースは D-006 の問題です。これは考慮されていますが、魔法のように解決されるわけではありません。
このプロジェクトが対象とする3つのチェーンすべてで、本番環境の基盤が稼働しています。EAS アテステーションは Base メインネット、Optimism メインネット、Ethereum メインネットに存在し、それぞれについて単に説明されているだけでなく、公開ブロックエクスプローラーのリンクから独立して検証できます。2つのインストール環境をシミュレートする、実行可能な公開サンプルはdocs/DISCOVERY-FIXTURE.mdにあります。npm run discovery-fixture で実行してください。DECISIONS.md の D-005 を参照してください。
EAS 以外の、本番品質の ClaimSource も同梱されています。httpClaimSource(src/http-source.ts)は、GET <url>?seller=<address> に対してクレームの JSON 配列を返す、規約に従った単純な HTTP エンドポイントです。これは discoverDeliveryHistory 自身のヘッダーコメントで言及されている「別のインストール環境の公開エンドポイント」の具体例の1つです。これは単に2つ目の EAS デプロイを用意するのではなく、まったく異なる種類のソースに対して集約レイヤーを実証するために存在します。ほかのすべてのソースと同様に信頼できないため、不正な形式の応答や悪意のある応答を受けても発見処理がクラッシュすることはなく、ソースごとのエラーとして表示されます。examples/reputation-lookup.mjs は、ローカルの台帳と両方の本番ソース(EAS と HTTP)を組み合わせて実際に検索する、実行可能な CLI です。npm run build && node examples/reputation-lookup.mjs <sellerAddress> で実行してください(必要に応じて、事前に RPC_URL や HTTP_SOURCE_URL を設定してください。読み取りのみのため、資金の入ったキーは不要です)。
docs/INTEGRATION-GUIDE.md では、3種類すべてのソースを実際のコードとともに解説しています。また、他のプロジェクトが構築した独立した実際の統合例を2つ(Base リンクのフィクスチャと BSV レール。いずれも当プロジェクトが構築したものではありません)取り上げ、新しいチェーンにこのクレーム形式を拡張する具体的な実例として紹介しています。
3. resolve_agent_identity (0.3.0 以降)
ERC-8004 Identity Registry に対する読み取り専用の検索機能です。agentId の所有者(ownerOf)と、その登録ファイルの場所(tokenURI)を確認します。呼び出されるのは標準の ERC-721 インターフェースのみで、ERC-8004 固有の機能は使用しません。呼び出し元は、agentRegistryRef("eip155:<chainId>:<registryAddress>")とそのチェーンの rpcUrl の両方を指定する必要があります。ERC-8004 はチェーンごとに独立してデプロイされ、EIP の本文にも固定アドレスが記載されていないため、このプロジェクトには意図的に独自の RPC プロバイダーも、標準となるレジストリーアドレスも同梱していません。tokenURI の参照先は意図的に取得しません(取得したい場合は、呼び出し元がポインターを使って自ら取得できます)。取得すると、呼び出し元が制御できるオンチェーンデータを介した SSRF に似たリスクが生じるためです。
差し替え可能な ContractFactory を使ったテスト(src/erc8004.test.ts、ネットワーク依存なし)と、Base メインネット上に実際にデプロイされたレジストリーを使った実環境でのテスト(examples/verify-erc8004-live.mjs、npm run build && node examples/verify-erc8004-live.mjs)を実施しています。詳細な背景については、DECISIONS.md の D-007 を参照してください。
4. publishReputationFeedback (0.6.0 以降、ライブラリ関数であり、MCP ツールではありません)
注記(2026-09-11 の敵対的レビュー時点):執筆時点で、npm にはこの関数を含まないバージョン 0.5.0 が引き続き公開されています。 GitHub でこれを読んですぐに、以下の説明に従って npm install capacity-attest を実行する方は、まだ publishReputationFeedback を利用できません。これをインポートする前に、npm view capacity-attest version で実際に公開されているバージョンを確認してください。以下の説明はすべて、main ブランチ上のコードに基づいています。
すでに署名済みのクレームの delivered という事実を、ERC-8004 Reputation Registry の giveFeedback() に公開します。この場所では、登録済みの約 500k のエージェントが、すでに評判のシグナルを確認できます。公開先は、このインストール固有の台帳や EAS だけではありません。コントラクトは数値の value と valueDecimals フィールドを必須としますが、このパッケージは評価尺度を独自に作り出すことを意図的に避けています。value は delivered を文字どおり機械的に反映した値(はい=1.0、一部=0.5、いいえ=0.0)であり、新たな判断を示すものではありません。また、capacity-attest 自体がこの数値を読み戻したり、どこかに表示したりすることはありません。オンチェーンに書き込む前に、クレームの署名を再検証します。
呼び出し元は reputationRegistryRef("eip155:<chainId>:<registryAddress>"。Reputation Registry であり、Identity Registry ではありません)、agentRegistryRef(同じチェーン上の Identity Registry)、および rpcUrl を指定する必要があります。これは resolve_agent_identity と同じく、必要なものをすべて呼び出し元が提供する方式です。agentId(販売者の ERC-8004 エージェント)は、有効な Identity Registry エージェントとしてすでに登録されている必要があります。コントラクトは、エージェント自身のオーナーからのフィードバックを拒否します(「Self-feedback not allowed」)。2026-09-11 の敵対的レビュー以降、オンチェーンに書き込む前に、agentRegistryRef を通じて agentId の登録済みオーナーが claim.sellerAddress と一致することも必ず確認します。この確認がなければ、呼び出し元は正規に署名された有効なクレームを、任意の別の agentId にひも付けることができてしまいます。
意図的に MCP ツールにはしていません。 EAS の publishClaim と同じ理由によるものです。これは、実際に資金があり、ガス代を支払える署名者を必要とする書き込み操作であり、このサーバーは独自の秘密鍵を同梱も保存もしません。自分で署名者を管理する方は、直接インポートして利用できます(src/erc8004-reputation.ts)。
注入可能な ReputationContractFactory に対するテスト(src/erc8004-reputation.test.ts、ネットワークに依存しない 19 件のテスト。value が delivered のみに依存することを明示的に検証するテストと、agentId のオーナー確認を検証する 3 件のテストを含みます)を実施済みです。また、Base メインネット上の実際にデプロイ済みのレジストリに対するライブテスト(examples/erc8004-reputation-live-demo.ts、npm run erc8004-reputation-demo)も実施済みです。2026-09-10 に、当方で用意した使い捨てのテスト用エージェント(agentId 85888)を使い、実際の giveFeedback() 呼び出しを確認しました。トランザクション 0x221797800d5941dff62e87022083e7c6dfba3e07b35c84e56b10fdca8967efc0 は、別途 eth_getTransactionReceipt を呼び出して二重に独立確認済みです。D-005 自身の発動条件にもかかわらず、なぜこれを今実装したのかを含む詳しい背景については、DECISIONS.md の D-016 を参照してください。
署名
クレームに署名するのは販売者ではなく購入者です。購入者は支払いを行っているため、何が届いたか、または届かなかったかを把握している当事者です。署名方式には、EIP-712 の型付きデータではなく、claimId に対するプレーンな EIP-191 personal_sign(ethers.Signer#signMessage 経由)を意図的に採用しています。これにより、この MVP の暗号処理の範囲を小さく保ち、監査しやすくしています。既存のクレームを無効にすることなく、後から EIP-712(mcp-paywall/src/x402.mjs のような方式)へ追加的に移行することも可能です。
クレームを独立して検証する
台帳に記録されたすべてのクレームは、このプロジェクトへのアクセスも、こちらへのネットワーク呼び出しも必要なく、npm パッケージとクレームの生バイトデータだけで再確認できます。アカウントも、ホストされた呼び出しも不要です。
npm install capacity-attest
// verify.mjs, run as an ES module (top-level await)
import { verifyClaim } from "capacity-attest/dist/signing.js";
const claim = JSON.parse(await (await fetch("<url to a claim.jsonl line>")).text());
console.log(verifyClaim(claim));
// { ok: true } if claimId really is the hash of the content AND signature really recovers to buyerAddress
注:パッケージのルートではなく、capacity-attest/dist/signing.js を直接インポートしてください。ルート(dist/index.js)はインポートされた瞬間に stdio 経由で MCP サーバーを起動するため、単独の検証スクリプトがハングします。
verifyClaim() が確認するのは、次の 2 点だけです。claimId がクレームの各フィールドのコンテンツアドレス付きハッシュであること、および signature(EIP-191)から buyerAddress が復元されることです。基盤となる決済(settlementRef)がオンチェーンで実際に有効かどうかは確認しません。これは該当するチェーンに対して別途確認する必要があります。また、delivered が true かどうかや、evidenceHash が実際の証拠をカバーしているかどうかも確認しません。これらは支払いを行うエージェント自身の申告に委ねられます。
これらの手順を実際に外部で再現した動作例は、github.com/YE-YI7/asm-spec, PR #18 にあります。実際に登録されたクレームに対してこれを実行した独立したプロジェクトです。
安全に依存できること
独自の検証器を作成する場合や、このリポジトリを仕様として固定する場合に必要なのは、変更されない部分です。
次の 4 点は固定されており、今日署名されたクレームも何年後でも検証できるように設計されています。
- クレームのハッシュ計算に使う正規形式。バイト単位で
docs/metered-delivery-spec.mdに規定されています。 - その正規形式から
claimIdを導出する方法。 - 署名対象となる EIP-191 メッセージ、および署名から
buyerAddressが復元されること。 - 厳密な
issuedAtの形式。小数部が正確に 3 桁のYYYY-MM-DDTHH:MM:SS.sssZです。
新しい任意フィールドの追加は破壊的変更ではなく、マイナーバージョンで行えます。新しいクレームを読み込む古い検証器でも、認識しているフィールドについては同じ claimId を得られるためです。フィールドの削除や名前の変更、正規形式の並べ替え、ハッシュ計算方法の変更は、これまでに署名されたすべてのクレームを無効にするため、バージョン管理の対象ではなく、行わないこととしています。
この約束は宣言するだけでなく、検証によって確かめています。examples/ にある公開済みテストベクトルには、正規化前の入力、バイト長、claimId、EIP-191 ダイジェスト、署名、期待される復元アドレスがそれぞれ個別に記録されています。2 つの単独スクリプトが CI の実行ごとにこれらを検証します。どちらも、このパッケージのソースをインポートせず、1 つの JSON ファイルを読み込む意図的な再実装です。そのため、検証対象のコードと同じ結果を返すだけでテストを通過することはありません。形式を壊せば、何かを公開する前に CI が失敗します。
破壊的変更が本当に避けられない場合は、別のパッケージ名で新しいメジャーバージョンとして公開し、旧バージョンは引き続き動作させ、公開し続けます。また、コードを変更する前に、その理由を DECISIONS.md に記載します。コミットを固定した関係者が、こちらの判断で変更されることはありません。
ホストに依存せず、自分が送信したクレームを共有する(D-006)
get_delivery_history は、MCP サーバーの運営者の誠実さに依存します。このツールの応答にある note と DECISIONS.md(D-006)を参照してください。表示されるクレームはすべて本当に実在するものです(2026-09-06以降は、書き込み時だけでなく読み取り時にも署名を再検証しています)が、ホストが実際に保有するすべてのクレームを表示していることを証明するものはありません。
自分でクレームを送信した購入者であれば、そのホストを待つ必要はありません。そのクレームには自分で署名しているため、ホストを介さず、疑念を持つ相手に直接提示できます。
// export-my-claims.mjs
import { claimsForSeller } from "capacity-attest/dist/ledger.js";
const myAddress = "0x..."; // your buyerAddress
const seller = "0x..."; // the seller in question
const mine = (await claimsForSeller(seller)).filter(
(c) => c.buyerAddress.toLowerCase() === myAddress.toLowerCase(),
);
console.log(JSON.stringify(mine, null, 2));
このリスト内のクレームはすべて、verifyClaim()(上記参照)で個別に検証できます。受信者は、あなたのインストール環境やホストを信頼する必要はありません。これによって、見つけやすさ(D-005:共有しなければ、他の人はどうやってあなたのクレームを見つけるのか)や、すべての購入者にわたる完全性(D-006:これはあなたが送信した内容だけを証明するものであり、ホストが他の購入者に対して隠している可能性のある内容は証明しません)の問題が解決するわけではありません。しかし、ホストを信頼することなく、特定の紛争について具体的かつ無料で証明できます。
ローカルでの実行
npm install
npm run build # tsc -> dist/
npm run typecheck # tsc --noEmit
npm test # vitest run
npm run demo # end-to-end local demo with TEST keys, no live infrastructure
npm start # start the MCP server over stdio (e.g. for Claude Desktop/Code as a local MCP server)
台帳の保存場所は CAPACITY_ATTEST_DATA_DIR で設定できます(デフォルトはこのパッケージ内の ./data です)。テストとデモでは、常に専用の使い捨て一時ディレクトリを使用し、実際の data/ フォルダーは使用しません。
ネットワークエンドポイントが必要なデプロイメント向けの、HTTP で到達可能なバリアント
一部の MCP レジストリやディレクトリでは、サーバーを掲載する前に、アクセス可能な HTTPS エンドポイントが必要です。capacity-attest-http(src/http-server.ts)は、そのためのバリアントです。MCP Streamable HTTP トランスポートを使用し、POST /mcp で通信する通常の Node HTTP サーバーです。
これは、意図的に上記の stdio サーバーより機能を絞っています。公開されるのは、読み取り専用で副作用のない2つのツール(get_delivery_history、resolve_agent_identity)だけです。record_delivery は意図的に公開していません。stdio サーバーの台帳は、単一のインストール環境でローカルに使用する設計です。認証のないパブリックな HTTP エンドポイントの背後に書き込み機能を置くと、「匿名の呼び出し元は誰の台帳に書き込むのか」という現実的な問題が生じますが、このファイルではその答えを示していません。詳しい理由と、必須の4つのチェック(認証、データ検証、公開範囲、レート制限)の適用方法については、http-server.ts 冒頭のコメントを参照してください。
npm run start:http # listens on :8402 by default, override with PORT=
curl -X POST http://localhost:8402/mcp \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
アーキテクチャ
src/
schema.ts DeliveryClaim zod schema + content-addressing (computeClaimId, canonicalize)
signing.ts sign/verify a claim (ethers, EIP-191 personal-sign)
ledger.ts append-only JSONL storage (data/claims.jsonl), never mutated
tools.ts the actual logic behind both MCP tools, transport-agnostic
config.ts where the ledger directory lives, lazy so tests can override it
index.ts MCP server wiring (registers record_delivery + get_delivery_history)
examples/demo.ts end-to-end local example with TEST keys
tools.ts に実際のビジネスロジックを置き、index.ts ではそれを MCP ツールの呼び出しに変換するだけにしています。これにより、stdio トランスポートを起動しなくても、テストとデモで同じロジックを直接呼び出せます。
x402 との関係
このプロジェクト自体は、x402 の支払いを検証も決済も行いません。それらは支払い時にすでに完了しています(完全な EIP-3009 の検証・決済実装については、このエコシステムの mcp-paywall/src/x402.mjs などを参照してください)。settlementRef は、すでに完了したその決済を指すだけです。つまり、実際の x402 ファシリテーターとの MVP 統合はシンプルに保てます。購入者が誠実に入力することを前提として、settlementRef は自由記述です。後のバージョンでは、このフィールドを実際のファシリテーターに照合して検証する機能を任意で追加できます(TODO。今回の MVP には含まれません)。
AWS Bedrock AgentCore Payments との関係
重複も競合もありません。チェーンの異なる段階を担います。Bedrock AgentCore Payments(Amazon、2026 年以降)は、決済そのものを、「加盟店が決済証明を確認し……要求されたコンテンツを返す」時点まで処理します(AWS 公式ドキュメント)。この証明が示すのは決済の証明であり、配信の証明ではありません。その段階の後、エージェントが約束されたものを実際に受け取ったかどうかは、どこにも記録されません。まさにそこを capacity-attest が引き継ぎます。上記の x402 の場合と同様、このプロジェクトは決済を処理せず、決済レールとも競合しません。決済にどのレール(x402 か、それ以外か)が使われたかにかかわらず、決済後に実際に届いたもの、または届かなかったものを記録します。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。