How to Deploy MCP Servers on AWS Lambda Using MCPEngine: A Practical Guide for Serverless LLM Tools

Learn how to deploy secure, scalable MCP servers for LLM tools on AWS Lambda using MCPEngine—covering stateless and stateful tools, authentication, and best practices for real-world API teams.

INEZA Felin-Michel

INEZA Felin-Michel

16 January 2026

How to Deploy MCP Servers on AWS Lambda Using MCPEngine: A Practical Guide for Serverless LLM Tools

Modern AI workflows increasingly demand real-time, secure, and scalable ways for Large Language Models (LLMs) like Claude and ChatGPT to access external APIs and services. The Model Context Protocol (MCP) is emerging as a standard for defining structured tools that LLMs can use to fetch live data, execute actions, and interact with third-party systems beyond their static training data.

However, running MCP "servers" (which expose these tools to LLMs) in production can be challenging—especially in stateless, event-driven cloud platforms like AWS Lambda. Many early MCP implementations were built for local machines or persistent servers, relying on stateful protocols like stdio or Server-Sent Events (SSE), which don't natively fit the Lambda model.

This guide will show API and backend engineers how to deploy robust, production-ready MCP servers on AWS Lambda using MCPEngine, an open-source Python implementation designed for serverless environments. We’ll cover stateless tools, state management, authentication, and best practices for integrating with LLM clients.


💡 Tip: Want to make LLMs like Cursor, Cline, or Windsurf work directly with your live API documentation? Apidog MCP Server enables you to serve OpenAPI docs—online or from local files—so AI agents can generate code, search endpoints, and stay perfectly synced with your real API contract.


Why Serverless MCP? Challenges & Benefits

Common obstacles with traditional MCP servers:

Why use AWS Lambda for MCP?

MCPEngine bridges these gaps:


MCPEngine + Lambda: Core Components

Before jumping into code, let’s break down the essential MCPEngine concepts for Lambda deployment:


Example 1: Building a Stateless MCP Tool on Lambda

Let’s start simple: Deploy a stateless greeting tool to Lambda.

Prerequisites:

Step 1: Install MCPEngine

bash
pip install mcpengine[cli,lambda]

Step 2: Create Your Application (app.py)

python
from mcpengine import MCPEngine, Context

engine = MCPEngine()

@engine.tool()
def personalized_greeting(name: str) -> str:
"""
Generates a friendly greeting for the specified name.
Use this tool when asked to greet someone.
"""
return f"Hello, {name}! Welcome to the serverless MCP world."

The handler variable is what Lambda will invoke.

Step 3: Dockerize the Application

Dockerfile:

dockerfile
FROM public.ecr.aws/lambda/python:3.12

Note: List mcpengine[cli,lambda] in requirements.txt or install directly.

Step 4: Build and Push to ECR

Replace , , and with your values.

bash
aws ecr create-repository --repository-name <repo-name> --region <region>
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com

Step 5: Create and Configure Lambda Function

Create an execution role:

aws iam create-role --role-name lambda-mcp-role --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"},"Action": "sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name lambda-mcp-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Deploy Lambda:

aws lambda create-function \
--function-name mcp-greeter-function \
--package-type Image \
--code ImageUri=<account-id>.dkr.ecr.<region>.amazonaws.com/<repo-name>:latest \
--role arn:aws:iam::<account-id>:role/lambda-mcp-role \
--timeout 30 \
--memory-size 512 \
--region <region>

Step 6: Expose Lambda via Function URL

bash
aws lambda create-function-url-config \
--function-name mcp-greeter-function \
--auth-type NONE \
--region <region>

Your stateless MCP server is now live via the returned Function URL!


Example 2: Managing State with MCPEngine Lifespan

Many real-world tools need to maintain connections to databases or other resources. While Lambda is stateless, MCPEngine’s lifespan argument provides an async context manager to handle this.

Scenario: Log and retrieve events in a Postgres database (e.g., AWS RDS).

Step 1: Update app.py for Stateful Operation

python
import os
import psycopg2
from contextlib import asynccontextmanager
from mcpengine import MCPEngine, Context

DBHOST = os.environ.get("DBHOST")
DBUSER = os.environ.get("DBUSER")
DBPASS = os.environ.get("DBPASS")
DBNAME = os.environ.get("DBNAME")

