SafetyCard Request a review

Amazon EKS MCP Server

MCP server for EKS cluster management and Kubernetes resources

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

Defense-in-depth score

4.7 / 10

With no flags this server is read-only: every tool that could change a cluster, deploy a CloudFormation stack, or edit IAM refuses in code, and logs, events and Secret reads are withheld. But it runs on the operator's full ambient AWS identity, its tools carry no risk annotations, and the README's own install buttons switch on both --allow-write and --allow-sensitive-data-access. Once they're on, the model can delete Kubernetes objects, deploy any CloudFormation template with IAM capability, and attach any IAM policy to any role, with no confirmation. Even in the default, the sensitive-data gate does not cover every path.

Safest setup

With no flags, Amazon EKS MCP Server is read-only and withholds logs and events, but it acts with your full ambient AWS identity, and the README's install examples turn both protections off. The safest setup keeps the code defaults and gives the server a narrow, read-only identity of its own.

SetupHowWhat it gives you
A read-only AWS identityPoint AWS_PROFILE at a dedicated role that holds only read permissions for EKS, CloudWatch and IAMAWS itself refuses writes, so safety no longer rests on the server's own read-only check C1
Narrow Kubernetes accessMap that role to a view-only Kubernetes access entry on just the clusters and namespaces the task needsReads stay inside the namespaces you chose instead of every cluster your account reaches C3
Read-only modeKeep the default --allow-write off, leaving it out of the install config the README suggestsEvery tool that could change a cluster, a CloudFormation stack or IAM refuses in code C1
Sensitive data access offKeep the default --allow-sensitive-data-access offPod logs, events and CloudWatch logs stay out of the model's context C8
Provider-side audit logsTurn on CloudTrail for the account and control-plane audit logging for each cluster the role reachesA durable record of every call the server's identity makes, kept outside the server C9
Server output keptHave your MCP host write the server's stderr to a file outside the workspaceThe server's per-request action lines and refusals outlive the session C9

Approving with confidence

  • Read each prompt and approve calls one at a time; manage_k8s_resource and manage_eks_stacks handle reads and writes under one name, so check the operation before approving.
  • If you turn on --allow-write, deletes, stack deploys and IAM policy changes run with no confirmation of their own, so the host prompt is the only check.

Handling data

  • Results can carry ConfigMaps, pod specs and IAM role policies; treat session transcripts like the cluster data they hold.
  • The server logs to stderr at the library's debug default, including any proxy URL; keep that stream out of shared logs.

Key gaps (1)

  1. Every AWS and Kubernetes call uses the operator's full ambient identity (README recommends IAMFullAccess for writes), so once the read-only check is off or bypassed nothing confines what the server can do, including adding arbitrary IAM policies to any role. C1 · Identity & least privilege

Criteria

C1 Identity & least privilege

0.40 / 1.00

The server signs every AWS and Kubernetes call with the operator's own ambient credentials: the boto3 default chain or AWS_PROFILE, and for Kubernetes a token minted from that same identity for whatever cluster name the model supplies. Nothing narrows the credential itself. What the server does have is a deterministic read-only switch, on by default, that every mutating tool checks before touching a client, so the default server can only describe and list. Pass --allow-write, as every README install example does, and the model can create or delete any Kubernetes object, deploy CloudFormation stacks with IAM capability, and attach arbitrary inline policies to any IAM role, including the server's own.

C2 Approval gates

0.33 / 1.00

The server owns no approval loop, so it is rated on what it gives the host. No tool carries read-only or destructive annotations, and two tools (manage_k8s_resource and manage_eks_stacks) mix read and write operations behind one name, so a host cannot tell a describe from a delete. There is no dry-run or preview. What protects the default install is the server-enforced read-only mode: with no flags, no tool can change anything. With --allow-write, deletes, stack deploys and IAM policy changes run immediately with no server-side confirmation.

C3 Tool & action scoping

0.38 / 1.00

The tools are broad. manage_k8s_resource performs any CRUD operation on any kind in any namespace of any cluster the model names; apply_yaml applies any manifest file; manage_eks_stacks deploys any CloudFormation template file with IAM capability; and add_inline_policy accepts arbitrary policy statements for any role. File paths are resolved and checked only against a short denylist of sensitive directories, and the app-manifest generator pastes unvalidated values (image, namespace, CPU, memory) into YAML by string replacement. The default read-only mode keeps the write tools inert, but the read tools still reach every resource kind across every reachable cluster.

C4 Code-execution isolation

0.15 / 1.00

The server never runs a shell, eval, or subprocess locally. It can, however, have model-chosen code run elsewhere: apply_yaml and manage_k8s_resource can create pods with any image and any security context, and manage_eks_stacks deploys any CloudFormation template with IAM capability in the operator's account. There is no isolation around any of these. The only thing standing in the way is the read-only default: without --allow-write none of these paths runs.

C5 Untrusted input blast radius

0.55 / 1.00

Tool results come back as a short status line plus a JSON document carrying the cluster, namespace, kind, and name each result came from, kept separate from instructions; the troubleshooting search returns the remote service's text verbatim. Nothing marks content as untrusted, and resource annotations, ConfigMaps and pod specs, which anyone who can edit cluster objects controls, reach the model as plain data. The defaults drop two risky legs: logs and events are withheld, and nothing can be changed. A hijacked host agent can still read sensitive cluster data through this server, but cannot use it to act or send data out.

C6 Memory, context & configuration integrity

N/A · full credit 1.00 / 1.00

The server keeps no memory, conversation store, or retrieval index and reads no instruction or configuration files from the working directory. Its configuration comes only from command-line flags and environment variables (auth mode, AWS profile, region, KUBECONFIG path), all set by the operator. Cluster objects the model writes and later reads back are untrusted input, covered in C5.

C7 Third-party extensions

N/A · full credit 1.00 / 1.00

The server loads no plugins, launches no MCP servers or subprocesses, installs no packages, and deserializes no model files. Container images and CloudFormation templates the model asks it to deploy run in the cluster or AWS account and are scored under C4 and C3.

C8 Secrets & sensitive-data protection

0.30 / 1.00

The server never puts its own AWS credentials or Kubernetes token into tool output; the Kubernetes token is minted from the ambient identity and cached for 14 minutes. A sensitive-data flag, off by default, withholds pod logs, events, CloudWatch logs and Secret reads. But it is only a gate on a few tool paths: its enforcement is not complete, pod and deployment specs with plaintext environment values are readable, and nothing is redacted anywhere. Logging goes through an unconfigured loguru logger, which emits debug lines (including any proxy URL) to stderr.

C9 Audit & traceability

0.33 / 1.00

Each tool writes free-text log lines prefixed with the MCP request ID, naming the operation and target (for example 'Deleted Pod ns/name') and recording write-mode and sensitive-data refusals as errors. The logger is never configured, so lines go to stderr at the library's default level, and FASTMCP_LOG_LEVEL, which the README sets, is not read. Nothing is written to a file, arguments such as patch bodies or policy statements are not recorded, nothing identifies the requesting user, and nothing protects the record from tampering.

C10 Limits & kill switch

0.25 / 1.00

The server bounds little of its own work. Pod logs default to the last 100 lines and 10 KB, CloudWatch queries to 50 entries, but the caller can raise each. Resource listing has no limit, Kubernetes and knowledge-base HTTP calls have no timeout, and the CloudWatch poll loop calls a blocking sleep inside an async handler for up to 60 attempts, leaving the query running when it gives up. There is no rate limit or cancellation.