django-admin-fastmcp
django-admin-fastmcp
Una aplicación Django reutilizable que expone el admin de Django como un servidor MCP, construida sobre FastMCP.
Cada llamada a una herramienta se ejecuta como el usuario del staff que posee el token de portador. Cada llamada a una herramienta pide permiso a ModelAdmin en primer lugar. Un superusuario puede hacer todo lo que un superusuario puede hacer en el admin. Un usuario del staff puede hacer exactamente lo que ese usuario del staff puede hacer en el admin, y nada más.
SPEC.md es la especificación completa.
Cómo funciona
Tres reglas definen el paquete:
Sin sistema de permisos paralelo. La autorización se delega en los métodos de
ModelAdmin:has_view_permission,has_add_permission,has_change_permission,has_delete_permission,get_queryset,get_readonly_fieldsyget_actions. Una sobreescritura deget_querysetque oculta filas las oculta también para MCP.Sin superficie de datos paralela. Las escrituras pasan por el
ModelFormy elsave_modelpropios del admin, y luego registran unLogEntry. La página de historial del admin se mantiene fiel.Cierre de fallos. Toda búsqueda no resuelta,
ModelAdminausente, acción desconocida, campo desconocido y herramienta desconocida deniega la llamada.
Instalación
uv add django-admin-fastmcpAñade la aplicación a tus ajustes:
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
}Monta los endpoints de OAuth en el mismo sitio que el 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),
]El paquete no fija ningún prefijo hardcodeado. Cada URL que anuncia el documento de metadatos sale de reverse(), así que un proyecto que monte los endpoints en /backoffice/oauth/ lo verá en el descubrimiento y los clientes lo seguirán. Dos reglas: el documento well-known debe estar en la raíz, porque un cliente deriva su URL del emisor, y los endpoints deberían estar en el mismo sitio que el admin, porque la página de consentimiento se apoya en la cookie de sesión del admin.
Aplica las migraciones:
python manage.py migrate django_admin_fastmcpNada más. Sin registro por modelo, sin mixins, sin decoradores. El servidor expone lo que el admin ya expone.
Conectar un cliente
Ejecuta el servidor (consulta Implementación) y regístralo:
# Claude Code
claude mcp add --transport http acme-admin https://<host>/admin/mcpUsa la ruta sin barra final. /admin/mcp/ responde con una redirección 307 a /admin/mcp, y no todos los clientes siguen una redirección en POST.
Sin token, sin cabecera. La primera llamada inicia el flujo OAuth estándar de MCP:
El cliente abre tu navegador en la página de autorización del sitio Django.
Tu cookie de sesión del admin te identifica. Si no tienes la sesión iniciada, aparece primero el login normal del admin.
Una página de consentimiento muestra el nombre del cliente y lo que significa la aprobación. Tú apruebas.
El cliente recibe sus tokens y se conecta. Los renueva por sí solo.
Cualquier cliente de MCP que hable HTTP streamable con OAuth funciona de la misma manera, por ejemplo Cursor o un Client de FastMCP.
Reglas sobre el acceso:
Cualquier usuario del staff puede autorizar un cliente, solo para sí.
Un acceso actúa con sus propios permisos de admin, nunca con más. No existe un sistema de permisos aparte: quien tenga permiso para cambiar un modelo en el admin podrá cambiarlo por MCP, siempre que el servidor tenga ese modelo en
WRITABLE_MODELS.Los tokens de refresco caducan tras
REFRESH_TOKEN_TTL_DAYS(90 por defecto), así que el re-consentimiento ocurre con esa frecuencia. La revocación es una acción del admin sobre la lista de cambios de las autorizaciones.
Herramientas
Once herramientas genéricas, montadas bajo el espacio de nombres admin, por eso los nombres que viajan por el protocolo son admin_list_models y similares. Cada una recibe model como "app_label.ModelName". La lista de herramientas es estática. Lo que varía por usuario es qué puede ver y hacer ese usuario con cada herramienta.
Lectura
Herramienta | Argumentos | Devuelve |
| ninguno | Cada modelo expuesto que este llamador pueda ver, con los indicadores de permisos. |
|
| Campos, visualización de lista, filtros, campos de búsqueda, campos de solo lectura y acciones disponibles. |
|
| Filas además de |
|
| Una instancia serializada. |
|
| Entradas de log del admin para ese objeto, la más reciente primero. |
|
| Entradas de log del admin, contextuales al llamador salvo si el llamador es superusuario. |
Escritura
Las herramientas de escritura exigen que el modelo esté en WRITABLE_MODELS; tus propios permisos de admin deciden el resto, por modelo y por objeto. Un modelo fuera de la lista rechaza toda escritura y toda acción, llame quien llame. Deja fuera los modelos sensibles, por ejemplo un registro de eventos, y ningún cliente MCP podrá escribirlos jamás.
Herramienta | Argumentos | Comportamiento |
|
| Valida con el formulario del admin y luego guarda y registra. |
|
| Actualización parcial. Los campos de solo lectura se ignoran. |
|
| Sin |
|
| Ejecuta una acción del admin. Sin |
|
| Resuelve un valor de clave foránea a una clave primaria buscando en el modelo relacionado. |
Cada fila devuelta incluye pk como cadena y un admin_url, de modo que un agente puede ofrecer a una persona un enlace al admin real.
Ajustes
Todas las claves viven en el diccionario ADMIN_FASTMCP. Una clave desconocida es un error al inicio.
Clave | Default | Significado |
|
| Nombre que anuncia el servidor MCP. |
|
| Ruta con puntos hacia el |
|
| Lista de permitidos de |
|
| Lista de denegados. Admite |
|
| Modelos que aceptan escrituras. Vacía significa que no se escribe, llame quien llame. |
|
| Nombres de herramientas eliminadas del catálogo por completo. |
|
| Coincidencia por substrings en los nombres de campo. Los valores se leen como |
|
| Límite máximo del tamaño de página en |
|
| Límite de |
|
| Tiempo de vida del token de acceso. Los clientes lo renuevan con el token de renovación. |
|
| Tiempo de vida del token de renovación. La reautorización se produce con esa frequent. |
|
| URL pública del sitio Django. Es el emisor de OAuth, y el servidor MCP lo designa como su servidor de autorización. |
|
| URL pública del endpoint MCP. |
Establece SITE_URL y MCP_URL en cualquier implementación real. MCP_URL es la única fuente de tres cosas que deben coincidir: la ruta en la que sirve el endpoint, el resource que anuncia el descubrimiento y la audiencia a la que está vinculado cada token. Su ruta por defecto es /admin/mcp. Una comprobación de inicio rechaza una MCP_URL sin ruta, porque entonces se anunciaría todo el origen como recurso protegido.
Opciones por ModelAdmin
Estos valores se ponen en una clase ModelAdmin, sin necesidad de mixin:
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 fieldsREDACT_FIELDS tiene prioridad sobre mcp_fields. Incluir explícitamente un campo de contraseña no lo revela.
Seguridad
Un servidor MCP de admin para un superusuario es un shell remoto sobre la base de datos de producción, guiado por un modelo de lenguaje. Las salvaguardias:
WRITABLE_MODELSestá vacío por defecto, así que ningún modelo acepta escrituras hasta que el despliegue lo indique. Todo lo demás son los permisos normales de Django, consultados a partir delModelAdminen cada llamada.Los tokens de acceso son de corta duración. Solo se almacenan hashes con sal, de modo que una fila filtrada de la base de datos no puede reproducirse.
delete_objectyrun_actionmuestran una vista previa en ayudante por defecto y no cambian nada hasta queconfirm=True.Cada mutación registra un
LogEntryatribuido al usuario de la autoriz, con el nombre del cliente en el mensaje de cambio, por ejemplo"Changed status. Via MCP (client: Claude Code).". Una escritura que no puede registrar unLogEntryse revierte.Los modelos propios del paquete, por ejemplo
sessions.Sessionyauthtoken.Token, no se exponen nunca, sin importar lo que digan los ajustes.Mantén
auth.Permissionyauth.Groupfuera deWRITABLE_MODELS. Un agente que puede otorgar permisos puede escapar del modelo de permisos.
Implementación
Proceso separado. Ejecuta el servidor MCP junto a tu proyecto:
python manage.py admin_mcp_serveSirve la ruta de MCP_URL, que por defecto es /admin/mcp, en el puerto de MCP_URL, o 8765 cuando la URL no define puerto. Ambos son configurable con --host y --port. No cambia nada de tu configuración de serviro existente. Encamina /admin/mcp a ese puerto a través de tu entrada, y asegúrate de que la cabecera Authorization pase.
Montado (M3). Monta el servidor en /admin/mcp dentro de tu archivo asgi.py. Una restricción: distribuye en la ruta exacta. Los endpoints de OAuth viven justo debajo del mismo prefijo (/admin/mcp/authorize y otros) y Django debe seguir sirviendo esos, así que un dispatcher que mande todo lo que esté bajo /admin/mcp a FastMCP se los tragaría. La receta se entrega con el hito M3.
El servidores sin estado, por lo que cualquier instancia detrás de un balanceador de carga puede servir cualquier solicitud.
Desarrollo
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 elseLicencia
MIT
This server cannot be installed
Maintenance
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
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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