AWS Bedrock AgentCore Runtime 上で Python 製 MCP サーバーを動かし、AgentCore Gateway 経由で query_cloudwatch_insights を公開する構成です。
関連ドキュメント:
.
├── .env.example
├── .dockerignore
├── Dockerfile
├── README.md
├── docs
│ └── project-structure.md
├── mcp.json
├── mcp_server.py
├── requirements.txt
└── terraform
├── agentcore_identity.tf
├── agentcore_runtime.tf
├── cognito.tf
├── ecr.tf
├── gateway.tf
├── iam.tf
├── locals.tf
├── outputs.tf
├── providers.tf
├── runtime_config.tf
├── scripts
│ ├── manage_oauth_provider.py
│ └── manage_runtime_config_secret.py
├── templates
│ ├── gateway.yaml.tftpl
│ └── runtime.yaml.tftpl
├── terraform.tfvars.example
├── variables.tf
└── versions.tf
Codex / Copilot / VS Code
|
| MCP over Streamable HTTP
v
AgentCore Gateway
|
| MCP target + OAuth(client_credentials)
v
AgentCore Runtime
- CustomJWTAuthorizer(Cognito)
- mcp_server.py
|
| boto3
v
CloudWatch Logs Insights
- StartQuery
- GetQueryResults
AWS_PROFILE- AWS CLI / Terraform / 補助スクリプトが使うローカルの認証プロファイル名です。
- 例:
your-aws-profile
AWS_REGION- AWS のデプロイ先リージョンです。
- ローカル MCP サーバーの
boto3でも使います。 - 例:
us-east-1
TARGET_APP_NAME- 監視対象アプリの名前です。
DEFAULT_LOG_GROUP_NAMEを省略したときの log group 名導出に使います。- 例:
todo-sample
TARGET_APP_ENV- 監視対象アプリの環境名です。
- 例:
prod
TARGET_APP_COMPONENT- 監視対象コンポーネント名です。
- 例:
backend
DEFAULT_LOG_GROUP_NAME- 既定の CloudWatch Logs log group 名です。
query_cloudwatch_insightsにdefaultまたは@defaultを渡したときに使われます。- 省略時は
TARGET_APP_*から/ecs/{app}-{env}-{component}を導出します。
ALLOWED_LOG_GROUP_NAMES- クエリ実行を許可する log group のカンマ区切り一覧です。
- アプリ側の入力制御と IAM Policy の両方で使います。
- 例:
/ecs/todo-sample-prod-backend,/ecs/another-app-prod-backend
TF_VAR_aws_region- Terraform の
aws_region変数に渡す値です。
- Terraform の
TF_VAR_project_name- Terraform の
project_name変数です。 - 作成される ECR / IAM / Runtime / Gateway の命名に使います。
- Terraform の
TF_VAR_environment- Terraform の
environment変数です。 - 例:
prod
- Terraform の
TF_VAR_python_executable- Terraform の
local-exec/externalが使う Python 実行ファイルです。 - 通常は
../.venv/bin/pythonを使います。
- Terraform の
TF_VAR_target_app_name- Terraform 側で使う監視対象アプリ名です。
- ふつうは
TARGET_APP_NAMEと同じ値にします。
TF_VAR_target_app_environment- Terraform 側で使う監視対象環境名です。
TF_VAR_target_app_component- Terraform 側で使う監視対象コンポーネント名です。
TF_VAR_default_log_group_name- Terraform 側で使う既定 log group 名です。
- IAM Policy と runtime config に反映されます。
TF_VAR_runtime_image_tag- AgentCore Runtime にデプロイするコンテナ image tag です。
docker buildx buildの tag と一致させる必要があります。TF_VAR_runtime_image_tagを export している場合は、Terraform の default よりそちらが優先されます。- Terraform はこの tag から ECR の digest を解決し、Runtime には
repo@sha256:...を渡します。
cp .env.example .envローカル MCP サーバーは .env を自動で読み込みます。Terraform は自動読込しないので、apply 前に export してください。
AWS 上の AgentCore Runtime では、対象アプリ設定を Runtime 環境変数へ直接埋め込まず、Terraform が作成する Secrets Manager の runtime config を起動時に読み込みます。
set -a
source .env
set +apython3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtset -a
source .env
set +a
python mcp_server.py起動後:
- MCP endpoint:
http://localhost:8000/mcp
log_group_name に default または @default を渡すと .env の既定 log group を使います。
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
set -a
source .env
set +aterraform/scripts/manage_oauth_provider.py と terraform/scripts/manage_runtime_config_secret.py が boto3 で AWS API を呼ぶため、.venv は必須です。
cd terraform
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform init
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform apply \
-target=aws_ecr_repository.runtime \
-target=aws_ecr_lifecycle_policy.runtimeAWS_ACCOUNT_ID=$(AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" aws sts get-caller-identity --query Account --output text)
ECR_REPOSITORY_URL=$(AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform output -raw ecr_repository_url)
IMAGE_TAG="${TF_VAR_runtime_image_tag:-latest}"
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" aws ecr get-login-password --region "${AWS_REGION:-us-east-1}" \
| docker login --username AWS --password-stdin "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION:-us-east-1}.amazonaws.com"
docker buildx build \
--platform linux/arm64 \
--provenance=false \
--sbom=false \
-t "${ECR_REPOSITORY_URL}:${IMAGE_TAG}" \
--push \
..AgentCore Runtime は arm64 image を要求します。
Terraform apply 時には、push 済み tag の digest を ECR から引いて Runtime に渡します。
TF_VAR_runtime_image_tag を export している場合は、ここで使う IMAGE_TAG も同じ値になります。
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform applyこの apply で次を作ります。
- ECR repository
- Runtime config secret (Secrets Manager)
- Runtime IAM Role
- Gateway IAM Role
- Cognito User Pool
- Cognito Resource Server
- Cognito App Client
- Cognito User Pool Domain
- AgentCore Identity OAuth credential provider
- AgentCore Runtime
- AgentCore Gateway
- AgentCore GatewayTarget
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform output -raw gateway_url
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform output gateway_target_status
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform output cognito_user_pool_id
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform output cognito_runtime_scope
AWS_PROFILE="${AWS_PROFILE:-your-aws-profile}" terraform output runtime_config_secret_arngateway_target_status が READY なら Gateway から Runtime の tools/list 同期まで成功しています。
- tool 名:
query_cloudwatch_insights - 引数:
log_group_nameminutesquery
- 返却値: JSON
返却例:
{
"ok": true,
"region": "us-east-1",
"log_group_name": "/ecs/todo-sample-prod-backend",
"minutes": 30,
"query": "fields @timestamp, @message | sort @timestamp desc | limit 20",
"query_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "Complete",
"results": [
{
"@timestamp": "2026-03-18 05:30:00.000",
"@message": "Started GET /api/tasks"
}
],
"statistics": {
"recordsMatched": 1.0
}
}直近 20 件:
fields @timestamp, @message, @logStream
| sort @timestamp desc
| limit 20Rails の 5xx / ERROR:
fields @timestamp, @message
| filter @message like /ERROR|FATAL|Completed 5\d\d/
| sort @timestamp desc
| limit 50tasks API:
fields @timestamp, @message
| filter @message like /tasks/
| sort @timestamp desc
| limit 30codex mcp add agentcoreCloudWatch --url "$(terraform -chdir=./terraform output -raw gateway_url)"mcp.json の url を gateway_url に置き換えます。
Gateway 経由で公開される tool 名には target 名の prefix が付きます。
この構成では:
cwlogs___query_cloudwatch_insights
- Runtime IAM Role:
- ECR pull
- Runtime logging / metrics / tracing
- 許可された log group に対する
logs:StartQuery/logs:GetQueryResults
- Runtime inbound auth:
- Cognito の JWT を
CustomJWTAuthorizerで検証
- Cognito の JWT を
- Gateway target outbound auth:
- AgentCore Identity OAuth credential provider
- Cognito client credentials grant
- Gateway IAM Role に次が必要
bedrock-agentcore:GetWorkloadAccessTokenbedrock-agentcore:GetResourceOauth2Tokensecretsmanager:GetSecretValue
- Gateway inbound auth:
- このサンプルでは
NONE
- このサンプルでは
ECR に image がないと Runtime 作成に失敗します。最初は ECR 作成 -> image push -> full apply の順です。
linux/amd64 を push すると Architecture incompatible で Runtime 作成に失敗します。
Terraform 中に terraform/scripts/manage_oauth_provider.py と terraform/scripts/manage_runtime_config_secret.py を実行するため、.venv/bin/python と boto3 が必要です。
AgentCore Runtime 上では TARGET_APP_* や DEFAULT_LOG_GROUP_NAME を直接環境変数へ入れず、Secrets Manager の JSON を RUNTIME_CONFIG_SECRET_ID 経由で読み込みます。ローカル実行では従来どおり .env を使います。
.env の ALLOWED_LOG_GROUP_NAMES と Terraform の IAM Policy がずれていると AccessDenied になります。
GatewayTarget は作成時に tools/list を呼びます。Runtime image 未反映、OAuth provider 未作成、Cognito scope 不一致のいずれかで FAILED になります。
このサンプルはクライアント接続を簡単にするため Gateway inbound auth を NONE にしています。本番では Gateway 自体にも Cognito などの inbound auth を付けることを推奨します。
An internal error occurred. Please retry later. の場合は、Gateway IAM Role の outbound OAuth 権限不足を疑ってください。
この構成では Gateway role に少なくとも次が必要です。
bedrock-agentcore:GetWorkloadAccessTokenbedrock-agentcore:GetResourceOauth2Tokensecretsmanager:GetSecretValue
GetResourceOauth2Token は次の resource 群で評価されました。
arn:aws:bedrock-agentcore:${region}:${account_id}:workload-identity-directory/defaultarn:aws:bedrock-agentcore:${region}:${account_id}:workload-identity-directory/default/workload-identity/${gateway_name}-*arn:aws:bedrock-agentcore:${region}:${account_id}:token-vault/defaultoauth2credentialproviderの provider ARN
Gateway URL:
cd terraform
AWS_PROFILE=your-aws-profile terraform output -raw gateway_urlRuntime target URL:
cd terraform
AWS_PROFILE=your-aws-profile terraform output -raw runtime_mcp_invoke_url許可 log group:
cd terraform
AWS_PROFILE=your-aws-profile terraform output allowed_log_group_namesCognito scope:
cd terraform
AWS_PROFILE=your-aws-profile terraform output cognito_runtime_scope