MCP、A2A、UCP、AP2……乱立するAIプロトコル、どこでどう使うべき?:6つの標準プロトコルの役割、使い分けをGoogleが解説
Googleは、AIエージェント開発の文脈で広まりつつある6つの主要プロトコル「MCP」「A2A」「UCP」「AP2」「A2UI」「AG-UI」についてサンプルコードとともに、それぞれの役割を解説した。
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」を介してメール送信を実行できるようになる。いずれも連携コードの作成は不要だ。
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],
)
A2A:エージェント間通信
食材の卸売価格や品質グレードなど、キッチンマネジャーエージェントが必要とする専門知識を、別のリモートエージェントが持っている場合がある。
A2Aは、エージェント同士の発見と通信を標準化するプロトコルだ。A2Aに対応する各エージェントは、well-known URLである「/.well-known/agent-card.json」で「エージェントカード」(名前、機能、エンドポイントを記述したもの)を公開する。これにより、新しいリモートエージェントの追加は、URLを1つ加えるだけで済み、手動でのコードの変更や再デプロイは不要となる。
# 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
UCP:購入フローの統一
MCPとA2Aにより、キッチンマネジャーエージェントはサプライヤーを発見し、見積もりを取得できるようになるが、注文する段階では別の問題が生じる。複数のサプライヤーに発注する場合、それぞれ異なるチェックアウトAPIを統合しなければならない。
UCPは、強く型付けされたリクエストおよびレスポンスのスキーマで購買ライフサイクルを標準化する。REST、MCP、A2Aなど複数のトランスポートに対応している。エージェントはUCPにより、A2Aと同様のURLパターン(/.well-known/ucp)でサプライヤーのカタログを発見し、統一的な方法で注文できる。
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()
AP2:支払い承認と証跡管理
UCPによってエージェントが注文できるようになっても、「誰がその支出を承認したか」の証跡管理が課題として残る。AP2は、型定義された権限委譲の仕組みによって承認レイヤーを追加し、全てのトランザクションにガードレールを適用する。
企業は「IntentMandate」を定義することで、購入先として許可した販売業者と自動承認の上限金額を指定する。エージェントは、取引とその金額にひも付いた「PaymentMandate」を生成する。購入金額が上限を超えるときはマネジャーの承認が必要となる。「PaymentReceipt」によって監査証跡が完成する。
AP2はUCPの拡張機能としてプラグインされ、チェックアウトフローに暗号学的な承認証明を追加することで連携する。現在はv0.1として別パッケージで提供されている。
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
A2UI:動的UIの宣言的生成
この段階で、キッチンマネジャーエージェントは在庫確認、見積もり取得、発注、支払い承認が可能になる。だが、処理結果は全てプレーンテキストで返される。これでは、エージェントが在庫ダッシュボード、注文フォーム、サプライヤー比較などを表示する必要がある場合、それぞれについて個別にフロントエンドコンポーネントを構築しなければならない。
A2UIは、エージェントが宣言的なJSON形式を使って、固定されたカタログから新しいレイアウトを動的に構成できるようにすることで、この問題を解決する。Row、Column、TextField、CheckBox、Cardなど18種類のコンポーネントプリミティブが使用でき、安全性と一貫性が保たれる。
A2UIはUI(ユーザーインタフェース)の構造とデータを分離する。クライアント側のレンダラが「Lit」「Flutter」「Angular」などのフレームワークを使って、JSONをネイティブUIに変換する。開発中はADKのWebインタフェース(adk web)がA2UIコンポーネントをネイティブにレンダリングするため、カスタムレンダラを構築せずにUIをテストできる。
# 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"},
]}},
]
AG-UI:ストリーミングの標準化
従来のREST APIはレスポンスを返すだけで完了する。だが、エージェントは、テキストを少しずつストリーミングしたり、レスポンスの途中でツールを呼び出したり、場合によってはユーザーの入力待ちで一時停止する。そのため、エージェントをフロントエンドに接続することは、通常のAPI呼び出しよりも複雑になる。
ADKは、ネイティブの「/run_sse」エンドポイントでストリーミングイベントを直接提供しており、数十行のフロントエンドコードさえあれば、ストリームを解析してツール呼び出しをレンダリングできる。だが、その解析コードはボイラープレート(定型コード)であり、イベント形式が変われば動作しない。
AG-UIは、こうしたボイラープレートを排除するミドルウェアとして機能し、フレームワーク固有のイベントを、標準化されたSSE(Server-Sent Events)ストリームに変換する。これにより、生成元のエージェントフレームワークを意識することなく、フロントエンドは「TEXT_MESSAGE_CONTENT」や「TOOL_CALL_START」のような型付きイベントをリッスンできる。
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
6つのプロトコルの組み合わせによる統合エージェントの動作
キッチンマネジャーエージェントは、「サーモンの在庫を確認し、今日の卸売価格と品質グレードを把握して、在庫が少なければ『Example Wholesale』に10ポンド注文し、支払いを承認してください」というリクエストを受けると、6つのプロトコルを組み合わせ、以下の3ステージで処理する。
ステージ1:情報収集
MCPで在庫データベースにクエリを発行し、A2Aで価格エージェントと品質エージェントに照会する。
ステージ2:取引完了
UCPでExample Wholesaleへのチェックアウトリクエストを送信し、AP2によってガードレール内で支払いマンデートを生成する。
ステージ3:結果の提示
A2UIでインタラクティブなウィジェットを構成し、AG-UIでツール呼び出しとテキストレスポンスをリアルタイムにストリーミングする。
これらのプロトコルを生かすための指針
Googleはこうしたプロトコルを活用するための指針を、次のように示している。
- 各プロトコルが解決する問題を理解する:MCPはツールやデータ接続、A2Aはエージェント間通信、UCPはコマース標準化、AP2は支払い承認、A2UIはレンダリング対象の定義、AG-UIはストリーミング方法の定義を担う
- 必要に応じてプロトコルを追加する:ほとんどのエージェントでは、MCPから始め、要件が拡大するにつれて適切なプロトコルを導入すればよい
- 一から始めない:プロトコルを使った構築に取り掛かる前に、ADKの統合機能、公式SDK、サンプルコードを確認する
- 標準を早期に採用する:これらのプロトコルはまだ成熟途上だが、確立されたパターン(分かりやすいURLによる発見、型付きのリクエストおよびレスポンススキーマ、標準的なイベントストリームなど)により、エージェントに、ツール、サービス、他のエージェントの拡大するエコシステムとの互換性を持たせられる
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
MCPは死んでない? MCPの2026年ロードマップ公開 「AIツール接続」から「AI自律連携インフラ」へ
AIと外部ツールをつなぐ規格「MCP(Model Context Protocol)」の2026年ロードマップは、MCPの役割が「単なるツール接続の仕組み」から「AI同士が連携する基盤」へと広がりつつあることを示している。そのポイントを整理し、「MCP vs. CLI」論争についても触れる。
「マルチエージェントシステム」設計パターン8選 Googleが解説
Googleは、マルチAIエージェントシステムにおける8つの基本的なデザインパターンを公式ブログで解説した。
なぜMCPやAIエージェントが使われると「API」が根本的に変わるのか? KongのCTOに聞く
MCPやAIエージェントが普及する時代の「API」とシステム連携は、従来の前提とは根本的に異なるものになる――そう語るのは、APIゲートウェイベンダーKongのCTO、マルコ・パラディーノ氏。APIとその利用がどう変わるのかを聞いた。
「Python一択ではなくなった」 AIコーディング時代、新人が学んで損しないプログラミング言語は?
生成AIの普及で「コードを書く力」の意味が変わりつつあります。新人であれば、どのプログラミング言語を学ぶべきなのでしょうか。人気や話題性、求人数、案件単価といった視点から、最新ランキングを基に「学んで損しない言語」を整理します。
リスクが見えても人手が足りない米国、リスクが見えてすらいない日本 サプライチェーン防衛の現実
ランサムウェア被害は取引先を起点に連鎖し、企業の枠を超えて広がり始めている。サプライチェーンの可視化すら進まない日本と、次の課題に直面する米国。このギャップはどうすれば埋められるか。日本企業の事情に合った現実解を考える。







