Skip to main content

AWS — Official AWS MCP Server

Connect Willow to the AWS MCP Server, AWS's managed remote MCP server, to give your AI assistants access to your AWS account: describing resources, reading configuration, searching AWS documentation, and running AWS API calls through the server's sandboxed run_script tool.

The server is available in these regions:

  • US East (N. Virginia): https://aws-mcp.us-east-1.api.aws/mcp
  • US West (Oregon): https://aws-mcp.us-west-2.api.aws/mcp
  • Asia Pacific (Singapore): https://aws-mcp.ap-southeast-1.api.aws/mcp
  • Asia Pacific (Sydney): https://aws-mcp.ap-southeast-2.api.aws/mcp
  • Asia Pacific (Tokyo): https://aws-mcp.ap-northeast-1.api.aws/mcp
  • Europe (Frankfurt): https://aws-mcp.eu-central-1.api.aws/mcp
  • Europe (Ireland): https://aws-mcp.eu-west-1.api.aws/mcp
  • Europe (London): https://aws-mcp.eu-west-2.api.aws/mcp
Replacing the AWS API MCP Server

AWS recommends the AWS MCP Server over the older awslabs.aws-api-mcp-server and aws-knowledge-mcp-server packages. If you already connected either of those to Willow, remove them after adding this server, so agents don't see two overlapping sets of AWS tools.

How authentication works​

You can connect the AWS MCP Server in three ways. The first two share one AWS identity across your organization, and nobody has to sign in to AWS. Willow signs each request with AWS Signature Version 4 (SigV4) in the gateway, doing the same job as AWS's MCP Proxy for AWS without running a local process. With the third, each person signs in to AWS as themselves.

  • An IAM role (recommended for a shared identity). You create a role that trusts Willow, and Willow assumes it for each session. You store no keys, and the credentials Willow gets last one hour. See Set up with an IAM role.
  • An IAM user's access key. You store the key in the Vault. Use this when Willow can't assume a role in your account. See Set up with an access key.
  • OAuth, one identity per person. Each person signs in through AWS Sign-In with their own IAM user, IAM Identity Center user, or federated identity. See Set up with OAuth.

The AWS MCP Server calls AWS APIs as that identity, so its IAM policies decide what your agents can and can't do. Choosing those policies is the most important part of the setup. See Example policies.

Prerequisites​

  • An AWS account and permission to create IAM roles and policies
  • A Willow admin account

1. In Willow — copy your Organization ID​

Go to Settings → General and open Organization Details. Copy the Organization ID. It's a fixed identifier that doesn't change when your organization is renamed, and your role's trust policy uses it as the external ID.

2. In AWS — create the role​

Create a role with this trust policy. Replace <organization-id> with the ID you copied, and use the principal for the region your Willow organization runs in:

Willow regionYour Willow URLsPrincipal
US*.withwillow.aiarn:aws:iam::992382826040:role/willow-production-run
EU*.eu.withwillow.aiarn:aws:iam::992382826040:role/willow-eu-production-run
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::992382826040:role/willow-production-run"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "sts:ExternalId": "<organization-id>" }
}
}
]
}

The external ID condition is what stops another Willow organization from using your role. Willow always sends your own Organization ID and never one taken from configuration. Don't remove the condition.

With the AWS CLI, save the trust policy as trust.json and run:

aws iam create-role \
--role-name willow-aws-mcp \
--assume-role-policy-document file://trust.json

aws iam attach-role-policy \
--role-name willow-aws-mcp \
--policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess

In the console, open IAM → Roles → Create role, choose Custom trust policy, paste the trust policy, and attach the policies you want on the next page.

Then add any policies from Example policies. They apply to a role the same way as to a user: use aws iam put-role-policy or aws iam attach-role-policy with --role-name instead of the user commands.

