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.ts — outputSchema for project, task, and column objects
src/tools/task/list-tasks.ts — outputSchema 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
Bug Description
get_project_dataandlist_taskstools 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_taskworks fine.Root Cause
The
outputSchemainget_project_dataandlist_tasksusesz.object({...})without.passthrough(), whileget_taskcorrectly 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:
But Claude Desktop reports:
Tool execution failedMeanwhile,
get_task(which has.passthrough()) works perfectly for the same tasks.Affected Files
src/tools/project/get-project-data.ts—outputSchemafor project, task, and column objectssrc/tools/task/list-tasks.ts—outputSchemafor the result objectFix
Add
.passthrough()to allz.object()calls inoutputSchema: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.tshas 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