mipyre
A Python web framework whose HTTP server is written in Rust and whose Python handlers run in parallel on every core, inside one process.
pip install mipyre
Python 3.14 (the regular build with the GIL). Wheels for Linux x86_64 and macOS arm64.
How it works
The Rust engine (tokio and hyper) owns the sockets, parses HTTP/1.1 and HTTP/2, enforces limits and writes responses. Python only runs your handlers.
By default the server runs one thread per physical core. Each thread owns a Python sub-interpreter with its own GIL (PEP 684), so handlers on different cores never wait for each other: one process, many GILs, no fork and no copy of your app per core. A request is accepted, parsed and answered on the same core.
Not every library can load in a sub-interpreter yet, so each route declares where it runs:
runtime= |
Where the handler runs | Use it for |
|---|---|---|
"subinterp" (default) |
the sub-interpreter of the core that took the request | pure Python, the standard library, extensions that support sub-interpreters |
"process" |
worker processes beside the server, reached through shared memory | C extensions that don't support sub-interpreters: numpy, pandas, polars, pydantic |
"main" |
the server's main interpreter (one GIL) | a few stateful routes: streaming responses (Stream), async database calls, objects that must live in one place |
"isolated" |
sub-interpreters that each load their own copy of an extension | a compatibility option when process doesn't fit; uses more memory per worker |
Workers share state through app.state, a concurrent map that lives in Rust and is visible to every interpreter and core. Queues are bounded: when the server is full it answers 503 instead of growing without limit.
Quick start
# app.py
from mipyre import Mipyre
app = Mipyre()
@app.get("/")
def index(req):
return {"message": "Hello from mipyre"}
@app.get("/hello/{name}")
def hello(req, name):
return {"message": f"Hello, {name}!"}
@app.post("/echo")
async def echo(req):
return req.json()
if __name__ == "__main__":
app.run()
python app.py # http://127.0.0.1:8000
mipyre run app:app --port 8080
mipyre dev app:app # reloads when a .py file changes
A handler takes the request first, then any path parameters by name. It returns a dict or list (JSON), str (text), bytes, or a Response(body, status_code=..., content_type=..., headers=...).
Routes that need a C extension
A sub-interpreter imports your module too, so a library that can't load there must not be imported at the top of a module the sub-interpreters import. Put those routes in a module of their own with a Router, and list it in the app:
# models.py
from pydantic import BaseModel
from mipyre import Router
router = Router(runtime="main") # or "process"
class Order(BaseModel):
ticker: str
quantity: int
@router.post("/order", model=Order)
def order(body):
return {"ticker": body.ticker, "quantity": body.quantity}
# app.py
from mipyre import Mipyre
app = Mipyre(routers=["models:router"])
Each runtime imports only the routers it serves. Apps with runtime="process" routes start with mipyre run.
Configuration
Everything can be set in code (app.run(...), Mipyre(...)), on the mipyre run command line, or through the environment. The most used variables:
| Variable | Meaning | Default |
|---|---|---|
MIPYRE_HOST / MIPYRE_PORT |
address and port | 127.0.0.1 / 8000 |
MIPYRE_WORKERS |
worker threads (one sub-interpreter each) | physical cores |
MIPYRE_RUNTIME |
the deployment's default runtime | subinterp |
MIPYRE_TPC |
0 switches from thread-per-core to a multi-thread server with a sub-interpreter pool |
on |
MIPYRE_PROCESS_WORKERS |
worker processes for runtime="process" |
physical cores |
MIPYRE_PROCESS_TIMEOUT_MS |
a process handler's time limit; the worker is replaced and the client gets 504 |
30000 |
MIPYRE_TLS_CERT / MIPYRE_TLS_KEY |
PEM certificate and key; turns on TLS with HTTP/2 over ALPN | unset |
MIPYRE_LOG |
1 turns logging on |
off |
MIPYRE_RELOAD |
1 turns hot reload on |
off |
An invalid value in a MIPYRE_* variable, or a runtime declared one way in code and another in the deployment, stops the server at startup with the reason.
Limits on the request path have safe defaults and setters on the app: body size (10 MB, 413), request timeout (30 s), minimum upload rate, header read timeout, and a write-stall timeout for clients that stop reading.
Features
- Routing: all HTTP methods, path parameters (
{id},{*rest}) injected by name, query parameters,Routermodules, a fallback route, prebuilt constant responses served without Python. - Handlers:
defandasync def; request context (mipyre.context.ctx); request ids. - Validation:
model=for JSON bodies andquery=for query strings with pydantic;422with the reasons. - OpenAPI 3.1 document from the routes and models:
app.enable_openapi(). - Middleware:
before_request/after_requesthooks,on_startup/on_shutdown. - Security: CORS, cookies with header-injection checks, CSRF checks on RPC and MCP, redirects that refuse CR/LF.
- Responses: gzip and brotli compression, static files with ETag /
304and precompressed.br/.gz. - Bodies and streams: multipart uploads, streaming request bodies (
stream=True), Server-Sent Events (Stream), WebSocket. - Services: RPC with JSON, MsgPack or Protobuf (
@app.rpc,RPCClient); an MCP endpoint for AI agents (@app.mcp.tool,resource,prompt). - Data: a PostgreSQL pool (
mipyre.db.PgPool), a per-worker JSON cache (@cached_json), shared state (app.state). - Operations:
/livezand/readyzprobes, Prometheus metrics, JSON or text logs, an access log with sampling (app.enable_access_log()), graceful shutdown, systemd socket activation, TLS, HTTP/2. - Development: hot reload,
mipyre routes, an in-memoryTestClientwith WebSocket support.
Examples
examples/ has runnable apps: a minimal API, sub-interpreters, SSE, WebSocket, an AI agent server with MCP tools, a full-stack REST API with auth and uploads, and a trading API with numpy and pandas.
Contributing
See CONTRIBUTING.md. Security issues: report them privately through the repository's Security tab.
License
Metadata
Release files for mipyre 1.0.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 | Actions Reset |
|---|---|---|---|---|
| mipyre-1.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.14 | CPython 3.14 | Linux glibc 2.17+ x86-64 | Details for mipyre-1.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
| mipyre-1.0.0-cp314-cp314-macosx_11_0_arm64.whl | CPython 3.14 | CPython 3.14 | macOS 11.0+ ARM64 | Details for mipyre-1.0.0-cp314-cp314-macosx_11_0_arm64.whl |
Total release size: 10.0 MB
Release files / mipyre-1.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | mipyre-1.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | CPython 3.14 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
74354c4d1461d839bf034151415c64cf8e51e4dd973d1e237a1a7464c4ddbd0b
|
|
BLAKE2b-256 checksum How to use checksums |
66b4a5591177856b400ef2da0c63ec60eedd6200c92f55be45d3b1e92d2f60da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 21, 2026.
Transparency logRelease files / mipyre-1.0.0-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | mipyre-1.0.0-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
5d64edfd2fe6015fd81d3588f3a3d338cb08eb5171827fa6661ed0b7afc44b98
|
|
BLAKE2b-256 checksum How to use checksums |
53a664648e9b7017d17b10c7ec72ea25d55613b1b37e83321883ad6a975749db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 21, 2026.
Transparency logSecurity for mipyre 1.0.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for mipyre-1.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
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 Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.