2025年 7月 AWS Summit New York City にて生成 AI 関連のアップデートが多数ありました。その中の 1つとして Amazon Bedrock AgentCore がプレビューですが発表されました。AgentCore はざっくりいうと AI エージェントをインフラを気にすることなく開発、実行、運用できるマネージドサービスです。その AgentCore の 1つの機能である Runtime で MCP サーバーをデプロイ、実行できるようでしたので試してみました。

はじめに

AgentCore とは

Amazon Bedrock AgentCore には様々なサービスがビルディングブロックとして提供されています。
(AgentCore は 2025年 7月 17日時点ではまだプレビューリリースである点ご注意ください)

AgentCore Runtime (ランタイム)

  • オープンソースのエージェントフレームワークを使った AI エージェントやツールをデプロイできるサーバーレスな実行環境で、スケーリングやセッション分離、高速コールドスタートなどがサポートされているようです。基盤となるフレームワークを問わずコンテナで実行できるのでオープンな仕組みと言えそうです。今回はこちらに MCP サーバーをデプロイしてみます。

AgentCore Identity (アイデンティティ)

  • エージェントへの認証やエージェントが外部 (AWS リソースなども含む) へアクセスする際の認証を管理することができます。接続先によって使える手段が変わってきますが、IAM 認証や OAuth 2.0 が利用できます。

AgentCore Memory (メモリ)

  • インフラを気にすることなく AI エージェントにコンテキストを記憶させることができます。複数ターンの会話に対応する短期メモリと、エージェントやセッション間で共有できる長期メモリがサポートされるようです。

AgentCore Code Interpreter (組み込みツールのコードインタープリター)

  • エージェントが隔離されたサンドボックス環境内で安全にコードを実行できるようにします。Python、TypeScript、JavaScript など複数の言語をサポートしています。推論だけでは難しい計算問題を解決したい場合などで利用します。

AgentCore Browser (組み込みツールのブラウザ)

  • エージェントにブラウザによる Web アクセスする機能を提供し、インタラクティブな操作をできるようにします。ブラウザのライブビュー画面や録画を参照したりもできるようです。

AgentCore Gateway (ゲートウェイ)

  • API や Lambda 関数、既存のサービスなどを MCP 互換ツールに変換し、エージェントから呼び出せるようにします。また、OAuth 認証で有効なユーザーやエージェントだけがアクセスできるようにします。

AgentCore Observability (オブザーバビリティ)

  • CloudWatch に専用のダッシュボードを用意し、エージェントのパフォーマンスをトレースしたり、監視を支援します。OpenTelemetry 互換のテレメトリとエージェントワークフローの各ステップの詳細な可視化をサポートしています。

MCP とは

