検索
ニュース

MCP、A2A、UCP、AP2……乱立するAIプロトコル、どこでどう使うべき?6つの標準プロトコルの役割、使い分けをGoogleが解説

Googleは、AIエージェント開発の文脈で広まりつつある6つの主要プロトコル「MCP」「A2A」「UCP」「AP2」「A2UI」「AG-UI」についてサンプルコードとともに、それぞれの役割を解説した。

Share
Tweet
LINE
Hatena

 Googleは2026年3月18日(米国時間)、AIエージェント開発に使われる主要プロトコルを公式ブログで解説した。

 レストランのサプライチェーンを管理する「キッチンマネジャーエージェント」の段階的な構築例を通じて、各プロトコルの役割を解説したものだ。AIエージェント開発を支援するさまざまなプロトコルの中から、以下の6つを取り上げている。

  • MCP(Model Context Protocol)
  • A2A(Agent2Agent Protocol)
  • UCP(Universal Commerce Protocol)
  • AP2(Agent Payments Protocol)
  • A2UI(Agent-to-User Interface Protocol)
  • AG-UI(Agent-User Interaction Protocol)

 構築例で紹介されているサンプルコードは、GoogleのオープンソースAIエージェント開発/デプロイフレームワーク「Agent Development Kit」(ADK)が用いられている。ハルシネーション(幻覚)を回答する素のLLM(大規模言語モデル)でも、主要プロトコルを活用することで以下のような複雑なタスクをこなせるようになる過程を示している。

  • 在庫確認
  • サプライヤーからの見積もり取得
  • 食材の注文
  • 支払い承認
  • インタラクティブなダッシュボード表示

MCP:ツールとデータへの接続

 エージェントを既存のシステムやデータに接続する際、通常はAPIごとに独自の連携コードを個別に書く必要がある。MCPは単一の標準的な接続パターンで数百のサーバに対応し、この問題を解決する。サーバ側がMCPでツールを公開すると、エージェントが自動的に検出し、常に最新のツール定義を利用できる仕組みだ。

 エージェントがMCPを利用できるようにするADKの「McpToolset」により、キッチンマネジャーエージェントは「MCP Toolbox for Databases」を介して「PostgreSQL」データベースの照会を、「Notion MCP」を介してレシピ検索を、「Mailgun MCP」を介してメール送信を実行できるようになる。いずれも連携コードの作成は不要だ。

MCPによるツールやデータソースへのアクセス(提供:Google)
MCPによるツールやデータソースへのアクセス(提供:Google)
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams
from google.adk.tools.toolbox_toolset import ToolboxToolset
from mcp import StdioServerParameters
# 1. Inventory database - MCP Toolbox for Databases (PostgreSQL, SQLite, BigQuery, etc.)
inventory_tools = ToolboxToolset(server_url=TOOLBOX_URL)
# 2. Kitchen SOPs and recipes - Notion MCP (read menus, ingredient lists, supplier contacts)
notion_tools = McpToolset(connection_params=StdioConnectionParams(
    server_params=StdioServerParameters(
        command="npx", args=["-y", "@notionhq/notion-mcp-server"],
        env={"NOTION_TOKEN": NOTION_TOKEN}),
    timeout=30))
# 3. Email suppliers about orders - Mailgun MCP (send confirmations, track delivery)
mailgun_tools = McpToolset(connection_params=StdioConnectionParams(
    server_params=StdioServerParameters(
        command="npx", args=["-y", "@mailgun/mcp-server"],
        env={"MAILGUN_API_KEY": MAILGUN_API_KEY}),
    timeout=30))
kitchen_agent = Agent(
    model="gemini-3-flash-preview",
    name="kitchen_manager",
    instruction="You manage a restaurant kitchen. Check inventory, look up recipes, email suppliers.",
    tools=[inventory_tools, notion_tools, mailgun_tools],
)
ADKのMcpToolsetでデータベース照会、レシピ検索、メール送信を実行するソースコードの例(提供:Google)

A2A:エージェント間通信

 食材の卸売価格や品質グレードなど、キッチンマネジャーエージェントが必要とする専門知識を、別のリモートエージェントが持っている場合がある。

 A2Aは、エージェント同士の発見と通信を標準化するプロトコルだ。A2Aに対応する各エージェントは、well-known URLである「/.well-known/agent-card.json」で「エージェントカード」(名前、機能、エンドポイントを記述したもの)を公開する。これにより、新しいリモートエージェントの追加は、URLを1つ加えるだけで済み、手動でのコードの変更や再デプロイは不要となる。

