BoilerplateHub

MCP Servers for Django

Django's ORM is the centre of gravity: it is expressive enough that an agent can write something readable and correct-looking that issues hundreds of queries. An agent working here needs to know the Django version, whether the project uses function based or class based views, how settings are split across environments, and that any model edit implies a migration. Async support exists but is partial, so the boundary between sync ORM code and async views is a real source of runtime failures rather than a style question.

Wiring MCP into a Django project

  • Give the database server a read-only role so the agent can inspect indexes and row counts without a path to writing.
  • Commit .mcp.json at the repo root and keep the connection string in an env var reference rather than inline.
  • Scope the filesystem server to the project package and tests so site-packages never enters the search space.

Servers worth adding

Filesystem MCP server

Scoped read and write access to the project tree.

Django apps are directories with conventional filenames, so the agent needs to see the real app layout before adding a model or a view.

Git MCP server

History, diffs, and blame.

The migrations directory history is the clearest record of how the schema actually evolved, which the models file alone does not show.

A Postgres MCP server

Inspects schema and runs read queries against the database.

It lets the agent confirm indexes exist before it proposes a query pattern that will table scan in production.

Sentry MCP server

Pulls issues and stack traces from Sentry.

Django's most useful production signal is the traceback plus the request context, and that lives in Sentry rather than the codebase.

Playwright MCP server

Browser automation against the running server.

Admin customisations and form flows depend on session and CSRF handling that only a real browser exercises.

Skills, MCP and plugins compared →

Rule these out for Django

These are the failures that repeat across sessions, so each one belongs in .mcp.json.

Queries that N+1 without select_related

An agent writes a view that returns Order.objects.all() and a template that renders order.customer.email, which issues one additional query per order. The code reads well and passes tests against a fixture of three rows. Add to your rules file: 'Any queryset that feeds a loop or a serializer must use select_related for forward foreign keys and prefetch_related for reverse and many to many relations. Assert query counts with assertNumQueries in tests for list endpoints.'

Changing models without generating a migration

Agents edit models.py, confirm the code looks right, and stop, leaving the database schema behind. Worse, some hand-write a migration file with an invented dependency graph rather than running makemigrations. Write: 'Every change to a models.py file is followed by python manage.py makemigrations and the generated file is committed. Never hand-author a migration except for a deliberate RunPython data migration.'

Filtering in Python instead of in the database

Agents call list() on a queryset or iterate it and then use a comprehension to filter, or use len(qs) where qs.count() belongs, pulling every row into memory to find a handful. Querysets are lazy and chainable specifically so this is unnecessary. Add: 'Do filtering, ordering, aggregation, and counting with queryset methods. Never load a queryset into a list to filter it, and use .count() and .exists() rather than len() and truthiness.'

Hardcoding settings and loosening security defaults

When something fails locally an agent will set DEBUG to True, add a wildcard to ALLOWED_HOSTS, or paste a SECRET_KEY literal into settings.py to make the traceback go away. Those edits then get committed. Make it a hard rule: 'Settings values come from environment variables. Never edit DEBUG, ALLOWED_HOSTS, SECRET_KEY, or any SECURE_ setting to resolve an error, and never commit a literal secret to a settings module.'

Wiring side effects through post_save signals

Asked to send a welcome email on signup, an agent adds a post_save receiver, which fires from fixtures, from bulk loads, and from every test that creates a user, and hides the control flow from anyone reading the view. Add: 'Side effects such as email, billing, and external API calls are called explicitly from a service function, not from model signals. Signals are reserved for cache invalidation and similar cross-cutting concerns.'

Calling the sync ORM from an async view

Agents convert a view to async def because it feels modern, then call the regular ORM inside it, which raises SynchronousOnlyOperation, or they wrap everything in sync_to_async and gain nothing but overhead. Async is only worth it when the view is genuinely IO bound on something external. Write: 'Views are sync by default. If a view is async, ORM access uses the async queryset methods or sync_to_async explicitly, and the reason for going async is stated in a comment.'

Same framework, other agents