MCP Server on AWS ECS

From Local to Cloud: Deploying MCP Server on AWS ECS with Ease

Deploying an intelligent tool-based server like MCP (Model Context Protocol) on the cloud opens doors to scalable, production-grade AI workflows. In this tutorial, you’ll learn exactly how to containerize and deploy your own FastMCP-powered MCP Server on AWS ECS (Elastic Container Service) using a lightweight, efficient stack—including FastAPI, Docker, UV, and ECR.

Prerequisites

Before jumping into the tutorial, let’s quickly set up a few things you’ll need. Make sure you’ve got the following ready:

  1. AWS CLI

Since we’re going to deploy on AWS, make sure you have set everything up on your machine with your configuration. If you haven’t done that yet, feel free to follow this tutorial to get started.

  1. Docker For Desktop

Make sure you also have Docker installed on your machine. This will be used to dockerize your application.

  1. UV for Python

UV is a super-fast Python package installer, so go ahead and install it from here.

Creating a Sample MCP Server

For the demo purpose, we are going to create an MCP server with weather and additional tools using FastMCP.

If you’re new to FastMCP or UV and want to learn how to build an MCP server and client with it, I highly recommend checking out this article first before jumping into the deployment process.

Here, I’ll initialize the project using UV.

PS D:\\mcp_demo> uv init 
PS D:\\mcp_demo> uv venv 
PS D:\\mcp_demo> .\\.venv\\Scripts\\activate #for windows

source .venv/bin/activate #For Mac or Linux

Installing the necessary packages.

uv add fastmcp requests fastapi

Now, set up the MCP server in main.py.

#import packages
from fastmcp import FastMCP
import requests
from fastapi import FastAPI

#initiate instance of MCP
mcp = FastMCP(name= "Hello MCP")

#create tools
@mcp.tool()
def add(x:str,y:str):
    """Adds two numbers"""

    return x + y

@mcp.tool()
def get_weather_by_city(city_name: str):
    """
    Fetches current weather information for a given city using OpenStreetMap Nominatim and Open-Meteo APIs.
    Returns a dictionary with temperature, windspeed, and weather code.
    """
    # Step 1: Get latitude and longitude from city name
    geo_url = "<https://nominatim.openstreetmap.org/search>"
    geo_params = {"q": city_name, "format": "json", "limit": 1}
    geo_resp = requests.get(geo_url, params=geo_params, headers={"User-Agent": "weather-app"})
    if geo_resp.status_code != 200 or not geo_resp.json():
        return {"error": "City not found"}
    geo_data = geo_resp.json()[0]
    lat, lon = geo_data["lat"], geo_data["lon"]

    # Step 2: Fetch weather using Open-Meteo
    weather_url = (
        "<https://api.open-meteo.com/v1/forecast>"
        f"?latitude={lat}&longitude={lon}&current_weather=true"
    )
    weather_resp = requests.get(weather_url)
    if weather_resp.status_code == 200:
        return weather_resp.json().get("current_weather", {})
    else:
        return {"error": f"Failed to fetch weather: {weather_resp.status_code}"}

#Wrap it in FastAPI
mcp_app = mcp.http_app(path='/mcp')

app = FastAPI(lifespan=mcp_app.lifespan)
app.mount('/mcp-server',mcp_app)

#add healthcheck endpoint
@app.get('/health')
def health_check():
    return {"status":"healthy"}

if __name__=='__main__':
    #Make sure transport is streamable-http.It is mandatory for running MCP remotely. 
    #transport = 'stdio' is suitable for local MCP.
    mcp.run(transport="streamable-http",host='0.0.0.0')

Our demo server is now ready! If you’d like to test whether it’s working, you can do so using AWS Strands or LangGraph. Check out this article to learn how to run the test.

Create a Dockerfile for Deployment

Now, we’ll create a Docker file. That includes all the necessary commands to build a Docker image for our MCP server. So, create a file name Dockerfile and put the following content.

FROM --platform=linux/arm64 python:3.12-slim-bookworm

COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

WORKDIR /code

COPY pyproject.toml uv.lock /code/

