{"id":34059891,"url":"https://github.com/gts360/django-mcp-server","last_synced_at":"2026-02-14T15:04:03.282Z","repository":{"id":292521096,"uuid":"981154693","full_name":"gts360/django-mcp-server","owner":"gts360","description":"Django MCP Server is a Django extensions to easily enable AI Agents to interact with Django Apps through the Model Context Protocol it works equally well on WSGI and ASGI","archived":false,"fork":false,"pushed_at":"2025-10-10T17:08:35.000Z","size":179,"stargazers_count":251,"open_issues_count":11,"forks_count":43,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-01-13T21:08:57.192Z","etag":null,"topics":["agentic-ai","ai","django","modelcontextprotocol"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gts360.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-10T13:14:41.000Z","updated_at":"2026-01-08T17:09:36.000Z","dependencies_parsed_at":"2025-08-09T20:18:17.087Z","dependency_job_id":"d18fdfd9-5d23-41fe-9d07-9924c807cb22","html_url":"https://github.com/gts360/django-mcp-server","commit_stats":null,"previous_names":["omarbenhamid/django-mcp-server","gts360/django-mcp-server"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/gts360/django-mcp-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gts360%2Fdjango-mcp-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gts360%2Fdjango-mcp-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gts360%2Fdjango-mcp-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gts360%2Fdjango-mcp-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gts360","download_url":"https://codeload.github.com/gts360/django-mcp-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gts360%2Fdjango-mcp-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29447768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T14:10:32.461Z","status":"ssl_error","status_checked_at":"2026-02-14T14:09:49.945Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","ai","django","modelcontextprotocol"],"created_at":"2025-12-14T04:02:30.594Z","updated_at":"2026-02-14T15:04:03.274Z","avatar_url":"https://github.com/gts360.png","language":"Python","funding_links":[],"categories":["📚 Projects (1974 total)"],"sub_categories":["MCP Servers"],"readme":"# Django MCP Server\n\n[![PyPI version](https://img.shields.io/pypi/v/django-mcp-server)](https://pypi.org/project/django-mcp-server/)\n![License](https://img.shields.io/pypi/l/django-mcp-server)\n[![Published on Django Packages](https://img.shields.io/badge/Published%20on-Django%20Packages-0c3c26)](https://djangopackages.org/packages/p/django-mcp-server/)\n![Python versions](https://img.shields.io/pypi/pyversions/django-mcp-server)\n[![Django versions](https://img.shields.io/pypi/frameworkversions/django/django-mcp-server)](https://pypi.org/project/django-mcp-server/)\n\n**Django MCP Server** is an implementation of the **Model Context Protocol (MCP)** extension for Django. This module allows **MCP Clients** and **AI agents** to interact with **any Django application** seamlessly.\n\n🚀 Django-Style declarative style tools to allow AI Agents and MCP clients tool to interact with Django.\u003cbr/\u003e\n🚀 Expose Django models for AI Agents and MCP Tools to query in 2 lines of code in a safe way.\u003cbr/\u003e\n🚀 Convert Django Rest Framework APIs to MCP tools with one annotation.\u003cbr/\u003e\n✅ Working on both WSGI and ASGI without infrastructure change.\u003cbr/\u003e\n✅ Validated as a Remote Integration with Claude AI.\u003cbr/\u003e\n🤖 Any MCP Client or AI Agent supporting MCP , (Google Agent Developement Kit, Claude AI, Claude Desktop ...) can interact with your application.\n\nMany thanks 🙏 to [all the contributor community](https://github.com/omarbenhamid/django-mcp-server/graphs/contributors)\n\nMaintained ✨ with care by [Smart GTS software engineering](https://www.smart-gts.com/#contact).\n\nLicensed under the **MIT License**.\n\n---\n\n## Features\n\n- Expose Django models and logic as **MCP tools**.\n- Serve an MCP endpoint inside your Django app.\n- Easily integrate with AI agents, MCP Clients, or tools like Google ADK.\n\n---\n\n## Quick Start\n\n### 1️⃣ Install\n\n```bash\npip install django-mcp-server\n```\n\nOr directly from GitHub:\n\n```bash\npip install git+https://github.com/omarbenhamid/django-mcp-server.git\n```\n\n---\n\n### 2️⃣ Configure Django\n\n✅ Add `mcp_server` to your `INSTALLED_APPS`:\n\n```python\nINSTALLED_APPS = [\n    # your apps...\n    'mcp_server',\n]\n```\n\n✅ Add the **MCP endpoint** to your `urls.py`:\n\n```python\nfrom django.urls import path, include\n\nurlpatterns = [\n    # your urls...\n    path(\"\", include('mcp_server.urls')),\n]\n```\n\nBy default, the MCP endpoint will be available at `/mcp`.\n\n---\n\n### 3️⃣ Define MCP Tools\n\nIn mcp.py create a subclass of `ModelQueryToolset` to give access to a model :\n\n```python\nfrom mcp_server import ModelQueryToolset\nfrom .models import *\n\n\nclass BirdQueryTool(ModelQueryToolset):\n    model = Bird\n\n    def get_queryset(self):\n        \"\"\"self.request can be used to filter the queryset\"\"\"\n        return super().get_queryset().filter(location__isnull=False)\n\nclass LocationTool(ModelQueryToolset):\n    model = Location\n\nclass CityTool(ModelQueryToolset):\n    model = City\n\n```\n\nOr create a sub class of `MCPToolset` to publish generic methods (private _ methods are not published) \n\nExample:\n```python\nfrom mcp_server import MCPToolset\nfrom django.core.mail import send_mail\n\nclass MyAITools(MCPToolset):\n    def add(self, a: int, b: int) -\u003e list[dict]:\n        \"\"\"A service to add two numbers together\"\"\"\n        return a+b\n\n    def send_email(self, to_email: str, subject: str, body: str):\n        \"\"\" A tool to send emails\"\"\"\n\n        send_mail(\n             subject=subject,\n             message=body,\n             from_email='your_email@example.com',\n             recipient_list=[to_email],\n             fail_silently=False,\n         )\n```\n\n---\n\n### Verify with MCP Inspect\n\nUse the management commande mcp_inspect to ensure your tools are correctly declared : \n\n```bash\npython manage.py mcp_inspect\n```\n\n### Use the MCP with any MCP Client\n\nThe mcp tool is now published on your Django App at `/mcp` endpoint. \n\n**IMPORTANT** For production setup, on non-public data, consider enabling \nauthorization through : DJANGO_MCP_AUTHENTICATION_CLASSES\n\n### Test with MCP Python SDK\n\nYou can test it with the python mcp SDK :\n\n```python\nfrom mcp.client.streamable_http import streamablehttp_client\nfrom mcp import ClientSession\n\n\nasync def main():\n    # Connect to a streamable HTTP server\n    async with streamablehttp_client(\"http://localhost:8000/mcp\") as (\n        read_stream,\n        write_stream,\n        _,\n    ):\n        # Create a session using the client streams\n        async with ClientSession(read_stream, write_stream) as session:\n            # Initialize the connection\n            await session.initialize()\n            # Call a tool\n            tool_result = await session.call_tool(\"get_alerts\", {\"state\": \"NY\"})\n            print(tool_result)\n\nif __name__ == \"__main__\":\n    import asyncio\n    asyncio.run(main())\n```\n\nReplace `http://localhost:8000/mcp` by the acutal Django host and run this cript.\n\n### Use from Claude AI\n\nAs of **June 2025** Claude AI support now MCPs through streamable HTTP protocol with preè-requisites :\n* \n* Setup OAuth2, for example :\n  * Install [Django Oauth Toolkit](https://django-oauth-toolkit.readthedocs.io/en/latest/))\n  * Include `'oauth2_provider.contrib.rest_framework.OAuth2Authentication'` in `DJANGO_MCP_AUTHENTICATION_CLASSES` in `settings.py`\n* Claude AI requires Dynamic Client Registration. as of today [it is not supported by django oauth toolkit](github.com/jazzband/django-oauth-toolkit/issues/670) but you can use [This Django Oauth Toolkit DCR Add-On](https://github.com/omarbenhamid/django-oauth-toolkit-dcr)\n* Unless you implement OAuth server Metadata RFC correctly, you need to keep OAuth2 URLS (`/register`, `/token` and `/authorize` at their default location).\n\n\n### Test in Claude Desktop\n\nYou can [test MCP servers in Claude Desktop](https://modelcontextprotocol.io/quickstart/server). As for now\nclaude desktop only supports local MCP Servers. So you need to have your app installed on the same machine, in a\ndev setting probably.\n\nFor this you need :\n\n1. To install Claude Desktop from [claude.ai](https://claude.ai)\n2. Open File \u003e Settings \u003e Developer and click **Edit Config**\n3. Open `claude_desktop_config.json` and setup your MCP server :\n   ```json\n   {\n    \"mcpServers\": {\n        \"test_django_mcp\": {\n            \"command\": \"/path/to/interpreter/python\",\n            \"args\": [\n                \"/path/to/your/project/manage.py\",\n                \"stdio_server\"\n            ]\n        }\n    }\n   ```\n\n**NOTE** `/path/to/interpreter/` should point to a python interpreter you use (can be in your venv for example)\nand `/path/to/your/project/` is the path to your django project.\n\n\n\n## Advanced topics\n\n### Publish Django Rest Framework APIs as MCP Tools\n\nYou can use `drf_publish_create_mcp_tool` / `drf_publish_update_mcp_tool` / `drf_publish_delete_mcp_tool` / \n`drf_publish_list_mcp_tool` as annotations or method calls to register DRF CreateModelMixin / UpdateModelMixin \n/ DestroyModelMixin / ListModelMixin based views  to MCP tools seamlessly. Django MCP Server will generate the schemas\nto allow MCP Clients to use them.\n\n**NOTE** in some *older DRF versions* schema generation is not supported out of the box, you should then provide to the registration\nannotation the \n\n```python\nfrom mcp_server import drf_publish_create_mcp_tool\n\n@drf_publish_create_mcp_tool\nclass MyModelView(CreateAPIView):\n    \"\"\"\n    A view to create MyModel instances\n    \"\"\"\n    serializer_class=MySerializer\n\n```\nnotice that the docstring of the view is used as instructions for the model.\nYou can better tune this like :\n\n```python\n@drf_publish_create_mcp_tool(instructions=\"Use this view to create instances of MyModel\")\nclass MyModelView(CreateAPIView):\n    \"\"\"\n    A view to create MyModel instances\n    \"\"\"\n    serializer_class=MySerializer\n\n```\n\nFinally, you can register after hand in mcp.py for example with: \n\n```python\ndrf_publish_update_mcp_tool(MyDRFAPIView, instructions=\"Use this tool to update my model, but use it with care\")\n```\n\n\n**IMPORTANT** \n\nNotice that **builti-in authentication classes are disabled** by default along with filter_backends, permission_classes and pagination_class, that's because\nthe MCP authentication is used.\n\nSince the pagination_class is also disabled, you will need to account for that if you're using an existing paginated DRF view (`self.paginator` will be `None`).\n\n\n### Django Rest Framework Serializer integration\n\nYou can annotate a tool with `drf_serialize_output(...)` to serialize its output using\ndjango rest framework, like : \n\n```python\nfrom mcp_server import drf_serialize_output\nfrom .serializers import FooBarSerializer\nfrom .models import FooBar\n\nclass MyTools(MCPToolset):\n   @drf_serialize_output(FooBarSerializer)\n   def get_foo_bar():\n       return FooBar.objects.first()\n```\n\n### Use low level mcp server annotation\n\nYou can import the DjangoMCP server instance and use FastMCP annotations to declare\nmcp tools and resources :\n\n```python\nfrom mcp_server import mcp_server as mcp\nfrom .models import Bird\n\n\n@mcp.tool()\nasync def get_species_count(name: str) -\u003e int:\n    '''Find the ID of a bird species by name (partial match). Returns the count.'''\n    ret = await Bird.objects.filter(species__icontains=name).afirst()\n    if ret is None:\n        ret = await Bird.objects.acreate(species=name)\n    return ret.count\n\n@mcp.tool()\nasync def increment_species(name: str, amount: int = 1) -\u003e int:\n    '''\n    Increment the count of a bird species by a specified amount.\n    Returns the new count.\n    '''\n    ret = await Bird.objects.filter(species__icontains=name).afirst()\n    if ret is None:\n        ret = await Bird.objects.acreate(species=name)\n    ret.count += amount\n    await ret.asave()\n    return ret.count\n```\n\n⚠️ **Important**:\n1. Always use **Django's async ORM API** when you define async tools.\n2. Be careful not to return a QuerySet as it will be evaluated asynchroniously which would create errors.\n\n### Customize the default MCP server settings\n\nIn `settings.py` you can initialize the `DJANGO_MCP_GLOBAL_SERVER_CONFIG` parameter. These will be \npassed to the `MCPServer` server during initialization\n```python\nDJANGO_MCP_GLOBAL_SERVER_CONFIG = {\n    \"name\":\"mymcp\",\n    \"instructions\": \"Some instructions to use this server\",\n    \"stateless\": False\n}\n```\n\n\n### Session management\n\nBy default the server is statefull, and state is managed as [Django session](https://docs.djangoproject.com/en/5.2/topics/http/sessions/)\n`request.session` object, so the session backend must thus be set up correctly. The \nrequest object is available in `self.request` for class based toolsets.\n\n**NOTE** The session middleware is not required to be set up as MCP sessions are managed\nindependently and without cookies.\n. \nYou can make the server stateless by defining : `DJANGO_MCP_GLOBAL_SERVER_CONFIG`\n\n**IMPORTANT** state is managed by django sessions, if you use low level `@mcp_server.tool()` annotation for example\nthe behaviour of preserving the server instance accross calls of the base python API is not preserved due to architecture\nof django in WSGI deployments where requests can be served by different threads !\n\n### Authorization\n\nThe MCP endpoint supports [Django Rest Framework authorization classes](https://www.django-rest-framework.org/api-guide/authentication/)\nYou can set them using `DJANGO_MCP_AUTHENTICATION_CLASSES` in `settings.py` ex. :\n\n```python\nDJANGO_MCP_AUTHENTICATION_CLASSES=[\"rest_framework.authentication.TokenAuthentication\"]\n```\n\n**IMPORTANT** Now the [MCP Specification version 2025-03-26](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization)\nadvices to use an OAuth2 workflow, so you should integrate \n[django-oauth-toolkit with djangorestframework integration](https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html) \nsetup, and use `'oauth2_provider.contrib.rest_framework.OAuth2Authentication'` in\n`DJANGO_MCP_AUTHENTICATION_CLASSES`. Refer to [the official documentation of django-oauth-toolkit](https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html) \n\n### Advanced / customized setup of the view\n\nYou can in your urls.py mount the MCPServerStreamableHttpView.as_view() view and customize it with any extra parameters.\n\n### Custom output format (renderers) for ModelQueryToolset\n\nYou can define any [DRF rendrer](https://www.django-rest-framework.org/api-guide/renderers/) to produce output, for this \nit must be declared in your settings:\n\n```python\nDJANGO_MCP_OUTPUT_RENDERER_CLASSES = [\n    \"rest_framework.renderers.JSONRenderer\",\n    \"rest_framework_csv.renderers.CSVRenderer\"\n]\n```\n\nThen in your `ModelQueryToolset` declaration you can add \n\n```python\n    ...\n    output_format=\"csv\"\n```\n\nfurther you can instruct the tool to attach the result as an [MCP Embedded Resource] rather than direct return with\n\n```python\n    ...\n    output_as_resource=True\n```\n\n*NOTE* some renderers like `drf-excel` are designed in a way that does not allow using them outside of DRF View, they will not \nwork here..\n\n### Secondary MCP endpoint\nin `mcp.py`\n```python\nfrom mcp_server.djangomcp import DjangoMCP\n\nsecond_mcp = DjangoMCP(name=\"altserver\")\n\n@second_mcp.tool()\nasync def my_tool():\n    ...\n```\n\nin urls.py \n```python\n...\nfrom yourapp.mcp import second_mcp\n...\npath(\"altmcp\", MCPServerStreamableHttpView.as_view(mcp_server=second_mcp))\n...\n```\n\n**IMPORTANT** When you do this the DJANGO_MCP_AUTHENTICATION_CLASSES settings is **ignored** and \nyour view is unsecure. You **SHOULD** [Setup DRF Authentication](https://www.django-rest-framework.org/api-guide/authentication/)\nfor your view, for exemple : \n```python\n...\nMCPServerStreamableHttpView.as_view(permission_classes=[IsAuthenticated], authentication_classes=[TokenAuthentication])\n...\n```\n\n## Testing\n\n### The server\nYou can setup you own app or use the [mcpexample django app](examples/mcpexample) app.\n\n### The client\n\nBy default, your MCP Server will be available as a \n[stateless streamable http transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http) \nendpoint at \u003cyour_django_server\u003e/mcp (ex. http://localhost:8000/mcp) (*without / at the end !).\n\nThere are many ways to test :\n\n1. Using the test [MCP Client script : test/test_mcp_client.py](test/test_mcp_client.py)  \n2. You can test using [MCP Inspector tool](https://github.com/modelcontextprotocol/inspector) \n3. or any compatible MCP Client like google agent developement kit.\n\n---\n\n## Integration with Agentic Frameworks and MCP Clients\n\n### Google Agent Developement Kit Example\n\n**NOTE** as of today the [official google adk does not support StreamableHTTP Transport](https://github.com/google/adk-python/issues/479) \nbut you could use [this fork](https://github.com/omarbenhamid/google-adk-python)\n\nThen you can use the [test agent in test/test_agent](test/test_agent/agent.py) with by \nstarting `adk web` in the `test` folder. Make sure first : \n\n1. Install adk with streamablehttp support : `pip install git+https://github.com/omarbenhamid/google-adk-python.git`\n2. Start a django app with an MCP endpoint : `python manage.py runserver` in the `examples/mcpexample` folder.\n2. If you use TokenAuthorization create an access token, for example in Django Admin of your app.\n3. Setup in `test/test_agent/agent.py` the right endpoint location and authentication header\n4. Enter the `test` folder.\n5. Run `adk web`\n6. In the shell you can for example use this prompt : \"I saw woody woodpecker, add it to my inventory\"\n\n\n### Other clients\nYou can easily plug your MCP server endpoint into any agentic framework supporting MCP streamable http servers.\nRefer to this [list of clients](https://modelcontextprotocol.io/clients)\n\n---\n\n## Settings\n\n- **DJANGO_MCP_GLOBAL_SERVER_CONFIG** a configuration dictionnary for the global MCP server default to empty. It can include the following parmaters\n   - name: a  name for the server\n   - instructions: global instructions\n   - stateless : when set to 'True' the server will not manage sessions \n\n- **DJANGO_MCP_AUTHENTICATION_CLASSES** (default to no authentication) a list of reference to Django Rest Framework authentication classes to enfors in the main MCP view.\n- **DJANGO_MCP_GET_SERVER_INSTRUCTIONS_TOOL** (default=True) if true a tool will be offered to obtain global instruction and tools will instruct the agent to use it, as agents do not always have the MCP server global instructions included in their system prompt.\n- **DJANGO_MCP_ENDPOINT** (default=\"mcp\") a string indicating the url endpoint used by the server. If you want it to have a trailing slash, for example, set it to \"mcp/\"\n\n## Roadmap\n\n- ✅ **Stateless streamable HTTP transport** (implemented)\n- 🔜 **STDIO transport integration for dev configuration (ex. Claude Desktop)**\n- 🔜 ****\n- 🔜 **Stateful streamable HTTP transport using Django sessions**\n- 🔜 **SSE endpoint integration (requires ASGI)**\n- 🔜 **Improved error management and logging**\n\n---\n\n## Issues\n\nIf you encounter bugs or have feature requests, please open an issue on [GitHub Issues](https://github.com/omarbenhamid/django-mcp-server/issues).\n\n---\n\n## License\n\nMIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgts360%2Fdjango-mcp-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgts360%2Fdjango-mcp-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgts360%2Fdjango-mcp-server/lists"}