TL;DR: Go to this repo for the SAM template

TL;DR: Go to this repo for a CLI to start with your next serverless MCP server

Hey devs 👋, if you saw my first two post in this series about building a minimal Model Context Protocol server with AWS Lambda using the Serverless Framework, this is the natural follow-up for those who prefer using AWS Serverless Application Model (SAM).

The post on how to deploy an MCP server in a serverless environment was particularly well received and even got featured in two outstanding newsletters: Serverless Developer Advocate #33 by Lee Gilmore and Ready, Set, Cloud #160 by Allen Helton. I highly recommend subscribing to both as they’re packed with insights and inspiration for serverless enthusiasts!

Also the. second post of this series was cited in Serverless Developer Advocate #34 by Lee Gilmore. I can't be happier about this community feedback.

Why SAM?

In my latest post I've shown to you this omparison table between Serverless Framework, AWS SAM and AWS CKD. Again: read it carefully before choosing your preferred way to do IaC in your project.

Feature / Tool Serverless Framework AWS SAM (Serverless Application Model) AWS CDK (Cloud Development Kit)
Ownership V3 independent (deprecated), V4 enterprise, OSS alternative to V4 AWS AWS
Abstraction Level High-level Medium-level Low to medium-level
Language YAML + plugins (JavaScript/TS) YAML + some scripting TypeScript, Python, Java, C#, Go
Cloud Provider Support Multi-cloud (AWS, Azure, GCP, etc) AWS only AWS only
Template Syntax Custom syntax (serverless.yml) CloudFormation-compatible YAML Imperative (code-based)
Local Development Good support via plugins Good (via sam local) Limited, depends on constructs
Deployment CLI-driven CLI-driven (sam deploy) CLI-driven (cdk deploy)
State Management Built-in via .serverless folder CloudFormation CloudFormation
Extensibility High (plugins, hooks) Moderate (some hooks/plugins) High (custom constructs, reusable code)
Maturity Very mature Mature Rapidly growing
Best For Multi-cloud serverless apps Simple AWS Lambda apps Complex infrastructure-as-code on AWS
Learning Curve Low to moderate Low Moderate to high
Testing/Debugging Plugin-based sam local invoke/start-api Manual / unit tests on code
CI/CD Integration Easy (via plugins or custom) Easy (via CodePipeline or custom) Easy (via CodePipeline or custom)
Cost V3 Free, V4 pricing Free Free

So, why pick AWS SAM over Serverless Framework and CDK?

  1. SAM is built and maintained by AWS. That means native integration for services like Lambda, API Gateway, DynamoDB, and integrations with CloudFormation, CloudWatch, and CodeDeploy out of the box. No need for external plugins or workarounds to make things “just work.”
  2. Designed only for serverless, unlike CDK, which is general purpose infrastructure as code. As an example: In CDK, to create an API Gateway connected to a Lambda function, you’ll write TypeScript or Python code that explicitly defines routes, integrations, permissions, and deploy stages, in SAM this is really simple with a couple of line of code.
  3. Local dev & testing is very powerful: SAM CLI lets you run Lambda functions locally and mock API Gateway events. This feels more like traditional dev workflows, which is something CDKdon’t handle as smoothly, while Serverless Framework require serverless offline plugin.
  4. Simpler learning curve than CDK, as CDK is powerful but verbose. You’re writing imperative code to describe declarative infrastructure. That’s cool, but not always necessary for serverless apps. SAM keeps things simple, YAML based, and readable across different teams: devs, ops, or whoever knows it.

So if you're building pure serverless apps on AWS: SAM it’s native, lightweight, and focused on serverless. CDK shines when you’re managing AWS infrastructure, but when your app is 90% serverless API based on Lambda, SAM is just way faster to learn.

📦 What’s Inside the Repo

This project spins up as the previous one:

  • An AWS Lambda function hosting a serverless MCP server
  • An Amazon API Gateway with a POST /mcp route

🛠️ Features

Our goal is always to have a skeleton to deploy our MCP server in a serverless environment, but using AWS SAM.

  • Simple MCP server with just a few lines of code
  • Runs in a single AWS Lambda function
  • HTTP POST endpoint at /mcp
  • Local development
  • Comes with a basic “add” tool (yeps, just adds two numbers via JSON-RPC: here you should put your endpoint logic!)

📦 Project Structure

We add template.yml, samconfig.toml and buildspec.yml respectively as our resource template, configuration (useful for deploy) and CI/CD pipiline build phase.

sam-serverless-mcp-server/
├── __tests__/              # Jest tests
├── src/                    # Source code
│   └── index.js                # MCP server handler
├── .gitignore              # Git ignore file
├── buildspec.yml           # Buildspec file for AWS CodeBuild and CodePipeline (CI/CD)
├── jest.config.mjs         # Jest config file
├── package.json            # Project dependencies
├── package-lock.json       # Project lock file
├── README.md               # This documentation file
├── samconfig.toml          # Serverless Application Model config
└── template.yml            # Serverless Application Model template

🏗️ SAM code

You can easily read the code following comments in the template file:

  • set a timeout
  • use nodejs22.x as runtime
  • spin up an AWS::Serverless::Function giving the proper handler path
  • create an API Gateway with a POST route on /mcp path, all automatically setting in Events attribute an event of type Api
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: serverless-mcp-server

Globals:
  Function:
    Timeout: 29
    Runtime: nodejs22.x

Resources:
  McpServerFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/index.handler
      Events:
        McpApi:
          Type: Api
          Properties:
            Path: /mcp
            Method: post

Tips: if you want to switch to API Gateway V2, just change the type to HttpApi and you're good to go.

🚀 Getting Started

To get it up and running follow those steps.

  1. Install dependencies:
npm install
  1. Run Locally with SAM
sam local start-api

Local endpoint will be available at:
POST http://localhost:3000/mcp

🧪 Test with jest

There are some basic tests included in the __tests__ folder. You can run them with:

npm run test

📡 Deploy to AWS

Follow those steps.

Build with SAM

sam build

And finally deploy (before that you should configure AWS Credentials with aws-cli)

sam deploy --guided

After deployment, the MCP server will be live at the URL output by the command.

🧪 Locally or once deployed, test also with curl requests

List tools

Change your-endpoint with the one noted after deploy or with localhost:3000.

curl --location 'https://your-endpoint/dev/mcp' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--header 'jsonrpc: 2.0' \
--data '{
  "jsonrpc": "2.0",
  "method": "tools/list",
  "id": 1
}'

➕ Use the add Tool

Change your-endpoint with the one noted.

curl --location 'https://your-endpoint/dev/mcp' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--header 'jsonrpc: 2.0' \
--data '{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "add",
    "arguments": {
      "a": 5,
      "b": 3
    }
  }
}'

💎 Kickstart your next serverless MCP project with a handy CLI

A little gem to help you kickstart your next MCP serverless projects on AWS: I created a CLI that lets you choose between the three boilerplates from this series (Serverless Framework, AWS CDK, or AWS SAM). It’s built with oclif and is easy to install.

It allows you to choose the framework with just a command "serverless-mcp-cli init" and automatically installs the dependencies so you are ready to go.

Image description

⏭️ Next Step

I'm planning to continue this series:

  • integrate authentication
  • integrate state management

🙋 Who am I

I'm D. De Sio and I work as a Head of Software Engineering in Eleva.
I'm currently (Apr 2025) an AWS Certified Solution Architect Professional and AWS Certified DevOps Engineer Professional, but also a User Group Leader (in Pavia), an AWS Community Builder and, last but not least, a #serverless enthusiast.

My work in this field is to advocate about serverless and help as more dev teams to adopt it, as well as customers break their monolith into API and micro-services using it.