[Update] IAM authentication is now available for MCP Server targets in Amazon Bedrock AgentCore Gateway

[Update] IAM authentication is now available for MCP Server targets in Amazon Bedrock AgentCore Gateway

2026.04.12

This page has been translated by machine translation. View original

Introduction

Hello, I'm Jinno from the Consulting Department, and I'm a big fan of cheese naan.

Previously, I introduced a configuration where AgentCore Gateway's Target is set to an MCP Server deployed on AgentCore Runtime.

https://dev.classmethod.jp/articles/amazon-bedrock-agentcore-gateway-target-agentcore-runtime-mcp-server/

In that article, I used Cognito M2M (Client Credentials) for Gateway→Runtime (MCP Server) Outbound authentication.
While it worked perfectly fine, I felt it was a bit cumbersome to use Cognito for communication between AWS resources.

Recently, GATEWAY_IAM_ROLE has been added as an Outbound authentication option for Gateway Target with MCP Server targets!
Now we can directly call Runtime with SigV4 signatures using the Gateway's IAM role, making integration much easier! That's great!

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-outbound-auth.html

In this article, I'll test whether we can directly call MCP tools on AgentCore Runtime from Claude Code using this configuration!

Prerequisites

  • AWS account (verified in us-east-1 region)
  • Terraform v1.14.4 + AWS Provider v6.39.0
  • Python 3.13 (for MCP Server code)
  • Docker v29.1.5 (for ARM64 image building)
  • Claude Code v2.1.84
  • uv v0.9.26 (used to run mcp-proxy-for-aws v1.1.6)

Architecture

The overall architecture is as follows:

01-architecture

It's nicely simple with just IAM. (Previously, we had to use Cognito as an intermediary...)
From the client's Claude Code, we connect to the Gateway as an MCP Server using MCP Proxy for AWS.

Implementation

MCP Server Implementation

The MCP Server code is the same as in the previous article. Using FastMCP 3.2.3, I implemented three tools: addition, multiplication, and greeting.

agent/mcp_server.py
from fastmcp import FastMCP

mcp = FastMCP("sample-tools")

@mcp.tool()
def add_numbers(a: int, b: int) -> int:
    """2つの数字を足し算します"""
    return a + b

@mcp.tool()
def multiply_numbers(a: int, b: int) -> int:
    """2つの数字を掛け算します"""
    return a * b

@mcp.tool()
def greet_user(name: str) -> str:
    """ユーザーに挨拶します"""
    return f"Hello, {name}! Welcome to AgentCore Runtime."

if __name__ == "__main__":
    mcp.run()

Functions with the @mcp.tool() decorator are published as MCP tools. The docstring becomes the tool's description, which helps the agent decide which tool to call.

Next is the Dockerfile for the container image. Since AgentCore Runtime runs on ARM64 architecture, we specify --platform linux/arm64 during the build (this is done in Terraform).

agent/Dockerfile
FROM public.ecr.aws/docker/library/python:3.12-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY mcp_server.py .

CMD ["python", "mcp_server.py"]

This is a simple configuration that uses Python 3.12 slim image as the base, installs dependency packages, and starts the MCP Server.

The only dependency package is fastmcp.

agent/requirements.txt
fastmcp

Deploying Runtime + Gateway with Terraform

Using Terraform, we'll create Runtime, ECR, IAM roles, and Gateway. We'll set up the Gateway Target in the console.

For the complete Terraform code, please refer to the GitHub repository.

https://github.com/yuu551/iam-identity-gateway

Here, I'll focus on explaining the important points from an IAM authentication perspective.

IAM Role Design

In this IAM configuration, three permissions appear.

Permission Who To What Purpose
bedrock-agentcore:InvokeGateway Caller (Claude Code user) Gateway Inbound: To pass Gateway IAM authentication
bedrock-agentcore:InvokeAgentRuntime Gateway IAM role Runtime Outbound: For Gateway to call Runtime
ecr:BatchGetImage etc. Runtime IAM role ECR repository For Runtime to pull container images

In Terraform, they're defined as follows:

iam.tf(Gateway role permission part)
# Policy for Gateway to call Runtime
resource "aws_iam_role_policy" "gateway_invoke_runtime" {
  name = "${var.project_name}-gateway-invoke-runtime-policy"
  role = aws_iam_role.gateway.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid      = "InvokeAgentRuntime"
      Effect   = "Allow"
      Action   = "bedrock-agentcore:InvokeAgentRuntime"
      Resource = "${aws_bedrockagentcore_agent_runtime.mcp_server.agent_runtime_arn}*"
    }]
  })
}

The only permission needed for the Gateway role is InvokeAgentRuntime. We add * at the end of Resource because the actual access destination is a subresource like runtime/xxx/runtime-endpoint/DEFAULT.

Gateway Configuration

The Gateway definition is simple. We specify AWS_IAM for authorizer_type.

gateway.tf
resource "aws_bedrockagentcore_gateway" "main" {
  name            = "${var.project_name}-gateway-${random_string.suffix.result}"
  description     = "AgentCore Gateway with IAM inbound authentication"
  role_arn        = aws_iam_role.gateway.arn
  authorizer_type = "AWS_IAM"
  protocol_type   = "MCP"
}