RUN uv sync

COPY . /code/

EXPOSE 8000

ENTRYPOINT ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Now, build the Docker image using the following command. I am creating the image with the name mcp.

PS D:\\mcp_demo> docker buildx build --platform linux/arm64 -t mcp .  

As you can see, I’m building the image for the arm64 Linux architecture, since AWS ECS is compatible with arm64 instances.

Testing Docker Image(Optional)

If you want to test out your created Docker Image, run the following command.

PS D:\\mcp_demo> docker run -p 8000:8000 mcp     

This command should run the uvicorn, and you will be able to see your app on HTTP://localhost:8000.

Create a Repository on ECR

Now to push the image to AWS ECR. Follow these instructions:

Step 1: Go to Amazon ECR on AWS.

Step 2: Go to Repositories and click on Create Repository

Creating Repository on ECR

Give the name to your repository. I am giving mine as mcp.

Step 4: Now, follow the Push commands and push your Docker image to ECR.

NOTE that we have already built the docker image above, that’s why skip the 3rd point(docker build -t mcp .) .

After following the push commands, you will be able to see your Docker image on ECR.

Create a Task Definition

Now we’re ready to create a task definition and set up a cluster for it on AWS ECS.

Step 1: Go to Task Definitions on Amazon Elastic Container Service and click on Create new task definition

Step 2: Give your task a name. Here I am giving my task name mcp_task . The Infrastructure requirements are as follows.

Since we’ve built the image for ARM64, the operating system will match that architecture. Here, I’m using 1 vCPU and 2GB of RAM, as the MCP server tool is lightweight and doesn’t require heavy processing.

Enter your ECR image URI and assign a name to your container. In the Port Mappings section, make sure to specify the port 8000, as that’s the port exposed by the Docker image.

Step 3: Click on Create

Now that we’ve successfully created the task definition for our MCP server, let’s go ahead and create a cluster and run the task as a service.

Create a Cluster and Task on ECS

Step 1: Go to Clusters and create one cluster with the default settings.

Step 2: Go inside a created cluster and click on create inside the Services tab.

Step 3: Select the name of your task definition from the dropdown. (mine is mcp_task).

Creating a ECS service for MCP server on AWS ECS

Since I don’t need load balancing or any additional configurations, I’ll create the service using the default settings. However, feel free to customize the setup based on your server’s requirements.

Now your ECS service is ready. Now go to your task’s configuration tab and grab the public IP. (Get the IP of the Load balance if you have used it.). Open it with 8000 port and see the \\docs . You will be able to see our health API there.

MCP server on AWS ECS

If you’re unable to access the URL, make sure to double-check the inbound and outbound rules in your security group. Ensure that all traffic is allowed.

Test Our Deployed MCP Server on ECS

For testing, I’ll use the AWS Strands library to create an MCP client and connect it to the public IP of the MCP server on AWS ECS instance.

Install it if you haven’t done it.

uv pip install strands-agents
from mcp.client.streamable_http import streamablehttp_client
from strands.tools.mcp import MCPClient
from strands import Agent

streamable_http_mcp_client = MCPClient(lambda: streamablehttp_client("<http://0.0.0.0:8000/mcp-server/mcp>")) #replace the URL with your ECS public IP

with streamable_http_mcp_client:
   agent = Agent(model="us.anthropic.claude-3-5-sonnet-20241022-v2:0",tools=streamable_http_mcp_client.list_tools_sync())
   response = agent("Tell me the weather of New York. Also add 5 celsius in the temprature and give me the resultant temprature.") 
## OUTPUT
I'll help you get the weather in New York and then add 5 to the temperature. Let me break this down into steps:

1. First, let's get the weather for New York:
Tool #1: get_weather_by_city
2. Now, let's add 5 to the current temperature of 30.7°C:
Tool #2: add
Current weather in New York:
- Temperature: 30.7°C
- Wind Speed: 8.7 m/s
- Weather Code: 3 (partly cloudy)

After adding 5°C to the current temperature:
The resultant temperature would be 35.7°C

As you can see, it’s giving the output from our hosted MCP server on AWS ECS.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top