DEV Community

Blessed Josiah
Blessed Josiah

Posted on AI-assisted

Build and Deploy a FastMCP Server to AWS EKS and Connect It to Claude Code

Model Context Protocol (MCP) lets AI clients connect to tools and external data sources through a consistent interface. Running an MCP server locally is useful during development, but what if you want to host one remotely?

In this tutorial, we'll deploy a Python weather MCP server built with FastMCP to Amazon EKS, expose it through a Kubernetes LoadBalancer Service, and connect it to Claude Code and Pydantic AI Agent.

What we're building

Our application follows this logical request flow:

Claude Code (MCP client)
        |
        | HTTP /mcp
        v
 AWS Load Balancer
        |
        v
 Kubernetes Service
        |
        +------------------+
        |                  |
        v                  v
   MCP Server Pod 1   MCP Server Pod 2
   Python :8000       Python :8000
        \                  /
         Amazon EKS worker nodes

Amazon ECR --> container image pulled by worker nodes
Enter fullscreen mode Exit fullscreen mode

The Deployment maintains two replicas of our application. Each pod runs one Python MCP server container, although Kubernetes pods can contain multiple containers. The Service gives those pods a stable network entry point and requests an AWS load balancer.

This is a logical diagram: the precise network path depends on how the AWS load balancer targets nodes or pods.

You can find the code on github.

Local Test

First we build the docker image for the demo project using:

docker build -t mcp-server:v1.0.0 .
Enter fullscreen mode Exit fullscreen mode

And run the application in a local container using:

docker run -p 3000:8000 --name weather-mcp-service mcp-server:v1.0.0
Enter fullscreen mode Exit fullscreen mode

To inspect the application on local use the MCP Inspector:

npx @modelcontextprotocol/inspector 
Enter fullscreen mode Exit fullscreen mode

Prerequisites

You'll need an AWS account with permissions (I'm using the AdministratorAccess) for ECR, EKS, and associated infrastructure, plus the AWS CLI, Docker with Buildx, eksctl, kubectl and Claude Code installed.

Cost reminder: EKS, EC2 instances, and load balancers can incur charges. Delete the demo resources when you're finished.

1. Sign in to AWS

I'm using an AWS SSO profile called demo:

export AWS_PROFILE=demo
aws sso login --profile demo
aws sts get-caller-identity
Enter fullscreen mode Exit fullscreen mode

The first command makes demo the active profile for this terminal session, so we don't need to add --profile to every AWS command.

2. Create an Amazon ECR repository

Amazon Elastic Container Registry (ECR) will store our Docker image.

aws ecr create-repository \
  --repository-name mcp-server \
  --region us-east-1
Enter fullscreen mode Exit fullscreen mode

Next, authenticate Docker to your ECR registry. Replace <AWS_ACCOUNT_ID> with the account ID returned by aws sts get-caller-identity:

aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com
Enter fullscreen mode Exit fullscreen mode

The Docker login target is the registry hostname, not the repository URL.

3. Build and push the Docker image

From the directory containing the application's Dockerfile, run:

docker buildx build \
  --platform linux/amd64 \
  -t <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/mcp-server:v1.0.0 \
  --push .
Enter fullscreen mode Exit fullscreen mode

I'm explicitly building for linux/amd64 because the demo uses x86-based EC2 instances, while development may happen on an Apple Silicon Mac. A .dockerignore file should exclude local files such as .venv/.

4. Provision an EKS cluster

Create eksctl-cluster.yaml:

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: mcp-cluster
  region: us-east-1
managedNodeGroups:
  - name: mcp-nodes
    instanceType: t3.medium
    desiredCapacity: 2
    minSize: 1
    maxSize: 3
Enter fullscreen mode Exit fullscreen mode

Then create the cluster and check the worker nodes:

eksctl create cluster -f eksctl-cluster.yaml
kubectl get nodes
Enter fullscreen mode Exit fullscreen mode

This provisions an EKS cluster with a managed node group initially targeting two EC2 instances. The minimum and maximum values define scaling limits; they don't install an autoscaler by themselves.

5. Deploy the MCP server

Kubernetes uses a Deployment to maintain the desired number of application pods. Create deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mcp-server-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mcp-server
  template:
    metadata:
      labels:
        app: mcp-server
    spec:
      containers:
        - name: mcp-server
          image: <AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/mcp-server:v1.0.0
          ports:
            - containerPort: 8000
Enter fullscreen mode Exit fullscreen mode

Replace <AWS_ACCOUNT_ID> before applying it. The MCP application must listen on 0.0.0.0:8000 inside its container.

kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get pods -o wide
Enter fullscreen mode Exit fullscreen mode

To follow the logs from both replicas:

kubectl logs -f -l app=mcp-server \
  --all-containers=true \
  --prefix=true
Enter fullscreen mode Exit fullscreen mode

Notice that we can inspect the pods and their logs before creating a Service. The Service is for stable networking and exposure; it doesn't create the pods.

6. Expose the application

Create service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: mcp-server-service
spec:
  type: LoadBalancer
  selector:
    app: mcp-server
  ports:
    - port: 80
      targetPort: 8000
Enter fullscreen mode Exit fullscreen mode

Apply it:

kubectl apply -f service.yaml
kubectl get svc
Enter fullscreen mode Exit fullscreen mode

Wait for an AWS hostname to appear under EXTERNAL-IP. The Service selects pods with the app: mcp-server label and makes the application available through the load balancer.

7. Connect Claude Code to the remote MCP server

Copy the load balancer hostname from the previous command. Then, from your project directory, run:

claude mcp add weather \
  --scope project \
  --transport http \
  http://<LOAD_BALANCER_HOSTNAME>/mcp
Enter fullscreen mode Exit fullscreen mode

This registers the already deployed MCP server with Claude Code under the name weather. It doesn't install another copy of the server on your machine.

Check the configuration:

claude mcp list
claude mcp get weather
Enter fullscreen mode Exit fullscreen mode

Inside Claude Code, use /mcp to inspect the connection. Then ask a weather-related question that your server's tools support and see Claude Code invoke the remote MCP tool.

Important: Public HTTP is appropriate only for a controlled demo. For production, use HTTPS, authentication/authorization, and appropriate network restrictions before exposing MCP tools.

8. Clean up

When you're finished, delete the EKS cluster:

eksctl delete cluster -f eksctl-cluster.yaml
Enter fullscreen mode Exit fullscreen mode

Check that the associated AWS load balancer and other cluster resources have been removed. ECR is separate, so the repository and its images remain until you delete them:

aws ecr delete-repository \
  --repository-name mcp-server \
  --region us-east-1 \
  --force
Enter fullscreen mode Exit fullscreen mode

Only run that final command if you want to permanently delete the repository and its images.

Final thoughts

We've taken a Python MCP server from a local application to a remotely accessible service running on Kubernetes. Along the way, we used Docker to package it, ECR to store the image, EKS to run two replicas, and a LoadBalancer Service to expose it to Claude Code.

This is a demo architecture, not a production-hardened setup, but it gives you a practical foundation for hosting your own MCP tools in AWS.

Thanks for watching! Subscribe to the channel for more content like this.

Happy coding! 🚀

Top comments (0)