Skip to main content
Glama
edelvalle

django-admin-fastmcp

by edelvalle

django-admin-fastmcp

Eine wiederverwendbare Django-App, die die Django-Admin-Oberfläche als MCP-Server bereitstellt, basierend auf FastMCP.

Jeder Tool-Aufruf läuft als der Staff-Benutzer, dem das Bearer-Token gehört. Jeder Tool-Aufruf fragt zuerst den ModelAdmin um Erlaubnis. Ein Superuser kann alles tun, was ein Superuser im Admin tun kann. Ein Staff-Benutzer kann genau das tun, was dieser Staff-Benutzer im Admin tun kann, und nicht mehr.

SPEC.md ist die vollständige Spezifikation.

So funktioniert es

Drei Regeln definieren das Paket:

  1. Kein paralleles Berechtigungssystem. Die Autorisierung delegiert an die ModelAdmin-Methoden: has_view_permission, has_add_permission, has_change_permission, has_delete_permission, get_queryset, get_readonly_fields und get_actions. Eine get_queryset-Überschreibung, die Zeilen verbirgt, verbirgt sie auch vor MCP.

  2. Keine parallele Datenoberfläche. Schreibvorgänge laufen über das eigene ModelForm des Admins und save_model und protokollieren dann einen LogEntry. Die Admin-Verlaufsseite bleibt wahrheitsgemäß.

  3. Fail closed. Jede unaufgelöste Suche, fehlender ModelAdmin, unbekannte Aktion, unbekanntes Feld und unbekanntes Tool verweigert den Aufruf.

Installation

uv add django-admin-fastmcp

Fügen Sie die App zu Ihren Einstellungen hinzu:

INSTALLED_APPS = [
    ...,
    "django.contrib.admin",
    "django_admin_fastmcp",
]

ADMIN_FASTMCP = {
    "SERVER_NAME": "acme-admin",
    "EXCLUDE_MODELS": ("auth.Permission", "auth.Group"),
    "WRITABLE_MODELS": (),          # empty means no writes at all
}

Mounten Sie die OAuth-Endpunkte auf derselben Site wie den Admin:

# urls.py
urlpatterns = [
    # RFC 8414 fixes this one at the site root.
    path("", include("django_admin_fastmcp.well_known_urls")),
    # This prefix is yours to choose. Match it to the path in MCP_URL.
    path("admin/mcp/", include("django_admin_fastmcp.urls")),
    path("admin/", admin.site.urls),
]

Das Paket legt kein Präfix fest. Jede URL, die das Metadaten-Dokument bewirbt, stammt von reverse(), sodass ein Projekt, das die Endpunkte unter /backoffice/oauth/ mountet, dies in der Discovery erhält und Clients dem folgen. Zwei Regeln: Das Well-Known-Dokument gehört an die Wurzel, weil ein Client seine URL vom Issuer ableitet, und die Endpunkte sollten auf derselben Site wie der Admin liegen, weil die Zustimmungsseite auf dem Admin-Session-Cookie reitet.

Wenden Sie die Migrationen an:

python manage.py migrate django_admin_fastmcp

Sonst nichts. Keine Pro-Modell-Registrierung, kein Mixin, keine Dekorateure. Der Server stellt genau das bereit, was der Admin bereits bereitstellt.

Einen Client verbinden

Starten Sie den Server (siehe Bereitstellung) und registrieren Sie ihn dann:

# Claude Code
claude mcp add --transport http acme-admin https://<host>/admin/mcp

Verwenden Sie den Pfad ohne abschließenden Schrägstrich. /admin/mcp/ antwortet mit einer 307-Weiterleitung auf /admin/mcp, und nicht jeder Client folgt einer Weiterleitung bei POST.

Kein Token, kein Header. Der erste Aufruf startet den standardmäßigen MCP-OAuth-Ablauf:

  1. Der Client öffnet Ihren Browser auf der Autorisierungsseite auf der Django-Site.

  2. Ihr Admin-Session-Cookie identifiziert Sie. Wenn Sie abgemeldet sind, erscheint zuerst die normale Admin-Anmeldung.

  3. Eine Zustimmungsseite zeigt den Client-Namen und was die Genehmigung bedeutet. Sie stimmen zu.

  4. Der Client erhält seine Tokens und verbindet sich. Er erneuert sie selbstständig.

Jeder MCP-Client, der streambares HTTP mit OAuth spricht, funktioniert auf die gleiche Weise, zum Beispiel Cursor oder ein FastMCP-Client.

Regeln zum Zugriff:

  • Jeder Staff-Benutzer kann einen Client autorisieren, nur für sich selbst.

  • Eine Genehmigung handelt mit Ihren eigenen Admin-Berechtigungen, niemals mehr. Es gibt kein separates Berechtigungssystem: Wer ein Modell im Admin ändern darf, darf es auch über MCP ändern, wenn der Server dieses Modell in WRITABLE_MODELS auflistet.

  • Refresh-Tokens laufen nach REFRESH_TOKEN_TTL_DAYS (Standard 90) ab, sodass eine erneute Zustimmung so oft erfolgt. Der Widerruf ist eine Admin-Aktion auf der Genehmigungs-Changelist.

Tools

Elf generische Tools, gemountet unter dem Namensraum admin, sodass die Drahtnamen admin_list_models usw. sind. Jedes nimmt model als "app_label.ModelName" entgegen. Die Tool-Liste ist statisch. Was pro Benutzer variiert, ist, was jedes Tool diesem Benutzer erlaubt zu sehen und zu tun.

Lesen

Tool

Argumente

Rückgabe

list_models

keine

Jedes freigegebene Modell, das dieser Aufrufer anzeigen darf, mit Berechtigungsflags.

describe_model

model

Felder, Listendarstellung, Filter, Suchfelder, schreibgeschützte Felder und verfügbare Aktionen.

search_objects

model, q, filters, order_by, page, page_size

Zeilen plus total. q verwendet die eigene Suche des Admins. Ein unbekannter Filter ist ein Fehler.

get_object

model, pk

Eine serialisierte Instanz.

object_history

model, pk

Admin-Log-Einträge für dieses Objekt, neueste zuerst.

recent_actions

limit

Admin-Log-Einträge, auf den Aufrufer beschränkt, es sei denn, der Aufrufer ist ein Superuser.

Schreiben

Schreib-Tools benötigen das Modell in WRITABLE_MODELS; Ihre eigenen Admin-Berechtigungen entscheiden den Rest, pro Modell und pro Objekt. Ein Modell außerhalb der Liste verweigert jeden Schreibvorgang und jede Aktion, wer auch immer aufruft. Lassen Sie sensible Modelle außen vor, z. B. ein Ereignisprotokoll, und kein MCP-Client kann jemals darauf schreiben.

Tool

Argumente

Verhalten

create_object

model, data

Validiert über das Admin-Formular, speichert dann und protokolliert.

update_object

model, pk, data

Teilweises Update. Schreibgeschützte Felder werden ignoriert.

delete_object

model, pk, confirm

Ohne confirm wird die genaue Löschkaskade zurückgegeben und nichts geändert.

run_action

model, action, pks, confirm

Führt eine Admin-Aktion aus. Ohne confirm wird eine Vorschau zurückgegeben.

autocomplete

model, field, q

Löst einen Fremdschlüsselwert in einen Primärschlüssel auf, indem das zugehörige Modell durchsucht wird.

Jede zurückgegebene Zeile trägt pk als Zeichenfolge und eine admin_url, sodass ein Agent einer Person einen Link in den echten Admin übergeben kann.

Einstellungen

Alle Schlüssel leben im ADMIN_FASTMCP-Wörterbuch. Ein unbekannter Schlüssel ist ein Fehler beim Start.

Schlüssel

Standard

Bedeutung

SERVER_NAME

"django-admin"

Name, den der MCP-Server bewirbt.

ADMIN_SITE

"django.contrib.admin.site"

Gepunkteter Pfad zur AdminSite.

MODELS

()

Whitelist von "app_label.ModelName". Wenn nicht leer, wird nichts anderes freigegeben.

EXCLUDE_MODELS

()

Blacklist. Unterstützt "app_label.*".

WRITABLE_MODELS

()

Modelle, die Schreibvorgänge akzeptieren. Leer bedeutet keine Schreibvorgänge, wer auch immer aufruft.

DISABLED_TOOLS

()

Tool-Namen, die vollständig aus dem Katalog entfernt werden.

REDACT_FIELDS

("password", "token", "secret", "api_key", "private_key")

Teilstring-Übereinstimmung auf Feldnamen. Werte lesen "[redacted]".

MAX_PAGE_SIZE

200

Obergrenze für die Seitengröße von search_objects.

MAX_PKS

1000

Obergrenze für pks pro run_action.

ACCESS_TOKEN_TTL_MINUTES

60

Lebensdauer des Zugriffstokens. Clients erneuern es mit dem Refresh-Token.

REFRESH_TOKEN_TTL_DAYS

90

Lebensdauer des Refresh-Tokens. Eine erneute Zustimmung erfolgt so oft.