3. In Willow — add the AWS MCP Server​

  1. In the sidebar, go to MCP Servers under the Build section and click + Add MCP Server.
  2. Search for AWS and select it.
  3. Pick the AWS Region the server runs in, and paste the role's ARN into IAM role ARN, for example arn:aws:iam::123456789012:role/willow-aws-mcp. With an ARN, setup skips AWS sign-in. Leave it empty and each person signs in to AWS instead; see Set up with OAuth.
  4. Create the MCP server.

Then test the connection. Which AWS identity am I using? should answer with an assumed-role session named willow-<organization-slug>-<mcp-server> under your role. CloudTrail records every call under that session name too.

Hybrid deployments

In a hybrid deployment, your own gateway assumes the role, not Willow's. Put the IAM role of your gateway's run service in the trust policy's Principal instead, and give that role sts:AssumeRole permission on your role. Keep the external ID condition.

Set up with OAuth​

Each person signs in to AWS as themselves, and the AWS MCP Server calls AWS with that person's permissions. CloudTrail records every call under their own identity. To stop agents from using everything a person can do, for example an administrator's full access, add Example 7.

AWS Sign-In only sends the sign-in back to a URL on the person's own computer, such as http://localhost, so Willow uses local sign-in: a small helper on each person's computer receives the sign-in and passes it to Willow. The helper is part of the Willow Scan Agent, or people can run it in a terminal.

Prerequisites​

  • An AWS identity for each person, with permission to sign in through OAuth (see step 1)
  • On each person's computer, the Willow Scan Agent running, or Node.js to run npx -y @mcp-s/mcp oauth-relay

1. In AWS — let people sign in through OAuth​

Attach the AWS managed policy AWSMCPSignInOAuthAccessPolicy to the IAM users or roles people sign in with. With IAM Identity Center, add it to their permission sets. It grants signin:AuthorizeOAuth2Access and signin:CreateOAuth2Token on the AWS MCP Server and nothing else.

aws iam attach-role-policy \
--role-name <role-name> \
--policy-arn arn:aws:iam::aws:policy/AWSMCPSignInOAuthAccessPolicy

Identities with AdministratorAccess already have these permissions.

2. In Willow — add the AWS MCP Server​

  1. In the sidebar, go to MCP Servers under the Build section and click + Add MCP Server.
  2. Search for AWS and select it.
  3. Pick the AWS Region and leave IAM role ARN empty. Click Set up AWS. The server card shows OAuth sign-in.
  4. Click Open, go to the Setup tab, and scroll to Authentication. OAuth sign-in is selected.
  5. Turn on Local sign-in. Willow registers itself with AWS Sign-In, and Active OAuth client shows Registered automatically (DCR) with an ID that starts with arn:aws:signin:.
  6. Click Save Changes.
  7. In Tools, turn on the tools you want, assign the server to groups, and click Publish.

3. Each person — sign in​

  1. Make sure the Willow Scan Agent is running, or run npx -y @mcp-s/mcp oauth-relay in a terminal and keep it open while signing in.
  2. The first time an assistant calls an AWS tool, Willow asks the person to sign in. Willow checks that the helper is running, then opens AWS Sign-In.
  3. On Connect MCP Client to AWS MCP Server, click Continue to sign in, sign in with your AWS identity, and approve.

Access tokens last one hour and Willow renews them automatically. AWS ends the sign-in after 12 hours, or earlier when a policy attached to the person changes, and the person signs in again. If they're still signed in to AWS in the browser, signing in again is one click.

Then test the connection. Which AWS identity am I using? should answer with the person's own identity.

Set up with an access key​

Prerequisites​

  • An AWS account and permission to create IAM users, policies, and access keys, plus CloudFormation stacks if you use the template
  • A Willow admin account with access to Security Center → Vault

Steps​

1. In AWS — create an IAM user for Willow​

Create a dedicated IAM user, rather than reusing one that people or other systems use. The examples below name it willow-aws-mcp.

You can create the user with CloudFormation, in the AWS console, or with the AWS CLI.

With CloudFormation:

