BibekBarik18/MCP-server-as-a-FastAPI-application
If you are the rightful owner of MCP-server-as-a-FastAPI-application and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The Model Context Protocol (MCP) server is a framework designed to facilitate communication between machine learning models and applications, leveraging the FastAPI framework for deployment.
Expose an MCP server via FastAPI
Build once. Deploy anywhere. Expose your Model Context Protocol (MCP) tools over a clean FastAPI surface.
Overview
This project shows how to:
- Turn a simple MCP server into a FastAPI application
- Run and manage the MCP lifecycle with FastAPI lifespan hooks
- Mount one or more MCP apps under path prefixes
- Deploy to common cloud platforms with container or process-based runners
What is MCP here?
MCP (Model Context Protocol) lets you expose “tools” callable by clients. The FastMCP helper from mcp.server.fastmcp converts those tools into an HTTP-ready app you can embed or mount in frameworks like FastAPI.
Project structure
.
├─ math_server.py # Defines a simple MCP tool surface
├─ main.py # FastAPI app that mounts the MCP app
├─ requirements.txt # Or pyproject.toml / poetry.lock
Example MCP server
math_server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(name="MathServer", stateless_http=True)
@mcp.tool(description="A simple add tool")
def add_two(n: int) -> int:
return n + 2
Key points:
- FastMCP collects decorated tools and exposes them over HTTP and WebSocket.
- stateless_http=True optimizes for ephemeral, per-request execution. Great for serverless and autoscaling.
Embedding MCP in FastAPI
main.py
import contextlib
from fastapi import FastAPI
from math_server import mcp
import os
@contextlib.asynccontextmanager
async def lifespan(app: FastAPI):
async with contextlib.AsyncExitStack() as stack:
# Start MCP runtime and keep it alive for the app lifecycle
await stack.enter_async_context(mcp.session_[manager.run](http://manager.run)())
yield
app = FastAPI(lifespan=lifespan)
# Mount the MCP app at a path prefix
app.mount("/echo", mcp.streamable_http_app())
PORT = int(os.environ.get("PORT", 10000))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=PORT)
How it works:
- Lifespan: keep the MCP session manager open for app lifetime so tools are ready across workers.
- Mounting: the MCP sub-app lives under
/echo. If the MCP app serves/mcp, the full path is/echo/mcp.
Run locally
Using Uvicorn:
uvicorn main:app --reload
Endpoints:
- Base mount: http://localhost:10000/echo
- MCP surface (example): http://localhost:10000/echo/mcp
Note: If you change the port via PORT, update your requests accordingly.
Multiple MCP servers under one host
Mount several MCP sub-apps under a shared host:
import contextlib
from fastapi import FastAPI
from echo_server import mcp as echo_mcp
from math_server import mcp as math_mcp
import os
@contextlib.asynccontextmanager
async def lifespan(app: FastAPI):
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(echo_mcp.session_[manager.run](http://manager.run)())
await stack.enter_async_context(math_mcp.session_[manager.run](http://manager.run)())
yield
app = FastAPI(lifespan=lifespan)
app.mount("/echo", echo_mcp.streamable_http_app())
app.mount("/math", math_mcp.streamable_http_app())
PORT = int(os.environ.get("PORT", 10000))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=PORT)
This yields:
- /echo/mcp
- /math/mcp
You can also add regular FastAPI routes at /api/... alongside these mounts.
Security considerations
- Add authentication at the FastAPI layer. API keys or OAuth are common.
- Apply rate limiting or a WAF/CDN for public endpoints.
- Validate tool inputs. Check types and ranges to avoid misuse.
Performance tips
-
For concurrency, run multiple workers:
uvicorn main:app --host 0.0.0.0 --port $PORT --workers 2 -
Keep MCP stateless for fast cold starts and horizontal scaling.
Troubleshooting
- Getting 404s on
/mcp? Check the mount prefix. Withapp.mount("/echo", ...), the path is/echo/mcp. - Port mismatches: align
PORTenv var, container exposure, and client requests. - Verify your platform’s health checks target a live route.
Summary
- Define tools with
FastMCPand@mcp.tool. - Manage MCP lifecycle in FastAPI’s lifespan.
- Mount the MCP app with
app.mount(prefix, mcp.streamable_http_app()). - Deploy to any cloud that runs ASGI apps or containers.
- Scale out easily and host multiple MCP servers behind a single URL space.