MCP Lambda Handler
A Python library for building serverless Model Context Protocol (MCP) HTTP servers on AWS Lambda. Register tools and resources using decorators, plug in session storage, and drop the handler into any Lambda function.
Installation
pip install aws-lambda-mcp-server
Quick Start
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server", version="1.0.0")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
def lambda_handler(event, context):
return mcp.handle_request(event, context)
Tools
Type hints become the input schema automatically
from typing import Optional
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server")
@mcp.tool()
def search_products(
query: str,
max_results: int,
category: Optional[str],
) -> str:
"""Search the product catalogue.
Args:
query: Search keywords
max_results: Maximum number of results to return
category: Optional category filter
"""
# ... your logic here
return f"Found results for: {query}"
Supported types: str, int, float, bool, List[T], Dict[str, T], Optional[T], and Enum.
Enum parameters
from enum import Enum
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server")
class Environment(Enum):
DEV = "dev"
STAGING = "staging"
PROD = "prod"
@mcp.tool()
def deploy(service: str, env: Environment) -> str:
"""Deploy a service to an environment.
Args:
service: Name of the service to deploy
env: Target environment
"""
return f"Deploying {service} to {env.value}"
Returning images
Return bytes from a tool and the handler automatically base64-encodes them as an image content block. JPEG, PNG, GIF, and WebP are auto-detected.
import boto3
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server")
@mcp.tool()
def get_chart(metric: str) -> bytes:
"""Generate a chart for a metric and return it as an image.
Args:
metric: The metric name to chart
"""
s3 = boto3.client("s3")
obj = s3.get_object(Bucket="my-charts", Key=f"{metric}.png")
return obj["Body"].read()
Resources
Static resource
from awslabs.mcp_lambda_handler import MCPLambdaHandler
from awslabs.mcp_lambda_handler.types import StaticResource
mcp = MCPLambdaHandler(name="my-mcp-server")
mcp.add_resource(StaticResource(
uri="config://app/settings",
name="App Settings",
content='{"timeout": 30, "retries": 3}',
description="Application configuration",
mime_type="application/json",
))
File resource
from awslabs.mcp_lambda_handler import MCPLambdaHandler
from awslabs.mcp_lambda_handler.types import FileResource
mcp = MCPLambdaHandler(name="my-mcp-server")
mcp.add_resource(FileResource(
uri="docs://openapi",
path="/var/task/openapi.yaml",
name="OpenAPI Spec",
description="API specification",
))
Resource decorator (dynamic content)
import json
import boto3
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server")
@mcp.resource(
uri="data://live-config",
name="Live Config",
description="Config fetched from Parameter Store at read time",
mime_type="application/json",
)
def live_config():
ssm = boto3.client("ssm")
value = ssm.get_parameter(Name="/myapp/config")["Parameter"]["Value"]
return value
Session Management
Stateless (default)
No session store is configured — each request is independent. Session IDs are still issued but nothing is persisted.
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server")
DynamoDB sessions
Pass a DynamoDB table name to enable persistent sessions with a 24-hour TTL.
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(
name="my-mcp-server",
session_store="mcp-sessions", # DynamoDB table name
)
Or use DynamoDBSessionStore directly:
from awslabs.mcp_lambda_handler import MCPLambdaHandler
from awslabs.mcp_lambda_handler.session import DynamoDBSessionStore
mcp = MCPLambdaHandler(
name="my-mcp-server",
session_store=DynamoDBSessionStore(table_name="mcp-sessions"),
)
Reading and writing session data from a tool
from awslabs.mcp_lambda_handler import MCPLambdaHandler
mcp = MCPLambdaHandler(name="my-mcp-server", session_store="mcp-sessions")
@mcp.tool()
def increment_counter() -> str:
"""Increment the per-session counter."""
session = mcp.get_session()
count = session.get("count", 0) + 1 if session else 1
mcp.update_session(lambda s: s.set("count", count))
return f"Count is now {count}"
@mcp.tool()
def get_counter() -> str:
"""Get the current per-session counter value."""
session = mcp.get_session()
count = session.get("count", 0) if session else 0
return f"Count: {count}"
Custom session backend
Subclass SessionStore to use any storage backend:
from typing import Any, Dict, Optional
from awslabs.mcp_lambda_handler import MCPLambdaHandler
from awslabs.mcp_lambda_handler.session import SessionStore
import uuid
class RedisSessionStore(SessionStore):
def __init__(self, redis_client):
self.redis = redis_client
def create_session(self, session_data: Optional[Dict[str, Any]] = None) -> str:
session_id = str(uuid.uuid4())
self.redis.setex(session_id, 86400, json.dumps(session_data or {}))
return session_id
def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
data = self.redis.get(session_id)
return json.loads(data) if data else None
def update_session(self, session_id: str, session_data: Dict[str, Any]) -> bool:
self.redis.setex(session_id, 86400, json.dumps(session_data))
return True
def delete_session(self, session_id: str) -> bool:
self.redis.delete(session_id)
return True
mcp = MCPLambdaHandler(
name="my-mcp-server",
session_store=RedisSessionStore(redis_client),
)
Example Architecture
A typical deployment looks like:
Client → API Gateway (/mcp)
│
├── Lambda Authorizer (validates bearer token)
│
└── MCP Lambda (this library)
│
└── DynamoDB (optional session store)
The Lambda function receives API Gateway proxy events and returns proxy responses — no extra configuration needed.
Development
git clone https://github.com/awslabs/mcp.git
cd mcp/src/mcp-lambda-handler
pip install -e ".[dev]"
pytest
License
Apache-2.0 — see LICENSE.
Metadata
Release files for lambda-mcp-server 0.1.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lambda_mcp_server-0.1.14.tar.gz | 71.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lambda_mcp_server-0.1.14-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 91.2 kB
Release files / lambda_mcp_server-0.1.14.tar.gz
| Download URL | lambda_mcp_server-0.1.14.tar.gz |
|---|---|
| Size | 71.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
20593d0996a97294c17979eef34f360ca753c2f13ff26cce4a7e8becebbf90d9
|
|
BLAKE2b-256 checksum How to use checksums |
b70722d9507ef51534bbb53d1e7c57b5c475fd803af9a9fdb16088cd4033adf2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 1, 2026.
Transparency logRelease files / lambda_mcp_server-0.1.14-py3-none-any.whl
| Download URL | lambda_mcp_server-0.1.14-py3-none-any.whl |
|---|---|
| Size | 19.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e333e92fcae7b27c05cebe219d6f0de738fe3b7c0e362d74ed10a753edee2a91
|
|
BLAKE2b-256 checksum How to use checksums |
5dc89755129e6815d8abca28919153cbed2f9b2b3b6d68fe9093376abbabe554
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 1, 2026.
Transparency log