django-admin-mcp-api
Exposes Django admin's ModelAdmin as MCP tools, with identical permissions, form validation, and session authentication.
README
django-admin-mcp-api
An MCP server for the Django admin β same permissions, same
ModelAdmin, no new features.
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_permissiongate 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_permissionvia django-admin-rest-api. If your admin says no, the tool returns the upstream 403. - π Field validation β
admin.create/admin.updateroute the payload through the sameModelFormDjango 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.actionruns the same action callables registered onModelAdmin.actions. Your code runs unmodified. Each action's descriptor carries atarget(batchordetail), derived by rest-api from the callable's signature: signatures ending inquerysetare batch (changelist shape), signatures ending inobj_id/pk/idare detail (single-object shape). Agents pass the right number of pks for the action's target. - π Search & filters β
admin.listusesModelAdmin.get_search_resultsandlist_filter. No parallel implementation. - π Audit log β writes go through Django's
LogEntry, surfaced byadmin.historyandadmin.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. Speaksinitialize,tools/list,tools/call. Full wire spec indocs/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 onPOSTβ Django's middleware 403. - Every
tools/callis validated against the tool's JSON Schema before it reaches the database. Schema violations returnINVALID_PARAMSwith 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:
- π Issues
- πΊοΈ Project board
- π
CONTRIBUTING.mdβ house rules - π€
CLAUDE.mdβ agent contract
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
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
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.
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.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
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.
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.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
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.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.