mcpField
A
AVEL

AVEL

ローカル
github.com/Ensi81セキュリティ04 週間前に更新

AVEL について

AVELは、エージェント間の支払い前に支払者と受取人の身元・評判を確認するPythonクライアントとサービスです。支払い自体は扱わず判定のみを返し、ネイティブ署名のほかx402、AP2、MPPの証明にも対応します。

主な機能

  1. 01支払者と受取人の身元・評判確認
  2. 02承認または拒否の判定
  3. 03x402、AP2、MPPの証明への対応
  4. 04販売者署名チャレンジの発行と検証
  5. 05取引当事者双方による判定の取得
  6. 06エージェントフレームワーク向けの支払い・残高ツール

活用シーン

  1. 01エージェントによる支払い前の取引相手確認
  2. 02販売者による取引条件の設定と署名
  3. 03取引当事者双方からの判定確認
  4. 04LangChain、CrewAI、AutoGenを介した支払い確認

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"ensi81-avel": {
"command": "uvx",
"args": [
"agent-interchange"
],
"env": {
"AVEL_BASE_URL": "<AVEL_BASE_URL>",
"AVEL_PRIVATE_KEY": "<AVEL_PRIVATE_KEY>"
}
}
}
}
起動コマンドuvx agent-interchange
設定が必要な環境変数
AVEL_BASE_URLBase URL of the AVEL instance to verify against (default: https://aisrail.fly.dev)
AVEL_PRIVATE_KEYシークレットEVM private key of the agent identity this MCP server represents — signs every verify()/issue_challenge()/verify_challenge()/get_verdict() call. Never exposed as a tool argument.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypiagent-interchange0.1.2

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

agent-interchange

AVEL(Agent Verification Layer)用の Python SDK — 支払者と受取人の本人性/評判を、あらゆる支払い方法で検証します。資金を預かることは一切ありません。サーバーはクローズドソースです。このパッケージはクライアント層であり、公開して再利用できるように設計されています(MIT ライセンス)。スタンドアロンで、サーバーコードへの依存はなく、httpx、eth-account、およびアクセス可能なインスタンスの URL(https://aisrail.fly.dev)のみを使用します。

インストール

pip install -e .

使い方

from agent_interchange import InterchangeClient

client = InterchangeClient("https://aisrail.fly.dev")
result = client.verify(
    payer_address=agent_a_address,
    payee_id="merchant-42",
    amount=25.0,
    currency="EUR",
    private_key=agent_a_private_key,
    fee_payment_method_id="pm_...",   # con cosa si paga LA VERIFICA
)

2人のエージェント間の支払いは、ここを経由しません。 この呼び出しは、安全に進められるかどうかを伝えるだけです。その後、エージェントはすでに使用している決済レールで支払います。当社が受け取るのは、実施したチェックの手数料のみです(検証した金額の1%、カードの場合は最低0.50)。ただし、呼び出し元の署名が有効である限り、DENIED 判定の場合も支払いが必要です。これは判定結果ではなく、チェックに対する料金です。

結果は3種類あります。

応答意味
verdict: "APPROVED"チェックに合格し、手数料が徴収されました。処理を進めてください
verdict: "DENIED"進めないでください。呼び出し元の署名が有効であれば手数料の支払いが必要です。署名が無効な場合のみ無料です(確実に請求できる相手がいないため)
verdict_withheld: true検証は実施されましたが、手数料はまだ徴収されていません。支払いが完了するまで、判定(APPROVED または DENIED)は保留されます

private_key はエージェントの EVM キーです(当社のものではありません)。認証済みの初回利用時に、そのIDは署名に使われたアドレスに紐付けられます(trust-on-first-use)。以降の呼び出しでは、必ず同じキーで署名する必要があります。事前登録は不要です。

verify() は protocol="native" を使用します。エージェントがすでに x402、AP2、MPP で支払いを行っている場合、2つ目の署名は必要ありません。支払い用にすでに生成した証明を送信してください。各プロトコルの例は scripts/protocol_adapters_demo.py にあります。

B の対称検証

販売者(B)がアドレス(payee_address)を申告する場合、そのアドレスを管理していることも証明する必要があります。そうしないと、判定は拒否されます。B(またはBに代わって交渉する者)が build_counterparty_message(payer_address, payee_id, amount, currency, nonce) に対する署名を計算し、payee_signature として渡します。

from agent_interchange.client import build_counterparty_message

message = build_counterparty_message(payer_address, payee_id, amount, currency, nonce)
payee_signature = "0x" + Account.sign_message(encode_defunct(text=message), private_key=b_private_key).signature.hex()

result = client.verify(
    payer_address=a_address, payee_id="merchant-42", amount=25.0, currency="EUR",
    private_key=a_private_key, nonce=nonce,
    payee_address=b_address, payee_signature=payee_signature,
)
B 主導モデル(challenge プロトコル)

x402/MPP の実際の動作により近い方式です。販売者(B)が価格と条件を設定し、最初に署名します。購入者(A)は同じ内容に署名して承諾します。

# Lato B — nessuna chiamata di rete, va consegnato ad A fuori banda
challenge = client.issue_challenge(
    payee_address=b_address, payee_id="merchant-42", amount=25.0, currency="EUR",
    private_key=b_private_key, ttl_seconds=600,
)

# Lato A — accetta il challenge e chiede il verdetto in un colpo solo
result = client.verify_challenge(
    challenge, payer_address=a_address, private_key=a_private_key,
    fee_payment_method_id="pm_...",   # o fee_method="x402" per pagare in stablecoin
)

challenge は、それを承諾する取引内容に対して一度だけ有効です。同一内容での再試行(402 の後に手数料の支払いを完了するために必要)は引き続き許可されますが、異なる条件での再利用は許可されません。

双方向判定

取引の結果は、verify()/verify_challenge() を呼び出した人だけでなく、双方が確認できます。

verdetto = client.get_verdict(
    payee_address=b_address, nonce=nonce,
    address=b_address, private_key=b_private_key,   # o quella di A
)

その取引の支払者または受取人であることを証明する署名が必要です。公開されている集計履歴(GET /ais/reputation/{address})とは異なり、個別取引の詳細は公開されません。

マーケットプレイスの場合

payee_id/payee_address が実際の商品/サービスの提供者ではなく、ストアフロントを指している場合、verify() では sub_merchant_address/sub_merchant_signature も指定できます(B の場合と同じ原則で、署名は build_sub_merchant_message(payer_address, payee_id, amount, currency, nonce, sub_merchant_address) に対して計算します)。指定された場合、その評判(応答内の sub_merchant_reputation)も、B の評判と同様に判定に反映されます。

基本的なフローを実行できるバージョンは example.py をご覧ください。

Agent Vaults のメソッド — 無効

pay(), get_balance(), deposit()、withdraw() は、サービスが内部残高を保管していた以前のモデルに属します。サーバーは現在、これらのエンドポイントに 410 を返します。資金は一瞬たりとも保管しません。コードは残っており、サーバー側で AGENT_VAULTS_ENABLED=true を設定すると再び有効にできます。以下のドキュメントは履歴資料として保存されています。

InterchangeClient

  • verify(payer_address, payee_id, amount, currency, private_key, nonce="", payee_address=None, payee_signature=None, sub_merchant_address=None, sub_merchant_signature=None, fee_payment_method_id=None) → dict。「A が宣言し、B が確認する」モデルで使用するメソッドです。トランザクションの正規化されたテキストに対する EIP-191 署名を行い、判定を要求して手数料を支払います。 402 はエラーではなく、想定された応答(「検証に合格しました。次に支払ってください」)です。返されるだけで、例外は発生しません。

  • issue_challenge(payee_address, payee_id, amount, currency, private_key, ttl_seconds=600) → dict。B 側(販売者)の B 主導モデルです。拘束力のある challenge を発行して署名します。ネットワーク呼び出しはありません。結果は帯域外で A に渡す必要があります。

  • verify_challenge(challenge, payer_address, private_key, fee_payment_method_id=None, fee_method=None) → dict。A 側(購入者)で、issue_challenge() の challenge を受け取り、1 回の呼び出しで判定を要求します。

  • get_verdict(payee_address, nonce, address, private_key) → dict。双方向の判定です。特定のトランザクションの結果を読み取り、関係するどちらの当事者も利用できます。address がそのトランザクションの支払者でも受取人でもない場合は InterchangeAPIError(403)を発生させ、payee_address/nonce に該当する記録済みの判定がない場合は(404)を発生させます。

  • get_agent_reputation はクライアントのメソッドではありません — 認証不要で公開されています。単純な HTTP リクエストを使って GET {base_url}/ais/reputation/{address} を呼び出します。

  • pay(payer_ref, payee_ref, amount, private_key, currency="USDC", task_id=None) (無効、410) → PaymentResult。private_key は、このトランザクションの内容を正確に拘束する EIP-191 メッセージに署名します(初回利用時に信頼を確立 — 上記の使用方法を参照)。Interchange が /pay にウォレット認証を追加したため、必須です。 task_id と呼び出し自体のパラメーターから agent_request_id を自動生成します(client._derive_request_id を参照)。エージェントフレームワーク独自のタスク/実行 ID を渡すと、正当な再試行(同じ task_id、同じ引数)は安全に冪等処理されます。一方、同じ task_id を使った別の支払いが誤って衝突することはありません。task_id を省略しても動作しますが、再試行時の安全性が失われます(新しいランダム ID が使われるため、実際の再試行は新規トランザクションとして扱われます)。

    次の例外が発生します:

    • InsufficientBalanceError — 支払者の残高が金額と手数料の合計に足りません。
    • RequestConflictError — HTTP 409:生成された ID が異なる内容ですでに使用されている(信頼できないミドルウェアによって取得された支払い証明のリプレイ/乗っ取りの可能性があり、拒否されて実行されません)か、予約済みですが未完了です(自動的には再試行されません)。
    • InterchangeAPIError — その他のすべての非 2xx 応答、または Interchange に到達できない場合。401 は private_key が署名と一致しないことを示します。403 は payer_ref がすでに別のアドレスにバインドされていることを示します(このキーではありません)。

    リスクスコアによる DENY(残高不足によるものは除く)は例外になりません。通常の PaymentResult として返され、その場合 .success == False になります。理由を確認するには .decision/.reasons を参照してください。

  • get_balance(agent_ref, private_key) → 通貨ごとの最小単位で表した dict[str, int]。例:{"USDC": 500000}。private_key は agent_ref の管理権限を証明します(pay() と同じ初回利用時の信頼バインディング)。agent_ref がまだ pay()/withdraw() で使用されていない場合に限り、どのキーでも利用できます。

  • withdraw(agent_ref, amount_usdc, payout_address, private_key, task_id=None) → dict。private_key は agent_ref 自身のキーであり、引き出し対象の残高を管理していることを証明します。オンチェーンで署名して支払いを行うのは引き続き Interchange 自身の財務アカウントです。ここでの private_key は、引き出しリクエスト自体の認証にのみ使われます。pay() と同じ task_id の導出方法および例外の仕様です(HTTP 402 では InsufficientBalanceError、409 では RequestConflictError、401/403 の意味は pay() と同じです)。その他の 2xx 以外の応答(例:ホワイトリストに登録されていないプラットフォーム財務アカウントからの引き出しに対する 403)では InterchangeAPIError が発生します。

  • await deposit(agent_ref, amount_usdc, private_key, task_id=None) → dict。他の 3 つのメソッドと異なり非同期で、入金するエージェント自身のキーで実際の x402 支払いに署名するため、deposit エクストラが必要です。pip install agent-interchange[deposit] を実行してください。エクストラをインストールせずに呼び出すと、手順を示す InterchangeAPIError が発生します(ImportError ではありません)。基本インストール(pip install -e .)では、これを呼び出さない限り x402/eth-account は必要ありません。

稼働中の Interchange を使って実環境で検証済みです(2026 年 9 月 4 日)。通常の支払い(手数料が amount に加算されるのではなく、正しく差し引かれること)、金額超過の pay()/withdraw() に対する InsufficientBalanceError、同じ task_id と同じ引数による冪等な再試行(2 回目の送金/払い出しを行わず、キャッシュされた同一の結果を返すこと)、異なる引数で同じ task_id を使用した場合に別個の支払いとして実行されること(誤った競合が発生しないこと)、内容が異なる同一 ID の偽造リクエストが RequestConflictError で正しく拒否されること(メインリポジトリの interchange/security.py にある Interchange 独自の P1 バインディングが防御するリプレイ/乗っ取りのシナリオを再現)、実際のオンチェーンでの withdraw() と deposit()(それぞれの結果のトランザクションが Base Sepolia で承認されること)、および deposit エクストラがインストールされていない場合に deposit() が明確な失敗メッセージを返すこと(インポートをブロックして再現)を検証しました。

InterchangeTool — LangChain/CrewAI/AutoGen

from agent_interchange import InterchangeClient, InterchangeTool

client = InterchangeClient("http://localhost:8000")
tool = InterchangeTool(client)

langchain_tools = tool.for_langchain()   # requires: pip install langchain-core
crewai_tools = tool.for_crewai()         # requires: pip install crewai
autogen_tools = tool.for_autogen()       # requires: pip install autogen-core

エージェントが呼び出せるツールとしてラップするのは pay/get_balance のみです。deposit/withdraw は意図的に対象外です。これらは実際の資金を移動し、deposit には生の秘密鍵が必要なため、デフォルトで LLM のツール呼び出しループに公開するには、より慎重な判断が求められます。代わりに、独自のコードから client のメソッドを直接呼び出してください。

インポートは遅延されます。InterchangeTool の構築や、そこから直接 pay()/get_balance() を呼び出す際に、3 つのフレームワークはいずれも必要ありません。必要なのは for_langchain()/for_crewai()/for_autogen() のみで、対応するパッケージがインストールされていない場合は、それぞれ正常に失敗します(ModuleNotFoundError)。実環境で検証済みです(構築、内部の _get_balance 呼び出し、および 3 つすべてのファクトリーにおける正常な失敗経路)。ツールデコレーターで装飾された出力自体の検証レベルは、メインリポジトリの framework_tools.py と同じです。各フレームワークの実際に公開されているソースコードに対して、内部の @tool/FunctionTool API の形式をどのように確認したかについては、そのファイルの docstring を参照してください。

ここに含まれないもの

メインリポジトリの agent_tools.py/framework_tools.py(リポジトリのルート)は同じ機能をカバーしていますが、パッケージ化されておらず、単独でインストールすることもできません。メインリポジトリ独自の開発環境以外では、この SDK をご利用ください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。