A2Aによるエージェント間通信(提供:Google)
A2Aによるエージェント間通信(提供:Google)
# An A2A agent serves an Agent Card at /.well-known/agent-card.json:
# {
#   "name": "pricing_agent",
#   "description": "Checks today's wholesale market prices for food items.",
#   "skills": [{"id": "pricing", "name": "Price Check",
#               "description": "Check current wholesale market prices"}],
#   "url": "http://pricing-agent:8001/",
#   "version": "1.0.0"
# }
# EXPOSE: Turn any ADK agent into an A2A service
from google.adk.a2a.utils.agent_to_a2a import to_a2a
app = to_a2a(pricing_agent, port=8001)
# DISCOVER: Resolve the Agent Card and create a client - just a URL
from a2a.client.client_factory import ClientFactory
client = await ClientFactory.connect("http://pricing-agent:8001")
card = await client.get_card()
print(f"{card.name} - {card.description}")
# -> "pricing_agent - Checks today's wholesale market prices for food items."
# CALL: Send a message via the A2A protocol
from a2a.client.helpers import create_text_message_object
msg = create_text_message_object(content="What's today's wholesale price for salmon?")
async for response in client.send_message(msg):
    ...  # response is a Task (with artifacts) or a direct Message
A2Aでリモートエージェントから食材の卸売価格を取得するソースコードの例(提供:Google)

UCP:購入フローの統一

 MCPとA2Aにより、キッチンマネジャーエージェントはサプライヤーを発見し、見積もりを取得できるようになるが、注文する段階では別の問題が生じる。複数のサプライヤーに発注する場合、それぞれ異なるチェックアウトAPIを統合しなければならない。

 UCPは、強く型付けされたリクエストおよびレスポンスのスキーマで購買ライフサイクルを標準化する。REST、MCP、A2Aなど複数のトランスポートに対応している。エージェントはUCPにより、A2Aと同様のURLパターン(/.well-known/ucp)でサプライヤーのカタログを発見し、統一的な方法で注文できる。

トランスポートを問わないUCPによる統一的な購買フロー(提供:Google)
トランスポートを問わないUCPによる統一的な購買フロー(提供:Google)
import httpx, uuid
from ucp_sdk.models.discovery.profile_schema import UcpDiscoveryProfile
from ucp_sdk.models.schemas.shopping.checkout_create_req import CheckoutCreateRequest
from ucp_sdk.models.schemas.shopping.types.line_item_create_req import LineItemCreateRequest
from ucp_sdk.models.schemas.shopping.types.item_create_req import ItemCreateRequest
from ucp_sdk.models.schemas.shopping.payment_create_req import PaymentCreateRequest
# DISCOVER: Parse the supplier's UCP profile
async with httpx.AsyncClient() as c:
    profile = UcpDiscoveryProfile.model_validate(
        (await c.get("http://example-wholesale:8182/.well-known/ucp")).json())
# ORDER: Build a typed checkout request
checkout_req = CheckoutCreateRequest(
    currency="USD",
    line_items=[
        LineItemCreateRequest(quantity=10, item=ItemCreateRequest(id="salmon")),
        LineItemCreateRequest(quantity=3,  item=ItemCreateRequest(id="olive_oil")),
    ],
    payment=PaymentCreateRequest(),
)
# SEND: Create checkout + complete (with required UCP headers)
# UCP-Agent header should point to your agent's capability profile
headers = {"UCP-Agent": 'profile="https://kitchen.example/agent"',
           "Idempotency-Key": str(uuid.uuid4()), "Request-Id": str(uuid.uuid4())}
async with httpx.AsyncClient() as c:
    checkout = (await c.post("http://example-wholesale:8182/checkout-sessions",
        json=checkout_req.model_dump(mode="json", by_alias=True, exclude_none=True),
        headers=headers)).json()
    headers["Idempotency-Key"] = str(uuid.uuid4())  # New Idempotency-Key per operation
    order = (await c.post(
        f"http://example-wholesale:8182/checkout-sessions/{checkout['id']}/complete",
        headers=headers)).json()
UCPでサプライヤーのカタログを発見し、発注するソースコードの例(提供:Google)

AP2:支払い承認と証跡管理

 UCPによってエージェントが注文できるようになっても、「誰がその支出を承認したか」の証跡管理が課題として残る。AP2は、型定義された権限委譲の仕組みによって承認レイヤーを追加し、全てのトランザクションにガードレールを適用する。

 企業は「IntentMandate」を定義することで、購入先として許可した販売業者と自動承認の上限金額を指定する。エージェントは、取引とその金額にひも付いた「PaymentMandate」を生成する。購入金額が上限を超えるときはマネジャーの承認が必要となる。「PaymentReceipt」によって監査証跡が完成する。

 AP2はUCPの拡張機能としてプラグインされ、チェックアウトフローに暗号学的な承認証明を追加することで連携する。現在はv0.1として別パッケージで提供されている。

