django-admin-mcp-api

django-admin-mcp-api

Exposes Django admin's ModelAdmin as MCP tools, with identical permissions, form validation, and session authentication.

Category
Visit Server

README

django-admin-mcp-api

An MCP server for the Django admin β€” same permissions, same ModelAdmin, no new features.

PyPI version Python versions Django versions License: MIT MCP protocol Wire contract: stable Latest on Django Packages

django-admin-mcp-api lets AI agents β€” Claude, Cursor, anything that speaks the Model Context Protocol β€” drive your Django admin. Every ModelAdmin you've already registered on django.contrib.admin.site becomes an MCP tool, with the same permissions, the same form validation, and the same session auth as the HTML admin.

It is the MCP face on top of django-admin-rest-api. No parallel permission system. No parallel form layer. No features the Django admin doesn't already have.

Project Role PyPI
🟦 django-admin-react React single-page admin frontend django-admin-react
🟩 django-admin-rest-api JSON REST API over ModelAdmin django-admin-rest-api
πŸŸͺ django-admin-mcp-api (this repo) MCP server exposing the same API to LLMs django-admin-mcp-api

✨ The one design principle

This package adds no new behavior. It is an MCP wire adapter.

Every one of these is owned by your existing Django setup β€” not by this library:

  • πŸ” Authentication β€” Django's session + login. The MCP endpoint enforces the same is_active + is_staff + AdminSite.has_permission gate the HTML admin uses. No tokens, no custom backends, no JWTs.
  • πŸ›‘οΈ Authorization β€” every tool delegates to the matching ModelAdmin.has_view_permission / has_add_permission / has_change_permission / has_delete_permission via django-admin-rest-api. If your admin says no, the tool returns the upstream 403.
  • πŸ“‹ Field validation β€” admin.create / admin.update route the payload through the same ModelForm Django would render in the HTML admin, plus a JSON Schema check on the wire so malformed calls fail fast with a json-pointer path of the offending field.
  • βš™οΈ Actions β€” admin.action runs the same action callables registered on ModelAdmin.actions. Your code runs unmodified. Each action's descriptor carries a target (batch or detail), derived by rest-api from the callable's signature: signatures ending in queryset are batch (changelist shape), signatures ending in obj_id/pk/id are detail (single-object shape). Agents pass the right number of pks for the action's target.
  • πŸ”Ž Search & filters β€” admin.list uses ModelAdmin.get_search_results and list_filter. No parallel implementation.
  • πŸ“œ Audit log β€” writes go through Django's LogEntry, surfaced by admin.history and admin.recent_actions.
  • 🌐 CSRF & sessions β€” Django's middleware. Nothing is @csrf_exempt.

If a behavior isn't in the HTML admin, it isn't here. If it is in the HTML admin, this library exposes it over MCP.


πŸš€ Plug-and-play install

pip install django-admin-mcp-api

Two changes to your project:

# settings.py
INSTALLED_APPS = [
    # ... your existing apps ...
    "django.contrib.admin",
    "django_admin_rest_api",         # ← the REST surface (mandatory)
    "django_admin_mcp_api",          # ← the MCP adapter
]
# urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/",  admin.site.urls),
    path("",        include("django_admin_rest_api.urls")),    # REST
    path("mcp/",    include("django_admin_mcp_api.urls")),     # MCP
]

That's it. Your admin now answers JSON-RPC at POST /mcp/, with the same session cookie and CSRF token your HTML admin already uses.


πŸ“‘ The 16 tools

Each MCP tool is a 1:1 mirror of a django-admin-rest-api endpoint β€” that's the whole design.

MCP tool What it does rest-api endpoint
admin.registry List every model the user can see GET /api/v1/registry/
admin.schema Full admin metadata schema GET /api/v1/schema/
admin.recent_actions The user's own LogEntry feed GET /api/v1/recent-actions/
admin.list A page of list-view results GET /api/v1/<app>/<model>/
admin.retrieve A single object's detail view GET /api/v1/<app>/<model>/<pk>/
admin.add_form Create-page field descriptors GET /api/v1/<app>/<model>/add/
admin.create Create one object POST /api/v1/<app>/<model>/
admin.update Partial-update one object PATCH /api/v1/<app>/<model>/<pk>/
admin.destroy Delete one object DELETE /api/v1/<app>/<model>/<pk>/
admin.bulk_update Apply the same patch to many objects PATCH /api/v1/<app>/<model>/bulk/
admin.autocomplete Autocomplete a related model GET /api/v1/<app>/<model>/autocomplete/
admin.action Run a ModelAdmin.actions action (batch or detail) POST /api/v1/<app>/<model>/actions/<name>/
admin.history One object's LogEntry timeline GET /api/v1/<app>/<model>/<pk>/history/
admin.delete_preview Cascade preview before a destroy GET /api/v1/<app>/<model>/<pk>/delete-preview/
admin.set_password Set/change a user-like password POST /api/v1/<app>/<model>/<pk>/password/
admin.panel A custom panel registered on the ModelAdmin GET /api/v1/<app>/<model>/<pk>/panel/<name>/

