-
Notifications
You must be signed in to change notification settings - Fork 39
Description
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:
- Create a simple
ListAPIView
as above. - Make a GET request to the endpoint.
$ curl http://localhost:8000/my-app/my-static-data/
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]
- Register it with
drf_publish_list_mcp_tool()
. - 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.