Download the template: willow-aws-mcp.yaml

It creates the IAM user and attaches the policies from Example policies that you choose with its parameters:

ParameterDefaultDescription
UserNamewillow-aws-mcpName of the IAM user.
BaseAccessViewOnlyAccessViewOnlyAccess or ReadOnlyAccess (Example 1), IncidentInvestigation (Example 3), or None to attach your own policies.
AdditionalPolicyArnsemptyComma-separated ARNs of existing managed policies to attach as well.
BlockSecretstrueAttaches Example 2.
DenyDestructiveViaMcptrueAttaches Example 5.
AllowedRegionsemptyComma-separated regions, for example us-east-1,eu-west-1. Attaches Example 4 with those regions. Leave empty to allow all regions.

To deploy it in the console:

  1. Open the CloudFormation console and click Create stack → With new resources (standard).
  2. Choose Upload a template file, select willow-aws-mcp.yaml, and click Next.
  3. Enter a Stack name, for example willow-aws-mcp, set the parameters, and click Next twice.
  4. Check I acknowledge that AWS CloudFormation might create IAM resources with custom names and click Submit.
  5. When the stack reaches CREATE_COMPLETE, open its Outputs tab and follow the CreateAccessKeyUrl link. Continue from step 6 of the console instructions below to create the access key.

Or with the AWS CLI:

aws cloudformation deploy \
--stack-name willow-aws-mcp \
--template-file willow-aws-mcp.yaml \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides BaseAccess=ViewOnlyAccess AllowedRegions=us-east-1,eu-west-1

aws iam create-access-key --user-name willow-aws-mcp

The template doesn't create the access key. CloudFormation could only return the secret through stack outputs, where anyone who can read the stack would see it, so you create the key yourself and AWS shows the secret once.

IAM is global, so you can deploy the stack in any region. To change the policies later, update the stack with new parameter values. Before deleting the stack, delete the user's access key; AWS won't delete an IAM user that still has one.

In the AWS console:

  1. Open the IAM console and go to Users → Create user.
  2. Enter a User name. Leave Provide user access to the AWS Management Console unchecked; the user only needs an access key.
  3. On Set permissions, choose Attach policies directly and select the AWS managed policies you want, for example ViewOnlyAccess. You can add custom policies after the user exists.
  4. Click Next, then Create user.
  5. Add any custom policies from Example policies. See Applying a custom policy.
  6. Open the user, go to the Security credentials tab, and under Access keys click Create access key.
  7. Choose Third-party service as the use case, confirm, and click Next, then Create access key.
  8. Copy the Access key and Secret access key, or click Download .csv file. AWS shows the secret only once.

With the AWS CLI:

aws iam create-user --user-name willow-aws-mcp

# Attach an AWS managed policy, for example ViewOnlyAccess
aws iam attach-user-policy \
--user-name willow-aws-mcp \
--policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess

# Attach any custom policies (see "Applying a custom policy" below)

aws iam create-access-key --user-name willow-aws-mcp

Copy AccessKeyId and SecretAccessKey from the output of create-access-key.

2. In Willow — store the access key in the Vault​

  1. Go to Security Center → Vault and click Add Secret.
  2. Add two secrets:
    • AWS_ACCESS_KEY_ID with the access key ID
    • AWS_SECRET_ACCESS_KEY with the secret access key

3. In Willow — add the AWS MCP Server as a custom MCP​

  1. In the sidebar, go to MCP Servers under the Build section.

  2. Click + Add MCP Server, hover over Custom MCP, and select Configure.

  3. Enter a Name (for example, AWS) and a Slug.

  4. Switch to JSON and paste:

    {
    "type": "http",
    "url": "https://aws-mcp.us-east-1.api.aws/mcp",
    "awsSigV4": {
    "accessKeyId": "{{vault.AWS_ACCESS_KEY_ID}}",
    "secretAccessKey": "{{vault.AWS_SECRET_ACCESS_KEY}}"
    }
    }

    For another region, replace us-east-1 in the URL with the region's code, for example https://aws-mcp.eu-west-1.api.aws/mcp.

  5. Leave Advanced Options authentication empty; the awsSigV4 block handles it.

  6. Click Create Integration.

