How we transformed Model Context Protocol servers into serverless Lambda functions for production AI agents
The Challenge
MCP servers are powerful but typically run as persistent processes. For production AI agents on AWS, we needed:
- Serverless scaling (0 to thousands of requests)
- Cost efficiency (pay per invocation)
- AWS integration (IAM, CloudWatch, VPC)
- Multi-tenant isolation
The Solution: MCP-to-Lambda Wrapper
We created a wrapper pattern that transforms any MCP server into a Lambda function while preserving full MCP protocol compatibility.
Architecture Pattern
AI Agent → Lambda Gateway → [MCP Lambda 1 | MCP Lambda 2 | MCP Lambda N]
AWS Docs Prometheus Custom Tools
Implementation Deep Dive
1. MCP Server Wrapper
# lambda_function.py
import json
from mcp_server import create_server
async def handler(event, context):
# Extract MCP request from Lambda event
method = event.get('method')
params = event.get('params', {})
# Initialize MCP server
server = await create_server()
# Route to appropriate MCP method
if method == 'tools/list':
result = await server.list_tools()
elif method == 'tools/call':
result = await server.call_tool(params['name'], params['arguments'])
return {
'statusCode': 200,
'body': json.dumps(result)
}
2. Gateway Router
# Multi-target gateway in AgentCore Runtime
async def route_mcp_request(tool_name: str, params: dict):
# Route based on tool prefix
if tool_name.startswith('aws-documentation-target___'):
lambda_name = 'mcp-server-aws-documentation'
clean_tool = tool_name.replace('aws-documentation-target___', '')
elif tool_name.startswith('prometheus-target___'):
lambda_name = 'mcp-server-prometheus-new'
clean_tool = tool_name.replace('prometheus-target___', '')
# Invoke Lambda with MCP payload
response = await lambda_client.invoke(
FunctionName=lambda_name,
Payload=json.dumps({
'method': 'tools/call',
'params': {'name': clean_tool, 'arguments': params}
})
)
return json.loads(response['Payload'].read())
Real-World Examples
AWS Documentation MCP → Lambda
**Original MCP server**
python -m mcp_server.aws_docs
**Wrapped as Lambda**
aws lambda invoke \
--function-name mcp-server-aws-documentation \
--payload '{"method":"tools/call","params":{"name":"search_documentation","arguments":{"search_phrase":"lambda"}}}' \
response.json
Prometheus MCP → Lambda
**Original MCP server**
python -m mcp_server.prometheus
**Wrapped as Lambda**
aws lambda invoke \
--function-name mcp-server-prometheus-new \
--payload '{"method":"tools/call","params":{"name":"ExecuteQuery","arguments":{"query":"up","workspace_id":"ws-123"}}}' \
response.json
Key Benefits Achieved
- Serverless Scaling
- Cold start: ~2-3 seconds for Python MCP servers
- Warm execution: ~100-500ms per tool call
- Auto-scaling: 0 to 1000+ concurrent executions
-
Cost Optimization
Traditional MCP Server: $50-100/month (always running)
Lambda MCP Wrapper: $5-15/month (pay per use)
Savings: 70-90% for typical SRE workloads
-
AWS Native Integration
- IAM roles for fine-grained permissions
- CloudWatch logs for debugging
- VPC integration for private resources
- X-Ray tracing for performance monitoring
Implementation Patterns
Memory Optimization by Use Case
**Documentation processing (heavy)**
aws lambda update-function-configuration \
--function-name mcp-server-aws-documentation \
--memory-size 2048
**Metrics queries (light) **
aws lambda update-function-configuration \
--function-name mcp-server-prometheus-new \
--memory-size 1024
The Result
We transformed traditional MCP servers into a serverless, scalable, cost-effective architecture:
- 8 MCP tools across 2 Lambda functions
- Sub-second response times for most queries
- 90% cost reduction vs always-on servers
- Production-ready monitoring and error handling
Key Takeaway
MCP servers + Lambda = Perfect match for production AI agents
The wrapper pattern preserves MCP protocol benefits while gaining serverless advantages. This approach scales from prototype to production without architectural changes.