mcp-lambda-server

VPPATEL-SPS/mcp-lambda-server

3.1

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