AP2による支払い承認、証跡管理(提供:Google)
AP2による支払い承認、証跡管理(提供:Google)
from ap2.types.mandate import IntentMandate, PaymentMandate, PaymentMandateContents
from ap2.types.payment_request import PaymentCurrencyAmount, PaymentItem, PaymentResponse
from ap2.types.payment_receipt import PaymentReceipt, Success
# The restaurant owner configures guardrails
intent = IntentMandate(
    natural_language_description="10 lbs salmon, 3 bottles olive oil",
    merchants=["Example Wholesale"],    # ONLY these suppliers
    requires_refundability=True,            # must be refundable
    user_cart_confirmation_required=False,  # auto-approve under limit
    intent_expiry="2026-02-23T20:00:00Z",   # expires in 1 hour
)
# Agent creates a PaymentMandate binding payment to the intent
mandate = PaymentMandate(payment_mandate_contents=PaymentMandateContents(
    payment_mandate_id="abc123",
    payment_details_id="order-001",
    payment_details_total=PaymentItem(
        label="10 lbs salmon + 3 bottles olive oil",
        amount=PaymentCurrencyAmount(currency="USD", value=294.00)),
    payment_response=PaymentResponse(request_id="order-001", method_name="CARD"),
    merchant_agent="Example Wholesale",
))
# Manager signs (simulated - real AP2 uses JWT/biometric on secure device)
mandate.user_authorization = "signed_hash_abc123"
# PaymentReceipt closes the audit trail
receipt = PaymentReceipt(
    payment_mandate_id="abc123", payment_id="PAY-001",
    amount=PaymentCurrencyAmount(currency="USD", value=294.00),
    payment_status=Success(merchant_confirmation_id="ORD-A1B2C3"),
)
# IntentMandate -> PaymentMandate (signed) -> PaymentReceipt
# Full audit trail: what was intended, authorized, and paid
AP2による支払い承認フローのソースコードの例(提供:Google)

A2UI:動的UIの宣言的生成

 この段階で、キッチンマネジャーエージェントは在庫確認、見積もり取得、発注、支払い承認が可能になる。だが、処理結果は全てプレーンテキストで返される。これでは、エージェントが在庫ダッシュボード、注文フォーム、サプライヤー比較などを表示する必要がある場合、それぞれについて個別にフロントエンドコンポーネントを構築しなければならない。

 A2UIは、エージェントが宣言的なJSON形式を使って、固定されたカタログから新しいレイアウトを動的に構成できるようにすることで、この問題を解決する。Row、Column、TextField、CheckBox、Cardなど18種類のコンポーネントプリミティブが使用でき、安全性と一貫性が保たれる。

18種類のプリミティブによるUIの動的生成(提供:Google)
18種類のプリミティブによるUIの動的生成(提供:Google)

 A2UIはUI(ユーザーインタフェース)の構造とデータを分離する。クライアント側のレンダラが「Lit」「Flutter」「Angular」などのフレームワークを使って、JSONをネイティブUIに変換する。開発中はADKのWebインタフェース(adk web)がA2UIコンポーネントをネイティブにレンダリングするため、カスタムレンダラを構築せずにUIをテストできる。

A2UIで生成された3種類のUI(在庫チェックリスト、注文フォーム、サプライヤー比較)(提供:Google)
A2UIで生成された3種類のUI(在庫チェックリスト、注文フォーム、サプライヤー比較)(提供:Google)
# This is what the agent sends. A renderer (Lit, Flutter, Angular) turns it into native UI.
a2ui_messages = [
    # 1. Create a rendering surface
    {"beginRendering": {"surfaceId": "default", "root": "card"}},
    # 2. Send the component tree (flat list, ID references - not nested)
    {"surfaceUpdate": {"surfaceId": "default", "components": [
        {"id": "card", "component": {"Card": {"child": "col"}}},
        {"id": "col", "component": {"Column": {"children": {"explicitList": ["title", "price", "buy"]}}}},
        {"id": "title", "component": {"Text": {"usageHint": "h3", "text": {"path": "name"}}}},
        {"id": "price", "component": {"Text": {"text": {"path": "price"}}}},
        {"id": "buy", "component": {"Button": {"child": "btn-label", "action": {"name": "purchase",
            "context": [{"key": "item", "value": {"path": "name"}}]}}}},
        {"id": "btn-label", "component": {"Text": {"text": {"literalString": "Buy Now"}}}},
    ]}},
    # 3. Send the data (separate from structure - update data without resending components)
    {"dataModelUpdate": {"surfaceId": "default", "contents": [
        {"key": "name",  "valueString": "Fresh Atlantic Salmon"},
        {"key": "price", "valueString": "$24.00/lb"},
    ]}},
]
エージェントが送信するJSONメッセージの例(提供:Google)