Two endpoints expose them β€” both gated by the same auth your admin already has:

  • POST /mcp/ β€” the MCP JSON-RPC 2.0 entry point. Speaks initialize, tools/list, tools/call. Full wire spec in docs/api-contract.md.
  • GET /mcp/manifest/ β€” a read-only catalogue (server info + every tool's name, description, JSON Schema) for humans and dashboards.

πŸ“Έ See it run

Captured against the examples/quickstart/ demo β€” fresh pip install, runserver, python smoke.py. No mocks.

// POST /mcp/  method=initialize
{
  "jsonrpc": "2.0", "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo":      { "name": "django-admin", "version": "1.0.2" },
    "capabilities":    { "tools": { "listChanged": false } }
  }
}

// POST /mcp/  method=tools/call  name=admin.registry
{
  "jsonrpc": "2.0", "id": 1,
  "result": {
    "content": [{ "type": "json", "json": {
      "user":  { "id": 1, "username": "admin", "is_staff": true },
      "apps":  [
        { "app_label": "auth",
          "models": [
            { "model_name": "group",
              "permissions": { "view": true, "add": true, "change": true, "delete": true } },
            { "model_name": "user",
              "permissions": { "view": true, "add": true, "change": true, "delete": true } }
          ] }
      ]
    } }],
    "isError": false,
    "status":  200
  }
}

The permissions block above comes straight from ModelAdmin.has_*_permission β€” the MCP layer doesn't decide a thing about authorization. That's the prime directive.


βš™οΈ Configuration

All settings live under a single optional dict β€” defaults are sane, so most projects need no entry at all.

# settings.py (all keys optional)
DJANGO_ADMIN_MCP_API = {
    # MCP protocol version advertised in the `initialize` result.
    "PROTOCOL_VERSION":  "2024-11-05",

    # The `serverInfo.name` field. Useful per-environment labelling.
    "SERVER_NAME":       "django-admin",

    # The `serverInfo.version`. None β†’ falls back to the package version.
    "SERVER_VERSION":    None,

    # Dotted path to the AdminSite the package introspects.
    "ADMIN_SITE":        "django.contrib.admin.site",

    # Dotted path to a zero-arg callable returning a Dispatcher.
    # None uses the built-in RestApiDispatcher.
    "DISPATCHER_FACTORY": None,
}

A copy-paste-ready block lives at the bottom of examples/quickstart/myproject/settings.py.


πŸ”’ Security

  • The MCP endpoint is not a parallel auth surface. It refuses any caller the HTML admin would refuse, with the same gate.
  • Anonymous β†’ 401. Authenticated but non-staff β†’ 403. CSRF missing on POST β†’ Django's middleware 403.
  • Every tools/call is validated against the tool's JSON Schema before it reaches the database. Schema violations return INVALID_PARAMS with the json-pointer path of the failing field.
  • The dispatcher carries the caller's session / user / cookies / CSRF state to django-admin-rest-api untouched. Per-tool permission is enforced inside rest-api by the relevant ModelAdmin.has_*_permission.
  • CSRF is enforced everywhere. No view in this package is @csrf_exempt β€” a pre-commit hook and a test assert this.
  • No token-shaped string is permitted in the repo (gitleaks + a pygrep hook + tests/test_security.py).

Threat model: docs/threat-model.md. Report a vulnerability privately here.


πŸ§ͺ Local development

git clone https://github.com/MartinCastroAlvarez/django-admin-mcp-api
cd django-admin-mcp-api
poetry install
poetry run pytest
poetry run bash scripts/lint.sh
poetry run bash scripts/audit-deps.sh

77 tests, 91% line coverage, including a real end-to-end run through django-admin-rest-api. CI runs the same suite across Python 3.10–3.13 Γ— Django 5.0/5.1/5.2/6.0 on every PR.


🀝 Contributing

Issues, PRs, and the roadmap are on GitHub:

The lint + security gate is the same set the upstream django-admin-rest-api and django-admin-react repos use: ruff, black, isort, flake8, pylint, mypy, bandit, pip-audit, gitleaks. Every change must pass all of them before merge.


πŸ“œ License

MIT. See LICENSE.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured