Skip to main content

Command Palette

Search for a command to run...

Read on: MCP on AWS Lambda

Updated
4 min read
Read on: MCP on AWS Lambda

Read more (Technical): https://blog.raeveen.dev/serverless-mcp-on-aws-lambda-using-go

The Model Context Protocol (MCP) is rapidly becoming the "USB-C for AI," allowing LLMs to seamlessly interface with local and remote tools. However, most MCP implementations rely on persistent connections (SSE) or local processes (stdio). What if you want to host your MCP server in a scalable, cost-effective cloud environment without managing a 24/7 server?

Enter Serverless MCP. By leveraging AWS Lambda and a specialized HTTP streaming bridge, we can deploy robust AI tools that only cost money when they are actually being called.

The Challenge: Stdio vs. The Cloud

MCP servers usually communicate in two ways:

  1. Stdio: Great for local use (e.g., Claude Desktop), but impossible to host as a web service.

  2. SSE (Server-Sent Events): The standard for remote MCP, but problematic for AWS Lambda because Lambda is inherently stateless and struggles with long-lived streaming connections without complex workarounds.

The mcp-http-streamer project solves this by providing a lightweight wrapper that adapts MCP’s JSON-RPC over HTTP, making it compatible with serverless request/response cycles while maintaining the ability to stream tool outputs.

Architecture Overview

The setup involves three main components:

  1. The MCP Server: Your core logic (Typescript/Python) using the standard MCP SDK.

  2. The Streamer Bridge: A layer that converts incoming HTTP POST requests into the JSON-RPC format the MCP server expects.

  3. AWS Lambda + API Gateway: The hosting environment that triggers your code on-demand.

Why Serverless MCP?

  1. Zero-Scale: Pay $0 when your AI isn't using the tools.

  2. Security: Use AWS IAM and Lambda Authorizers to ensure only your specific AI agent can access your private data or tools.

  3. Scale: If your AI agent needs to perform 100 parallel data lookups, Lambda scales instantly to handle the load.


Implementation Guide

To build this, we use the official aws-lambda-go SDK alongside an MCP server implementation.

  1. Defining the MCP Server

    First, we set up the basic structure to handle tool definitions.

     package main
    
     import (
         "context"
         "encoding/json"
         "github.com/aws/aws-lambda-go/events"
         "github.com/aws/aws-lambda-go/lambda"
     )
    
     // MCPRequest represents the standard JSON-RPC 2.0 structure
     type MCPRequest struct {
         Method string          `json:"method"`
         Params json.RawMessage `json:"params"`
         ID     interface{}     `json:"id"`
     }
    
     func HandleRequest(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
         var mcpReq MCPRequest
         if err := json.Unmarshal([]byte(request.Body), &mcpReq); err != nil {
             return events.APIGatewayProxyResponse{StatusCode: 400}, nil
         }
    
         // Logic to route MCP methods (e.g., tools/call, tools/list)
         switch mcpReq.Method {
         case "tools/list":
             return handleListTools()
         case "tools/call":
             return handleCallTool(mcpReq.Params)
         default:
             return events.APIGatewayProxyResponse{StatusCode: 404}, nil
         }
     }
    
     func main() {
         lambda.Start(HandleRequest)
     }
    
  2. Handling Tool Execution

    Go's struct tags make it incredibly easy to define the schemas that the LLM needs to understand your tool.

     type GetWeatherArgs struct {
         Location string `json:"location"`
     }
    
     func handleCallTool(params json.RawMessage) (events.APIGatewayProxyResponse, error) {
         var args GetWeatherArgs
         json.Unmarshal(params, &args)
    
         // Your tool logic here
         result := fmt.Sprintf("The weather in %s is 72°F and sunny.", args.Location)
    
         responseBody, _ := json.Marshal(map[string]interface{}{
             "result": map[string]interface{}{
                 "content": []map[string]string{
                     {"type": "text", "text": result},
                 },
             },
         })
    
         return events.APIGatewayProxyResponse{
             StatusCode: 200,
             Body:       string(responseBody),
             Headers:    map[string]string{"Content-Type": "application/json"},
         }, nil
     }
    

Why Go for Serverless MCP?

  1. Cold Start Performance: Go binaries are compiled to machine code. Unlike Node.js or Python, which have to parse scripts at startup, Go Lambdas typically start in under 10ms. This is vital for AI UX where latency is already high.

  2. Type Safety: MCP relies heavily on specific JSON-RPC structures. Go’s strong typing ensures your tool schemas are strictly followed.

  3. Single Binary: Deployment is a simple .zip file containing one executable. No node_modules or virtual environments required.

Deployment Tips

When deploying your Go MCP server to AWS:

  1. Use Function URLs: For the simplest setup, use AWS Lambda Function URLs to get an HTTPS endpoint without the overhead of API Gateway.

  2. Memory Settings: Since Go is efficient, you can often run these functions at the minimum memory setting (128MB), keeping costs extremely low.

  3. Security: Always implement a simple Authorization header check within your Go code to ensure only your specific AI client (like Claude or a custom frontend) can trigger your tools.

Conclusion

By porting the mcp-http-streamer philosophy to Go, you get a production-ready, ultra-fast toolset for your AI agents. You pay nothing when the tools aren't in use, and you get lightning-fast execution when they are.

#go #mcp #ai #agents #serverless #aws #docker

AWS

Part 1 of 6

In this series, I will help you uncover tips and tricks within AWS. The tips shared will be beneficial for you to start your cloud or hacking journey!

Up next

Technical: Serverless MCP on AWS Lambda using Go

Growth vs. Savings. Gain++