SITE_URL

"http://127.0.0.1:8000"

Öffentliche URL der Django-Site. Sie ist der OAuth-Issuer, und der MCP-Server nennt sie als seinen Autorisierungsserver.

MCP_URL

"http://127.0.0.1:8765/admin/mcp"

Öffentliche URL des MCP-Endpunkts.

Setzen Sie SITE_URL und MCP_URL für jede echte Bereitstellung. MCP_URL ist die einzige Quelle für drei Dinge, die übereinstimmen müssen: den Pfad, auf dem der Endpunkt bereitgestellt wird, die resource, die die Discovery bewirbt, und die Zielgruppe, an die jedes Token gebunden ist. Sein Pfad standardmäßig auf /admin/mcp. Ein Startcheck verweigert eine MCP_URL ohne Pfad, weil dann die gesamte Herkunft als geschützte Ressource beworben würde.

Pro-ModelAdmin-Einstellungen

Setzen Sie diese auf einer ModelAdmin-Klasse, kein Mixin erforderlich:

class InvoiceAdmin(admin.ModelAdmin):
    mcp_expose = False                     # hide this model from MCP entirely
    mcp_fields = ("number", "total")       # allowlist of serialized fields
    mcp_exclude_fields = ("internal_note",)  # denylist of serialized fields

REDACT_FIELDS gewinnt über mcp_fields. Ein Passwortfeld explizit aufzulisten, offenbart es nicht.

Sicherheit

Ein Admin-MCP-Server für einen Superuser ist eine Remote-Shell über der Produktionsdatenbank, gesteuert von einem Sprachmodell. Die Leitplanken:

  • WRITABLE_MODELS ist standardmäßig leer, sodass kein Modell Schreibvorgänge akzeptiert, bis die Bereitstellung es benennt. Alles andere sind Ihre gewöhnlichen Django-Berechtigungen, die über den ModelAdmin bei jedem Aufruf abgefragt werden.

  • Zugriffstokens sind kurzlebig. Es werden nur gesalzene Hashes gespeichert, sodass eine durchgesickerte Datenbankzeile nicht wiederverwendet werden kann.

  • delete_object und run_action zeigen standardmäßig eine Vorschau und ändern nichts, bis confirm=True.

  • Jede Mutation protokolliert einen LogEntry, der dem Benutzer der Genehmigung zugeordnet ist, mit dem Client-Namen in der Änderungsnachricht, z. B. "Status geändert. Über MCP (Client: Claude Code).". Ein Schreibvorgang, der keinen LogEntry protokollieren kann, wird zurückgerollt.

  • Die eigenen Modelle des Pakets, sessions.Session und authtoken.Token werden niemals freigegeben, was auch immer die Einstellungen sagen.

  • Halten Sie auth.Permission und auth.Group aus WRITABLE_MODELS heraus. Ein Agent, der Berechtigungen erteilen kann, kann dem Berechtigungsmodell entkommen.

Bereitstellung

Separater Prozess. Führen Sie den MCP-Server neben Ihrem Django-Projekt aus:

python manage.py admin_mcp_serve

Er bedient den Pfad von MCP_URL, standardmäßig /admin/mcp, auf dem Port von MCP_URL oder 8765, wenn diese URL keinen Port nennt. Beide sind mit --host und --port überschreibbar. Nichts an Ihrer bestehenden Serving-Konfiguration ändert sich. Leiten Sie /admin/mcp über Ihren Ingress zu diesem Port und stellen Sie sicher, dass der Authorization-Header durchgereicht wird.

Gemountet (M3). Mounten Sie den Server unter /admin/mcp in der asgi.py Ihres Projekts. Eine Einschränkung: Dispatch auf den genauen Pfad. Die OAuth-Endpunkte liegen direkt unter demselben Präfix (/admin/mcp/authorize und Verwandte) und Django muss diese weiterhin bedienen, sodass ein Dispatcher, der alles unter /admin/mcp an FastMCP sendet, sie verschlucken würde. Das Rezept wird mit Meilenstein M3 geliefert.

Der Server ist zustandslos, sodass jede Instanz hinter einem Lastenausgleicher jede Anfrage bedienen kann.

Entwicklung

make install     # bootstrap uv, pin Python, install dependencies
make test        # run the permission matrix
make check       # format, lint, typecheck, and test
make migrate     # migrate the test project
make serve       # run the MCP server against the test project on :8765/admin/mcp
make help        # everything else

Lizenz

MIT

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server for AI dialogue using various LLM models via AceDataCloud

  • An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/edelvalle/django-admin-fastmcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server