Release notes
Reverse-chronological log of every published version. Each entry covers what's new, what's fixed, and what (if anything) consumer projects need to do on upgrade.
1.4.0 — 2026-05-07
Bearer token authentication as an opt-in module — coexists with `X-Api-Key` and cookie sessions, no OAuth Authorization Server logic in the framework.
What's new
- **`
Authorization: Bearer <token>support.** Wired intoBaseResource._authenticateand the/docs//openapi.json` auth gate. Bearer takes precedence over X-Api-Key and cookie session when all are present. - Pluggable resolver. Set `
MCP['BEARER_RESOLVER']to a dotted path or callable. The resolver receives the raw token and returns the same session dict shape used by the X-Api-Key resolver ({'user': {...}, 'account': {...}}). Sync and async resolvers both supported (detection viainspect.isawaitable` on the result, so wrappers/decorators that return coroutines are handled correctly). - *Strict mode (`
REQUIRE_VALID_BEARER).** Optional gate: when enabled, routes withauthenticated=True` accept only* a valid Bearer token. No fallback to X-Api-Key or cookie. Public routes are unaffected. - RFC 9728 discovery. Set `
MCP['OAUTH_AS_URL']andMCP['OAUTH_RESOURCE_URL']to publish/.well-known/oauth-protected-resource`. MCP clients use this to locate the external Authorization Server. - **OpenAPI `
bearerAuth** added tosecuritySchemes.apiKeyAuth(X-Api-Key) andcookieAuth` are unchanged — all three coexist. - Tri-state parser. The `
Authorization` header parser distinguishes absent (no header / non-Bearer scheme), invalid (Bearer scheme but malformed), and token (well-formed). Strict mode and resolver dispatch use this distinction. Scheme is case-insensitive; outer whitespace stripped; token whitespace rejected. - Boot-time validation. Setting `
OAUTH_AS_URLwithoutOAUTH_RESOURCE_URLraisesImproperlyConfiguredfromget_routes()` — fails on application start, never at request time. - Token never logged raw. Resolver exceptions are warned with `
sha256(token)[:12]`. Inspect logs for the prefix; raw tokens stay out of observability pipelines.
Action required
- Bump the dependency: `
pip install -U django-zeromcpordjango-zeromcp>=1.4.0`. - No code changes required. Bearer auth activates only when `
BEARER_RESOLVER` is configured. - See Bearer auth for the full configuration matrix and resolver examples.
1.3.0 — 2026-05-04
Per-resource and credential-path rate-limit primitives, clearer errors when CRUD hooks return the wrong type, and a polished `init` flow.
What's new
- Credential-path auto-defense. A tight per-IP bucket auto-applied to `
MCP['CREDENTIAL_PATHS'](defaults:['/forgot', '/change_password', '/signup', '/reset', '/recover', '/register'],5 hits / 30s). Match is segment-based —/login/forgotand/user/change_passwordare caught;/forgottenis not. SettingCREDENTIAL_PATHS` in your project replaces the default; copy the list to extend. - Declarative `
rate_limits` on Resources. Multi-bucket support keyed by anything callable from the resource — per-user, per-email, per-IP. Multi-window combos cover both rate-limit and lockout patterns with the same primitive. See Rate limiting. - **Clearer `
TypeErrorfor CRUD hook contract violations.** Whenupdate_obj/get_obj/alter_detailreturns a builtHttpResponseinstead of adict, the framework now raisesTypeErrorwith a self-explanatory message instead of crashing on'JsonResponse' has no attribute 'pop'`. - **`
0-mcp initUX polish.** Init now prints the count of internal Django tables filtered (so80 tables, exposed 69doesn't read like a generator bug), the elapsed wall time (✨ done in 12.4s), and a warning when the user picks read-only mode (read-only blocks the MCP JSON-RPC endpoint — POST/mcp` returns 405).
Action required
- Bump the dependency: `
pip install -U django-zeromcpordjango-zeromcp>=1.3.0`. - No code changes required — credential-path defense activates automatically.
Known issues
- Project overrides of `
update_objthat previously returnedJsonResponsefor short-circuit responses (validation errors, custom status) used to crash with a confusingAttributeError. Now they raise a clearTypeErrorwith the contract explanation. The fix is in the project, not the framework — return adictor raiseHTTPException`.
1.2.0 — 2026-05-03
Init flow now prints copy-pasteable next-steps; OpenAPI `info.version` follows the installed framework version.
What's new
- **`
zeromcp.__version__exposed** viaimportlib.metadata.get_routes()andbuild_spec()default to that value, so every generated project's/docs` page tracks the installed framework version automatically. - **`
0-mcp initnext-steps.** After generation, the CLI prints the workingcd+./run.sh` + REST/MCP curl examples — using the first generated resource as a real sample. Zero-copy run.
Action required
- `
pip install -U django-zeromcp(or>=1.2.0`). - No code changes.
1.1.1 — 1.1.3 — 2026-05-02 to 2026-05-03
Three patch releases, all packaging-related; `1.1.1 and 1.1.2 were never published cleanly to PyPI — install 1.1.3` (or higher) directly.
Fixes
- **`
0-mcp initworks afterpip install.** Generator dotfile templates (.env.example.j2,.gitignore.j2) were dropped by setuptools'**/*glob in some install paths. Renamed toenv.example.j2/gitignore.j2` (target filenames in the generated project unchanged). - OpenAPI module docstring corrected from "3.1" to "3.0.3" (the actual emitted spec version).
1.1.0 — 2026-05-02
`READ_ONLY global gate, regression fix for default list_fields`, friendlier Redis error.
What's new
- **`
MCP['READ_ONLY'] = True** rejects every non-GET request with 405 across REST and MCP. Replaces per-resourceallowed_methods = ['get']boilerplate. Generated projects now ship with this enabled by default — flip the key (or pass--writableat init) to allow writes. **Caveat:**READ_ONLYblocks the MCP JSON-RPC endpoint (POST/mcp); use--writable` if you need a working MCP server. - Generated project README ships with copy-pasteable `
curl` examples that reference a real sample resource from the introspected schema.
Fixes
- **Default `
list_fieldsincludes*_idfor ForeignKey/OneToOne** again. An earlier refactor walked_meta.get_fields()and skipped FKs entirely; the defaultGET /resourcelostaccount_id/owner_id/created_by_id. Fixed — walks_meta.local_fieldsand emitsfield.attname` for relations. - **Redis < 6.2 `
unknown command 'GETEX'error** is now translated into a clearRuntimeErrorwith platform-specific upgrade recipes (RHEL, Ubuntu/Debian, Docker, Homebrew). Previously this surfaced as a crypticResponseError` that took hours to diagnose.
Action required
- Confirm Redis ≥ 6.2 in production. The framework needs `
GETEX` for sliding session TTLs. - Projects relying on the regression-broken behaviour (`
*_idcolumns absent from list responses) need to either set an explicitlist_fields = [...]` without those columns, or accept the restored shape.
1.0.x — 2026-04-30 to 2026-05-02
Initial public release line. `1.0.0 was the rebrand from easyapi-django; 1.0.1–1.0.2` were small generator polish patches.
What's new
- Initial public release — REST + MCP from the same `
BaseResourceclass. Async dispatch, Redis-backed sessions and rate limiting, multi-tenant DB routing, OpenAPI 3.0.3, Scalar UI, sanitized 500s.0-mcp init` reads MySQL/Postgres schemas and generates a working Django project. - Sliding session TTLs for cookie + API-key sessions via Redis `
GETEX. Configurable throughMCP['SESSION_TTL'](default 1800s) andMCP['API_SESSION_TTL']` (default 300s). - Ownership scoping — `
owner_field = 'owner_id'on a Resource gates every CRUD verb (GET, LIST, PATCH, DELETE) to rows owned by the authenticated user.POSTforcesowner_idto the caller (override withallow_owner_override = True` for admin paths). - Anti-CSRF startup warning when `
DEFAULT_AUTHENTICATEDis on but neitherENFORCE_TOKENnorALLOWED_ORIGINS` is configured.
Migration from `easyapi-django`
- `
pip uninstall easyapi-django && pip install django-zeromcp`. - Find/replace `
from easyapi→from zeromcp;import easyapi→import zeromcp;EASYAPI = {→MCP = {;'easyapi.X'(settings string refs) →'zeromcp.X'`. - Reset semver from here — `
1.0.0` is the new floor.
Versions `1.0.0–1.0.2 and 1.1.0–1.1.3 were published incrementally; subsequent patch upgrades within a minor line are always safe (no breaking changes within 1.x). When in doubt, install the latest 1.x.y` and skip intermediate patches.
0-mcp by Stamatios Stamou Jr — github.com/ssjunior/0-mcp