mcp-lambda-server

VPPATEL-SPS/mcp-lambda-server

3.2

If you are the rightful owner of mcp-lambda-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The Model Context Protocol (MCP) server template is a reusable AWS SAM blueprint for deploying a server on AWS Lambda and API Gateway, featuring token-based authorization and customizable tools.

Tools
5
Resources
0
Prompts
0

Generic MCP Lambda Server Template

A reusable AWS SAM template and reference implementation for deploying a Model Context Protocol (MCP) server on AWS Lambda and API Gateway with token-based authorization. Use this generic blueprint to build and extend your own MCP tools, integrating custom business logic, data sources, or external APIs as needed.

✨ What's Included

  • AWS SAM / CloudFormation infrastructure (API Gateway, Lambda, optional DynamoDB table, session store)
  • pluggable token authorizer (simple bearer token)
  • Session persistence table (TTL-based)
  • Example tools (echo, add, utc_timestamp, optional DynamoDB sample)
  • Minimal dependency footprint

πŸ—‚ Project Structure

mcp-lambda-server/
β”œβ”€β”€ template.yml                # SAM infrastructure definition
β”œβ”€β”€ README.md                   # This guide
β”œβ”€β”€ authorizer/
β”‚   β”œβ”€β”€ app.py                  # Custom Lambda token authorizer
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ app.py                  # MCP server + example tools
β”‚   └── requirements.txt        # Python dependencies
└── examples/
    β”œβ”€β”€ simple_client.py        # Minimal MCP call example
    └── strands_client.py       # Interactive Strands Agent chat example

🧰 Example Tools Provided

ToolPurpose
echo(text)Returns the same text (connectivity sanity check)
add(a, b)Adds two numbers and returns a structured JSON result
utc_timestamp()Returns current UTC timestamp & ISO8601 string
list_items(limit)(Optional) Lists items from a demo DynamoDB table if configured
health()Basic server/config status

You can remove or extend these freely.

πŸ— Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   HTTPS (Bearer token)   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MCP Client  β”‚ ───────────────────────▢ β”‚ API Gateway  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚  (Authorizer)β”‚
                                         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                                                β”‚Invoke
                                         β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                         β”‚  Lambda (MCP)  β”‚
                                         β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                 β”‚ (optional)
                                         β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                         β”‚ DynamoDB Table β”‚
                                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ” Security Model

  • Simple bearer token (passed as Authorization: Bearer <token>) validated by a Lambda authorizer.
  • Token stored as a NoEcho CloudFormation parameter (not logged in plaintext).
  • Session table uses TTL for automatic cleanup.

βš™ Parameters (template.yml)

NameDescriptionDefaultRequired
McpAuthTokenBearer token clients must sendyour-secure-token-hereYes (change in prod)
CreateDemoTableCreate a sample DynamoDB table for list_items toolfalseNo
DemoTableNameName of existing or new table (if CreateDemoTable=true)McpDemoItemsConditionally

πŸ§ͺ Local Development (Option A: SAM CLI)

# From repo root (where template.yml resides)
cd mcp-lambda-server
sam build
sam local invoke McpServerFunction --event events/sample.json

You can craft a minimal invoke event (POST body) β€” see the awslabs.mcp_lambda_handler docs for request schema. Usually you'll deploy and call via HTTP instead.

πŸš€ Deployment

cd mcp-lambda-server
sam build
sam deploy \
  --stack-name generic-mcp-server \
  --capabilities CAPABILITY_IAM \
  --parameter-overrides \
    McpAuthToken="REPLACE_WITH_STRONG_TOKEN" \
    CreateDemoTable="true" \
    DemoTableName="McpDemoItems"

After deployment note the output McpApiUrl, e.g.:

https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/mcp

πŸ”Œ Connecting From GitHub Copilot (mcp.json)

Example entry:

{
  "servers": {
    "generic-mcp": {
      "url": "https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/mcp",
      "requestInit": {
        "headers": { "Authorization": "Bearer REPLACE_WITH_STRONG_TOKEN" }
      }
    }
  }
}

βž• Adding New Tools

In server/app.py:

@mcp_server.tool()
def my_new_tool(arg1: str) -> str:
    return json.dumps({"tool": "my_new_tool", "arg1": arg1})

Return plain strings or JSON-serialized strings. Keep responses concise & structured.

🧱 DynamoDB Demo Table Schema (Optional)

If CreateDemoTable=true, a PAY_PER_REQUEST table with partition key pk is created. You can manually insert sample items:

aws dynamodb put-item \
  --table-name McpDemoItems \
  --item '{"pk":{"S":"item#1"},"message":{"S":"Hello"}}'

Then call list_items(limit=25) via MCP client.

πŸ§ͺ Quick MCP Client Smoke Test (Python)

from mcp.client.streamable_http import streamablehttp_client
from strands.tools.mcp import MCPClient

API_URL = "https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/mcp"
TOKEN = "REPLACE_WITH_STRONG_TOKEN"

client = MCPClient(lambda: streamablehttp_client(
    url=API_URL,
    headers={"Authorization": f"Bearer {TOKEN}"}
))

with client:
    tools = client.list_tools_sync()
    print("Tools:", [t.name for t in tools])
    res = client.call_tool_sync("utc_timestamp", {})
    print(res.content[0].text)

πŸ‘©β€πŸ’» Minimal Direct Usage Example

(See examples/simple_client.py)

from mcp.client.streamable_http import streamablehttp_client
from strands.tools.mcp import MCPClient
import json

API_URL = "https://your-api.execute-api.us-east-1.amazonaws.com/Prod/mcp"
TOKEN = "YOUR_TOKEN"

client = MCPClient(lambda: streamablehttp_client(
    url=API_URL,
    headers={"Authorization": f"Bearer {TOKEN}"}
))

with client:
    for t in client.list_tools_sync():
        print("Tool:", t.name, t.description)
    # Call echo tool
    resp = client.call_tool_sync("echo", {"text": "hello"})
    print("echo β†’", resp.content[0].text)

πŸ—£ Interactive Strands Agent Chat Example

(See examples/strands_client.py) Uses a Bedrock model + discovered MCP tools.

Key steps:

  1. Build MCP client with bearer auth
  2. List tools
  3. Construct Agent(model=..., tools=tools)
  4. Read user input loop and invoke agent(user_text)

Environment requirements:

  • strands (and its Bedrock integration) & dependencies
  • Correct Bedrock model ID with region access

πŸ“ Example Scripts Summary

FilePurpose
examples/simple_client.pyMinimal list + call tool demonstration
examples/strands_client.pyInteractive chat loop with Strands Agent

🩺 Health & Troubleshooting

SymptomCheck
403 UnauthorizedEnsure header uses correct bearer token & matches deployed parameter
500 Error (tool)CloudWatch logs for McpServerFunction for stack traces
TimeoutIncrease Lambda timeout in Globals.Function.Timeout
Empty tool listConfirm correct URL path /mcp and POST method

Fetch logs quickly:

sam logs -n McpServerFunction --stack-name generic-mcp-server --tail

🧹 Maintenance

  • Update code β†’ sam build && sam deploy
  • Rotate token β†’ deploy new parameter, update all clients
  • Add tools β†’ modify server/app.py and redeploy

πŸ“„ License

Use freely in your org; validate security posture before production.


Feel free to tailor this template further for your specific domain logic (Jira, internal APIs, etc.).