OpenAPI
Spec generation and a beautiful Scalar UI, built into the library.
Always on
get_routes() always registers three routes:
GET /— index page linking to every doc, registry and resourceGET /openapi.json— OpenAPI 3.0.3 specGET /docs— Scalar API reference (interactive UI)
By default these routes require a valid session cookie, X-Api-Key, or Authorization: Bearer (when BEARER_RESOLVER is configured). The same auth as the rest of your API. No special flag needed. REQUIRE_VALID_BEARER strict mode applies here too — locking the API to Bearer-only also locks the docs surface.
Public docs
When you want the spec and the UI to be open to anyone (public APIs, demos, OSS projects):
urlpatterns = get_routes(endpoints, docs_public=True)
Customize
Without an explicit version=, the spec emits the installed zeromcp.__version__ so the docs page tracks framework upgrades automatically. Pass an explicit value when your API has its own release cadence.
get_routes(
endpoints,
docs_public=False, # default — auth required
title='My API',
version='2.0', # default: zeromcp.__version__
description='Internal API for ...',
)Per-resource metadata
Set summary and description on the resource — they show up as the tag and operation labels in the spec, and are reused by the MCP server (when enabled).
class UserResource(BaseResource):
model = User
summary = 'User'
description = '''
End-user accounts. Each user belongs to exactly one Account
(multi-tenant). Use POST /users to invite, PATCH for profile
updates, GET /users/me for the current session.
'''How the spec is generated
For each registered resource:
- If a Pydantic schema is set on the relevant slot, the spec uses
model_json_schema()and references it fromcomponents.schemas. - Otherwise the library inspects the Django model and emits inline schemas with field types, lengths, defaults and nullability.
Both list and detail paths are emitted. List endpoints include the standard query parameters (page, limit, order_by, search, fields, filter).
Custom routes
Custom routes are picked up automatically. Decorate the handler with @openapi(...) to enrich the entry:
@openapi(summary='Current user', response=UserOut, tags=['Auth'])
async def me(self, request, match=None):
...Security schemes
The spec declares all three auth mechanisms in components.securitySchemes:
cookieAuth— session id cookieapiKeyAuth—X-Api-KeyheaderbearerAuth—Authorization: Bearer <token>(HTTP schemebearer)
Scalar's "Try it out" can use any of them when you click "Authorize".
Why Scalar
Two-column layout, dark-mode by default, search, copy-as-curl/python/js, request runner — and the AI assistant is disabled in the 0-mcp build for privacy.
The Scalar bundle is loaded from jsdelivr. If you serve docs from a private network, host the bundle yourself and tweak SCALAR_HTML in zeromcp/openapi.py.
0-mcp by Stamatios Stamou Jr — github.com/ssjunior/0-mcp