Skip to content

Instantly share code, notes, and snippets.

@codingjoe
Last active June 5, 2025 20:22
Show Gist options
  • Save codingjoe/a2eaa65b9debf2a237c7f0e79280252a to your computer and use it in GitHub Desktop.
Save codingjoe/a2eaa65b9debf2a237c7f0e79280252a to your computer and use it in GitHub Desktop.
Run MCP on Django w/o a headache

WSGI and ASGI on a single server

We want to attach a an ASGI app, like FastAPI, to an existing Django app, without any performance downsides.

In our example we are attaching an MCP server, including auto-loading.

Preparation

You have an existing Django app, you serve via WSGI on a server like guinicorn. That's it!

Depdencies

You will only need a two dependencies, Starlette (the package behind FastAPI), and a2wsgi.

python3 -m pip install starlette a2wsgi
# optional for our example: mcp
python3 -m pip install mcp

Setup

Create asgi.py file as shown below.

Optionally, create an CMP app, that has no expernal depencies, so you can safely import anywhere in your stack.

Going on production

If you are coming from guinicorn, uvinicorn should be the safest transition.

python3 -m pip install mcp

Finally, you can run your compbine server via:

uvicorn my_mapp.asgi:app

Enjoy!

import contextlib
import importlib
from django.apps import apps
from a2wsgi import WSGIMiddleware
from starlette.applications import Starlette
from starlette.routing import Mount
from contrib.mcp import mcp
# This should point to your WSGI module.
from my_app.wsgi import application as wsgi_app
# Convert the WSGI app to ASGI using a2wsgi
a2wsgi_app = WSGIMiddleware(wsgi_app)
# Autoload all mcp modules from installed apps
for app in apps.get_app_configs():
if app.ready:
try:
importlib.import_module(f"{app.name}.mcp")
except ImportError:
pass
# Create a combined lifespan to manage multiple session
@contextlib.asynccontextmanager
async def lifespan(app):
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(mcp.session_manager.run())
yield
# Create the Starlette app with the combined lifespan
app = Starlette(
routes=[
Mount("/mcp", app=mcp.streamable_http_app()),
Mount("", app=a2wsgi_app),
],
lifespan=lifespan,
)
from mcp.server import FastMCP
mcp = FastMCP(
"voiio",
instructions="Explore voiio's offers around health, family and work.",
stateless_http=True,
json_response=True,
streamable_http_path="",
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment