
Amazon Bedrock AgentCore RuntimeがStateful MCPに対応——1セッション内で複数回やり取りできるMCPサーバーとは
AgentCore RuntimeがStateful MCPに対応し、1セッション内でMCPサーバーが複数回のやり取りにわたって状態を保持できるようになった。
これにより「ユーザーと複数回やり取りしながら情報を収集する」「長時間かかる処理の進捗をリアルタイムで通知する」といったユースケースがMCPサーバーの仕組みの上で実現できる。この記事ではStateful MCPとは何か、Statefulになることで使えるようになったMCPの機能の仕組みと使いどころを整理する。
AgentCore Runtimeとは
Amazon Bedrock AgentCore Runtimeは、AIエージェントをサーバーレスで動かすためのマネージドサービス。コードをアップロードするかコンテナをデプロイするだけで、8時間の非同期ワークロードから低レイテンシな対話まで対応できる実行基盤として機能する。
エージェントの実行環境はユーザーセッションごとに分離されており、データが他のセッションに漏れない設計になっている。
Stateless MCPとの違い
MCPの仕様はもともとステートレスな設計で、クライアントがサーバーにリクエストを送り、サーバーがレスポンスを返す——これで1回のやり取りが完結する。前のリクエストのコンテキストはサーバー側に残らない。
【Stateless MCP(従来)】
クライアント → リクエスト → サーバー → レスポンス
(1回のやり取りで完結。前回の文脈はサーバーに残らない)
【Stateful MCP(今回)】
クライアント ←→ サーバー ←→ クライアント ←→ サーバー
(Mcp-Session-Idで紐づけ。同一セッション内で文脈を保持したまま複数回やり取り)
Stateful MCPでは Mcp-Session-Id ヘッダーを使い、同一セッション内の複数インタラクション間でコンテキストを維持する。「ユーザーに追加情報を聞き返す」「長い処理の途中経過を都度通知する」といった複数ターンの会話が、MCPの仕組みの上で成立する。セッションをまたいだ永続化ではない点に注意。
各ユーザーセッションは専用のmicroVMで実行される。セッションが異なれば別のmicroVMが使われるため、リソースの分離が保証されている。
Statefulになることで使えるMCPの機能
1. Elicitation(情報収集)
サーバーがクライアントに対して情報の入力を求めることができる。
従来はクライアント側からリクエストを送るのが基本だったが、Elicitationではサーバー側が会話を開始して「次の情報を教えてください」と聞き返せる。
ユースケース例
ユーザー: 「航空券を予約したい」
↓
MCPサーバー(Elicitation): 「出発地を教えてください」
↓
ユーザー: 「東京」
↓
MCPサーバー(Elicitation): 「目的地は?」
↓
ユーザー: 「ニューヨーク」
↓
MCPサーバー: 予約処理を実行
ユーザー設定の収集、フォームの段階的な入力、条件によって分岐するウィザード形式のフロー——こういった「サーバー主導の複数ターン会話」を実装できる。
2. Sampling(サンプリング)
Samplingでは、MCPサーバーがクライアントに対してLLMによるテキスト生成を依頼できる。
これは「モデル呼び出しの主体はクライアント側に残しつつ、サーバー側のロジックから生成処理をトリガーできる」仕組みである。
ユースケース例
- ユーザーの行動履歴・好みに基づいたパーソナライズ推薦の生成
- サーバー側の文脈情報を使ったカスタマイズコンテンツの作成
- MCPサーバーが処理の途中でLLMの判断を必要とするケース
モデルの呼び出し主体はクライアントのままなので、コスト管理やモデルの選択はクライアント側で制御できる。
3. Progress notifications(進捗通知)
長時間かかる処理の途中経過をリアルタイムでクライアントに通知できる。
従来はサーバーがレスポンスを返すまでクライアントは待つだけだった。Progress notificationsを使うと、処理の各ステップが完了するたびにクライアントへ通知が届く。
ユースケース例
「フライトを検索して予約して」
↓ MCPサーバー からの通知:
[25%] フライト候補を検索中...
[50%] 最安値の便を選択中...
[75%] 予約フォームを入力中...
[100%] 予約完了
フライト検索・予約、バッチデータ処理、複数ステップのワークフロー実行——処理時間が長いほどユーザー体験の改善効果が大きい。
なぜAgentCore RuntimeでStateful MCPが重要か
AgentCore Runtimeは「エージェントを動かす実行基盤」。エージェントが外部ツールと会話するためにMCPを使う場面では、必然的に複数回のやり取りが発生する。
Stateless MCPでこれを実現しようとすると、セッション状態の管理をアプリ側で持つ必要があった。Stateful MCPではMCPのプロトコル層でセッションが維持されるため、アプリ側の実装がシンプルになる。
【Stateless MCPでのセッション管理(従来)】
アプリ側でセッションIDを生成・管理
→ リクエストごとに前回の文脈をDBから取得して渡す
→ 管理コストが高い
【Stateful MCPでのセッション管理(今回)】
Mcp-Session-Idでセッションが自動管理
→ サーバー側がコンテキストを保持
→ アプリ側の実装がシンプル
microVMによるセッション分離が入っているため、マルチユーザー環境でも他のユーザーの状態が混入するリスクがない。
なぜ今このアップデートが重要なのか
これまでのLLMアプリは「1リクエスト=1レスポンス」の設計が中心だった。
Stateful MCPの登場により、複数ターンの対話・状態を持ったワークフロー・長時間処理といった「エージェントらしい挙動」がプロトコルレベルで実現できるようになった。アプリ側で独自にセッション管理を実装しなくていい分、エージェントの実装コストが下がる。
実際に試してみた
東京リージョン(ap-northeast-1)でAgentCore Runtimeに実際にMCPサーバーをデプロイして3機能の動作を確認した。
デプロイ時のポイント
AgentCore RuntimeはARM64(aarch64)環境で動作する。Pythonパッケージをバンドルする場合は --platform manylinux2014_aarch64 --python-version 3.12 でビルドする必要がある。起動時間の制限(30秒)があるため、パッケージはあらかじめZIPに含めておくのが安定する。
FastMCP(3.1.1で確認)を使う場合は、stateless_http=False と host="0.0.0.0" を mcp.run() に指定する。stateless_http=True にするとSSEストリームが機能せずProgress notificationsなどが動かなくなる。
from fastmcp import FastMCP, Context
mcp = FastMCP("my-server")
if __name__ == "__main__":
mcp.run(
transport="streamable-http",
host="0.0.0.0",
stateless_http=False,
)
各機能のAPI:
# Progress notifications
await ctx.report_progress(progress=1, total=4, message="処理中")
# Elicitation
result = await ctx.elicit(message="情報を入力してください", response_type=MySchema)
if result.action == "accept":
data = result.data # MySchema のインスタンス
# Sampling
result = await ctx.sample("質問テキスト", max_tokens=100)
return result.text
クライアント側の実装
invoke_agent_runtime(boto3 SDK)はリクエスト/レスポンス型のAPIのため、3機能には対応できない。ElicitationやSamplingは中間リクエストの処理、Progress notificationsはSSEストリームの受信が必要になるため、SigV4署名付きでMCPプロトコルを直接叩く実装が必要になる。
エンドポイントURLのフォーマットは以下の形式:
https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{URL-encoded-runtime-arn}/invocations?qualifier={endpoint-name}
AgentCore RuntimeはGETリクエストを受け付けない(405を返す)。すべてのMCPメッセージはPOSTで送り、レスポンスのSSEストリームで中間通知や中間リクエストを受信する。
各機能の確認結果
東京リージョン(ap-northeast-1)でFastMCP 3.1.1を使ってデプロイし、3機能すべての動作を確認した。
Progress notifications: 動作する。_meta.progressToken を付けて tools/call を呼ぶと、サーバーが ctx.report_progress() を呼ぶたびにPOSTレスポンスのSSEストリームに notifications/progress が届く。
Elicitation: 動作する。サーバーが ctx.elicit() を呼ぶと、SSEストリームに elicitation/create リクエストが届く。クライアントが新たなPOSTでフォームデータを応答すると、サーバーが処理を続行して最終結果を返す。
Sampling: 動作する。サーバーが ctx.sample() を呼ぶと、SSEストリームに sampling/createMessage リクエストが届く。クライアントがLLM(今回はBedrock Claude Haiku)を呼び出して生成結果を応答すると、サーバーに返ってきて処理が完了する。
対応リージョン
14のAWSリージョンでサポートされている(米国・アジア太平洋・カナダ・ヨーロッパ)。
まとめ
- AgentCore RuntimeのStateful MCPは
Mcp-Session-Idでセッション状態を維持する仕組み - Statefulになることで以下のMCP機能が使えるようになる
- Elicitation:サーバー主導の複数ターン情報収集
- Sampling:サーバーからクライアントへAIテキスト生成を依頼
- Progress notifications:長時間処理の進捗をリアルタイム通知
- セッションはmicroVMで分離されており、マルチユーザー環境でも安全
- 既存のリソース・プロンプト・ツール機能と共存して動作
従来のMCPが「1問1答」の設計だったのに対し、Stateful MCPは「会話」の形で複数回やり取りできるように拡張された。エージェントが複雑なタスクをこなすには必要な変化で、AgentCore Runtimeがエージェント実行基盤として実用的に使えるかどうかを左右する機能だと思う。