A quick and dirty MCP server on AWS Lambda

23/6/2025

Model Context Protocol is all the rage right now. In this post I will demonstrate a simple and definitely not production-ready way to deploy your MCP server to Lambda.

Some requirements before we get started:

  • an AWS account
  • Docker
  • Python 3.13
  • Terraform (optional, but highly recommended)

The Dockerfile:

FROM public.ecr.aws/docker/library/python:3.13-rc-slim-bullseye

COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.1 /lambda-adapter /opt/extensions/lambda-adapter

COPY . ${LAMBDA_TASK_ROOT}

COPY requirements.txt .

RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}" -U --no-cache-dir

EXPOSE 8080

CMD ["python", "main.py"]

This is pretty much all standard stuff, with he exception of the aws-lambda-adapter line, which we’ll need to handle the streaming part, since it’s not currently supported for python out of the box.

The server (main.py):

# main.py

from mcp.server.fastmcp import FastMCP

from tools import get_user_repos
import logging


logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)

mcp = FastMCP(
    name="Serverless MCP",
    host="0.0.0.0",
    port=8080,
    stateless_http=True,
    json_response=True,
)


@mcp.tool(name="List Github User's Public Repos")
async def list_repos(username: str):
    """Retrieves a list of a given Github user's public repositories

    Args:
        - username

    Returns:
        - List of Github repositories
    """
    return get_user_repos(username)


if __name__ == "__main__":
    logger.info("Starting mcp server...")
    mcp.run(transport="streamable-http")

Setting stateless_http=True and stateless_http=True are important here, to make the server play nice with AWS Lambda.

For tools, the sky is the limit. Here’s a simple one that uses the github API to fetch a user’s public repos:


# tools.py
import requests


def get_user_repos(username: str):
    url = f"https://api.github.com/users/{username}/repos"
    try:
        data = requests.get(
            url,
            headers={
                "Accept": "application/vnd.github+json",
                "X-GitHub-Api-Version": "2022-11-28",
            },
        )
        return data.json()
    except Exception as e:
        raise Exception(f"Failed to fetch repositories: {e}")

That’s pretty much it. The only thing left is to set up an AWS Lambda function with response streaming enabled. This can be achieved either by using Terraform through the AWS Console. If using Terraform, you can define the Lambda function resource with the appropriate settings for response streaming. Alternatively, in the AWS Console, you can create a new Lambda function, upload the Docker image to an ECR repository, and enable response streaming in the function’s configuration. You’ll also need a function URL to be able to connect to the server.

Important: Make sure you add the following environment variables to your Lambda function to help the aws-lambda-adapter do its thing:

AWS_LWA_INVOKE_MODE = "RESPONSE_STREAM"
AWS_LWA_PORT        = 8080 # or whatever port you expose in your Dockerfile

You can test it with the MCP Inspector :

In your MCP server directory, run:

uv run mcp dev main.py

You will see something like this:

 uv run mcp dev main.py
Starting MCP inspector...
⚙️ Proxy server listening on 127.0.0.1:6277
🔑 Session token: a435aa85241700929aef5959756ddc57a63132de3fd7abf011f4ab821d964b12
Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth

🔗 Open inspector with token pre-filled:
   http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=a435aa85241700929aef5959756ddc57a63132de3fd7abf011f4ab821d964b12
   (Auto-open is disabled when authentication is enabled)

🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀

Copy the session token, go to the url, paste it under Configuration > Proxy Session Token

For transport type select Streamable HTTP and then paste the Lambda Function url into the URL input field. As of this writing, you’ll need to append /mcp/ to the end of the url for things to work. Your url should look something like: https://blahblah.lambda-url.eu-central-1.on.aws/mcp/

And now, for the big finale:

demo

Full code: https://github.com/dmitkov28/mcp-aws-lambda