@asynccontextmanager
async def dbconnectionmanager():
conn = None
try:
print("Establishing DB connection...")
conn = psycopg2.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASS,
dbname=DB_NAME
)
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE IF NOT EXISTS events (
id SERIAL PRIMARY KEY,
event_name TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT now()
);
""")
conn.commit()
print("DB connection ready.")
yield {"db_conn": conn}
finally:
if conn:
print("Closing DB connection.")
conn.close()

engine = MCPEngine(lifespan=dbconnectionmanager)

@engine.tool()
def logevent(eventname: str, ctx: Context) -> str:
try:
with ctx.db_conn.cursor() as cur:
cur.execute("INSERT INTO events (eventname) VALUES (%s)", (eventname,))
ctx.db_conn.commit()
return f"Event '{event_name}' logged successfully."
except Exception as e:
ctx.db_conn.rollback()
return f"Error logging event: {e}"

@engine.tool()
def getlatestevents(limit: int = 5, ctx: Context) -> list[str]:
try:
with ctx.db_conn.cursor() as cur:
cur.execute("SELECT event_name, timestamp FROM events ORDER BY timestamp DESC LIMIT %s", (limit,))
events = [f"[{row[1].strftime('%Y-%m-%d %H:%M:%S')}] {row[0]}" for row in cur.fetchall()]
return events
except Exception as e:
return [f"Error retrieving events: {e}"]

Deployment Considerations:


Example 3: Securing MCP Tools with Authentication

Production APIs should be protected. MCPEngine supports OpenID Connect (OIDC) providers such as Google, AWS Cognito, and Auth0.

Step 1: Configure Your OIDC Provider

Set up an OAuth client with your provider (e.g., Google Cloud Console) and obtain the Client ID.

Step 2: Update app.py for Authenticated Endpoints

python
import os
from mcpengine import MCPEngine, Context, GoogleIdpConfig

... dbconnectionmanager ...

google_config = GoogleIdpConfig(
clientid=os.environ.get("GOOGLECLIENT_ID")
)

engine = MCPEngine(
lifespan=dbconnectionmanager,
idpconfig=googleconfig
)

@engine.auth()
@engine.tool()
def logevent(eventname: str, ctx: Context) -> str:
user_email = ctx.user.email if ctx.user else "unknown"
print(f"Authenticated user: {user_email}")
try:
# ... database logic ...
return f"Event '{eventname}' logged successfully by {useremail}."
except Exception as e:
return f"Error logging event for {user_email}: {e}"

@engine.tool()
def getlatestevents(limit: int = 5, ctx: Context) -> list[str]:
# ... logic unchanged ...

Key Points:

Rebuild your image and redeploy as before.


Connecting LLM Clients to Your Lambda MCP Server

Once your MCP server is live, use mcpengine proxy to bridge LLMs like Claude:

bash
mcpengine proxy <service-name> <lambda-function-url> --mode http --claude

For authenticated endpoints:

bash
mcpengine proxy <service-name> <lambda-function-url> \
--mode http \
--claude \
--client-id <google-client-id> \
--client-secret <google-client-secret>

This proxy lets the LLM discover and invoke your MCP tools securely and seamlessly.


Apidog & MCP: Streamlining API-Driven AI Development

As LLM-augmented development becomes mainstream, connecting AI agents directly to live API documentation and contracts is essential for reliability and productivity.

How Apidog MCP Server Helps:

Learn more: Apidog MCP Server Documentation.


Conclusion

Deploying MCP servers on AWS Lambda with MCPEngine offers API engineers a scalable, secure, and truly serverless way to expose tools for LLMs. Unlike traditional MCP setups, MCPEngine’s Lambda-ready design, streaming HTTP support, and built-in authentication make it a practical foundation for production use—whether you’re building stateless helpers or complex, stateful APIs.

For engineering teams seeking even greater alignment between their API designs and AI-driven development, Apidog’s MCP Server bridges the gap—making it easy for LLMs to access, understand, and reliably work with your actual API documentation.

button

Explore more

How to Use Claude Code for CI/CD Workflows

How to Use Claude Code for CI/CD Workflows

Technical guide to integrating Claude Code into CI/CD pipelines. Covers container setup, GitHub Actions/GitLab CI integration, skill development, and practical workflows for DevOps automation.

21 January 2026

How to Use Claude Code Skills for API Request/Networking (data-fetching)

How to Use Claude Code Skills for API Request/Networking (data-fetching)

Technical guide to using Claude Code skills for API networking. Covers setup, core request patterns, advanced scenarios, and practical examples for building AI-driven data-fetching workflows.

21 January 2026

How to Use Claude Code Skills for Building UI

How to Use Claude Code Skills for Building UI

Technical guide to using Claude Code skills for UI development. Covers setup, core tools, advanced patterns, and debugging for building production-ready React/Vue/Svelte components.

21 January 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs