m0serve
Realtime from a synchronous Python app, with no added infrastructure.
A WSGI/ASGI server written in Mojo. Point it at a Django, Flask, FastHTML or Starlette app and it serves it — no Mojo toolchain required, no compilation step, nothing to configure:
pip install m0serve
m0serve myproject.wsgi:application
What it adds over gunicorn or uvicorn is that a plain synchronous view can hold a Server-Sent Events stream or a WebSocket, by answering with two response headers — and reach every subscriber on every worker with one function call. No Channels, no Redis, no daphne, no Pushpin, no second process:
from m0serve import m0pub
def events(request): # an ordinary synchronous view
r = HttpResponse(": connected\n\n", content_type="text/event-stream")
r["M0-Hold"] = "stream" # m0serve holds the connection open
r["M0-Channel"] = "news" # ...subscribed to this channel
return r # Django's part in it ends here
def announce(request): # any view, command, or cron job
m0pub.publish("news", "deploy finished")
return HttpResponse("ok")
Run it with m0serve myproject.wsgi --realtime. The view runs first, with
sessions and permissions in hand — which is where your auth belongs. Under
gunicorn the two headers are ignored and the same view degrades to a short
plain response, so adopting this is not a fork of your codebase.
The ten-minute quickstart goes from pip install to live multi-tab sync
from one synchronous Django file:
https://github.com/codetalcott/mojo-http/blob/main/QUICKSTART.md — every
command in it is executed by CI on every pull request.
It also hosts several applications in one process, each in its native
execution mode: m0serve --mount /=shop.wsgi --mount /app=live.asgi runs
sync Django on handler threads and async FastHTML on an asyncio executor,
behind one listener with one shutdown.
The protocol is detected from the object, so the same command serves WSGI and
ASGI. m0serve --help lists the flags; --workers N, --threads N (on
free-threaded CPython) and --blocking-threads N are the topology ones.
When it is up it prints one line per worker — 🔥 m0serve: myproject.wsgi: application on http://0.0.0.0:8000 (protocol=wsgi workers=4) — after the
application has been imported, so "it printed" means "it is serving". For an
orchestrator use --health-path /health or a TCP check rather than the log
line.
If something will not start, m0serve --doctor myproject.wsgi prints a JSON
report — the interpreter it resolved and the virtualenv it came from, the
spec it discovered, the topology it settled on, and every startup check with
the fix for the ones that failed — and exits with the code the server itself
would have used. It binds nothing and imports nothing twice.
What is in the wheel
One compiled binary and the Mojo runtime it loads. No CPython — m0serve resolves libpython at run time from the interpreter it is installed beside, which is why there is no ABI tag and one wheel per platform covers CPython 3.10 through 3.14, free-threaded builds included. It has no Python dependencies and fetches nothing at install time.
Install it into the same virtual environment as your application, the way you would gunicorn or uvicorn; the console script points the embedded interpreter at that environment.
Platforms
| platform | status |
|---|---|
| macOS arm64 (Apple Silicon) | supported |
| Linux x86_64 (glibc) | supported |
| Linux aarch64 (Graviton, Ampere, arm64 Docker) | supported |
| macOS x86_64 (Intel) | not possible — Modular ships no Intel Mac toolchain |
| musl / Alpine, Windows | not supported |
The wheel's filename carries the exact macOS and glibc floors it was built
against. On an older system pip declines to install it rather than
installing something that crashes.
Status
Pre-1.0 and deliberately small: HTTP/1.1 only, no TLS, no HTTP/2 — terminate at a proxy, which is gunicorn's answer too. The API will change before 1.0.
The full capability matrix, with the CI gate behind each row, is docs/SPEC.md.
Source, documentation and issues: https://github.com/codetalcott/mojo-http
Licence
MIT, and the wheel redistributes third-party components under their own
terms — the Mojo runtime (Apache-2.0 with LLVM Exceptions) and a fork of
lightbug_http (MIT). Full text and attribution ship inside the wheel; see
NOTICE.txt beside the installed package.
Release files for m0serve 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| m0serve-1.6.0-py3-none-manylinux_2_35_x86_64.whl | Python 3 | none | Linux glibc 2.35+ x86-64 | Details |
| m0serve-1.6.0-py3-none-manylinux_2_35_aarch64.whl | Python 3 | none | Linux glibc 2.35+ ARM64 | Details |
| m0serve-1.6.0-py3-none-macosx_13_0_arm64.whl | Python 3 | none | macOS 13.0+ ARM64 | Details |
Total release size: 4.6 MB
Release files / m0serve-1.6.0-py3-none-manylinux_2_35_x86_64.whl
| Download URL | m0serve-1.6.0-py3-none-manylinux_2_35_x86_64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | Linux glibc 2.35+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
cad7d2e555f329cd18dbd72aee8ad2d3c6c40d25aad9f3a52dddd684d0278246
|
|
BLAKE2b-256 checksum How to use checksums |
317610881b0fa053792619457864af015fe5ebbad5304b00ecaa364c266e0246
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / m0serve-1.6.0-py3-none-manylinux_2_35_aarch64.whl
| Download URL | m0serve-1.6.0-py3-none-manylinux_2_35_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | Linux glibc 2.35+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
8b3184aab409b1126efb68585bdd660c84c882e6320b233acf52bbbe0f252bb2
|
|
BLAKE2b-256 checksum How to use checksums |
da83810a68caa9460517c3a607e9323de4ea046a2b1b2efc4c87c17ad1abef06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / m0serve-1.6.0-py3-none-macosx_13_0_arm64.whl
| Download URL | m0serve-1.6.0-py3-none-macosx_13_0_arm64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Python 3 macOS 13.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
94383c8caecd68cb8d89e64256508e93bc19be1c434f0963035ddefe6cd32237
|
|
BLAKE2b-256 checksum How to use checksums |
b119a70264ed6029eb1950d6f2e55296010b19189dc341222e3ef4ce51f60eb2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log