SafetyCard Request a review

AWS API MCP Server

MCP server letting agents run arbitrary AWS CLI commands

github.com/awslabs/mcp › src/aws-api-mcp-server · 2026-10-03 · 93991b8

Defense-in-depth score

4.5 / 10

As shipped, this server runs any AWS API the model asks for, with the operator's own AWS credentials and no confirmation, including IAM changes, deletions and remote shell commands through SSM. AWS IAM is the only real limit, so deploy it with a scoped-down role. The opt-in read-only mode and per-write consent are well built, mapping every request to AWS's own permission data and failing closed, but both are off by default. File access is confined to a working directory by default, and there is no local shell.

Safest setup

As shipped, the server runs any AWS operation the model asks for with your own credentials and no confirmation, so AWS IAM is the real boundary. It parses commands without a shell and keeps local file arguments inside a working directory, and its read-only and consent modes are well built but off by default. The safest setup starts with a scoped role and turns those modes on.

SetupHowWhat it gives you
A scoped-down AWS roleSet AWS_API_MCP_PROFILE_NAME to a profile whose role allows only the actions and resources the task needs, and run the server where that is the only profile configuredAWS itself refuses anything outside that role, whichever command or profile the model picks C1
Remote execution left outGrant SSM Run Command, CloudFormation and Lambda actions in that role only when the task needs themModel-written scripts and templates have no route to run in your account C4
Read-only modeREAD_OPERATIONS_ONLY=true in the server's environmentEvery operation AWS classes as a write is refused before it runs, and unknown services fail closed C1
Per-write consentFor tasks that need writes, REQUIRE_MUTATION_CONSENT=true with a client that supports elicitationA person sees the exact CLI command before each write runs, and a client that can't ask refuses the call C2
A denylist of operationsList operations the task never needs under denyList in mcp-security-policy.json in ~/.aws/aws-api-mcpThose operations are blocked outright, ahead of every other mode C3
A dedicated working directoryKeep the default workdir for AWS_API_MCP_ALLOW_UNRESTRICTED_LOCAL_FILE_ACCESS with AWS_API_MCP_WORKING_DIR set to a directory for this task, or no-access when no local files are neededLocal file arguments stay inside one directory you chose for the task C3
An AWS-side audit trailTurn on AWS CloudTrail for the account and regions the role can reachA record of every call with its parameters and identity, kept where the server can't change it C9

Approving with confidence

  • Read each consent prompt and approve calls one at a time; it shows the exact CLI command, so check the account, region and resources it names.
  • Calls AWS classes as read-only run without a prompt, including token-minting ones such as eks get-token, so scope the role to keep those within what the task needs.

Handling data

  • AWS responses reach the model unredacted, including any secret it reads; treat the conversation like the data it touched.
  • The server log in ~/.aws/aws-api-mcp records only service and operation; CloudTrail holds the detail.
  • AWS_API_MCP_TELEMETRY=false leaves the client name and configuration flags out of the AWS User-Agent.

Key gaps (4)

  1. Default policy allows every AWS operation, so the model can modify the server's own IAM permissions or mint new access keys (C1-SELFESC). C1 · Identity & least privilege
  2. The server acts with the operator's full ambient AWS authority, unscoped (C1 blast radius L0). C1 · Identity & least privilege
  3. Model-written code reaches remote execution (SSM RunCommand, CloudFormation deploy, Lambda) with the operator's credentials and no isolation (C4 blast radius L0). C4 · Code-execution isolation
  4. A hijacked session can exfiltrate data through AWS and take irreversible actions with no human step in the default configuration (C5-WORSTCASE). C5 · Untrusted input blast radius

Criteria

C1 Identity & least privilege

0.38 / 1.00

The server runs every AWS call with the operator's ambient credentials (the boto3 default chain or a configured profile), and the model may switch to any other locally configured profile with --profile. By default there is no authorization layer: every operation, including IAM changes to the server's own identity, is allowed. An opt-in read-only mode maps each request to AWS's own Service Authorization data and denies writes, failing closed on unknown services or fetch errors, but it still lets the model mint EKS, ECR and RDS tokens and pick a more privileged profile. IAM policy on the operator's credentials is the only real bound.

