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.29.0.tar.gz (504.7 kB 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.29.0-py3-none-any.whl (332.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for genro_asgi-0.29.0.tar.gz
Algorithm Hash digest
SHA256 39bf9e3f5dcfe88ea2a412d35c560ef89dd718cc1aeb401e7954ca718268f097
MD5 3a4a053e07bf4ba4762b481bd26096a6
BLAKE2b-256 9f5c272d6ffc78ae74cbdfe959733d3d36b9777404210c320dc1eb362ce0afd3

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_asgi-0.29.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.29.0-py3-none-any.whl.

File metadata

  • Download URL: genro_asgi-0.29.0-py3-none-any.whl
  • Upload date:
  • Size: 332.0 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.29.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5d99d4fc92774c444d714f3e1cd43e9b328e122a72d06090eb20cac03b60844e
MD5 8d98c51dd78d5b0bcc352849a14e1b92
BLAKE2b-256 e398a4d2fb8b4801a6acea1038ef3a7f003e4ea9f907339d2510ca4c5cfd7e3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for genro_asgi-0.29.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

0.35.0

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

This release

0.29.0 This release

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