MCP についてここであまり深く説明する必要はないと思いますが、MCP は AI エージェントがファイルシステムの操作や API、データベースなどへのアクセスできるようにするための標準的なプロトコルで、AI エージェントに質問の応答だけでなく「何かを実行する能力」を与えるものです。
詳しく知りたい方は公式のドキュメントを読んでくださいませ。 ( https://modelcontextprotocol.io/ )

AgentCore Runtime を使用して MCP サーバーをデプロイする

ここからが本題です。AgentCore のドキュメントによると、先ほどご紹介したエージェントの実行環境である AgentCore Runtime に MCP サーバーをデプロイし、実行することができるとあります。すなわちリモート MCP サーバーとして利用できそうです。

大まかな流れとしては、ほぼドキュメントの通りですが以下の順でやってみます。

  1. 準備 (実行環境用の IAM ロールの作成と、OAuth 用 Cognito User Pool の作成)
  2. MCP サーバーの作成
  3. MCP サーバーをローカルでテストする
  4. MCP サーバーを AWS にデプロイする
  5. リモート MCP サーバーを MCP Inspector からテストする

0. 準備

0.1. IAM ロールの作成

まず、AgentCore Runtime 実行環境用の IAM ロールを作成します。ドキュメントでもサンプルが紹介されていますが、今回試した範囲では少し過不足がありましたので以下にポリシーを紹介します。

IAM ポリシー ({{REGION}}{{ACCOUNT_ID}} は環境に合わせて変更してください。)
18行目: ECR リポジトリのリソース範囲は手順を簡単にするため広めの権限にしていますのでご注意ください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage"
      ],
      "Resource": [
        "arn:aws:ecr:{{REGION}}:{{ACCOUNT_ID}}:repository/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "bedrock-agentcore:GetWorkloadAccessToken",
        "bedrock-agentcore:GetWorkloadAccessTokenForUserId",
        "bedrock-agentcore:GetWorkloadAccessTokenForJWT",
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "cloudwatch:PutMetricData",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "cloudwatch:namespace": "bedrock-agentcore"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:DescribeLogStreams",
        "logs:CreateLogGroup"
      ],
      "Resource": [
        "arn:aws:logs:{{REGION}}:{{ACCOUNT_ID}}:log-group:/aws/bedrock-agentcore/runtimes/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:{{REGION}}:{{ACCOUNT_ID}}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*"
    },
    {
      "Effect": "Allow",
      "Action": "logs:DescribeLogGroups",
      "Resource": "arn:aws:logs:{{REGION}}:{{ACCOUNT_ID}}:log-group:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "xray:PutTelemetryRecords",
        "xray:GetSamplingRules",
        "xray:GetSamplingTargets",
        "xray:UpdateTraceSegmentDestination",
        "xray:PutTraceSegments"
      ],
      "Resource": "*"
    }
  ]
}

信頼ポリシー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "bedrock-agentcore.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "{{ACCOUNT_ID}}"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:bedrock-agentcore:{{REGION}}:{{ACCOUNT_ID}}:*"
        }
      }
    }
  ]
}

0.2. Cognito User Pool の作成

続いて MCP サーバーとの認証に IAM か OAuth を利用できるのですが、今回は OAuth を選択しました。そのための Cognito User Pool とユーザーを 1つ作成します。ドキュメントに User Pool とユーザーを作成し、さらにアクセストークンを取得するまでのスクリプトが用意されているのでこちらを流用します。User Pool 名や Client 名がハードコーディングされていたので変更しやすいように変数にしました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash

REGION=us-east-1
POOL_NAME='MyUserPool'
CLIENT_NAME='MyClient'
USER_NAME='testuser'
TEMPORARY_PASSWORD='Temp123!'
PASSWORD='MyPassword123!'

# Create User Pool and capture Pool ID directly
export COGNITO_USER_POOL_ID=$(aws cognito-idp create-user-pool \
  --pool-name ${POOL_NAME} \
  --policies '{"PasswordPolicy":{"MinimumLength":8}}' \
  --region ${REGION} | jq -r '.UserPool.Id')

# Create App Client and capture Client ID directly
export COGNITO_CLIENT_ID=$(aws cognito-idp create-user-pool-client \
  --user-pool-id ${COGNITO_USER_POOL_ID} \
  --client-name ${CLIENT_NAME} \
  --no-generate-secret \
  --explicit-auth-flows "ALLOW_USER_PASSWORD_AUTH" "ALLOW_REFRESH_TOKEN_AUTH" \
  --region ${REGION} | jq -r '.UserPoolClient.ClientId')

# Create User
aws cognito-idp admin-create-user \
  --user-pool-id ${COGNITO_USER_POOL_ID} \
  --username ${USER_NAME} \
  --temporary-password "${TEMPORARY_PASSWORD}" \
  --region ${REGION} \
  --message-action SUPPRESS > /dev/null

# Set Permanent Password
aws cognito-idp admin-set-user-password \
  --user-pool-id ${COGNITO_USER_POOL_ID} \
  --username ${USER_NAME} \
  --password "${PASSWORD}" \
  --region ${REGION} \
  --permanent > /dev/null

# Authenticate User and capture Access Token
export BEARER_TOKEN=$(aws cognito-idp initiate-auth \
  --client-id "${COGNITO_CLIENT_ID}" \
  --auth-flow USER_PASSWORD_AUTH \
  --auth-parameters USERNAME="${USER_NAME}",PASSWORD="${PASSWORD}" \
  --region ${REGION} | jq -r '.AuthenticationResult.AccessToken')

