Skip to main content
Glama
paritoshv

django-admin-mcp

by paritoshv

django-admin-mcp

Give an AI agent read-only access to your Django admin data over MCP — scoped to exactly what the signed-in staff user could already see in the admin. No new data surface, just a new protocol over the one you already trust.

agent ──stdio──▶ shim ──HTTPS(x-api-key)──▶ /admin-mcp/ views ──▶ ModelAdmin (perms + queryset) ──▶ read replica

Every read is driven through the model's own ModelAdmin, so the agent sees precisely what that user sees in /admin/ — same permission checks, same row scoping, same search — with secrets redacted and cost gates on every query.

Why it's different

  • Permission-faithful by construction. Access is gated by ModelAdmin.has_view_permission (model and object level), scoped by ModelAdmin.get_queryset, and searched via ModelAdmin.get_search_results — the exact calls the admin UI makes. A user with view rights on three models sees three models. There is no parallel permission system to keep in sync.

  • Zero-copy auth. No API keys to mint, paste, or rotate. The MCP shim runs a loopback browser sign-in (OAuth-style PKCE): it opens /auth/, catches a one-time code on a 127.0.0.1 listener, and exchanges it for a scoped, sliding-expiry token stored per-host at 0600. Expired token → the agent silently re-auths. The token authenticates to this endpoint only, so a leak can't reach any other API.

  • Safe to point at production. Reads route to a configurable replica alias, run under a per-query statement timeout, never issue an unbounded COUNT(*), refuse deep pagination, and are per-user rate-limited. Secret-looking fields (password, token, api_key, …, incl. keys nested in JSON columns) come back ***. Whole models can be hidden by policy.

  • Drop-in. One include() in your URLconf, a few optional settings, zero required dependencies beyond Django. Works with any MCP client (Claude Code, Codex, …) — the shim is stdlib-only.

Related MCP server: django-admin-mcp-api

Install

pip install django-admin-mcp
# settings.py
INSTALLED_APPS = [..., "admin_mcp"]
ADMIN_MCP_BASE_PATH = "/admin-mcp"          # must match where you mount the urls

# urls.py
from django.urls import include, path
urlpatterns = [
    path("admin/", admin.site.urls),
    path("admin-mcp/", include("admin_mcp.urls")),
]

That's the minimum. Then a staff user opens https://<your-host>/admin-mcp/auth/ and copies the one command it shows for their agent.

Try it in 60 seconds

git clone https://github.com/paritoshv/django-admin-mcp && cd django-admin-mcp/example
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
# open http://127.0.0.1:8000/admin-mcp/auth/  → follow the one-liner it prints

The demo app ships an Author/Book model (with a redacted api_key field) and a SecretRecord model that's hidden from MCP via ADMIN_MCP_HIDDEN_MODELS — so you can see scoping, redaction, and model-hiding immediately.

MCP tools

Tool

Maps to

Notes

admin_list_models

which models you may view

discovery entry point

admin_get_model_schema

fields, relations, search_fields, list_filter, sortable fields

read this to know what's queryable

admin_search

the changelist

query needs search_fields; filters must be within list_filter; bounded count

admin_get

the change view

one row by pk, object-level permission enforced

authenticate

the loopback sign-in

usually automatic; call to sign in ahead of time

Endpoints

Mounted under ADMIN_MCP_BASE_PATH. model is app_label.ModelName.

Path

Params

Auth

Returns

models/

staff

models the caller may view

schema/

model

staff

fields, relations, search/filter/sort surface

search/

model, query?, filters?, order_by?, page?, page_size?

staff

changelist rows + bounded count

object/

model, pk

staff

one object

auth/

redirect_uri?, state?, code_challenge?

browser session

setup page, or the loopback PKCE redirect

auth/token/

code, code_verifier (POST)

one-time PKCE code

exchanges a loopback code for a fresh token

shim/

staff

the stdio shim source (so setup is one curl)

Configuration

Everything is optional; defaults are safe.

Setting

Default

Purpose

ADMIN_MCP_ENABLED

True

master on/off

ADMIN_MCP_ENABLED_HOOK

dotted path to callable() -> bool — a runtime killswitch (feature flag / infra toggle) with no deploy

ADMIN_MCP_READONLY_DB

"default"

DB alias reads route to; point at a replica in prod

ADMIN_MCP_HIDDEN_MODELS

[]

"app.Model" labels never served (and hidden from discovery)

ADMIN_MCP_HIDDEN_MODELS_HOOK

dotted path to callable(model) -> bool for dynamic hiding (e.g. an encrypted/PII data-classification router)

ADMIN_MCP_CACHE_ALIAS

"default"

Django cache backing tokens/codes/throttle — use a shared Redis/Memcached in production

ADMIN_MCP_SECRET_MARKERS

password, secret, token, api_key, …

substrings that mark a field for redaction

ADMIN_MCP_SERVER_NAME

"admin-mcp"

MCP server name on the setup page; scope per environment

ADMIN_MCP_BASE_PATH

"/admin-mcp"

where the app is mounted (advertised to the shim)

ADMIN_MCP_PAGE_SIZE / _MAX_PAGE_SIZE / _COUNT_CAP / _STATEMENT_TIMEOUT_MS

25 / 100 / 1000 / 5000

pagination + cost caps

ADMIN_MCP_THROTTLE_AT / _THROTTLE_TIMEFRAME

120 / 60

per-user rate limit

ADMIN_MCP_TOKEN_TTL_SECONDS / _TOKEN_MAX_LIFETIME_SECONDS / _CODE_TTL_SECONDS

86400 / 604800 / 60

token idle window, absolute lifetime, one-time-code TTL

Production notes

  • Set ADMIN_MCP_CACHE_ALIAS to a shared cache (Redis/Memcached). The default LocMem cache is per-process, so tokens minted on one worker won't resolve on another.

  • Point ADMIN_MCP_READONLY_DB at a read replica so agent reads never touch the primary.

  • Wire ADMIN_MCP_ENABLED_HOOK to a feature flag if you want to kill the endpoint without a deploy.

Security model

  • Auth: a live admin session, or a scoped token in the x-api-key header. The token is a random opaque string; only its SHA-256 is stored. Idle 24h expiry that slides on use, plus a 7-day absolute cap. It resolves to an active staff user on every call, so deactivating the account or revoking staff invalidates it immediately, TTL notwithstanding.

  • Loopback PKCE refresh: /auth/ only ever redirects the one-time code to a validated http://127.0.0.1|localhost URI — never an external host — and the code (60s, single-use) is worthless without the PKCE verifier held by the shim that started the flow.

  • Redaction runs after honouring each admin's exclude/fields whitelist — defence in depth, so even a mis-configured admin can't leak a secret column into an LLM context.

  • Never evaluates list_display callables (they can trigger N+1s or side effects); serialises concrete fields only.

  • Audit trail: one structured record per call (who/what/outcome/timing) on the admin_mcp.audit logger — never the response values, so the log isn't a second data-egress path.

Tests

python runtests.py

License

MIT

A
license - permissive license
-
quality - not tested
C
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 Servers

View all related MCP servers

Related MCP Connectors

  • Read-only MCP server for ClassQuill, a tutoring-business-management platform.

  • Read-only MCP access to sessions, funnels, campaigns, errors, live visitors, and anomalies.

  • Query metrics, targets, entities, and team data in your Steep workspace via MCP.

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/paritoshv/django-admin-mcp'

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