C2 Approval gates

0.45 / 1.00

Everything goes through one call_aws tool that mixes reads and writes; by default it is simply annotated destructive, so the host must gate every call because it can't tell reads from writes. The server offers an opt-in consent mode that, for every operation AWS classes as a write, shows the user the exact CLI command through MCP elicitation and refuses if the client can't ask. It is off by default, and when it is off every AWS action, including deletes and terminations, runs without any server-side confirmation. AWS actions cannot be rolled back by the server.

C3 Tool & action scoping

0.42 / 1.00

call_aws is a general tool: any AWS API in any region with the operator's credentials. Inputs are parsed as AWS CLI syntax, not passed to a shell. The parser checks parameters against the service schema, rejects --debug, --no-verify-ssl and --no-sign-request, only allows loopback --endpoint-url values, and limits CLI customizations to an allowlist that spawns no subprocesses. Local file arguments are confined by default to a working directory using resolved paths. Files referenced indirectly (for example artefacts listed inside a CloudFormation template) are not confined, and nothing limits which AWS resources or quantities a call may touch.

C4 Code-execution isolation

0.00 / 1.00

The server has no local shell or eval: model output is parsed into AWS API calls, and the CLI customizations it allows spawn no subprocesses. It does, however, forward model-written code for execution in the operator's AWS account (SSM RunCommand shell scripts, CloudFormation deploys, Lambda code, EC2 user data), all allowed by default with no isolation boundary and the operator's credentials. The opt-in unrestricted file-access mode also does not confine local execution.

C5 Untrusted input blast radius

0.25 / 1.00

The server returns AWS data, including content anyone with write access to the account's resources can control (S3 objects, log events, tags, queue messages), as structured JSON with the command, service, operation and region attached, but with nothing marking it as untrusted. In the default configuration a hijacked model can both read sensitive data and act on it: copy data to an external bucket or topic, mint credentials, or delete resources, all without a human step. The opt-in read-only and consent modes narrow this, but they are off by default.

C6 Memory, context & configuration integrity

N/A · full credit 1.00 / 1.00

The server keeps no memory and loads no context from the working directory. Its only configuration files are environment variables and a user-scope policy file in ~/.aws/aws-api-mcp, which the model cannot write in the default working-directory file mode because of resolved-path containment. Opt-in unrestricted file access would let the model overwrite that file.

C7 Third-party extensions

N/A · full credit 1.00 / 1.00

The server loads no plugins, MCP servers, packages or model files at runtime. Remote data it fetches (AWS service-reference documents and command suggestions from an AWS endpoint) is data, not code. Opt-in agent scripts are markdown read from a directory the operator chooses. The AWS CLI's own [plugins] config section in ~/.aws/config is user scope and outside this server's code.

C8 Secrets & sensitive-data protection

0.20 / 1.00

The server never puts its own AWS keys into model context or logs, and its execution log deliberately omits command parameters. But credentials are held in a plain model with no masking, the suggest tool logs the user's query verbatim, and AWS responses go to the model unredacted, including secrets the model asks for (Secrets Manager values, SSM SecureString parameters, new IAM access keys, which are allowed by default). Telemetry is on by default. It sends no content, only the MCP client name, version and configuration flags in the AWS User-Agent.

C9 Audit & traceability

0.38 / 1.00

The server writes a loguru log to ~/.aws/aws-api-mcp/aws-api-mcp-server.log (10 MB rotation, 7-day retention), outside the working directory. Each executed command is recorded only as service and operation; parameters are deliberately left out. Policy denials and user consent decisions go back to the client as errors, not into the server log. Nothing records which user or client made a call, and nothing protects the log from tampering, so an incident can be traced to operations but not to the exact resources touched or who approved them.

C10 Limits & kill switch

0.45 / 1.00

The server caps a batch at 20 commands and sets 10-second connect and 60-second read timeouts with three retries on each AWS call. Pagination is unbounded unless the caller passes max_results, and --region * multiplies each command across every enabled region. There is no rate limit, no session budget, no limit on how many resources a call creates, and no way to cancel an in-flight call.