DRF And React By Schema - MCP
A generic, schema-driven MCP server for projects built with DRF And React By Schema (DRBS).
It exposes any DRBS project’s DRF API (/api/...) to MCP clients such as opencode through a small set of generic tools — consultar, resumo, criar, editar, minha_conta — plus optional per-project shortcuts, so an assistant can read (and, when opted in, write) the project’s data with no per-model tool explosion.
The server is a stateless proxy: it takes the caller’s OAuth 2.1 Bearer token (issued by drf-react-by-schema-oauth), forwards it to the project’s /api/... and lets the project’s own DRF permissions scope the data. It stores no credentials.
About the suite
drf-react-by-schema is a suite that builds headless Django + React applications directly from your models:
drf-react-by-schema-django (PyPI) — generates the DRF API (serializers, viewsets, filters, schemas) from your models;
drf-react-by-schema-react (npm) — consumes those schemas to build the React forms, grids and CRUD interfaces;
drf-react-by-schema-oauth — OAuth 2.1 authorization/resource server that issues the tokens both the API and this MCP server accept;
drf-react-by-schema-mcp (this package) — the generic MCP server that exposes the same API to MCP clients.
About this package
A DRBS project already exposes a rich DRF API generated from its models. This package mounts a FastMCP server that proxies that API to MCP clients, so an assistant can:
read any /api/... endpoint (consultar), count and sum filtered sets without downloading them (resumo) and identify the logged-in account (minha_conta);
write — opt-in per project — with criar (POST) and editar (PATCH); DELETE is never exposed.
It is deliberately generic: the tool surface is bounded by a fixed set of generic tools plus any project shortcuts, not one tool per model. The same OAuth token authenticates /mcp and /api/..., and the project’s DRF permissions and OAuth scopes (read/write) remain the authority.
Compatibility
The base DRBS package supports Django ≥ 3.2, and some deployments are still on Django 3.2. This package therefore supports Django 3.2 through 5.x (and the 2.x django-oauth-toolkit line pulled in by drf-react-by-schema-oauth). It requires Python ≥ 3.10 (the mcp SDK).
Pre-requisites
Django ≥ 3.2
djangorestframework
drf-react-by-schema-oauth (installed automatically) — provides the OAuth server and the DRF authentication/scopes
mcp (installed automatically)
Quick start
Install:
pip install drf-react-by-schema-mcpAdd the app (after the OAuth package) and include the URLs:
INSTALLED_APPS = [ ... 'oauth2_provider', 'drf_react_by_schema_oauth', 'drf_react_by_schema_mcp', ] urlpatterns = [ ... path('', include('drf_react_by_schema_oauth.urls')), path('', include('drf_react_by_schema_mcp.urls')), # Protected Resource Metadata ]Mount the MCP endpoint (see Mounting /mcp).
Configure (all keys optional):
DRBS_MCP = { 'WRITE': False, # read-only by default 'RESOURCE_URL': '/mcp', 'SHORTCUTS': [], # dotted paths to project-specific tools }
Mounting /mcp
/mcp speaks the MCP streamable-http transport, a long-lived ASGI application (it cannot be served from a synchronous WSGI URLconf). There are two supported deployments:
Combined — one ASGI process serves both Django and /mcp:
# asgi.py from drf_react_by_schema_mcp.server import get_mcp_asgi_application application = get_mcp_asgi_application()Standalone — a second ASGI process serves only /mcp (point DRBS_MCP['API_URL'] at the Django host) and the reverse proxy routes /mcp to it:
python -m drf_react_by_schema_mcp.server # or: uvicorn drf_react_by_schema_mcp.server:get_mcp_asgi_application --factory
In both cases the endpoint is protected: an unauthenticated request answers 401 with WWW-Authenticate: Bearer resource_metadata="…", so an MCP client can discover the OAuth server (RFC 9728) and start the flow automatically.
Connecting an MCP client
Point a remote MCP client at https://<host>/mcp with OAuth (no secret file):
"example": {
"type": "remote",
"url": "https://<host>/mcp",
"enabled": true,
"oauth": {}
}
With opencode that is opencode mcp auth example, followed by opencode mcp debug example.
Tools
The generic tools mirror the DRF API. List endpoints return the results list; detail/object endpoints return the object; metadados=True returns the full {count, next, previous, sum_rows, results} envelope.
Tool |
What it does |
|---|---|
minha_conta() |
GET /api/my_account/ — the logged-in account. |
consultar(caminho, parametros?, metadados?) |
GET /api/... (list or object). parametros is the querystring. |
resumo(caminho, campos?, parametros?) |
{count, sum_rows} for the whole filtered set, without the list. |
criar(caminho, dados) |
POST /api/... (registered only when WRITE is on). |
editar(caminho, registro_id, dados) |
PATCH /api/.../<id>/ (registered only when WRITE is on). |
Accepted querystring parametros (combinable): page (100 rows/page), search (text), ordering (- for descending), sum_rows (comma-separated numeric fields), and the grid filter field / operator / value. The three filter keys may each be a list; items match positionally and combine with AND. Common operators: equals, contains, startsWith, endsWith, isAnyOf, is, not, after, before, onOrAfter, onOrBefore, entre ("start,end"), isEmpty, isNotEmpty. field accepts relation paths with __.
# one page of 2026 entries
consultar("/api/movimento/",
{"field": "data", "operator": "entre",
"value": "2026-01-01,2026-12-31", "page": 1})
# count + sums for the whole filter, without the list
resumo("/api/movimento/", ["valor", "valor_bruto"],
{"field": "data", "operator": "entre",
"value": "2026-01-01,2026-12-31"})
Shortcuts
Register project-specific tools with dotted paths; each is a callable taking the MCP Context first (exactly like the generic tools) and is exposed under its own name:
DRBS_MCP = {
"SHORTCUTS": ["myproject.mcp.saldo_ferias"],
# optionally limit/rename the surface:
"TOOLS": ["consultar", "resumo", {"ferias": "saldo_ferias"}],
}
Settings
DRBS_MCP is a single dict; every key is optional.
Key |
Default |
Meaning |
|---|---|---|
WRITE |
False |
Register the write tools (criar/editar). |
TOOLS |
None |
Allowlist of tools to expose. None = all generic (minus writes when WRITE is off) plus every shortcut. A list limits and orders the surface; an entry may rename, e.g. {"buscar": "consultar"}. |
SHORTCUTS |
[] |
Dotted paths to project-specific tool callables. |
RESOURCE_URL |
"/mcp" |
Path (or absolute URL) of the protected resource. |
API_URL |
None |
Base URL the proxy forwards to. None = this request’s origin (the right value when combined with Django); set it for a standalone process. |
SERVER_NAME |
"drf-react-by-schema" |
Name advertised to MCP clients. |
READ_SCOPE / WRITE_SCOPE |
"read" / "write" |
Scope names advertised in the Protected Resource Metadata. |
VALIDATE_TOKEN |
True |
Validate the Bearer token against VALIDATE_PATH before handling a request (so an expired token yields 401). |
VALIDATE_PATH |
"/api/my_account/" |
API path used for that check. |
ALLOWED_HOSTS |
[] |
Transport Host allowlist (anti-DNS-rebinding); empty disables it. |
HOST / PORT |
"127.0.0.1" / 8000 |
Bind address for the standalone entrypoint. |
TIMEOUT |
60 |
Upstream request timeout, in seconds. |
Security model
Stateless proxy — no credentials are stored server-side; the caller’s Bearer token is forwarded to /api/... on every call.
Read-only by default — writes require WRITE=True and a token carrying the write scope and the project’s DRF permissions.
No ``DELETE`` — only GET/POST/PATCH are exposed.
Scope enforcement is the project’s: read for safe methods, write for unsafe ones, via drf_react_by_schema_oauth.permissions.HasScope.
License
GPLv3 — Cooperativa EITA.
Metadata
Release files for drf-react-by-schema-mcp 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| drf_react_by_schema_mcp-0.1.1.tar.gz | 596.4 kB | Details |
Release files / drf_react_by_schema_mcp-0.1.1.tar.gz
| Download URL | drf_react_by_schema_mcp-0.1.1.tar.gz |
|---|---|
| Size | 596.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
37147281c4455119bf23914f5d61a4cef359494fe5e50c465d996e33b6b9c021
|
|
BLAKE2b-256 checksum How to use checksums |
f3531cc3bbb42303353fb35bfb60519500a80d1b7397e4449da210313fcade2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.0.0 CPython/3.12.3
|