Skip to content

VPPATEL-SPS/mcp-lambda-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

Tool Purpose
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)

Name Description Default Required
McpAuthToken Bearer token clients must send your-secure-token-here Yes (change in prod)
CreateDemoTable Create a sample DynamoDB table for list_items tool false No
DemoTableName Name of existing or new table (if CreateDemoTable=true) McpDemoItems Conditionally

🧪 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

File Purpose
examples/simple_client.py Minimal list + call tool demonstration
examples/strands_client.py Interactive chat loop with Strands Agent

🩺 Health & Troubleshooting

Symptom Check
403 Unauthorized Ensure header uses correct bearer token & matches deployed parameter
500 Error (tool) CloudWatch logs for McpServerFunction for stack traces
Timeout Increase Lambda timeout in Globals.Function.Timeout
Empty tool list Confirm 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.).

About

This repo contains the mcp lambda server example

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages