-
Notifications
You must be signed in to change notification settings - Fork 32
Open
Description
When using DRF decorators (with vanilla DRF *APIView classes), tool schema provided by MCP Server does not match what DRF views are actually process. I've set up a simple example with absolutely no custom code:
views.py
from blog.models import BlogPost
from rest_framework import viewsets, serializers
from mcp_server import drf_publish_create_mcp_tool, drf_publish_update_mcp_tool, drf_publish_destroy_mcp_tool, drf_publish_list_mcp_tool
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
fields = "__all__"
@drf_publish_create_mcp_tool(instructions="Create a new blog post", actions={'post': 'create'})
@drf_publish_destroy_mcp_tool(instructions="Delete a blog post", actions={'delete': 'destroy'})
@drf_publish_list_mcp_tool(instructions="List all blog posts", actions={'get': 'list'})
@drf_publish_update_mcp_tool(instructions="Update a blog post", actions={'put': 'update'})
class PostViewSet(viewsets.ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = PostSerializer
models.py
from django.db import models
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Issue
Here's what being returned by MCP server when queried for tools/list
:
2025-08-07T23:11:14.688Z [django-mcp-testing] [info] Message from server: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"PostViewSet_UpdateTool","description":"Update a blog post","inputSchema":{"properties":{"id":{"title":"id","type":"string"},"body":{"type":"object","properties":{"id":{"type":"integer","readOnly":true},"title":{"type":"string","maxLength":200},"content":{"type":"string"},"created_at":{"type":"string","format":"date-time","readOnly":true},"updated_at":{"type":"string","format":"date-time","readOnly":true}},"required":["title","content"]}},"required":["id","body"],"title":"_dumb_updateArguments","type":"object"}},{"name":"PostViewSet_ListTool","description":"List all blog posts","inputSchema":{"properties":{},"title":"_dumb_listArguments","type":"object"}},{"name":"PostViewSet_DeleteTool","description":"Delete a blog post","inputSchema":{"properties":{"id":{"title":"id","type":"string"}},"required":["id"],"title":"_dumb_deleteArguments","type":"object"}},{"name":"PostViewSet_CreateTool","description":"Create a new blog post","inputSchema":{"properties":{"body":{"type":"object","properties":{"id":{"type":"integer","readOnly":true},"title":{"type":"string","maxLength":200},"content":{"type":"string"},"created_at":{"type":"string","format":"date-time","readOnly":true},"updated_at":{"type":"string","format":"date-time","readOnly":true}},"required":["title","content"]}},"required":["body"],"title":"_dumb_createArguments","type":"object"}}]}} { metadata: undefined }
When I prompt the LLM to create a new post using the PostViewSet_CreateTool
, we hit errors.
It attempts to use this input:
{
`body`: {
`title`: `Coffee Shop Chronicles`,
`content`: `The local coffee shop has become my unofficial office. Between the gentle hum of conversation and the rhythmic grinding of beans, I find myself more productive here than anywhere else. Today's barista, Maya, creates latte art that belongs in a gallery. Her latest masterpiece was a perfect rosetta that I almost couldn't bring myself to drink. Almost.`
}
}
And gets this Response:
Error executing tool PostViewSet_CreateTool: {'title': [ErrorDetail(string='This field is required.', code='required')], 'content': [ErrorDetail(string='This field is required.', code='required')]}
Root Cause
There is a mismatch between the schema the MCP server is providing when listing tools and the schema the tools actually expect.
- If you look at the value of
PostViewSet_CreateTool
'sinputSchema.properties
it is asking for all values to be nested inside ofbody
. - But the Tool is actually expecting
title
, etc. as the top level keys.
Metadata
Metadata
Assignees
Labels
No labels