4. Test the connection​

Ask your AI assistant:

  • Which AWS identity am I using? The answer should be the willow-aws-mcp user. This confirms that signing works, because the assistant has to call sts:GetCallerIdentity as that user.
  • An action your policies should block, such as List my KMS keys. It should fail with an access denied error.

A question like What AWS Regions are available? isn't a useful test. The server answers region and documentation questions without checking credentials, so it succeeds even when authentication is broken.

Example policies​

The policies below are examples to adapt, not a required setup. Pick the ones that match what your agents need, combine them, and narrow them further for your account. Whatever you attach, the MCP server can do exactly what the IAM user can do.

Two IAM rules to keep in mind when combining policies:

  • An action is allowed only if some policy allows it.
  • An explicit Deny always wins over any Allow, which makes deny policies a reliable guardrail on top of broad read access.

Applying a custom policy​

Every JSON example below can be applied the same way. Save it to a file, for example policy.json.

In the AWS console, as an inline policy for this user only:

  1. In the IAM console, open Users → willow-aws-mcp → Permissions.
  2. Click Add permissions → Create inline policy.
  3. Switch the Policy editor to JSON, paste the policy, and click Next.
  4. Enter a Policy name and click Create policy.

To reuse a policy across users, create it under Policies → Create policy instead, then attach it from the user's Add permissions → Attach policies directly.

With the AWS CLI:

# Inline policy on this user only
aws iam put-user-policy \
--user-name willow-aws-mcp \
--policy-name <policy-name> \
--policy-document file://policy.json

# Or a reusable managed policy
aws iam create-policy \
--policy-name <policy-name> \
--policy-document file://policy.json

aws iam attach-user-policy \
--user-name willow-aws-mcp \
--policy-arn arn:aws:iam::<account-id>:policy/<policy-name>

Example 1: Read-only access with an AWS managed policy​

AWS maintains two managed policies for read-only access. Attach one of them instead of writing your own allow list.

PolicyWhat it allows
ViewOnlyAccessLists and describes resources and their configuration. Doesn't read data inside them.
ReadOnlyAccessEverything ViewOnlyAccess allows, plus reading data: S3 objects, DynamoDB items, CloudWatch Logs, and more.

ViewOnlyAccess is the safer starting point for an agent. Use ReadOnlyAccess when agents need to read data, and pair it with Example 2.

aws iam attach-user-policy \
--user-name willow-aws-mcp \
--policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess

In the console, choose Attach policies directly and search for ViewOnlyAccess.

Example 2: Block secrets and encryption keys​

Denies KMS and Secrets Manager entirely, plus the other places secrets usually live: Parameter Store values, Lambda environment variables, and EC2 Windows passwords. It also denies creating access keys and assuming other roles, so the user can't step outside its own permissions.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyKmsAndSecretsManager",
"Effect": "Deny",
"Action": ["kms:*", "secretsmanager:*"],
"Resource": "*"
},
{
"Sid": "DenyOtherPlacesSecretsLive",
"Effect": "Deny",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath",
"ssm:GetParameterHistory",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"ec2:GetPasswordData",
"iam:CreateAccessKey",
"sts:AssumeRole"
],
"Resource": "*"
}
]
}

Example 3: Scoped read access for incident investigation​

An allow list for an agent that investigates incidents: metrics, alarms, logs, and the compute resources behind them, and nothing else. Use it instead of Example 1 when you want a narrow scope.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadMonitoring",
"Effect": "Allow",
"Action": [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"logs:Describe*",
"logs:FilterLogEvents",
"logs:GetLogEvents",
"logs:StartQuery",
"logs:GetQueryResults"
],
"Resource": "*"
},
{
"Sid": "ReadCompute",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ecs:Describe*",
"ecs:List*",
"eks:Describe*",
"eks:List*",
"elasticloadbalancing:Describe*",
"autoscaling:Describe*"
],
"Resource": "*"
}
]
}

