From dcee07f4b51f139738638f01e83677207869e24a Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Tue, 23 Dec 2025 23:49:36 -0800 Subject: [PATCH] fix: add output_schema=None to MCP tools for Claude Code compatibility (bd-49kw) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude Code enforces outputSchema must have type: object at root, but FastMCP generates schemas with $ref for self-referential Pydantic models like Issue. Adds output_schema=None to 8 tools returning complex models: ready, list, show, create, update, close, reopen, blocked This disables structured output schema generation, allowing Claude Code to call these tools without validation errors. Related: https://github.com/modelcontextprotocol/inspector/issues/552 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- integrations/beads-mcp/src/beads_mcp/server.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/integrations/beads-mcp/src/beads_mcp/server.py b/integrations/beads-mcp/src/beads_mcp/server.py index f522c3b9..ea6b313e 100644 --- a/integrations/beads-mcp/src/beads_mcp/server.py +++ b/integrations/beads-mcp/src/beads_mcp/server.py @@ -766,7 +766,7 @@ def _truncate_description(issue: Issue, max_length: int) -> Issue: return issue -@mcp.tool(name="ready", description="Find tasks that have no blockers and are ready to be worked on. Returns minimal format for context efficiency.") +@mcp.tool(name="ready", description="Find tasks that have no blockers and are ready to be worked on. Returns minimal format for context efficiency.", output_schema=None) @with_workspace async def ready_work( limit: int = 10, @@ -840,6 +840,7 @@ async def ready_work( @mcp.tool( name="list", description="List all issues with optional filters. When status='blocked', returns BlockedIssue with blocked_by info.", + output_schema=None, ) @with_workspace async def list_issues( @@ -920,6 +921,7 @@ async def list_issues( @mcp.tool( name="show", description="Show detailed information about a specific issue including dependencies and dependents.", + output_schema=None, ) @with_workspace async def show_issue( @@ -966,6 +968,7 @@ async def show_issue( name="create", description="""Create a new issue (bug, feature, task, epic, or chore) with optional design, acceptance criteria, and dependencies.""", + output_schema=None, ) @with_workspace @require_context @@ -1012,6 +1015,7 @@ async def create_issue( name="update", description="""Update an existing issue's status, priority, assignee, description, design notes, or acceptance criteria. Use this to claim work (set status=in_progress).""", + output_schema=None, ) @with_workspace @require_context @@ -1066,6 +1070,7 @@ async def update_issue( @mcp.tool( name="close", description="Close (complete) an issue. Mark work as done when you've finished implementing/fixing it.", + output_schema=None, ) @with_workspace @require_context @@ -1091,6 +1096,7 @@ async def close_issue( @mcp.tool( name="reopen", description="Reopen one or more closed issues. Sets status to 'open' and clears closed_at timestamp.", + output_schema=None, ) @with_workspace @require_context @@ -1146,6 +1152,7 @@ async def stats(workspace_root: str | None = None) -> Stats: @mcp.tool( name="blocked", description="Get blocked issues showing what dependencies are blocking them from being worked on.", + output_schema=None, ) @with_workspace async def blocked(