Skip to content

drf_publish_list_mcp_tool() breaks GET requests to DRF ListAPIView #32

@gustahrodrigues

Description

@gustahrodrigues

Description:
I'm experiencing an issue when using drf_publish_list_mcp_tool() from django-mcp-server to expose a DRF ListAPIView. After wrapping my view with this function, direct GET requests to the API endpoint no longer work as expected.

Setup:

  • Django==4.2.23
  • djangorestframework (DRF)==3.15.1
  • django-mcp-server==0.5.6
  • uvicorn[standard]==0.35.0
  • Python 3.10

Code Example:
my_app/views.py:

from rest_framework.generics import ListAPIView
from rest_framework import serializers

class MyStaticDataSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField()

class MyStaticDataListAPIView(ListAPIView):
    serializer_class = MyStaticDataSerializer
    permission_classes = []

    def get_queryset(self):
        return [
            {"id": 1, "name": "Alice"},
            {"id": 2, "name": "Bob"},
        ]

my_app/mcp.py:

from mcp_server import drf_publish_list_mcp_tool
from my_app.views import MyStaticDataListAPIView

# Everything works if I comment the section below
drf_publish_list_mcp_tool(
    MyStaticDataListAPIView,
    name="list_my_static_data_api_view",
    instructions="API view to list static data objects.",
)

validate_mcp.py

from mcp.client.streamable_http import streamablehttp_client
from mcp import ClientSession

async def main():
    async with streamablehttp_client("http://localhost:8000/mcp") as (
        read_stream,
        write_stream,
        _,
    ):
        async with ClientSession(read_stream, write_stream) as session:
            await session.initialize()
            tool_result = await session.call_tool("list_my_static_data_api_view")
            print(tool_result)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

settings.py

...
INSTALLED_APPS = [
    "rest_framework",
    "mcp_server",
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]
...
...
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "mozilla_django_oidc.middleware.SessionRefresh",
]
...

asgi.py

import os
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_project.settings')
application = get_asgi_application()

Startup command: uvicorn my_project.asgi:application --host 0.0.0.0 --port 8000 --reload

Problem:
After using drf_publish_list_mcp_tool() to wrap my MyStaticDataListAPIView, direct GET requests to the endpoint (e.g., http://localhost:8000/my-app/my-static-data/) result in errors. The view works as expected before wrapping it with drf_publish_list_mcp_tool().

Stack trace:

INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     Started server process [8]
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
[error    ] Internal Server Error: /my-app/my-static-data/ [django.request] dd.env= dd.service= dd.span_id=0 dd.trace_id=0 dd.version= request=<ASGIRequest: GET '/my-app/my-static-data/'> span_id=0 status_code=500 trace_id=0
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/asgiref/sync.py", line 489, in thread_handler
    raise exc_info[1]
  File "/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
  File "/usr/local/lib/python3.10/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
  File "/usr/local/lib/python3.10/site-packages/asgiref/sync.py", line 439, in __call__
    ret = await asyncio.shield(exec_coro)
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.10/site-packages/asgiref/sync.py", line 493, in thread_handler
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/sentry_sdk/integrations/django/views.py", line 94, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 498, in dispatch
    request = self.initialize_request(request, *args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/mcp_server/djangomcp.py", line 489, in _patched_initialize_request
    original_request = request.original_request
AttributeError: 'ASGIRequest' object has no attribute 'original_request'

Expected Behavior:
Wrapping a DRF ListAPIView with drf_publish_list_mcp_tool() should not interfere with the standard GET behavior of the view.

Actual Behavior:
GET requests to the endpoint fail or return unexpected results after wrapping the view.

Steps to Reproduce:

  1. Create a simple ListAPIView as above.
  2. Make a GET request to the endpoint.
$ curl http://localhost:8000/my-app/my-static-data/
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]
  1. Register it with drf_publish_list_mcp_tool().
  2. Make another GET request to the endpoint and observe the error or unexpected response.
$ curl http://localhost:8000/my-app/my-static-data/
< Django error shown above> 

Relates to PR #27

Request:
Please advise if this is a known issue or if there is a recommended way to expose DRF list views to MCP without breaking their standard API behavior.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingenhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions