Skip to content

When using DRF decorators, tool schema provided by MCP Server does not match what DRF views can actually process #39

@zacharypodbela

Description

@zacharypodbela

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's inputSchema.properties it is asking for all values to be nested inside of body.
  • But the Tool is actually expecting title, etc. as the top level keys.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions