# Run Model Context Protocol Servers With Aws Lambda

> Run existing Model Context Protocol (MCP) stdio-based servers in AWS Lambda functions

- **Type:** MCP server
- **Install:** `agentstack add mcp-awslabs-run-model-context-protocol-servers-with-aws-lambda`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [awslabs](https://agentstack.voostack.com/s/awslabs)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [awslabs](https://github.com/awslabs)
- **Source:** https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda

## Install

```sh
agentstack add mcp-awslabs-run-model-context-protocol-servers-with-aws-lambda
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Run Model Context Protocol (MCP) servers with AWS Lambda

[](https://pypi.org/project/run-mcp-servers-with-aws-lambda/)
[](https://www.npmjs.com/package/@aws/run-mcp-servers-with-aws-lambda)

This project enables you to run [Model Context Protocol](https://modelcontextprotocol.io) stdio-based servers in AWS Lambda functions.

Currently, most implementations of MCP servers and clients are entirely local on a single machine.
A desktop application such as an IDE or Claude Desktop initiates MCP servers locally as child processes
and communicates with each of those servers over a long-running stdio stream.

```mermaid
flowchart LR
    subgraph "Your Laptop"
        Host["Desktop Applicationwith MCP Clients"]
        S1["MCP Server A(child process)"]
        S2["MCP Server B(child process)"]
        Host |"MCP Protocol(over stdio stream)"| S1
        Host |"MCP Protocol(over stdio stream)"| S2
    end
```

This library helps you to wrap existing stdio MCP servers into Lambda functions.
You can invoke these function-based MCP servers from your application using the MCP protocol
over short-lived HTTPS connections.
Your application can then be a desktop-based app, a distributed system running in the cloud,
or any other architecture.

```mermaid
flowchart LR
    subgraph "Distributed System"
        App["Your Applicationwith MCP Clients"]
        S3["MCP Server A(Lambda function)"]
        S4["MCP Server B(Lambda function)"]
        App |"MCP Protocol(over HTTPS connection)"| S3
        App |"MCP Protocol(over HTTPS connection)"| S4
    end
```

Using this library, the Lambda function will manage the lifecycle of your stdio MCP server.
Each Lambda function invocation will:

1. Start the stdio MCP server as a child process
1. Initialize the MCP server
1. Forward the incoming request to the local server
1. Return the server's response to the function caller
1. Shut down the MCP server child process

This library supports connecting to Lambda-based MCP servers in four ways:

1. The [MCP Streamable HTTP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http), using Amazon API Gateway. Typically authenticated using OAuth.
1. The MCP Streamable HTTP transport, using Amazon Bedrock AgentCore Gateway. Authenticated using OAuth.
1. A custom Streamable HTTP transport with support for SigV4, using a Lambda function URL. Authenticated with AWS IAM.
1. A custom Lambda invocation transport, using the Lambda Invoke API directly. Authenticated with AWS IAM.

## Determine your server parameters

Many stdio-based MCP servers's documentation encourages using tools that download and run the server on-demand.
For example, `uvx my-mcp-server` or `npx my-mcp-server`.
These tools are often not pre-packaged in the Lambda environment, and it can be inefficient to
re-download the server on every Lambda invocation.

Instead, the examples in this repository show how to package the MCP server along with
the Lambda function code, then start it with `python` or `node` (or `npx --offline`) directly.

You will need to determine the right parameters depending on your MCP server's package.
This can often be a trial and error process locally, since MCP server packaging varies.

Python server examples

Basic example:

```python
from mcp.client.stdio import StdioServerParameters

server_params = StdioServerParameters(
    command=sys.executable,
    args=[
        "-m",
        "my_mcp_server_python_module",
        "--my-server-command-line-parameter",
        "some_value",
    ],
)
```

Locally, you would run this module using:

```bash
python -m my_mcp_server_python_module --my-server-command-line-parameter some_value
```

Other examples:

```bash
python -m mcpdoc.cli # Note the sub-module

python -c "from mcp_openapi_proxy import main; main()"

python -c "import asyncio; from postgres_mcp.server import main; asyncio.run(main())"
```

If you use Lambda layers, you need to also set the PYTHONPATH for the python sub-process:

```python
lambda_paths = ["/opt/python"] + sys.path
env_config = {"PYTHONPATH": ":".join(lambda_paths)}

server_params = StdioServerParameters(
    command=sys.executable,
    args=[
        "-c",
        "from mcp_openapi_proxy import main; main()",
    ],
    env=env_config,
)
```

Typescript server examples

Basic example:

```typescript
const serverParams = {
  command: "npx",
  args: [
    "--offline",
    "my-mcp-server-typescript-module",
    "--my-server-command-line-parameter",
    "some_value",
  ],
};
```

Locally, you would run this module using:

```bash
npx --offline my-mcp-server-typescript-module --my-server-command-line-parameter some_value
```

Other examples:
```bash
node /var/task/node_modules/@ivotoby/openapi-mcp-server/bin/mcp-server.js
```

### Passing credentials and other secrets to the MCP server

This library does not provide out-of-the-box mechanisms for managing any secrets needed by the wrapped
MCP server. For example, the [GitHub MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/github)
and the [Brave search MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search)
require API keys to make requests to third-party APIs.
You may configure these API keys as
[encrypted environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars-encryption.html)
in the Lambda function's configuration or retrieve them from Secrets Manager in the Lambda function code (examples below).
However, note that anyone with access to invoke the Lambda function
will then have access to use your API key to call the third-party APIs by invoking the function.
We recommend limiting access to the Lambda function using
[least-privilege IAM policies](https://docs.aws.amazon.com/lambda/latest/dg/security-iam.html).
If you use an identity-based authentication mechanism such as OAuth, you could also store and retrieve API keys per user but there are no implementation examples in this repository.

Python server example retrieving an API key from Secrets Manager

```python
import sys

import boto3
from mcp.client.stdio import StdioServerParameters

# Retrieve API key from Secrets Manager
secrets_client = boto3.client("secretsmanager")
api_key = secrets_client.get_secret_value(SecretId="my-api-key-secret")["SecretString"]

server_params = StdioServerParameters(
    command=sys.executable,
    args=["-m", "my_mcp_server"],
    env={
        "API_KEY": api_key,
    },
)
```

Typescript server example retrieving an API key from Secrets Manager

```typescript
import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";

const secretsClient = new SecretsManagerClient({});
const secret = await secretsClient.send(
  new GetSecretValueCommand({ SecretId: "my-api-key-secret" })
);
const apiKey = secret.SecretString;

const serverParams = {
  command: "npx",
  args: ["--offline", "my-mcp-server"],
  env: {
    API_KEY: apiKey,
  },
};
```

If your MCP server needs to call AWS APIs (such as the [MCP servers for AWS](https://github.com/awslabs/mcp)),
you can pass the Lambda function's AWS credentials to the wrapped MCP server via environment variables.
The wrapped MCP server's child process does not automatically inherit the Lambda execution role's credentials.
Again, note that anyone with access to invoke the Lambda function
will then have access to use the function's AWS credentials to call AWS APIs by invoking the function.
We recommend limiting access to the Lambda function using
[least-privilege IAM policies](https://docs.aws.amazon.com/lambda/latest/dg/security-iam.html).

Python server example using AWS credentials via environment variables

```python
import os
import sys

import boto3
from mcp.client.stdio import StdioServerParameters

# Get AWS credentials from Lambda execution role to pass to subprocess
session = boto3.Session()
credentials = session.get_credentials()
if credentials is None:
    raise RuntimeError("Unable to retrieve AWS credentials from the execution environment")
resolved = credentials.get_frozen_credentials()

server_params = StdioServerParameters(
    command=sys.executable,
    args=["-m", "my_mcp_server"],
    env={
        "AWS_REGION": os.environ.get("AWS_REGION", "us-west-2"),
        "AWS_DEFAULT_REGION": os.environ.get("AWS_REGION", "us-west-2"),
        "AWS_ACCESS_KEY_ID": resolved.access_key,
        "AWS_SECRET_ACCESS_KEY": resolved.secret_key,
        "AWS_SESSION_TOKEN": resolved.token or "",
    },
)
```

Python server example using AWS credentials via credentials file

Some MCP servers require an AWS profile and do not support credentials passed via environment variables.
In this case, you can write the credentials to a file and point the MCP server to it.

```python
import os
import sys

import boto3
from mcp.client.stdio import StdioServerParameters

# Get AWS credentials from Lambda execution role to pass to subprocess
session = boto3.Session()
credentials = session.get_credentials()
if credentials is None:
    raise RuntimeError("Unable to retrieve AWS credentials from the execution environment")
resolved = credentials.get_frozen_credentials()

# Write credentials to disk as default profile
aws_dir = "/tmp/.aws"
os.makedirs(aws_dir, exist_ok=True)
with open(f"{aws_dir}/credentials", "w") as f:
    f.write("[default]\n")
    f.write(f"aws_access_key_id = {resolved.access_key}\n")
    f.write(f"aws_secret_access_key = {resolved.secret_key}\n")
    if resolved.token:
        f.write(f"aws_session_token = {resolved.token}\n")

server_params = StdioServerParameters(
    command=sys.executable,
    args=["-m", "my_mcp_server"],
    env={
        "AWS_REGION": os.environ.get("AWS_REGION", "us-west-2"),
        "AWS_DEFAULT_REGION": os.environ.get("AWS_REGION", "us-west-2"),
        "AWS_SHARED_CREDENTIALS_FILE": f"{aws_dir}/credentials",
    },
)
```

See a full, deployable example [here](examples/servers/sns-sqs/).

## Use API Gateway

```mermaid
flowchart LR
    App["MCP Client"]
    T1["MCP Server(Lambda function)"]
    T2["API Gateway"]
    T3["OAuth Server(Cognito or similar)"]
    App -->|"MCP StreamableHTTP Transport"| T2
    T2 -->|"Invoke"| T1
    T2 -->|"Authorize"| T3
```

This solution is compatible with most MCP clients that support the streamable HTTP transport.
MCP servers deployed with this architecture can typically be used with off-the-shelf
MCP-compatible applications such as Cursor, Cline, Claude Desktop, etc.

You can choose your desired OAuth server provider for this solution. The examples in this
repository use Amazon Cognito, or you can use third-party providers such as Okta or Auth0
with API Gateway custom authorization.

Python server example

```python
import sys
from mcp.client.stdio import StdioServerParameters
from mcp_lambda import APIGatewayProxyEventHandler, StdioServerAdapterRequestHandler

server_params = StdioServerParameters(
    command=sys.executable,
    args=[
        "-m",
        "my_mcp_server_python_module",
        "--my-server-command-line-parameter",
        "some_value",
    ],
)

request_handler = StdioServerAdapterRequestHandler(server_params)
event_handler = APIGatewayProxyEventHandler(request_handler)

def handler(event, context):
    return event_handler.handle(event, context)
```

See a full, deployable example [here](examples/servers/dad-jokes/).

Typescript server example

```typescript
import {
  Handler,
  Context,
  APIGatewayProxyWithCognitoAuthorizerEvent,
  APIGatewayProxyResult,
} from "aws-lambda";
import {
  APIGatewayProxyEventHandler,
  StdioServerAdapterRequestHandler,
} from "@aws/run-mcp-servers-with-aws-lambda";

const serverParams = {
  command: "npx",
  args: [
    "--offline",
    "my-mcp-server-typescript-module",
    "--my-server-command-line-parameter",
    "some_value",
  ],
};

const requestHandler = new APIGatewayProxyEventHandler(
  new StdioServerAdapterRequestHandler(serverParams)
);

export const handler: Handler = async (
  event: APIGatewayProxyWithCognitoAuthorizerEvent,
  context: Context
): Promise => {
  return requestHandler.handle(event, context);
};
```

See a full, deployable example [here](examples/servers/dog-facts/).

Python client example

```python
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

# Create OAuth client provider here

async with streamablehttp_client(
    url="https://abc123.execute-api.us-west-2.amazonaws.com/prod/mcp",
    auth=oauth_client_provider,
) as (
    read_stream,
    write_stream,
    _,
):
    async with ClientSession(read_stream, write_stream) as session:
        await session.initialize()
        tool_result = await session.call_tool("echo", {"message": "hello"})
```

See a full example as part of the sample chatbot [here](examples/chatbots/python/interactive_oauth.py).

Typescript client example

```typescript
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";

const client = new Client(
  {
    name: "my-client",
    version: "0.0.1",
  },
  {
    capabilities: {
      sampling: {},
    },
  }
);

// Create OAuth client provider here

const transport = new StreamableHTTPClientTransport(
  "https://abc123.execute-api.us-west-2.amazonaws.com/prod/mcp",
  {
    authProvider: oauthProvider,
  }
);
await client.connect(transport);
```

See a full example as part of the sample chatbot [here](examples/chatbots/typescript/src/interactive_oauth.ts).

## Use Bedrock AgentCore Gateway

```mermaid
flowchart LR
    App["MCP Client"]
    T1["MCP Server(Lambda function)"]
    T2["Bedrock AgentCore Gateway"]
    T3["OAuth Server(Cognito or similar)"]
    App -->|"MCP StreamableHTTP Transport"| T2
    T2 -->|"Invoke"| T1
    T2 -->|"Authorize"| T3
```

This solution is compatible with most MCP clients that support the streamable HTTP transport.
MCP servers deployed with this architecture can typically be used with off-the-shelf
MCP-compatible applications such as Cursor, Cline, Claude Desktop, etc.

You can choose your desired OAuth server provider with Bedrock AgentCore Gateway,
such as Amazon Cognito, Okta, or Auth0.

Using Bedrock AgentCore Gateway in front of your stdio-based MCP server requires that
you retrieve the MCP server's tool schema, and provide it in the
[AgentCore Gateway Lambda target configuration](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-add-target-lambda.html#gateway-building-lambda-multiple-tools).
AgentCore Gateway can then advertise the schema to HTTP clients and validate request inputs and outputs.

To retrieve and save your stdio-based MCP server's tool schema to a file, run:

```bash
npx @modelcontextprotocol/inspector --cli --method tools/list  > tool-schema.json

# For example:
npx @modelcontextprotocol/inspector --cli --method tools/list uvx mcp-server-time > tool-schema.json
```

Some MCP servers generate tool schemas that AgentCore Gateway rejects with strict validation,
such as `"items": {}`, `"default": null`, or `anyOf` with `{"type": "null"}`.
You may need to clean up the schema before using it:

```bash
python3 scripts/clean-tool-schema.py tool-schema.json
```

Python server example

```python
import sys
from mcp.client.stdio import StdioServerParameters
from mcp_lambda import BedrockAgentCoreGatewayTargetHandler, StdioServerAdapterRequestHandler

server_params = StdioServerParameters(
    command=sys.executable,
    args=[
        "-m",
        "my_mcp_server_python_module",
        "--my-server-command-line-parameter",
        "some_value",
    ],
)

request_handler = StdioServerAdapterRequestHandler(server_params)
event_handler = BedrockAgentCoreGatewayTargetHandler(request_handler)

def handler(event, context):
    return event_handler.handle(event, context)
```

See a full, deployable example [here](examples/servers/book-search/).

Typescript server example

```typescript
import { Handler, Context } f

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [awslabs](https://github.com/awslabs)
- **Source:** [awslabs/run-model-context-protocol-servers-with-aws-lambda](https://github.com/awslabs/run-model-context-protocol-servers-with-aws-lambda)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** yes
- **Shell / process execution:** yes
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-awslabs-run-model-context-protocol-servers-with-aws-lambda
- Seller: https://agentstack.voostack.com/s/awslabs
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
