Skip to content

Bug: get_project_data and list_tasks fail due to missing .passthrough() in outputSchema #20

@SirNich0las

Description

@SirNich0las

Bug Description

get_project_data and list_tasks tools always return "Tool execution failed" in Claude Desktop, even though the MCP server successfully fetches and returns the correct data from the Dida365 API. get_task works fine.

Root Cause

The outputSchema in get_project_data and list_tasks uses z.object({...}) without .passthrough(), while get_task correctly uses .passthrough().

The Dida365 API returns fields not defined in the schema (e.g., etag, tags, columnId, kind, modifiedTime). Without .passthrough(), Zod's strict validation rejects these extra fields, causing the MCP SDK to report the tool call as failed — even though the server-side API call succeeded.

Evidence

From the MCP server log, the server returns valid JSON for all projects:

Message from server: {"jsonrpc":"2.0","id":17,"result":{"content":[...], 
"structuredContent":{"project":{...},"tasks":[{"id":"...","etag":"854td1r1","kind":"TEXT","modifiedTime":"..."}],...}}}

But Claude Desktop reports: Tool execution failed

Meanwhile, get_task (which has .passthrough()) works perfectly for the same tasks.

Affected Files

  • src/tools/project/get-project-data.tsoutputSchema for project, task, and column objects
  • src/tools/task/list-tasks.tsoutputSchema for the result object

Fix

Add .passthrough() to all z.object() calls in outputSchema:

get-project-data.ts (3 changes):

  outputSchema: {
      project: z.object({
          ...
          sortOrder: z.number().optional(),
-     }),
+     }).passthrough(),
      tasks: z.array(z.object({
          ...
          items: z.array(z.any()).optional(),
-     })).optional(),
+     }).passthrough()).optional(),
      columns: z.array(z.object({
          ...
          sortOrder: z.number().optional(),
-     })).optional(),
+     }).passthrough()).optional(),
  },

list-tasks.ts (1 change):

  outputSchema: z.object({
      tasks: z.array(z.any()),
      total: z.number(),
      filtered: z.boolean(),
      projects: z.array(z.string()),
- }),
+ }).passthrough(),

Additional Note

list-projects.ts has the same pattern (z.array(z.object({...})) without .passthrough()) and may break if the API ever returns additional fields for projects. Consider adding .passthrough() there as well for future-proofing.

Environment

  • Package version: 0.2.2
  • Client: Claude Desktop (Windows 11)
  • Node.js: v22.x

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