# Output the required values
echo "Pool id: ${COGNITO_USER_POOL_ID}"
echo "Discovery URL: https://cognito-idp.${REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}/.well-known/openid-configuration"
echo "Client ID: ${COGNITO_CLIENT_ID}"
echo "Bearer Token: ${BEARER_TOKEN}"

1. MCP サーバの作成

それでは MCP サーバを作っていきます。まずは環境を整えていきます。ドキュメントでは pip を使っていますが、uv を使っていきます。

uv init my-mcp-server
cd my-mcp-server

uv add mcp

source .venv/bin/activate

続いて main.py に MCP サーバ本体のコードを書いていきます。ドキュメントにサンプルがあるのでそのまま使ってみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from mcp.server.fastmcp import FastMCP
from starlette.responses import JSONResponse

mcp = FastMCP(host="0.0.0.0", stateless_http=True)

@mcp.tool()
def add_numbers(a: int, b: int) -> int:
    """Add two numbers together"""
    return a + b

@mcp.tool()
def multiply_numbers(a: int, b: int) -> int:
    """Multiply two numbers together"""
    return a * b

@mcp.tool()
def greet_user(name: str) -> str:
    """Greet a user by name"""
    return f"Hello, {name}! Nice to meet you."

if __name__ == "__main__":
    mcp.run(transport="streamable-http")

22行目の MCP のトランスポートとして streamable-http を指定しているのがポイントですかね。

2. MCP サーバーをローカルでテストする

作成した MCP サーバーを起動します。

uv run main.py

以下のように表示されれば OK です。

INFO:     Started server process [59214]
INFO:     Waiting for application startup.
StreamableHTTP session manager started
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

ドキュメントではテスト用の MCP クライアントのサンプルがあります。また、MCP Inspector というものでもテストできるようなので (使ったことないので) 試しに使ってみます。

別のターミナルから以下を実行します。

npx @modelcontextprotocol/inspector

以下のように表示され、ブラウザが起動します。

Starting MCP inspector...
⚙️ Proxy server listening on localhost:6277
🔑 Session token: 84b3ef9d855c5d5ab10da725138b94f240aa09f340a05a3f83f77b0d04d94518
   Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth

🚀 MCP Inspector is up and running at:
   http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=84b3ef9d855c5d5ab10da725138b94f240aa09f340a05a3f83f77b0d04d94518

🌐 Opening browser...

(ブラウザが起動しない場合は、表示されている URL http://localhost:6274/?.... を開いてみてください。)

Transport Type を “Streamable HTTP” にし、URL に先ほど起動した MCP サーバーの URL “http://localhost:8000/mcp” を入力して “Connect” を押します。

Initialize MCP Inspector

画面上部から “Tools” - “List Tools” と選択すると、中央あたりにサーバーの Python コードで @mcp.tool() で修飾したメソッドがツールのリストとして表示されます。
ツールの中から “add_numbers” を選択し、右側の “a” と “b” に適当に数値を入れ、"Run Tool" で実行します。結果が返ってこれば OK です。

Run Tool on MCP Inspector

3. MCP サーバーを AWS にデプロイする

3.1. デプロイのための準備

はじめに __init__.py を生成しておきます。

touch __init__.py

MCP サーバーを AWS にデプロイするためにツールが提供されているようなのでインストールします。プロジェクトに閉じてインストールしたい場合は venv を activate した状態で実行します。

uv add --dev bedrock-agentcore-starter-toolkit
uv sync

これで agentcore というコマンドが使えるようになります。

デプロイするための情報を以下の通り agentcore configure で設定します。

# 手順 0.1 で作成した IAM 実行ロールの ARN
EXECUTION_ROLE_ARN=arn:aws:iam::{{ACCOUNT_ID}}:role/{{ROLE_NAME}}

# 手順 0.2 で作成した Cognito の User Pool ID と Client ID
COGNITO_USER_POOL_ID=us-east-1_XXXXXXXXX
COGNITO_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxx

# 利用リージョン
REGION=us-east-1

# 必要な情報を設定
agentcore configure \
  --name my_mcp_server \
  --entrypoint main.py \
  --execution-role ${EXECUTION_ROLE_ARN} \
  --authorizer-config "{
    \"customJWTAuthorizer\": {
      \"discoveryUrl\": \"https://cognito-idp.${REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}/.well-known/openid-configuration\",
      \"allowedClients\": [\"${COGNITO_CLIENT_ID}\"]
    }
  }" \
  --protocol MCP