Deployment

Run the terraform apply command to deploy.

Execution command
terraform init
terraform apply 

# When asked if you want to apply, select yes

After apply completes, the following Output is displayed.

Output example
gateway_id             = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
gateway_url            = "https://xxxxxxxx.gateway.bedrock-agentcore.us-east-1.amazonaws.com"
runtime_arn_url_encoded = "https://bedrock-agentcore.us-east-1.amazonaws.com/runtimes/arn%3Aaws%3A.../invocations"

gateway_url will be used in the Gateway Target configuration and .mcp.json. runtime_arn_url_encoded will be used as the Endpoint for Gateway Target.

Creating a Gateway Target in the Console (IAM Authentication)

Once the Gateway is created, add Runtime as a Target.

Opening the Gateway details screen confirms that the Inbound Auth type is "IAM permissions". Click "Add" for targets.

02-gateway-detail

Enter the following and click "Add target":

  • Target type: MCP server
  • MCP endpoint: Enter the runtime_arn_url_encoded from Terraform output
  • Outbound authentication configuration: Select IAM role
  • Service: bedrock-agentcore

03-add-target-form

When the Target status becomes Ready, it's complete. You can also confirm that the Outbound Auth configurations is "IAM roles".

04-target-ready

Note that Outbound IAM authentication (SigV4) is only available with MCP servers behind AWS services that can verify SigV4 signatures. These include AgentCore Runtime, AgentCore Gateway, API Gateway, and Lambda Function URLs. It cannot be used with MCP servers on ALB or EC2, so be aware of this limitation.

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-target-MCPservers.html

Setting Caller IAM Permissions

Since Gateway Inbound authentication is AWS_IAM, we need to grant InvokeGateway permission to the IAM entity used by Claude Code (mcp-proxy-for-aws). Without this permission, access to the Gateway will be denied.

IAM Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowGatewayInvocation",
      "Effect": "Allow",
      "Action": "bedrock-agentcore:InvokeGateway",
      "Resource": "arn:aws:bedrock-agentcore:us-east-1:<ACCOUNT_ID>:gateway/<GATEWAY_ID>"
    }
  ]
}

Attach this policy to the IAM user or role linked to your local AWS profile. You can confirm <GATEWAY_ID> from the Terraform output gateway_id. While it's possible to use wildcards for Resource, it's recommended to narrow it down to specific Gateway ARNs for security reasons.

https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-inbound-auth.html

Connection Settings from Claude Code

What is MCP Proxy for AWS?

MCP Proxy for AWS is an official AWS open-source tool. MCP clients like Claude Code don't natively support SigV4 signatures. This proxy automatically adds SigV4 signatures to MCP requests using local AWS credentials (~/.aws/credentials or environment variables) and forwards them to the Gateway.

https://github.com/aws/mcp-proxy-for-aws

It can be directly configured in Claude Code's .mcp.json.

.mcp.json Configuration

Create a .mcp.json file in the project root.

.mcp.json
{
  "mcpServers": {
    "agentcore-gateway": {
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws@latest",
        "https://<GATEWAY_ID>.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp",
        "--service", "bedrock-agentcore",
        "--region", "us-east-1"
      ]
    }
  }
}

Replace <GATEWAY_ID> with the value of gateway_id from the Terraform output. --service bedrock-agentcore is the service name for SigV4 signature, and --region is the region for signing.

If you want to add it directly from Claude Code, you can use the following command:

Adding via CLI
claude mcp add --transport stdio agentcore-gateway -- \
  uvx mcp-proxy-for-aws@latest \
  "https://<GATEWAY_ID>.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp" \
  --service bedrock-agentcore \
  --region us-east-1

Operation Check

When you start Claude Code, mcp-proxy-for-aws starts as a stdio process, establishing a SigV4-signed connection to the Gateway. MCP Server tools are automatically loaded.

First, to check if the connection is established, run /mcp.
When the connection to the MCP Server is established, you'll see connected.

05-claude-code-connected

Checking the tool list shows that the three tools on Runtime are recognized.

06-tools-list

Let's try calling a tool. When I enter "Use the addition tool to add 3123 + 31341234", Claude Code calls the add_numbers tool.

07-tool-call

And the result comes back!

08-tool-result

We successfully called an MCP tool on Runtime from Claude Code via AgentCore Gateway. That was easy!

Conclusion

I tried out an IAM authentication configuration combining AgentCore Gateway's Outbound IAM authentication support with MCP Proxy for AWS!

I think this is a good approach for use cases where you want to unify with IAM authentication, such as for internal tools or within AWS accounts. It's a good update since I previously found it cumbersome to call an MCP Server deployed on Runtime via Gateway!
I used to avoid deploying MCP Servers on Runtime and linking them to Gateway because I didn't want to add Cognito in between, but now I'd like to actively use this approach.

I hope this article has been helpful. Thank you for reading to the end!

Share this article