Application logs can contain tokens and personal data. Consider narrowing the logs: actions to specific log groups by replacing "Resource": "*" with their ARNs, for example arn:aws:logs:us-east-1:<account-id>:log-group:/ecs/my-service:*.

Example 4: Limit agents to specific regions​

Denies any regional call outside the listed regions. Global services such as IAM and STS are excluded, because they don't run in a single region.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideApprovedRegions",
"Effect": "Deny",
"NotAction": [
"iam:*",
"sts:*",
"organizations:*",
"route53:*",
"cloudfront:*",
"support:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": ["us-east-1", "eu-west-1"]
}
}
}
]
}

Example 5: Guardrails that apply only through the MCP server​

The AWS MCP Server adds two condition keys to every call it makes on your behalf:

  • aws:ViaAWSMCPService is true for any request through an AWS managed MCP server.
  • aws:CalledViaAWSMCP names the specific server, aws-mcp.amazonaws.com for this one.

Direct calls don't carry these keys, so a deny that checks them affects agents but not people or scripts using the same identity. This is useful when the identity isn't dedicated to Willow, or as a second layer on top of the other examples. This example blocks destructive actions when they come through the MCP server:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyDestructiveActionsViaMcp",
"Effect": "Deny",
"Action": [
"ec2:TerminateInstances",
"ec2:DeleteVolume",
"ec2:DeleteSnapshot",
"s3:DeleteBucket",
"s3:DeleteObject",
"rds:DeleteDBInstance",
"rds:DeleteDBCluster",
"dynamodb:DeleteTable",
"lambda:DeleteFunction",
"cloudformation:DeleteStack",
"iam:Create*",
"iam:Delete*",
"iam:Attach*",
"iam:Put*"
],
"Resource": "*",
"Condition": {
"Bool": { "aws:ViaAWSMCPService": "true" }
}
}
]
}

To target only the AWS MCP Server rather than every AWS managed MCP server, replace the condition with "StringEquals": { "aws:CalledViaAWSMCP": "aws-mcp.amazonaws.com" }.

Example 6: Organization-wide guardrail with a service control policy​

If you use AWS Organizations, a service control policy (SCP) applies to every identity in the accounts it targets, including users created later. This SCP blocks secrets access through any AWS managed MCP server across those accounts:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenySecretsViaMcp",
"Effect": "Deny",
"Action": ["kms:*", "secretsmanager:*", "ssm:GetParameter*"],
"Resource": "*",
"Condition": {
"Bool": { "aws:ViaAWSMCPService": "true" }
}
}
]
}

In the AWS console: open AWS Organizations → Policies → Service control policies (enable them if prompted), click Create policy, paste the JSON, and click Create policy. Then open the policy, go to Targets → Attach, and choose the accounts or organizational units.

With the AWS CLI, from the organization's management account:

aws organizations create-policy \
--name DenySecretsViaMcp \
--type SERVICE_CONTROL_POLICY \
--description "Block secrets access through AWS managed MCP servers" \
--content file://scp.json

aws organizations attach-policy \
--policy-id <policy-id> \
--target-id <account-id-or-ou-id>

Example 7: Allow only specific actions through the MCP server, even for administrators​

With OAuth, agents get the permissions of whoever signed in, which can be full administrator access. This policy denies every action except the listed ones when the call comes through the AWS MCP Server. An explicit Deny beats AdministratorAccess, so an administrator's agent can only do what's on the list, while the same administrator keeps full access in the console and CLI. The list below is the incident-investigation scope from Example 3; replace it with your own.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "OnlyTheseActionsViaAwsMcp",
"Effect": "Deny",
"NotAction": [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"logs:Describe*",
"logs:FilterLogEvents",
"logs:GetLogEvents",
"logs:StartQuery",
"logs:GetQueryResults",
"ec2:Describe*",
"ecs:Describe*",
"ecs:List*",
"sts:GetCallerIdentity"
],
"Resource": "*",
"Condition": {
"StringEquals": { "aws:CalledViaAWSMCP": "aws-mcp.amazonaws.com" }
}
}
]
}

