AWS API Gateway transport adapter for mcpbytes-lambda-core
Project description
mcpbytes-lambda-apigw
Production-ready AWS API Gateway transport adapter for Model Context Protocol (MCP) servers. Seamlessly converts between HTTP requests and MCP JSON-RPC with enterprise-grade authentication and CORS handling.
๐ Quick Start
from mcpbytes_lambda.core import MCPServer
from mcpbytes_lambda.apigw import ApiGatewayAdapter
# Create your MCP server with tools
mcp = MCPServer(name="my-server", version="1.0.0")
@mcp.tool(name="example.tool")
def my_tool(message: str) -> str:
return f"Processed: {message}"
# Zero-boilerplate Lambda handler
def lambda_handler(event, context):
adapter = ApiGatewayAdapter()
return adapter.handle(event, mcp) # That's it!
โจ Features
- ๐ Smart Authentication - Auto-detects Lambda Authorizers, supports custom token validation
- ๐ CORS Compliance - Full preflight handling with configurable origins
- ๐ก MCP Streamable HTTP - Compliant with MCP 2025-06-18 transport specification
- โก High Performance - Optimized for AWS Lambda cold starts and execution
- ๐ก๏ธ Input Validation - JSON-RPC 2.0 validation with detailed error responses
- ๐ Production Logging - Structured logging for debugging and monitoring
- ๐ Base64 Support - Automatic handling of API Gateway base64 encoding
๐ Authentication
The API Gateway adapter provides flexible authentication with smart auto-detection:
Authentication Flow
- Lambda Authorizer Detection: Auto-detects and uses existing Lambda Authorizer context
- Token Format Validation: Validates Bearer token format when auth is required
- Custom Validation: Executes custom token validation logic (if provided)
- User Context Access: Provides unified access to authentication context
Usage Patterns
Lambda Authorizer (Auto-detected)
def lambda_handler(event, context):
adapter = ApiGatewayAdapter(require_auth=True)
user_info = adapter.get_user_context(event) # From Lambda Authorizer
return adapter.handle(event, mcp_server)
Custom Token Validation
import jwt
from typing import Dict, Any, Union
def validate_jwt_token(token: str) -> Union[Dict[str, Any], bool]:
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return {"user_id": payload["sub"], "role": payload["role"]}
except jwt.InvalidTokenError:
return False
def lambda_handler(event, context):
adapter = ApiGatewayAdapter(require_auth=True, token_validator=validate_jwt_token)
user_info = adapter.get_user_context(event) # From custom validator
return adapter.handle(event, mcp_server)
โ๏ธ Configuration
adapter = ApiGatewayAdapter(
cors_origin="https://myapp.com", # CORS origin header
require_auth=True, # Enable authentication
auth_header="Authorization", # Auth header name
token_validator=my_custom_validator # Custom validation function
)
Parameters:
cors_origin: CORS origin header value (default: "*")require_auth: Whether to require Bearer token authentication (default: False)auth_header: Header name for authentication token (default: "Authorization")token_validator: Optional custom token validation function- Should return
Dict[str, Any]for user context on success - Should return
Falsefor explicit rejection - Should return
Truefor acceptance without context - May raise exceptions for validation errors
- Should return
๐ Requirements
- Python 3.12+
mcpbytes-lambda-corepackage- AWS API Gateway Lambda Proxy Integration
- Bearer token authentication (via Lambda Authorizer or custom validation)
๐๏ธ Architecture
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ API Gateway โโโโโถโ APIGW Adapter โโโโโถโ MCP Core โ
โ HTTP Request โ โ (Transport) โ โ JSON-RPC โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Authentication โ โ
โ โ CORS Handling โ โ
โ โ Error Mapping โ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โผ โผ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ HTTP Response โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ Tool Results โ
โ (200/500) โ โ JSON-RPC โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
๐ ๏ธ Usage Examples
Basic Lambda Handler
def lambda_handler(event, context):
adapter = ApiGatewayAdapter()
return adapter.handle(event, mcp)
Lambda Authorizer Integration
def lambda_handler(event, context):
adapter = ApiGatewayAdapter(require_auth=True)
# Access user context from Lambda Authorizer
user_info = adapter.get_user_context(event)
if user_info:
print(f"User: {user_info.get('principalId')}")
return adapter.handle(event, mcp)
JWT Token Validation
import jwt
import os
from typing import Dict, Any, Union
from mcpbytes_lambda.core.exceptions import AuthenticationError
def validate_jwt(token: str) -> Union[Dict[str, Any], bool]:
try:
payload = jwt.decode(token, os.environ["JWT_SECRET"], algorithms=["HS256"])
return {
"user_id": payload["sub"],
"email": payload["email"],
"role": payload.get("role", "user")
}
except jwt.ExpiredSignatureError:
raise AuthenticationError("Token has expired")
except jwt.InvalidTokenError:
return False
def lambda_handler(event, context):
adapter = ApiGatewayAdapter(
require_auth=True,
token_validator=validate_jwt
)
user_context = adapter.get_user_context(event)
return adapter.handle(event, mcp)
Multi-Server Routing
# Route to different MCP servers based on path
def lambda_handler(event, context):
path = event.get("path", "")
if path.startswith("/math"):
server = math_mcp_server
elif path.startswith("/weather"):
server = weather_mcp_server
else:
server = default_mcp_server
adapter = ApiGatewayAdapter(require_auth=True)
return adapter.handle(event, server)
๐ก MCP Protocol Compliance
Streamable HTTP Transport (2025-06-18)
โ
HTTP POST for JSON-RPC requests/notifications/responses
โ
HTTP GET for optional Server-Sent Events (SSE) streams
โ
Proper status codes: 200 OK, 202 Accepted, 4xx/5xx errors
โ
MCP-Protocol-Version header support
โ
Bearer token authentication (RFC 6750)
โ
Session management with Mcp-Session-Id
โ
CORS preflight handling
โ
Content negotiation (application/json + text/event-stream)
Lambda Limitations
โ Server-Sent Events (SSE) streaming not supported
โ Real-time server-to-client notifications not supported
โ HTTP GET for stream initiation not supported
โ Stream resumability not supported
For full streaming support, deploy as a long-running server process.
Required Headers
Client must send:
POST /your-endpoint HTTP/1.1
Content-Type: application/json
Accept: application/json, text/event-stream #BOTH headers
Authorization: Bearer <token> #if needed/enabled
MCP-Protocol-Version: 2025-06-18 / multiple supported
Server responds with:
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: https://example.com
JSON-RPC Format
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "example.tool",
"arguments": {"message": "Hello MCP!"}
},
"id": "request-1"
}
๐ Error Handling
HTTP Status Codes
- 200 OK - CORS preflight successful, JSON-RPC requests processed
- 400 Bad Request - Malformed requests, unsupported protocol versions
- 401 Unauthorized - Missing or invalid Bearer token
- 403 Forbidden - Origin not allowed (CORS violation)
- 406 Not Acceptable - Accept header doesn't include required content types
- 415 Unsupported Media Type - Content-Type is not application/json
- 500 Internal Server Error - JSON-RPC error or server failure
JSON-RPC Error Codes
# Standard JSON-RPC 2.0 error codes
-32700 # Parse error (invalid JSON)
-32600 # Invalid request (missing method, bad headers)
-32601 # Method not found
-32602 # Invalid params
-32603 # Internal error
๐ก๏ธ Security Best Practices
Authentication Strategies
-
Lambda Authorizer (Recommended for production)
- Centralized authentication logic
- Automatic caching and performance optimization
- Built-in AWS integration
-
Custom Token Validation
- Flexible validation logic
- Support for JWT, API keys, custom tokens
- Direct integration with your auth system
Environment Variables
# Production CORS configuration
ALLOWED_ORIGINS="https://example.com,https://app.example.com"
# JWT Secret for token validation
JWT_SECRET="your-secret-key"
# Development (allows all origins - not recommended for production)
# ALLOWED_ORIGINS="" # Empty = allow all
API Gateway Setup
# SAM Template example
Resources:
McpApi:
Type: AWS::Serverless::Api
Properties:
Cors:
AllowMethods: "'POST,OPTIONS'"
AllowHeaders: "'Content-Type,Authorization,MCP-Protocol-Version'"
AllowOrigin: "'*'" # Override with adapter's origin validation
Auth:
DefaultAuthorizer: TokenAuth
Authorizers:
TokenAuth:
FunctionArn: !GetAtt AuthFunction.Arn
๐ Deployment
SAM Template
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
McpFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: .
Handler: handler.lambda_handler
Runtime: python3.12
Environment:
Variables:
ALLOWED_ORIGINS: "https://myapp.com,https://admin.myapp.com"
JWT_SECRET: !Ref JWTSecret
Events:
McpApi:
Type: Api
Properties:
Path: /mcp
Method: any
CDK Deployment
from aws_cdk import aws_lambda as lambda_
from aws_cdk import aws_apigateway as apigw
lambda_function = lambda_.Function(
self, "McpFunction",
runtime=lambda_.Runtime.PYTHON_3_12,
handler="handler.lambda_handler",
code=lambda_.Code.from_directory("src/"),
environment={
"ALLOWED_ORIGINS": "https://myapp.com",
"JWT_SECRET": jwt_secret.secret_value_from_json("secret").to_string()
}
)
api = apigw.RestApi(self, "McpApi")
api.root.add_proxy(default_integration=apigw.LambdaIntegration(lambda_function))
๐ค Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes and add tests
- Run tests:
python -m pytest - Submit a pull request
๐ License
Apache 2.0 License - see LICENSE for details.
๐ Related Packages
mcpbytes-lambda-core- Transport-agnostic MCP server coremcpbytes-lambda-stdio- Stdio transport adapter
๐ Documentation
Built with โค๏ธ for the MCP ecosystem
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcpbytes_lambda_apigw-0.1.0.tar.gz.
File metadata
- Download URL: mcpbytes_lambda_apigw-0.1.0.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d7a7ab9b6c8f756932434040bbaf1e48fd4890876860a27b416a4618441b4f1
|
|
| MD5 |
9c06147b3df8cbefe0febf49a927ba94
|
|
| BLAKE2b-256 |
b1dc24f3010e1cfaab9b2b19351f468eb8d89269fc201ffe25a5dedebe6d7a56
|
File details
Details for the file mcpbytes_lambda_apigw-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcpbytes_lambda_apigw-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
90f56a4c555355e5d5a6e833a947482d36d71d50be38d0630e62800373075ea5
|
|
| MD5 |
7c4662574dab5d4eb96f12956d2af46d
|
|
| BLAKE2b-256 |
f918c24e58daf0561b7e4878f678c5ebc18379a27706d0922c89f41707f10729
|