上記を実行すると、下記のように ECR リポジトリの URI が聞かれます。今回は自動作成にしますので、そのままエンターを押します。自分で作成した ECR リポジトリを指定する場合は、コマンドラインオプション --ecr で指定することもできます。

🏗️  ECR Repository
Press Enter to auto-create ECR repository, or provide ECR Repository URI to use existing
ECR Repository URI (or skip to auto-create):

続いて、ライブラリの依存ファイルの指定を求められます。今回は uv を使ってきたので pyproject.toml を指定します。pip を使ってきた場合は requirements.txt を指定します。(オプション --requirements-file であらかじめ指定することもできます。)

🔍 Detected dependency file: pyproject.toml
Press Enter to use this file, or type a different path (use Tab for autocomplete):
Path or Press Enter to use detected dependency file:

agentcore configure コマンドを実行するとフォルダ内に .bedrock_agentcore.yaml というファイルや、AgentCore Runtime はコンテナとしてデプロイ、実行されるので Dockerfile が作成されます。

3.2. デプロイ

デプロイは agentcore launch というコマンドを使います。作成した MCP サーバー (Python コード) は自動的にコンテナとしてビルドされ ECR にプッシュされるので楽ですね。

agentcore launch

デプロイに成功すると以下のように表示されます。

╭──────────────────────────────────── Bedrock AgentCore Deployed ──────────────────────────────────────╮
│ Deployment Successful!                                                                               │
│                                                                                                      │
│ Agent Name: my_mcp_server                                                                            │
│ Agent ARN: arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my_mcp_server-XXXXXXXXXX         │
│ ECR URI: 123456789012.dkr.ecr.us-east-1.amazonaws.com/bedrock_agentcore-my_mcp_server                │
│                                                                                                      │
│ You can now check the status of your Bedrock AgentCore endpoint with:                                │
│ agentcore status                                                                                     │
│                                                                                                      │
│ You can now invoke your Bedrock AgentCore endpoint with:                                             │
│ agentcore invoke '{"prompt": "Hello"}'                                                               │
│                                                                                                      │
│ 📋 Agent logs available at:                                                                          │
│    /aws/bedrock-agentcore/runtimes/my_mcp_server-XXXXXXXXXX-DEFAULT                                  │
│    /aws/bedrock-agentcore/runtimes/my_mcp_server-XXXXXXXXXX-DEFAULT/runtime-logs                     │
│                                                                                                      │
│ 💡 Tail logs with:                                                                                   │
│    aws logs tail /aws/bedrock-agentcore/runtimes/my_mcp_server-XXXXXXXXXX-DEFAULT --follow           │
│    aws logs tail /aws/bedrock-agentcore/runtimes/my_mcp_server-XXXXXXXXXX-DEFAULT --since 1h         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯

4. リモート MCP サーバーを MCP Inspector からテストする

ではデプロイした MCP サーバーに MCP Inspector から接続してみます。MCP Inspector を終了した場合はあらためて起動します。

npx @modelcontextprotocol/inspector

接続先のエンドポイント URL はマネジメントコンソールを探しても見つかりません、ドキュメントのテストクライアントのコードを見てみると、デプロイした MCP サーバーのエンドポイントは以下となるようです。

https://bedrock-agentcore.{{REGION}}.amazonaws.com/runtimes/{{ENCODED_AGENT_ARN}}/invocations?qualifier=DEFAULT

{{REGION}} はデプロイしたリージョンなので問題ないでしょう。{{ENCODED_AGENT_ARN}} は先ほどデプロイした際に出力された Agent ARN の値を URL エンコードしたものを指定します。
つまり今回の例ですと

arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my_mcp_server-XXXXXXXXXX

を URL エンコードします。具体的には :%3A に、/%2F に変換した、

arn%3Aaws%3Abedrock-agentcore%3Aus-east-1%3A123456789012%3Aruntime%2Fmy_mcp_server-XXXXXXXXXX

を指定することになります。
まとめると、リモート MCP サーバーのエンドポイント URL は以下になります。
(ARN が入るということなので AWS アカウント ID が丸見えになるのがとても気になります…)

https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn%3Aaws%3Abedrock-agentcore%3Aus-east-1%3A123456789012%3Aruntime%2Fmy_mcp_server-XXXXXXXXXX/invocations?qualifier=DEFAULT

そして、リモート MCP サーバーに接続するためにはベアラートークンとして OAuth のアクセストークンが必要です。手順 0.2. のスクリプトを実行すると Bearer Token が出力されますが、ここまでの手順で期限が切れているかもしれないので Cognito から再発行します。
(Cognito のデフォルトではアクセストークンは 1時間で期限切れになります)

(手順 0.2. のスクリプトの 41 - 45行目です)

export BEARER_TOKEN=$(aws cognito-idp initiate-auth \
  --client-id "${COGNITO_CLIENT_ID}" \
  --auth-flow USER_PASSWORD_AUTH \
  --auth-parameters USERNAME="${USER_NAME}",PASSWORD="${PASSWORD}" \
  --region ${REGION} | jq -r '.AuthenticationResult.AccessToken')

echo "Bearer Token: ${BEARER_TOKEN}"

この リモート MCP サーバーのエンドポイント URL と ベアラートークンを MCP Inspector に指定し接続してみます。

Connect to remote MCP server

補足

mcp のバージョンが 1.12.0 で接続に失敗する場合は、pyproject.toml で 1.11.0 にして再度デプロイ (agentcore launch) してみてください。

dependencies = [
-    "mcp>=1.12.0",
+    "mcp==1.11.0",
]

接続できたら、ローカルでテストした時と同様に、画面上部の “Tools” - “List Tools” - “add_numbers” と選択し、右側の “a” と “b” に適当に数値を入れ、"Run Tool" で実行します。結果が返ってこれば OK です。

Claude Code からリモート MCP サーバーとして利用してみる

実際に Claude Code からも接続してみます。Claude Code に MCP サーバーを追加します。

claude mcp add --transport http \
  my-mcp-server 'https://bedrock-agentcore.{{REGION}}.amazonaws.com/runtimes/{{DECODED_AGENT_ARN}}/invocations?qualifier=DEFAULT' \
  -H 'Authorization: Bearer {{BARER_TOKEN}}'

もしくは ~/.claude.json などに以下を追加します。

{
  // :
  // (snip)
  // :
  "mcpServers": {
    "my-mcp-server": {
      "type": "http",
      "url": "https://bedrock-agentcore.{{REGION}}.amazonaws.com/runtimes/{{DECODED_AGENT_ARN}}/invocations?qualifier=DEFAULT",
      "headers": {
        "Authorization": "Bearer {{BARER_TOKEN}}"
      }
    }
  }
}

Claude Code を起動し、/mcp で見てみます。

MCP server status in Claude Code

良さそうです。足し算を依頼してみました。MCP サーバーを使ってくれそうです。

Request to add 2 numbers to Claude Code

正しい結果が返ってきました!

Result of respond from MCP server

まとめ

Amazon Bedrock AgentCore Runtime を使ってリモート MCP サーバーをデプロイして、Claude Code から利用してみました。MCP サーバーのエンドポイント URL に ARN が入ってしまうので AWS アカウント ID が MCP クライアント側に知られてしまいます。恐らく、AgentCore Runtime に直接アクセスするのではなく、AgentCore Gateway を介したりしてアクセスするべきなのでしょう。まだプレビューリリースということもあるので今後も注目ですね。

最後に・・・

この投稿は個人的なものであり、所属組織を代表するものではありません。ご了承ください。