Skip to main content
Glama

Production MCP on AWS (Bedrock + EKS/GitOps)

A production-oriented Model Context Protocol (MCP) platform: an MCP server exposing tools, resources, and prompts over Streamable HTTP, secured with JWT authentication and per-tool RBAC, consumed by an Amazon Bedrock (Claude) client, and packaged for delivery on Amazon EKS via Helm, ArgoCD (GitOps), and GitLab CI/CD.

Architecture

Developer push -> GitLab CI/CD (test -> build image -> push to ECR -> bump tag in Git)
                                                                |
                                                                v
                                          ArgoCD (GitOps: watches Git, syncs to EKS)
                                                                |
                                                                v
   Bedrock Claude client --(JWT over HTTPS)--> ALB Ingress -> Service -> MCP server pods (HPA)
                                                                          |  IRSA
                                                                          v
                                                    AWS Secrets Manager (JWT key) + Bedrock
  • Authentication: JWT (signing key from AWS Secrets Manager), verified in middleware.

  • Authorization: per-tool RBAC (admin/user/guest), deny-by-default.

  • Transport: Streamable HTTP (remote MCP).

  • Scaling: multiple stateless pods behind a Service/ALB, autoscaled by HPA.

  • Security: no static keys — IRSA for pods, Secrets Manager for the signing key.

Related MCP server: production-grade-mcp-agentic-system

Repository layout

server/            MCP server + auth (JWT + RBAC)
client/            Bedrock Claude MCP client
scaling/           Round-robin load balancer (demonstrates LB internals)
deploy/Dockerfile  Container image
deploy/helm/       Helm chart (Deployment, Service, Ingress/ALB, HPA, IRSA SA)
deploy/argocd/     ArgoCD Application (GitOps)
.gitlab-ci.yml     CI/CD pipeline

Status: implemented vs design

Implemented and run locally

  • MCP server with tools, resources, and prompts (server/mcp_server.py)

  • JWT auth + per-tool RBAC with 401/403 handling (server/auth.py)

  • JWT signing key sourced from AWS Secrets Manager

  • Bedrock Claude client with tool discovery + tool-use execution (client/bedrock_client.py)

  • Round-robin load balancer with health checks (scaling/load_balancer.py)

  • Container image (deploy/Dockerfile) built and run locally

Delivered as config-as-code (validated with helm lint / YAML checks; deploy on a real EKS cluster)

  • Helm chart: Deployment, Service, ALB Ingress, HPA, IRSA ServiceAccount

  • ArgoCD Application (automated sync, prune, self-heal)

  • GitLab CI/CD (test -> build/push to ECR -> update image tag in Git)

Prerequisites

  • Python 3.12, an MCP-compatible environment (pip install -r requirements.txt)

  • AWS account with Bedrock (Claude) access

  • A secret in AWS Secrets Manager named mcp/jwt-signing-key

  • For deployment: an EKS cluster, ECR repo, AWS Load Balancer Controller, ArgoCD

Run locally

Create the JWT signing secret (one time):

aws secretsmanager create-secret \
  --name "mcp/jwt-signing-key" \
  --secret-string "$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')" \
  --region us-east-1

Start the server:

cd server
uvicorn mcp_server:app --host 0.0.0.0 --port 8000

Run the Bedrock client (role is optional: user | admin | guest):

cd client
python bedrock_client.py "What is 5 plus 59?" user
python bedrock_client.py "reset the counter" admin

/health is public (for probes); all MCP requests require a valid JWT, and tool calls are authorized per role.

Notes

  • Model ID and region are read from env (BEDROCK_MODEL_ID, BEDROCK_REGION) to avoid hardcoding a model that may be retired.

  • Secrets are never committed or baked into the image; they are fetched at runtime (Secrets Manager) and, in EKS, accessed via IRSA.

Related MCP Connectors

Related MCP Servers