Skip to main content

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 aws-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)

Source distribution for aws-lambda-mcp-server 0.1.14
File Size Uploaded
aws_lambda_mcp_server-0.1.14.tar.gz 71.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aws-lambda-mcp-server 0.1.14
File Interpreter ABI Platform
aws_lambda_mcp_server-0.1.14-py3-none-any.whl Python 3 none any Details

Total release size: 91.2 kB

Release files / aws_lambda_mcp_server-0.1.14.tar.gz

Download URL aws_lambda_mcp_server-0.1.14.tar.gz
Size 71.8 kB
Tags Source
SHA-256 checksum
How to use checksums
52cacb23239131008b0c1b88a6e8d5469eb2a602b579e8ab81701c3aacfd7b3c
BLAKE2b-256 checksum
How to use checksums
bc8ec8adf49a64f2cea06c3e78e80e225f1360c1a3c9f2196af44bcca3550cd6
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

Release files / aws_lambda_mcp_server-0.1.14-py3-none-any.whl

Download URL aws_lambda_mcp_server-0.1.14-py3-none-any.whl
Size 19.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8e0a80c03fbc026239852bf0fd7fc3eefd34e89eacaee4672cf9b1a525654a4a
BLAKE2b-256 checksum
How to use checksums
5f1932275a1c6cdfb878a9f3aad629cca1308a895521ccc310c13b6fb2cccdd9
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

Release history Release notifications | RSS feed

This release

0.1.14 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page