Skip to main content

genro-asgi

A minimal ASGI server core — one instance-isolated server that mounts your applications, routes requests through genro-routes, and grows authentication, sessions, background tasks, OpenAPI and MCP by composition. No globals, no module state: the server is an object you build, run, and throw away.

PyPI version Python versions License

Status: Beta. Feature-complete core, API stabilizing. This repository is a spec-first redesign — see SPECIFICATION.md for the founding decision log.

What it does

  • Serves applications — each app declares its mount, the URL prefix it answers under ("" is the site root); the server demultiplexes on the first path segment.
  • Routes requests — handlers are @route-decorated methods on your application class; query and body parameters bind to the signature, typed.
  • Authenticates — basic / bearer / JWT credentials, API keys (gak_…), and OIDC providers; per-route auth_rule filtering, default-deny.
  • Manages sessions — in-memory or file-backed store, cookie reconnection, Avatar identity (tags + extensible Bag data).
  • Applies middleware — errors, CORS, logging, auth, session, well-known — composed as an ordered chain, each turned on by config.
  • Runs background tasks — a spool + executor + cron/interval scheduler, managed over /_server/tasks.
  • Generates OpenAPI & Swagger — subclass OpenApiApplication and the same @route methods yield an OpenAPI 3.1 schema and a Swagger UI.
  • Speaks MCP — subclass McpApplication (or McpOpenApiApplication) and your routes become tools an AI agent can call, over MCP Streamable HTTP.
  • StreamsStreamingResponse for chunked bodies, SseStream for Server-Sent Events.

Installation

pip install genro-asgi

Requires Python 3.11+.

Hello world

One file. A RoutedApplication subclass with two @route handlers, served by an AsgiServer:

# hello.py
from genro_asgi import AsgiServer, RoutedApplication
from genro_routes import route


class Hello(RoutedApplication):
    mount = ""          # this app answers the site root

    @route()
    def index(self) -> dict[str, str]:
        return {"hello": "world"}

    @route()
    def greet(self, name: str = "world") -> dict[str, str]:
        return {"hello": name}


if __name__ == "__main__":
    server = AsgiServer(applications=[Hello()])
    server.serve(host="127.0.0.1", port=8000)
python hello.py
$ curl http://127.0.0.1:8000/index
{"hello": "world"}
$ curl "http://127.0.0.1:8000/greet?name=genro"
{"hello": "genro"}

A handler that returns a dict answers JSON; the query string binds to the method signature (name above), with defaults and type coercion. An unknown path answers 404 through the always-on error middleware.

REST + OpenAPI + Swagger from one class

Subclass OpenApiApplication instead of RoutedApplication, declare openapi_info, and enable the plugins — the same @route methods now expose an OpenAPI 3.1 schema and a Swagger UI, generated from their signatures:

from genro_asgi import AsgiServer, OpenApiApplication
from genro_routes import route


class Shop(OpenApiApplication):
    mount = ""
    openapi_info = {"title": "Shop API", "version": "1.0.0"}

    @route()
    def search(self, q: str = "", max_price: float = 100.0) -> dict:
        return {"query": q, "hits": []}


server = AsgiServer(applications=[Shop()], plugins={"openapi": True, "pydantic": True})
server.serve(port=8000)
  • /search?q=moka&max_price=30 — the endpoint, params typed and coerced
  • /_meta/docs — the Swagger UI
  • /_meta/schema_json — the OpenAPI 3.1 document

If you know FastAPI, this is the same decorate-a-method workflow. The difference is where the route description lives: genro-routes keeps it protocol-neutral, so other transports read the same tree. Switch the base class to McpOpenApiApplication and the app grows an MCP face on /mcp — the routes you mark with @route(channel_channels="mcp") become tools an agent can call, with the same parameter handling as REST. See Coming from Starlette / FastAPI for a full concept mapping.

Architecture at a glance

The server is an instance with its own state — no global variables. Every component is an isolated object connected by a semantic parent reference (an app holds self.server, a request holds self.application).

uvicorn → AsgiServer → middleware chain (errors → cors → auth → session)
  → demultiplex on first path segment → application
    → @route handler(**params) → Response → ASGI send

AsgiServer is the shipped composition: it stacks the capability mixins (communication, auth, session, middleware, plugins, storage, tasks) over BaseServer in one MRO. You turn features on through constructor kwargs (auth=…, middleware=…, tasks=…, plugins=…) — objects always exist, their backends come from config.

Documentation

Full documentation (guides, architecture, API reference) is built with Sphinx under docs/ and published on Read the Docs.

Build it locally:

pip install -e ".[docs]"
sphinx-build -b html docs docs/_build/html

Development

git clone https://github.com/genropy/genro-asgi.git
cd genro-asgi
pip install -e ".[dev]"

pytest                    # run tests
ruff check src/           # lint
mypy src/                 # type check (advisory)

See CONTRIBUTING.md for the full workflow.

License

Copyright © 2025 Softwell S.r.l.

Licensed under the Apache License 2.0. This project may include third-party components under separate open-source licenses; see the NOTICE file for attribution.

Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

genro_asgi-0.35.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

genro_asgi-0.35.0-py3-none-any.whl (481.1 kB view details)

Uploaded Python 3

File details

Details for the file genro_asgi-0.35.0.tar.gz.

File metadata

  • Download URL: genro_asgi-0.35.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for genro_asgi-0.35.0.tar.gz
Algorithm Hash digest
SHA256 cb69b10ae2f7eae1c1c761fe24757c9146ee14e671e75ea158ecdbdc84da8ed2
MD5 fa9ad89155154cfe9dfbcf91d4a09587
BLAKE2b-256 c8b7a3f1e00e1f2c703a3cc926db401556cceed8e58edb74acfe27c31287368f

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_asgi-0.35.0.tar.gz:

Publisher: publish.yml on genropy/genro-asgi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file genro_asgi-0.35.0-py3-none-any.whl.

File metadata

  • Download URL: genro_asgi-0.35.0-py3-none-any.whl
  • Upload date:
  • Size: 481.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for genro_asgi-0.35.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d9dba4766dac9722de3ba3bb3204b6aed9c61bc48318289f3950766a0dbda2cf
MD5 43f712b0b9ab565a468f502c3f6ea561
BLAKE2b-256 177666adb699fff78e507357379d8b96d5801f0e2d7286898c783638661ad3c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_asgi-0.35.0-py3-none-any.whl:

Publisher: publish.yml on genropy/genro-asgi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.37.0

2 files

0.36.0

2 files

This release

0.35.0 This release

2 files

0.34.0

2 files

0.33.0

2 files

0.32.0

2 files

0.31.0

2 files

0.30.0

2 files

0.29.0

2 files

0.28.0

2 files

0.27.0

2 files

0.26.0

2 files

0.25.0

2 files

0.24.0

2 files

0.23.0

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.13.0

2 files

0.10.0

2 files

0.9.0

2 files

0.7.0

2 files

0.6.7

2 files

0.6.6

2 files

0.6.5

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page