AG-UI:ストリーミングの標準化

 従来のREST APIはレスポンスを返すだけで完了する。だが、エージェントは、テキストを少しずつストリーミングしたり、レスポンスの途中でツールを呼び出したり、場合によってはユーザーの入力待ちで一時停止する。そのため、エージェントをフロントエンドに接続することは、通常のAPI呼び出しよりも複雑になる。

 ADKは、ネイティブの「/run_sse」エンドポイントでストリーミングイベントを直接提供しており、数十行のフロントエンドコードさえあれば、ストリームを解析してツール呼び出しをレンダリングできる。だが、その解析コードはボイラープレート(定型コード)であり、イベント形式が変われば動作しない。

 AG-UIは、こうしたボイラープレートを排除するミドルウェアとして機能し、フレームワーク固有のイベントを、標準化されたSSE(Server-Sent Events)ストリームに変換する。これにより、生成元のエージェントフレームワークを意識することなく、フロントエンドは「TEXT_MESSAGE_CONTENT」や「TOOL_CALL_START」のような型付きイベントをリッスンできる。

AG-UIによるエージェントからフロントエンドへのストリーミング(提供:Google)
AG-UIによるエージェントからフロントエンドへのストリーミング(提供:Google)

 ADKエージェントをAG-UIストリーミングエンドポイントに変換するには、「ag_ui_adk」パッケージでラップし、FastAPIアプリにマウントする。

from ag_ui_adk import ADKAgent, add_adk_fastapi_endpoint
from fastapi import FastAPI
# Wrap the agent, create the app, mount the endpoint
ag_ui_agent = ADKAgent(adk_agent=kitchen_mgr, app_name="kitchen", user_id="chef")
app = FastAPI()
add_adk_fastapi_endpoint(app, ag_ui_agent, path="/")
# Run with: uvicorn module:app
# The SSE stream emits typed events:
#   RUN_STARTED
#   TOOL_CALL_START    toolCallName="check_inventory"
#   TOOL_CALL_RESULT   content="3 lbs in stock, REORDER NEEDED"
#   TOOL_CALL_END
#   TEXT_MESSAGE_CONTENT  delta="Based on "
#   TEXT_MESSAGE_CONTENT  delta="current inventory..."
#   RUN_FINISHED
AG-UIでエージェントをストリーミングエンドポイントに変換するソースコードの例(提供:Google)

6つのプロトコルの組み合わせによる統合エージェントの動作

 キッチンマネジャーエージェントは、「サーモンの在庫を確認し、今日の卸売価格と品質グレードを把握して、在庫が少なければ『Example Wholesale』に10ポンド注文し、支払いを承認してください」というリクエストを受けると、6つのプロトコルを組み合わせ、以下の3ステージで処理する。

ステージ1:情報収集

 MCPで在庫データベースにクエリを発行し、A2Aで価格エージェントと品質エージェントに照会する。

ステージ2:取引完了

 UCPでExample Wholesaleへのチェックアウトリクエストを送信し、AP2によってガードレール内で支払いマンデートを生成する。

ステージ3:結果の提示

 A2UIでインタラクティブなウィジェットを構成し、AG-UIでツール呼び出しとテキストレスポンスをリアルタイムにストリーミングする。

キッチンマネジャーエージェントの全体像(提供:Google)
キッチンマネジャーエージェントの動作デモ(提供:Google)

これらのプロトコルを生かすための指針

 Googleはこうしたプロトコルを活用するための指針を、次のように示している。

  • 各プロトコルが解決する問題を理解する:MCPはツールやデータ接続、A2Aはエージェント間通信、UCPはコマース標準化、AP2は支払い承認、A2UIはレンダリング対象の定義、AG-UIはストリーミング方法の定義を担う
  • 必要に応じてプロトコルを追加する:ほとんどのエージェントでは、MCPから始め、要件が拡大するにつれて適切なプロトコルを導入すればよい
  • 一から始めない:プロトコルを使った構築に取り掛かる前に、ADKの統合機能、公式SDK、サンプルコードを確認する
  • 標準を早期に採用する:これらのプロトコルはまだ成熟途上だが、確立されたパターン(分かりやすいURLによる発見、型付きのリクエストおよびレスポンススキーマ、標準的なイベントストリームなど)により、エージェントに、ツール、サービス、他のエージェントの拡大するエコシステムとの互換性を持たせられる

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る