Keep sts:GetCallerIdentity on the list so Which AWS identity am I using? still works. Signing in through OAuth doesn't go through the MCP server, so this policy never blocks sign-in. To cover every AWS managed MCP server, such as the EKS and ECS ones, use "Bool": { "aws:ViaAWSMCPService": "true" } as the condition instead.

Where you attach it decides who can remove it:

  • As a service control policy. Follow the steps in Example 6. It then applies to every identity in the target accounts, including administrators and the root user, and only the Organizations management account can change it. SCPs don't apply to the management account itself, and are limited to 5,120 characters; wildcards like ec2:Describe* keep the list short.
  • As an inline policy on an IAM Identity Center permission set or an IAM role. Use this for the management account, or without AWS Organizations. Anyone with IAM permissions, such as an administrator, can remove it from themselves.

For a permission set, with the AWS CLI:

aws sso-admin put-inline-policy-to-permission-set \
--instance-arn <instance-arn> \
--permission-set-arn <permission-set-arn> \
--inline-policy file://policy.json

aws sso-admin provision-permission-set \
--instance-arn <instance-arn> \
--permission-set-arn <permission-set-arn> \
--target-type ALL_PROVISIONED_ACCOUNTS

A permission set allows one inline policy. If it already has one, add this statement to it instead of replacing it.

Suggested combinations​

GoalPolicies
Let agents explore the account safelyExample 1 (ViewOnlyAccess) + Example 2
Let agents read data, but not secretsExample 1 (ReadOnlyAccess) + Example 2
Incident investigation in your production regionsExample 3 + Example 2 + Example 4
Use an identity that people or scripts also useThat identity's existing policies + Example 5
A guardrail that holds even if someone changes the user's policiesAny of the above + Example 6
OAuth, where people sign in with broad access such as administratorsExample 7, as an SCP where possible

Checking a policy before you rely on it​

Use the IAM policy simulator to see how AWS evaluates specific actions for the user. Open the IAM policy simulator, select the willow-aws-mcp user, and choose the actions to test, or run:

aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::<account-id>:user/willow-aws-mcp \
--action-names kms:Decrypt secretsmanager:GetSecretValue ec2:DescribeInstances

For Examples 1 through 4, you can also run the same calls with the user's access key from your terminal. Policies that check aws:CalledViaAWSMCP or aws:ViaAWSMCPService (Examples 5 and 7) only apply to requests made through the MCP server. To simulate those, pass the key the MCP server would add:

aws iam simulate-principal-policy \
--policy-source-arn <user-or-role-arn> \
--context-entries ContextKeyName=aws:CalledViaAWSMCP,ContextKeyValues=aws-mcp.amazonaws.com,ContextKeyType=string \
--action-names ec2:DescribeInstances s3:ListAllMyBuckets

Then confirm with your assistant, which runs the calls for real.

Configuration reference​

The awsSigV4 block in the MCP server's JSON configuration takes these fields. Set either roleArn, or accessKeyId and secretAccessKey.

FieldRequiredDescription
roleArnOne of theseIAM role Willow assumes, with your Organization ID as the external ID. The catalog's AWS server sets it when you fill in IAM role ARN.
accessKeyIdOne of theseIAM access key ID. Use a vault reference.
secretAccessKeyWith accessKeyIdIAM secret access key. Use a vault reference.
sessionTokenNoSession token, for temporary credentials. Temporary credentials expire, so prefer an IAM user's access key.
regionNoSigning region. Defaults to the region in the URL, for example us-east-1 for aws-mcp.us-east-1.api.aws.
serviceNoSigning service name. Defaults to the first part of the host, aws-mcp.

region and service can only be inferred from <service>.<region>.api.aws hosts. Other AWS managed MCP servers on that pattern, such as https://eks-mcp.us-west-2.api.aws/mcp, work with the same config. For any other host, set both explicitly.

The signing region is where the MCP server runs, not where your resources are. AWS's own proxy can set a default region for AWS operations; Willow doesn't send one, so operations default to us-east-1. Name the region in your prompt, for example List EC2 instances in eu-west-1, to work elsewhere.

Troubleshooting​

"Authentication failed: Unable to verify your user identity"

AWS received the request without a signature. Check that the configuration has an awsSigV4 block. Access keys passed as headers are never read by AWS.

"Willow could not assume arn:aws:iam::…: check that the role's trust policy allows Willow's role with sts:ExternalId …"

AWS refused to let Willow assume your role. Check the role's trust policy:

  • The Principal is the Willow role for your region, from Set up with an IAM role.
  • The sts:ExternalId value matches the ID in the error exactly. It's your Organization ID, not the slug.
  • The role ARN in Willow has no typo, and the role exists.

"awsSigV4.roleArn is not an IAM role ARN"

The value isn't a role ARN. It must look like arn:aws:iam::123456789012:role/willow-aws-mcp. A user ARN or a policy ARN doesn't work.

"awsSigV4.secretAccessKey references a vault secret that doesn't exist or has no value"

The vault reference didn't resolve. Check that the secret name in the configuration matches the name in Security Center → Vault exactly.

"Your AWS credentials are invalid or have expired" or UnrecognizedClientException

AWS doesn't recognize the key. It may have been deactivated or deleted, or the IAM user was deleted. Create a new access key, update the vault secrets, and see MCP Connection Failed After Secret Update.

ExpiredTokenException

The configuration uses temporary credentials (sessionToken) that have expired. Switch to an IAM user's access key, which doesn't expire, or refresh all three values.

"Credential should be scoped to correct service: 'aws-mcp'" or InvalidSignatureException

The signature doesn't match. Usually a service or region override doesn't match the endpoint; remove both and let Willow infer them from the URL. SigV4 also requires the signing clock to be within five minutes of AWS's.

A tool call fails with "no identity-based policy allows the … action"

No policy on the IAM role or user allows that action. If agents should be able to do it, add a policy that allows it.

A tool call fails with "explicit deny in an identity-based policy" or "explicit deny in a service control policy"

A deny policy blocked the action, as intended. The error says which kind of policy denied it.

"Start the Willow sign-in helper" when signing in with OAuth

Nothing on the person's computer is listening for the sign-in. Start the Willow Scan Agent, or run npx -y @mcp-s/mcp oauth-relay in a terminal, then click Try again. If the browser asks to let the site reach devices on your network, allow it.

A 400 error page from AWS after signing in with OAuth

The identity is missing signin:AuthorizeOAuth2Access or signin:CreateOAuth2Token. Attach AWSMCPSignInOAuthAccessPolicy, as in step 1 of the OAuth setup.

AWS asks to log you out of your current session when signing in with OAuth

The browser is already signed in to AWS as a different identity. Continuing signs that session out. To sign in as someone else without losing it, use a private browser window.

Notes​

  • The AWS MCP Server is published by AWS. Willow passes its tools through without modifying their behavior. To hide specific tools from agents, see Manage Tools.
  • AWS's proxy has a read-only mode that hides write-capable tools. Willow doesn't use it, so rely on IAM policies to block writes.
  • Every call appears in AWS CloudTrail under the role's session, the IAM user, or, with OAuth, the person who signed in.
  • With an IAM role or access key, all of your organization's assistants share one IAM identity per MCP server. For separate permissions per team, create a separate role and MCP server for each, or use OAuth so each person uses their own identity.