TL;DR
- 新しいサービスは LLM のナレッジが薄く、存在する機能を「ありません」と否定されることがある
- MCP サーバーを追加すると改善しますが、効き方には段階があります
- MCPなし → 機能の存在自体を否定される
- 横断MCP(AWS Knowledge) → 用語は正しくなるが、仮説が発散する
- 専用MCP(AgentCore) →
Vended Logsなど固有の語彙には到達できる
- 一方で、MCP が返した検索結果を唯一の答えとして扱ったために遠回りもしました。「見つからない=存在しない」と解釈してしまうケースです
- 最終的な正解は AWS 公式ドキュメントの1ページで、内容としては最初から到達可能な場所にありました
- つまり課題は MCP の性能ではなく、問い方と使い分けを設計していなかったこと。ここを最初から設計していれば、もっと短時間で解けたはずです
作ったもの
社内向けの在庫照会エージェント(「A-001の在庫ある?」に自然言語で答えるもの)です。要件定義から実装まで IBM Bob に通しで担当させています。
構成は Runtime → Gateway → Lambda → DynamoDB、IaC は Terraform、リージョンは us-east-1。サービス自体は本題ではないため、詳細は割愛します。
【アーキテクチャ図】
経験した課題:CMKで暗号化すると、Gatewayのログが記録されない
この例には、機能要件よりも影響の大きい非機能要件が乗っています。
- Gateway がいつ・どのツール呼び出しを受けたか、後から CloudWatch で確認できること
- IAM ロールは自前定義・最小権限(マネージドポリシー不可)
-
保存データの暗号化はすべて CMK(カスタマーマネージドキー)。AWSマネージドキー/デフォルト暗号化は不可
3つ目は、エンタープライズの現場では一般的な要件かと思います。
この要件を新サービスに適用したところ、次の状態になりました。
ロググループ : 存在する
ログストリーム : なし
storedBytes : 0
ツール呼び出し : 成功している(Runtime側のログで確認済み)
エラー : どこにも出ていない
処理は成功しているのにログだけが記録されず、エラーも発生しません。 ここから原因特定に数時間を要することになります。
以下、この課題を解消していく過程です。MCP の効き方が段階的に変わっていく点が本題になります。
第0段階:MCPなし ─ 「その機能はありません」
素の状態で実装させたところ、次の回答が返ってきました。
AgentCore Gateway にログ機能はありません
実際には存在します。学習データにまだ十分に含まれていないだけです。
ナレッジが不足している領域では、回答が「わかりません」ではなく**「存在しません」という断定**になる場合があります。表現としては自信のある口調のため、そのまま受け取ってしまいがちです。
結果として、要件に「CloudWatchで確認できること」と書いてあるにもかかわらず、実装計画から静かに落ちます。レビューで検知できなければそのまま本番に到達します。
第1段階:AWS Knowledge MCP ─ 用語は合うが、仮説が発散する
AWS Knowledge MCP を追加しました。ログ機能の存在は認識され、ロググループも作成されるようになりましたが、症状は冒頭のまま storedBytes: 0 です。
このときエージェントが出した仮説が次のものです。
**現時点の仮説:**
1. AgentCore Gateway は外部クライアントから /invocations を直接呼ばれた場合のみ
ログを記録し、Runtime → Gateway の内部 MCP 通信は対象外の可能性
2. Gateway ロールが CWL CMK で PutLogEvents する際、暗号化コンテキスト条件の
評価が通らない可能性
このうち仮説1は誤りでした。一見もっともらしいものの、根拠となる仕様の裏付けがありません。そしてこの仮説を検証するために、CloudTrail の確認や curl による直接呼び出しといったアクションが積み上がっていきます。
この後に試して結果的に外れたのが、ロググループ名の変更、Vended Logs 配信3リソースの追加、キーポリシーへの delivery.logs.amazonaws.com 追加、そしてCMKあり/なしの切り分け試験です。
最後の切り分けが特に判断を誤らせました。CMKなしでもログが出なかったため「KMSは原因ではない」と結論しているのですが、実際には複数の原因が同時に存在していたため、切り分け実験そのものが成立していませんでした。
ナレッジが薄い領域では仮説の質が下がり、仮説の質が下がると検証アクションの数が発散します。
第2段階:AgentCore MCP 追加 ─ 語彙は正しくなった
bedrock-agentcore-mcp-server を追加したところ、Vended Logs という正しい概念に到達しました。ロググループのパスも正しくなります。
/aws/vendedlogs/bedrock-agentcore/gateway/APPLICATION_LOGS/inventory-gateway-xxxxx
配信パイプラインの検証ストリームも生成されており、配線自体は通っていることが確認できます。それでもアプリケーションログのみ 0 バイトのままでした。
検証ストリームの存在が保証するのは IAM と配線の疎通までです。CMK の条件評価が失敗しているケースは、この検証を通過してしまいます。
ここで調査が停滞しました。
第3段階:公式ドキュメントの1ページで解決した
調査が止まった段階で、AWS 公式ドキュメントを直接確認しました。該当していたのが次のページです。
Encrypt your AgentCore gateway with a customer-managed KMS key
Prerequisites セクションに、Gateway のサービスロールに必要な権限(kms:CreateGrant / kms:DescribeKey / kms:Decrypt / kms:GenerateDataKey)と、CloudWatch Logs 向けのステートメントを含むキーポリシーの完全な例が掲載されています。
必要な情報はすべてこのページに揃っていました。あとは現行の terraform/kms.tf と1行ずつ照合するだけです。
MCPは同じページに到達できたのか
原因が判明した後で、答えが分かっている状態から逆に検証してみました。各MCPが同じページに到達できるかを確認するためです。
結果として、AgentCore MCP(bedrock-agentcore-mcp-server)では、ページタイトルをそのまま検索語に与えた場合でもヒットしませんでした。
ここから言えるのは、専用MCPを追加すること=そのサービスのドキュメント全体を参照できること、ではないという点です。MCPサーバーが参照するのはインデックス化された範囲であり、新しいサービスほどその範囲と実際のドキュメントに差が生じやすいと考えられます。
一方で、第2段階で Vended Logs に到達できたのも事実です。MCPが機能していなかったのではなく、単一のMCPの検索結果を「その範囲がすべて」と扱った運用側の問題と捉えるのが妥当だと考えています。検索語の与え方を変える、複数の経路を併用して照合する、といった設計を最初から入れていれば、結果は違った可能性があります。
一方、AWS Knowledge MCP(aws-knowledge-mcp-server)からは同じページに到達できました。
| MCPサーバー | 位置づけ | 該当ページへの到達 |
|---|---|---|
bedrock-agentcore-mcp-server |
サービス専用 | ✗(タイトル完全一致でも不可) |
aws-knowledge-mcp-server |
AWS横断 | ✓ |
ここから言えるのは、専用MCPを追加すること=そのサービスのドキュメント全体を参照できること、ではないという点です。参照先はインデックス化された範囲に限られ、新しいサービスほどその範囲と実際のドキュメントに差が生じやすいと考えられます。
そして重要なのは、この差が横断MCP側で埋まっていたことです。両方を構成に入れ、片方で見つからなければもう片方を当たる。この手順があれば、第2段階の時点で該当ページに到達できていた可能性が高いと考えています。今回の遠回りは MCP の性能ではなく、単一の検索結果を「その範囲がすべて」と扱った運用側の設計不足と整理するのが妥当です。
根本原因:KMSキーポリシーの2つの不足
仕様例と terraform/kms.tf を1行ずつ照合したところ、差分が2箇所ありました。
① kms:CreateGrant の欠落
Gateway サービスは CMK で暗号化グラントを作成します。グラントを作成できないとログデータを暗号化できず、書き込み自体が発生しません。 一般的な「CloudWatch Logs + KMS」の知識だけでは、この権限の必要性は見えにくい部分です。
② 条件キーの誤り
| 項目 | 設定していた値 | 正しい値 |
|---|---|---|
| 条件キー | aws:SourceAccount |
kms:EncryptionContext:SourceArn |
| 値 | "<ACCOUNT_ID>" |
"arn:aws:logs:us-east-1:<ACCOUNT_ID>:*" |
前者は汎用のグローバル条件キー、後者は KMS 固有の条件キーです。名称は似ていますが意味は異なります。 KMS はこの条件評価に失敗し、CMK の使用を拒否していました。
修正後、Gateway にリクエストを送信して約60秒後にアプリケーションログストリームが生成されました。冒頭の storedBytes: 0 がここで解消されます。
示唆1:MCPは「仮説を作る」より「仮説を消す」ために効く
エージェントは仮説→検証のループを回しますが、仮説の生成品質は事前知識に依存するため、ナレッジが薄い領域では発散しやすくなります。
一次情報に直接到達できると、このループの形が変わります。
到達経路なし : 仮説を立てる → 試す → 外れ → 別の仮説 → ...(発散)
到達経路あり : 仕様を引く → 現行コードと差分照合 → 差分を直す(収束)
「仮説を立てて検索する」から「仕様を直接照合する」へ。 実際、照合に切り替えてからの所要時間は数分でした。MCPはこの経路を作るための手段のひとつと位置づけるのが適切だと思います。
示唆2:「見つからない」は「存在しない」の根拠にならない
今回もっとも参考になった点です。専用MCPを追加すると、そのサービスについては網羅的に参照できると暗黙に期待しがちですが、実際にはタイトル完全一致でも返らないケースがありました。
エージェントが「見つかりませんでした」と返したとき、その意味は少なくとも3通りあります。
| 返答 | 実際に起きていること |
|---|---|
| 存在しません | 学習データに含まれていない(第0段階) |
| 見つかりません | MCPのインデックスに含まれていない ← 今回のケース |
| 見つかりません | 実際に存在しない |
単一の経路しか持たない場合、エージェント側にこの3つを区別する手段はありません。ただし今回のように、別系統のMCPで引き直せば2番目と3番目は切り分けられます。 否定的な回答をそのまま結論とせず、経路を変えて確認する。この一手順の有無で結果が変わります。
示唆3:暗号化が絡む失敗は表面化しにくい
- IAM権限エラー →
AccessDeniedが出るため検知できる - 配線ミス → 検証ストリームが生成されないため検知できる
-
KMSの条件評価失敗 → ログが出ないという形でしか現れず、検知しにくい
ログを書き込むための暗号化が失敗しているため、失敗そのものをログで検知できない構造になります。さらに今回は複数の原因が同時に存在していたため、「CMKなしで試す」という一般的な切り分け手法も機能しませんでした。
切り分け実験は「他の要因がすべて正しい」という前提でしか成立しません。
次回に向けた改善点
1. 専用MCP + 横断MCP を最初から併用し、経路を複線化する
今回、決め手となったページは専用MCPでは引けず、横断MCPでは引けました。カバレッジの差が実際に互いを補完しているため、併用する意味は明確にあります。加えて、AgentCore MCP を初期から入れていれば vendedlogs には早期に到達できたはずです。
2. 検索結果が空のときは、検索語を変えて再試行する手順を入れる
1回の検索結果で判断せず、正式名称・機能名・エラー文言など複数の切り口で引き直す。今回はこの再試行がありませんでした。
3. 否定的な回答を、そのまま結論にしない
「ありません」「見つかりません」が返った場合は、公式ドキュメントで直接確認する工程を挟みます。要件が実装計画から落ちた場合も同様です。
4. 「調査」と「実装」を分けて指示する
調査フェーズでは差分の提示までに留め、コードは書かせない。根拠が確定する前に実装が進むと、誤った仮説がコードに残ります。
5. 横断機能(暗号化・ログ・IAM)こそサービス専用ドキュメントを確認する
誤誘導が起きやすいのは「一般知識が豊富にありそうな領域」です。CloudWatch Logs + KMS の一般論は十分に学習されているため回答は自信を持って返りますが、kms:CreateGrant の要否も条件キーもサービスごとに異なります。
AWSは多くのサービスで Encrypt your <service> with a customer-managed key という専用ページを用意しています。CMKが要件に入った時点で、このページの確認をタスク化する。 CMK要件は現場で一般的に発生するため、常設のチェック項目として運用できます。
6. 非機能要件は「実装後の確認」ではなく「実装前の仕様調査」に置く
「ログが取れること」「CMKを使うこと」は動作確認項目として扱われがちですが、仕様を把握していないと構造から誤る類のものは、要件定義の直後に調査タスクとして切り出すべきでした。
7. 最小差分 + -target で影響範囲を絞る
ファイル全体ではなく変更ブロックのみを置換します。plan の差分が意図した変更のみになり、apply も安全です。
おわりに
「AIエージェントで新しいサービスを構築するのは難しい」と感じた要因は、モデルの能力ではなく一次情報への到達経路の設計不足でした。MCPはその経路を提供する仕組みですが、追加しただけで経路が保証されるわけではありません。
今回の反省点は、単一の検索結果を確定情報として扱ったことです。検索語を変える、複数の経路で照合する、返ってこなかった場合の手順を決めておく。この程度の設計を最初から入れていれば、同じ結論にもっと短時間で到達できたと考えています。
MCPをどう使うかまで含めて設計する。次に新しいサービスを扱うときは、ここから始めるつもりです。
