JonyGPT
ServicesWorkPromptsToolsAboutBlogLet's Talk
Back to blog
July 24, 2026

I Built mcp-asgi-http So MCP Works on AWS Lambda

mcpaws-lambdafastapipythonserverless

I wanted an MCP server on AWS Lambda. Same FastAPI app I already run. Streamable HTTP. Optional API keys or JWT. No special snowflake deploy path.

That should have been a weekend. It was not.

The MCP SDK gives you a server. FastAPI gives you ASGI. Mangum wraps ASGI for Lambda. On paper they compose. In practice, slash redirects, disabled lifespan, and auth middleware fight you until the Function URL stops answering /mcp.

So I packaged the glue. It is open source as mcp-asgi-http. Docs live at johnny-rice.github.io/mcp-asgi-http.

What broke on Lambda

Three things kept showing up.

Slash redirects. Starlette Mount and FastAPI's default redirect_slashes love to bounce /mcp to /mcp/ (or the other way). Fine on a local uvicorn. Painful behind an API Gateway or Function URL, where redirects and clients disagree about the path.

Lifespan is off. Mangum often runs with lifespan="off". Your FastAPI startup hooks never fire. DB pools, caches, and "run this once" setup sit idle while every cold start looks brand new.

Auth belongs at the edge of the MCP route. Some teams put keys on API Gateway. Others want Bearer keys or JWKS JWT on the app. I needed both patterns, plus a dual mode, without rewriting the transport each time.

None of that is hard once you see it. All of it is easy to get wrong when you are wiring MCP for the first time.

What the package does

mcp-asgi-http mounts an official MCP Server on an ASGI app over Streamable HTTP. You keep tool registration however you already do it. This library is the mount and the HTTP auth layer, not another tool-registration framework.

Install:

pip install mcp-asgi-http
pip install 'mcp-asgi-http[jwt]'   # only if you need JwtAuth / DualAuth JWT

Minimal mount:

from fastapi import FastAPI
from mcp.server import Server
from mcp_asgi_http import ApiKeyAuth, mount_mcp

server = Server("demo")
# register tools on server

api = FastAPI(redirect_slashes=False)
app = mount_mcp(
    api,
    server,
    auth=ApiKeyAuth(allowed_keys={"dev-secret"}),
    # auth=None if API Gateway (or your middleware) already authenticates
)

mount_mcp routes /mcp through path middleware so you avoid Mount slash-redirect loops. Set redirect_slashes=False on FastAPI. That combination is what made Function URL behave.

Lambda with Mangum

When lifespan is off, pass lazy init through once_ready:

from mangum import Mangum
from mcp_asgi_http import ApiKeyAuth, mount_mcp, once_ready

async def warm() -> None:
    # open pool, warm caches, etc.
    ...

app = mount_mcp(
    api,
    server,
    auth=ApiKeyAuth(allowed_keys={"lambda-dev-key"}),
    on_ready=once_ready(warm),
)
handler = Mangum(app, lifespan="off")

once_ready runs the callback once per process, the first time a request needs it. That is the pattern that replaces FastAPI lifespan under Mangum.

More detail is in the serverless guide and the Mangum example in the repo.

Auth options

ModeBehavior
auth=NoneLibrary does no auth. Use the gateway or your own middleware.
ApiKeyAuthAuthorization: Bearer or X-API-Key
JwtAuthBearer JWT via JWKS (issuer, audience, optional jwks_url)
DualAuthAPI key first, then JWT

I use auth=None when API Gateway already checks the caller. I use API keys for quick demos and internal tools. JWT when the same issuer already issues tokens for the rest of the stack.

What this is not

It is not FastMCP. FastMCP is about tool registration and developer experience. This package mounts a server you already have and authenticates the HTTP transport.

It is also not the AWS Serverless MCP Server. That product gives MCP tools for SAM and Lambda development. Different problem.

If you need a stdio to HTTP bridge, look elsewhere. This is for hosting Streamable HTTP on an ASGI app you control.

Try it

Source and issues: github.com/johnny-rice/mcp-asgi-http.

Install notes, auth, serverless, and sample apps: johnny-rice.github.io/mcp-asgi-http.

If you are putting MCP behind Lambda and the path keeps bouncing or startup never runs, start with mount_mcp, redirect_slashes=False, and once_ready. That is the whole reason this package exists.

JonyGPT

AI coaching and development for businesses of all sizes.

ServicesWorkPromptsToolsApproachCoachCodingOffice AI TrainingChallengesProcessAboutBlog
Privacy PolicyTerms of Service

© 2026 JonyGPT. All rights reserved.