django-spec-mcp¶
Serve django-service-specs
services and selectors as a Model Context Protocol
(MCP) server, conforming to MCP 2026-07-28 and 2025-11-25 (Streamable HTTP).
Coming from drf-mcp?
This package is djangorestframework-mcp-server moved onto the kernel.
Moving from drf-mcp lists what a project has to
change, starting with the live state its first deploy drops.
What this is¶
django-service-specs is the kernel: a Django project declares each operation
once as a spec. A ServiceSpec is a mutation, a side-effecting callable; a
SelectorSpec is a read. The spec carries what the operation takes (a
Validator, or reads declared as Parameters), who may run it (its
permissions, kernel PermissionChecks), and what it returns (a
Presenter), and the kernel's dispatch runs it the same way for every
transport.
django-spec-mcp is the MCP transport over those specs. It mounts a single
/mcp endpoint that speaks Streamable HTTP per the MCP spec, and registers
your specs as MCP tools and resources. The endpoints are plain Django views,
and the unit of registration is the spec, not a view.
When to use it¶
Reach for this package when:
- Your project declares its operations as
django-service-specsspecs (or is about to) and you want to expose them to an MCP-aware client (Claude Desktop, Inspector, Cursor, etc.). - You want a single, spec-compliant
/mcpendpoint with pluggable auth (anMCPAuthBackendfor the authorization server you run) 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_tool, over a kernelServiceSpec(mutations) orSelectorSpec(reads, with an optionalFilterSet, ordering and pagination).register_toolsregisters every spec in a kernelSpecRegistry. - Resources —
resources/list,resources/templates/list,resources/readagainst a kernelRETRIEVESelectorSpec; RFC 6570 templated URIs whose variables are the spec's reads. - Prompts —
prompts/list,prompts/getagainst render callables returning strings,PromptMessages, or async coroutines. - Discovery —
server/discover, the 2026-07-28 revision's replacement for theinitializehandshake. Answered without a session, so a modern client can lead with it. - Argument completion —
completion/completeagainst per-argument completers on prompts and resource templates. - Pluggable auth — an
MCPAuthBackendverifies the bearer token;AllowAnyBackend(dev only) ships, andbearer_challengebuilds the 401 challenge a backend of your own answers with. A tool or resource is guarded by its spec's own kernelpermissions, andscopes=at registration adds an OAuth scope gate. - RFC 8707 audience binding through
audience_matches, which a backend calls; RFC 9728 PRM served from the configured backend. - Per-binding rate limits —
MCPRateLimitProtocol withFixedWindowRateLimit,SlidingWindowRateLimit, andTokenBucketRateLimitimplementations shipped. - 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 transport rules of both revisions.
2026-07-28and later declare version, identity and capabilities on every request and hold no session;2025-11-25and earlier negotiate once throughinitialize. Both are served concurrently on one endpoint, because a legacy client has no fall-forward mechanism.
Install¶
pip install django-spec-mcp # base install
pip install "django-spec-mcp[redis]" # +Redis SSE broker for multi-worker ASGI
pip install "django-spec-mcp[otel]" # +OpenTelemetry instrumentation
pip install "django-spec-mcp[redis,otel]" # everything
…or with uv:
uv add django-spec-mcp # base install
uv add "django-spec-mcp[redis]" # +Redis SSE broker for multi-worker ASGI
uv add "django-spec-mcp[otel]" # +OpenTelemetry instrumentation
uv add "django-spec-mcp[redis,otel]" # everything
Optional extras degrade gracefully:
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 spec needsdjango-filter, which the kernel'sfilterextra installs; nothing else here imports it.
Where to next¶
- Quickstart — copy-pasteable end-to-end recipe.
- Moving from drf-mcp — what a project on
djangorestframework-mcp-serverchanges to move across. - Concepts — tools vs resources, sessions, tool results, origin allowlist.
- Authentication — backends, permissions, RFC 9728 PRM, RFC 8707 audience binding.
- Recipes — opinionated cookbook entries.
- Reference — autodocs for
MCPServerand the protocol types.