Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Django Mcp Kit

БесплатноНе проверен

Turns Django/Wagtail code into MCP tools (and resources) for Claude clients

GitHubEmbed

Описание

Turns Django/Wagtail code into MCP tools (and resources) for Claude clients

README

PyPI version Python versions Django License: MIT

Turns Django/Wagtail code into MCP tools (and resources) for Claude clients — without coupling your business logic to any MCP framework.

  • Transport-neutral core. A registry + dispatcher own initialize / tools.list / tools.call; the official MCP SDK is used only at the wire (transports/sdk.py) and is swappable. No FastMCP.
  • Native Django authz. DRF-style permission_classes checked before run(); object permissions (Wagtail permissions_for_user) stay in your service layer.
  • Pluggable auth. Static bearer tokens and OAuth 2.1 resource server (django-oauth-toolkit) behind one Authenticator interface, with RFC 9728 discovery metadata and the 401 + WWW-Authenticate handshake.
  • On-ramps. Register a DRF ViewSet, expose a model (read-only by default), or declare MCP resources.

Install

pip install django-mcp-kit              # core: MCP SDK wire transport, OAuth, DRF on-ramp, singleserver
pip install "django-mcp-kit[wagtail]"   # + the optional Wagtail admin settings page

Batteries included. The MCP SDK + uvicorn (the only wire transport today), django-oauth-toolkit (OAuth resource server), DRF (the ViewSet/model on-ramp), and singleserver are all core dependencies — their imports stay lazy/contained, so the architectural boundary holds in code even though the packages ship by default. The one optional extra is [wagtail], for the Wagtail admin settings page (Django-only projects don't need Wagtail).

Quickstart

# settings.py
INSTALLED_APPS += ["django_mcp_kit"]
DJANGO_MCP_KIT = {
    "SERVER_NAME": "my-content",
    "AUTH_BACKENDS": [
        "django_mcp_kit.auth.OAuthResourceServer",
        "django_mcp_kit.auth.StaticBearer",
    ],
    "STATIC_BEARER_RESOLVER": "myapp.models:UserProfile.user_for_token",
    "OAUTH_ISSUER_URL": "https://example.com",
    "RESOURCE_SERVER_URL": "https://example.com/mcp",
    "REQUIRED_SCOPES": ["mcp"],
}

# urls.py — discovery + health for the Django site
path("", include("django_mcp_kit.urls")),  # /healthz, /.well-known/oauth-protected-resource
# myapp/mcp_tools.py — autodiscovered on app load
from django_mcp_kit import Tool, Schema, tool
from . import services

class PatchBlock(Tool):
    name = "patch_block"
    description = "Replace one homepage block by id; saves a DRAFT."

    class Input(Schema):
        block_id: str
        value: dict

    def run(self, user, block_id, value):           # sync — runs off the event loop
        return services.save_homepage_draft(user, block_id=block_id, value=value)

@tool(name="get_draft", description="Latest homepage draft.")
def get_draft(user) -> dict:
    return services.homepage_draft()
# Register a DRF ViewSet (one tool per action) or a model (read-only by default)
from django_mcp_kit.drf import register_drf_viewset
from django_mcp_kit.models import ModelToolset

register_drf_viewset(OrderViewSet, prefix="order")  # order_list, order_create, …

class ProductToolset(ModelToolset):
    model = Product
    actions = ["list", "retrieve"]   # add "create"/"update"/"delete" to opt in
    as_resource = True

Run it

python manage.py runserver_mcp --port 8810      # ASGI/uvicorn MCP process

Deployment

The MCP endpoint is always ASGI (Streamable HTTP uses SSE), but how it runs is a choice. All topologies run the same code — runserver_mcp serving the app from django_mcp_kit.asgi:get_application — only the process management differs. Pick by how your site is served and how much isolation you want:

Topology Site stays WSGI Process Best for
A — Co-located no (site → ASGI) one ASGI process single-service / already-ASGI sites
B — singleserver aux yes gunicorn boots the MCP process, workers share it dev == prod, no systemd
C — separate systemd unit yes independent ASGI daemon production SSE (recommended)

Health checks point at /healthz (a plain 200) — never /mcp, which is the Streamable-HTTP endpoint and returns 4xx to a bare GET.

A — Co-located (one ASGI process)

Mount the MCP app beside your Django ASGI app; requests to /mcp (and /healthz, /.well-known/...) go to MCP, everything else to Django:

# asgi.py
from django.core.asgi import get_asgi_application
from django_mcp_kit.asgi import mount

application = mount(get_asgi_application())   # serves /mcp on the same process

B — singleserver-managed aux (deploy/gunicorn.conf.py)

Your site stays WSGI/gunicorn. The first gunicorn worker boots the MCP process; all workers share it via an atomic socket lock (no systemd). Wire it in post_fork:

# gunicorn.conf.py
def post_fork(server, worker):
    from django_mcp_kit.services import connect
    connect()

Point your front-end proxy /mcp at DJANGO_MCP_KIT["PORT"] (default 8810). The shipped SingleServer uses health_check_url="/healthz" and a bounded graceful shutdown.

C — Separate systemd unit (deploy/django-mcp.service)

Run the MCP server as its own daemon — decoupled lifecycle, real graceful restart. The sample unit runs runserver_mcp with a bounded --timeout-graceful-shutdown (so long-lived SSE streams don't stall stop/restart) and Restart=always. Edit the paths/user, then:

sudo cp deploy/django-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now django-mcp

nginx (deploy/nginx-mcp.conf)

For B and C, proxy /mcp to the MCP process. SSE requires buffering off and long read timeouts — the sample sets proxy_buffering off and proxy_read_timeout 3600s, and also proxies the /.well-known/oauth-protected-resource metadata. Add it inside your server {} block and reload nginx.

Authorization Server (OAuth) setup

This library is the Resource Server — it validates bearer tokens and serves the RFC 9728 discovery metadata. It does not provide the Authorization Server (the login, /o/authorize, /o/token, and the consent page). That role is django-oauth-toolkit (DOT), which ships as a dependency but must be wired up by the project:

# settings.py
INSTALLED_APPS += ["oauth2_provider"]
OAUTH2_PROVIDER = {
    "SCOPES": {"mcp": "Access MCP tools"},
    "PKCE_REQUIRED": True,   # public clients (browser/native, e.g. claude.ai)
}

# urls.py — mount the Authorization Server endpoints
path("o/", include("oauth2_provider.urls", namespace="oauth2_provider")),

Provisioning the OAuth client

Register an OAuth client (a DOT Application) per connector with the bundled command — idempotent, public + PKCE by default:

python manage.py create_mcp_oauth_client https://claude.ai/api/mcp/auth_callback \
    --name "My connector"        # name shown on the consent page; --skip-consent to auto-approve

The client name defaults to DJANGO_MCP_KIT["OAUTH_APP_NAME"] ("MCP connector") when --name is omitted. The command prints the Client ID to paste into the connector. django_mcp_kit.oauth_client.ensure_oauth_application(...) is the same helper if you'd rather provision from code.

The consent page

The consent screen is rendered by DOT's AuthorizationView at /o/authorize/ using its default template oauth2_provider/authorize.html (a plain approve/deny form). Whether it appears is controlled per-client by Application.skip_authorization:

  • skip_authorization=False (DOT default) — the user is shown the consent page on first authorization.
  • skip_authorization=True — consent is auto-approved (no page). Reasonable for a trusted first-party connector.

The name shown on that consent page is the Application.name — set it per client with create_mcp_oauth_client --name, or change the default via DJANGO_MCP_KIT["OAUTH_APP_NAME"]. To customise the consent UI, override oauth2_provider/authorize.html in your own templates directory. This library has no opinion on and no default for the consent page — it only consumes the access token DOT issues.

Configuring it from the Wagtail admin (optional)

For Wagtail projects, add the optional app to get a "MCP connector" page under the admin Settings menu that provisions/updates the client on save:

pip install "django-mcp-kit[wagtail]"    # Wagtail 6.x or 7.x
INSTALLED_APPS += ["django_mcp_kit.wagtail_connector"]
# then: python manage.py migrate

Fields: enable, the consent-page name, redirect URIs, and skip-consent. Access is gated by the change_mcpconnectorsettings permission — i.e. superusers only by default; delegate to specific staff by granting that permission via a Group. Wagtail is not a core dependency — it's the optional [wagtail] extra, so Django-only projects skip it.

Develop

poetry install
poetry run pytest

from github.com/Technology-Company/django-mcp-kit

Установка Django Mcp Kit

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/Technology-Company/django-mcp-kit

FAQ

Django Mcp Kit MCP бесплатный?

Да, Django Mcp Kit MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Django Mcp Kit?

Нет, Django Mcp Kit работает без API-ключей и переменных окружения.

Django Mcp Kit — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Django Mcp Kit в Claude Desktop, Claude Code или Cursor?

Открой Django Mcp Kit на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Django Mcp Kit with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development