py-1.3.0 shipped — workspace_root is now a first-class argument, silent failure closed #28
Replies: 1 comment
|
A small nicety I noticed after shipping this — the compound cache key For mono-repos with multiple Django projects: the per-call |
|
A small nicety I noticed after shipping this — the compound cache key For mono-repos with multiple Django projects: the per-call |
Uh oh!
There was an error while loading. Please reload this page.
py-1.3.0 shipped — closes a silent-failure class that also lives in five other MCP servers I could find.
The bug
Every one of the 9 tools accepted a
workspace_rootargument that FastMCP silently dropped. Any AI agent inspecting thetools/listschema saw noworkspace_rootfield, so they intuitively passed it anyway (Cursor and Claude Desktop do this on the first call). FastMCP treats unknown kwargs as noise; the tool fell back to$DJANGO_ORM_LENS_ROOTorcwd. When cwd was not a Django project,list_appsreturned[]— no error, no hint. The agent assumed the server was broken and moved on.Same symptom in the wild: microsoft/AL#8273, openai/codex#9989, aws-toolkit-jetbrains#6173, kirodotdev/Kiro#5662, modelcontextprotocol/python-sdk#1097.
The fix — three parts
workspace_root: str = ""on all 9 tool signatures. FastMCP now advertises it ininputSchemaand the value reaches the handler unchanged. Priority: explicit arg →$DJANGO_ORM_LENS_ROOT→ cwd. Ported from the official filesystem-server pattern.expanduser+expandvars+Path.resolve()before any validation collapses..and follows symlinks. Windows reserved names (CON,PRN,AUX,NUL,COMn,LPTn) rejected on every OS. Django-marker required (manage.py/djangoinpyproject.toml/ anymodels.py).[]. Seven stable codes:WORKSPACE_EMPTY,WORKSPACE_NOT_FOUND,WORKSPACE_NOT_A_DIRECTORY,WORKSPACE_NOT_DJANGO,WORKSPACE_NOT_ALLOWED,WORKSPACE_WINDOWS_RESERVED,WORKSPACE_RESOLVE_FAILED. Every failure returns{"error": "…", "hint": "…"}.Before / after
Tests
23 unit + 22 integration + 18 subtests in two new files. Full Python suite: 236 passed (was 191), zero regressions. TS suite: 104/104 unchanged. E2E round-trip on the freshly-published PyPI wheel: 9/9 tools advertise
workspace_root, happy path returns real 4-app result, invalid path returns actionable envelope.Deliberately not done
MCP
roots/list(native workspace discovery) is skipped — the SDK issue linked above tracks a client-side deadlock. Sync fix with explicit-arg-first covers 100% of real cases. Async roots layer will come later, behind a capability check.Install / upgrade
No config change required. The argument is optional and the env-var workflow still works — existing Cursor / Claude Desktop / Aider setups keep working. Just upgrade.
Release notes: https://github.com/FROWNINGdev/django-orm-lens/releases/tag/py-v1.3.0
Feedback welcome — if you hit anything, open an issue and I will look at it same-day.
All reactions