djangorestframework-mcp-server¶
Expose djangorestframework-services
services and selectors as a Model Context Protocol
(MCP) server, conforming to MCP 2025-11-25 (Streamable HTTP).
What this is¶
djangorestframework-services lets a Django project expose services (mutations,
side-effecting callables) and selectors (read callables) as a thin layer above
DRF. Both are registered through ServiceSpec and dispatched via
inspect.signature so any callable that names the kwargs it wants (request,
user, data, instance, …) just works.
djangorestframework-mcp-server is an alternate transport over the same primitives.
It mounts a single /mcp endpoint that speaks Streamable HTTP per the MCP
spec, and registers your ServiceSpecs as MCP tools and resources. It does not
walk DRF viewsets or routers — the unit of registration is the ServiceSpec,
not a view.
When to use it¶
Reach for this package when:
- Your project already uses
ServiceViewSet(or plainServiceSpecdefinitions) and you want to expose those callables to an MCP-aware client (Claude Desktop, Inspector, Cursor, etc.). - You want a single, spec-compliant
/mcpendpoint with pluggable auth (django-oauth-toolkit out of the box) and a small surface that you can audit. - You don't want to rewrite your service layer in a parallel framework.
Skip it when you don't need the MCP wire format — call your services directly.
What ships¶
- Tools —
tools/list,tools/callforregister_service_tool(mutations) andregister_selector_tool(reads, with optionalFilterSet+ ordering + pagination). - Resources —
resources/list,resources/templates/list,resources/readagainstSelectorSpec-backed callables; RFC 6570 templated URIs. - Prompts —
prompts/list,prompts/getagainst render callables returning strings,PromptMessages, or async coroutines. - Pluggable auth —
DjangoOAuthToolkitBackend(default whenoauth2_provideris installed) andAllowAnyBackend(dev only). Per-bindingMCPPermissionclasses (ScopeRequired,DjangoPermRequired) plus your own. - RFC 8707 audience binding when
RESOURCE_URLis configured; RFC 9728 PRM served from the configured backend. - Per-binding rate limits —
MCPRateLimitProtocol withFixedWindowRateLimit,SlidingWindowRateLimit, andTokenBucketRateLimitimplementations shipped. - Output formats — JSON (default) and TOON (token-oriented; optional extra with safe JSON fallback).
- Async POST/DELETE + GET-side SSE push — sync
urlsfor WSGI,async_urlsfor ASGI;MCPServer.notify(session_id, payload)pushes JSON-RPC frames on the session's SSE stream. Per-workerInMemorySSEBrokeror cross-workerRedisSSEBroker(behind[redis]);Last-Event-IDresume viaInMemorySSEReplayBuffer/RedisSSEReplayBuffer. - OpenTelemetry instrumentation —
mcp.tools.call,mcp.resources.read,mcp.prompts.getspans (no-op without the[otel]extra installed). - Origin allowlist + protocol-version validation + session lifecycle per the 2025-11-25 transport rules.
Install¶
pip install djangorestframework-mcp-server # JSON only
pip install "djangorestframework-mcp-server[toon]" # +TOON encoder
pip install "djangorestframework-mcp-server[oauth]" # +django-oauth-toolkit backend
pip install "djangorestframework-mcp-server[redis]" # +Redis SSE broker for multi-worker ASGI
pip install "djangorestframework-mcp-server[otel]" # +OpenTelemetry instrumentation
pip install "djangorestframework-mcp-server[filter]" # +django-filter for selector-tool FilterSets
pip install "djangorestframework-mcp-server[spectacular]" # +drf-spectacular schema overrides
pip install "djangorestframework-mcp-server[toon,oauth,redis,otel,filter,spectacular]" # everything
…or with uv:
uv add djangorestframework-mcp-server # JSON only
uv add "djangorestframework-mcp-server[toon]" # +TOON encoder
uv add "djangorestframework-mcp-server[oauth]" # +django-oauth-toolkit backend
uv add "djangorestframework-mcp-server[redis]" # +Redis SSE broker for multi-worker ASGI
uv add "djangorestframework-mcp-server[otel]" # +OpenTelemetry instrumentation
uv add "djangorestframework-mcp-server[filter]" # +django-filter for selector-tool FilterSets
uv add "djangorestframework-mcp-server[spectacular]" # +drf-spectacular schema overrides
uv add "djangorestframework-mcp-server[toon,oauth,redis,otel,filter,spectacular]" # everything
Optional extras degrade gracefully:
- TOON falls back to JSON with a runtime warning if
python-toonis not installed. - The OAuth backend module imports cleanly without
oauth2_provider; theImportErroronly fires if you actually configure the backend and a request reachesauthenticate(). RedisSSEBroker/RedisSSEReplayBufferraise a clearImportErrorfrom__init__ifredisisn't installed.- The OTel tracing helper yields a no-op span when
opentelemetry-apiisn't importable, so handlers stay branch-free. filter_set=on a selector tool raises a clearImportErroronly if you declare it withoutdjango-filterinstalled.
Where to next¶
- Quickstart — copy-pasteable end-to-end recipe.
- Concepts — tools vs resources, sessions, output formats, origin allowlist.
- Authentication — backends, permissions, RFC 9728 PRM, RFC 8707 audience binding.
- Recipes — opinionated cookbook entries.
- Reference — autodocs for
MCPServerand the protocol types.