
Try having Claude Code reference multiple AWS accounts via MCP
This page has been translated by machine translation. View original
Introduction
Hello everyone, this is Akaike.
Have you ever wanted to have Claude Code reference multiple AWS accounts? I have.
However, manually switching roles one account at a time isn't practical, so I decided to connect Claude Code to an AWS MCP Server and have it do the research.
So this time, I'll summarize the configuration for having Claude Code cross-reference multiple AWS accounts.
Prerequisites
- IAM roles for switching from the base account to each target AWS account must be deployed in the switch destination accounts
- Configuration is easier if the role name is consistent across all accounts
- The IAM roles at the switch destinations should have read-only permissions
- I believe the principle when letting AI interact with resources is to grant only read permissions. More details below
- AWS CLI 2.32.0 or later must be installed
- This version is required to use the
aws logincommand
- This version is required to use the
uv(uvx) must be installed
Authentication uses aws login.
Note that if you're using IAM Identity Center, the base profile definition changes to use sso_session, but the role switching and MCP configuration beyond that remains the same.
Authentication Flow
The configuration covered in this blog is as follows.
- Define profiles in the AWS CLI configuration file to switch roles from the base account to each account
- Pass those profile names together to the proxy in the MCP configuration
The credential chain looks like this.
Browser authentication only happens once for the origin profile, and role switches to each account are derived from that session.
The request flow is as follows.
Since Claude Code can specify the target account with the aws_profile parameter on each tool call, no MCP server restart is required.
This aws_profile-based switching is a feature provided exclusively when using AWS MCP Server with SigV4 authentication.
With OAuth authentication, the session is fixed to a single IAM role, so re-authentication is required each time you switch accounts.
Configuration Details
IAM User for Role Switching (Source)
This is the IAM user in the base account that signs in with aws login.
Two permissions are required.
The first is the permission to use console credentials with aws login, which is granted by attaching the AWS managed policy SignInLocalDevelopmentAccess.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"signin:AuthorizeOAuth2Access",
"signin:CreateOAuth2Token"
],
"Resource": "arn:aws:signin:*:*:oauth2/public-client/*"
}
]
}
The second is the permission to switch roles to each account.
This is added as an inline policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeReadOnlyRoleInTargetAccounts",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::*:role/AIAgentReadOnlyRole"
}
]
}
IAM Role at the Switch Destination
This is the role deployed to each target account.
Here we assume it's named AIAgentReadOnlyRole and deployed with the same name across all accounts.
The permission policy has ReadOnlyAccess attached.
The trust policy allows assumption only from the base account.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXXX:root"
},
"Action": "sts:AssumeRole"
}
]
}
AWS CLI Configuration File
This is the profile definition.
You can write it directly in ~/.aws/config, but here I'm separating it into a dedicated file.
# Origin profile
[profile hub-account]
region = ap-northeast-1
output = json
# Switch destination profiles
[profile network-account]
source_profile = hub-account
role_arn = arn:aws:iam::YYYYYYYYYYYY:role/AIAgentReadOnlyRole
role_session_name = claude-code
region = ap-northeast-1
output = json
[profile security-account]
source_profile = hub-account
role_arn = arn:aws:iam::ZZZZZZZZZZZZ:role/AIAgentReadOnlyRole
role_session_name = claude-code
region = ap-northeast-1
output = json
[profile workload-prd-account]
source_profile = hub-account
role_arn = arn:aws:iam::AAAAAAAAAAAA:role/AIAgentReadOnlyRole
role_session_name = claude-code
region = ap-northeast-1
output = json
MCP Configuration File
This is .mcp.json in the project root.
{
"mcpServers": {
"aws-audit": {
"command": "uvx",
"args": [
"mcp-proxy-for-aws-cli@latest",
"https://aws-mcp.ap-northeast-1.api.aws/mcp",
"--metadata",
"AWS_REGION=ap-northeast-1"
],
"env": {
"AWS_CONFIG_FILE": "/Users/example/work/aws-audit/aws-config",
"AWS_MCP_PROXY_PROFILES": "hub-account network-account security-account workload-prd-account"
}
}
}
}
Notes on Each Configuration
Restrict IAM to Read-Only Permissions
The key to ensuring safety in this configuration is that the switch destination roles are granted only read permissions.
First, as a premise, I believe the principle for roles passed to AI agents is to grant read-only permissions.
The reason is that a misjudgment by the agent directly translates to a change in the production environment.
It would be problematic if the agent decided to "go ahead and fix the configuration" during an investigation, and there's also the possibility that unintended operations could be triggered by external factors like prompt injection.
In such cases, a role with only read permissions means nothing beyond read-level operations can happen, no matter what.
In this case I'm using ReadOnlyAccess, but if you have requirements like "I don't want S3 objects to be readable!", you might consider using ViewOnlyAccess depending on your use case.
On the source IAM user side as well, the target of sts:AssumeRole is limited to the role name AIAgentReadOnlyRole.
This ensures that even if the base account credentials are used without authorization, only the read-only role can be assumed.
Origin Profile and aws login
Specify the origin profile with aws login.
export AWS_CONFIG_FILE=/Users/example/work/aws-audit/aws-config
aws login --profile hub-account
A browser will open, so sign in with the IAM user of the base account.
If you're already signed into the management console, you just need to select that session.
Role Switching Profiles
By specifying source_profile = hub-account, a chain is set up to AssumeRole using the credentials of the origin profile.
The session obtained with aws login can also be used as-is as the starting point of this chain.
Even as more accounts are added, you just need to append these blocks, so if you have a CSV list of accounts, you might as well generate them with a script.
Also, role_session_name is recorded in CloudTrail, so it's recommended to use a value that lets you trace back that the operation was performed via an AI agent.
Environment Variables Passed in the MCP Configuration
The two settings passed in env are the key points.
AWS_CONFIG_FILE specifies the dedicated configuration file created earlier.
This allows complete separation from the profiles in the regular ~/.aws/config.
AWS_MCP_PROXY_PROFILES is an environment variable that lists the profiles to be used by the proxy, separated by spaces.
Only the profiles listed here become available options for the aws_profile parameter during tool calls. The first one, hub-account, is used as the default, and calls that omit aws_profile are executed with this profile.
The important point here is that profiles not listed cannot be used.
Even if they're written in the configuration file, they won't be visible from Claude Code and will be rejected with an error if specified.
Since it functions as an explicit allowlist, it structurally prevents accidents where "unintended accounts are referenced."
Also, by separating .mcp.json per project, you can isolate the AWS accounts that can be referenced on a per-project basis.
Verification
First, verify that role switching works with AWS CLI alone.
export AWS_CONFIG_FILE=/Users/example/work/aws-audit/aws-config
# Origin
aws sts get-caller-identity --profile hub-account
# Switch destination
aws sts get-caller-identity --profile security-account
For the switch destination, the ARN of the assumed role should be returned.
{
"UserId": "AROAEXAMPLEID:claude-code",
"Account": "ZZZZZZZZZZZZ",
"Arn": "arn:aws:sts::ZZZZZZZZZZZZ:assumed-role/AIAgentReadOnlyRole/claude-code"
}
Once you've confirmed it works, launch Claude Code and verify the server is connected with /mcp.
After that, just ask in natural language.
Check if there are any S3 buckets with public access enabled
in the two accounts: security-account and workload-prd-account
Since Claude Code will call tools with the appropriate aws_profile specified for each account, you can submit cross-account investigations in natural language.
Closing
That's it — a method for having Claude Code reference multiple AWS accounts by combining AWS profiles and MCP configuration.
It's straightforward in principle, but cross-account investigations are fairly tedious work, so personally this has been extremely helpful.
I hope this serves as a reference for others who want to use AI agents in multi-account environments.
