Lambda MCP Server
README.md
# Lambda MCP Server Container
A stateless Python MCP server packaged as a custom AWS Lambda container image and exposed through an API Gateway HTTP API. It uses MCP Streamable HTTP at `/mcp`.
## Included tools
- `hello(name)` — returns a greeting
- `add(a, b)` — adds two numbers
- `current_time()` — returns the current UTC time
Add your own functions in `src/server.py` and decorate them with `@mcp.tool()`.
## Prerequisites
- Docker
- AWS CLI authenticated to your AWS account
## Test the Python tools
```powershell
py -3.12 -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements-dev.txt
pytest
```
## Build the Lambda image
Lambda is configured for ARM64 by default in these examples:
```powershell
docker buildx build --platform linux/arm64 --provenance=false -t lambda-mcp-server:latest --load .
```
For an x86_64 Lambda, use `--platform linux/amd64` instead.
## Test the container locally
Start the Lambda runtime emulator included in the AWS base image:
```powershell
docker run --platform linux/arm64 --rm -p 9000:8080 lambda-mcp-server:latest
```
Invoke it from another terminal with an API Gateway HTTP API v2 event:
```powershell
$body = '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
$event = @{
version = "2.0"
routeKey = "POST /mcp"
rawPath = "/mcp"
rawQueryString = ""
headers = @{ "content-type" = "application/json"; "accept" = "application/json, text/event-stream" }
requestContext = @{ http = @{ method = "POST"; path = "/mcp"; protocol = "HTTP/1.1"; sourceIp = "127.0.0.1"; userAgent = "local" }; requestId = "local"; routeKey = "POST /mcp"; stage = '$default'; time = ""; timeEpoch = 0 }
body = $body
isBase64Encoded = $false
} | ConvertTo-Json -Depth 10 -Compress
Invoke-RestMethod -Method Post -Uri http://localhost:9000/2015-03-31/functions/function/invocations -ContentType application/json -Body $event
```
## Push to Amazon ECR
Replace the variables with your AWS account details:
```powershell
$Region = "ap-south-1"
$AccountId = aws sts get-caller-identity --query Account --output text
$Repository = "lambda-mcp-server"
aws ecr create-repository --repository-name $Repository --region $Region
aws ecr get-login-password --region $Region | docker login --username AWS --password-stdin "$AccountId.dkr.ecr.$Region.amazonaws.com"
docker tag "lambda-mcp-server:latest" "$AccountId.dkr.ecr.$Region.amazonaws.com/${Repository}:latest"
docker push "$AccountId.dkr.ecr.$Region.amazonaws.com/${Repository}:latest"
```
Create or update a Lambda function using that image URI. Set its architecture to `arm64`, timeout to 30 seconds, and memory to at least 512 MB.
## API Gateway
Create an API Gateway **HTTP API** with Lambda proxy integration. Add an `ANY /mcp` route targeting the Lambda function, then grant API Gateway permission to invoke it. The MCP URL will look like:
```text
https://YOUR_API_ID.execute-api.ap-south-1.amazonaws.com/mcp
```
## Connect through AgentCore Gateway
Keep the Lambda image command as `src.server.handler` and expose the function through the API Gateway `ANY /mcp` route described above.
In Amazon Bedrock AgentCore Gateway, add an **MCP server target** using the full API Gateway endpoint:
```text
https://YOUR_API_ID.execute-api.ap-south-1.amazonaws.com/mcp
```
Use `DEFAULT` listing mode so AgentCore synchronizes the tools exposed by FastMCP. No separate tool-schema JSON is needed because AgentCore discovers the tools through MCP `tools/list`.
For initial testing you can use no outbound authorization. For production, configure IAM authorization on API Gateway and select IAM (SigV4) outbound authorization for the AgentCore target.
## Connect an MCP client
Configure a client that supports Streamable HTTP with the deployed output URL:
```json
{
"mcpServers": {
"lambda-tools": {
"url": "https://YOUR_API_ID.execute-api.ap-south-1.amazonaws.com/mcp"
}
}
}
```
## Production note
An unauthenticated API Gateway route is public. Before exposing tools that access private data or perform writes, add authentication at API Gateway (for example JWT/Cognito) and validate authorization in the application. Keep tools stateless, or store shared state in an external service such as DynamoDB.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues