Remote MCP connector tools receive structured array params as JSON-encoded strings — strict servers reject with -32602 (typed inputSchema is present)
Environment
- Claude Code CLI 2.1.202; Claude Desktop (CCD) 2.1.215; macOS 26.5.2 (Darwin 25.5.0)
- Connector: Todoist remote MCP (claude.ai-managed connector, OAuth), reached from a Claude Code desktop session
- Tools were deferred and loaded mid-session via tool search (large-toolset session, ~15 MCP servers connected)
Summary
Calling a remote-connector MCP tool whose schema declares an array-of-objects parameter (add-tasks, param tasks) fails 100% of the time with MCP error -32602. The server's zod validation reports Invalid input: expected array, received string for path tasks — i.e. the client serialized the structured argument as a JSON string instead of passing it as a JSON array in the tools/call params.
This is NOT a schema-advertisement problem: the inputSchema loaded into the session was fully typed (tasks: array, items with content/description/projectId/priority enum/dueString, max 25, required). The client had everything needed to send a proper array.
Repro
- Claude Code session with the Todoist claude.ai connector enabled (tools deferred, loaded via tool search).
- Model calls
mcp__<todoist-server-id>__add-taskswithtasks=[{"content":"test-parse","projectId":"<any-project-id>"}] - Server responds: MCP error -32602, zod issues:
{expected:"array", code:"invalid_type", path:["tasks"], message:"Invalid input: expected array, received string"}{origin:"string", code:"too_big", maximum:25, path:["tasks"], message:"Too big: expected string to have <=25 characters"}
(the second issue reveals the server's runtime union TaskObject[] | string — the stringified array failed both branches)
- Reproduced with three payload shapes: full single-task object array, minimal one-field array, bare short string. All rejected identically. Reads on the same server (
find-projects, string param) work fine.
Why it looks client-side
- The typed schema was demonstrably delivered to the session (recorded in the tool-load result), so the server advertisement is correct.
- In the SAME session, the Linear remote connector accepted identical structured params (arrays) without error — consistent with Linear's server coercing stringified JSON while Todoist validates strictly. A client that sent real JSON arrays would work against both.
- Local logs (
~/Library/Caches/claude-cli-nodejs/<project>/mcp-logs-<serverId>/*.jsonland~/Library/Logs/Claude/main.log) show the calls going out and the -32602 coming back ("Remote tool call succeeded" then the JSON-RPC-level validation error).
Expected
tools/call params should carry tasks as a JSON array per the tool's inputSchema.
Actual
tasks arrives at the server as a string containing serialized JSON; strictly-validated servers reject every write.
Impact
All write operations on the Todoist connector (and presumably any remote MCP server that validates strictly instead of coercing) are unusable from Claude Code. Reads work, which masks the problem until the first write.
Workaround
Direct REST calls (curl to the provider's API with a personal token) from Bash.
Notes for triage
- Suspected interaction with the deferred-tool loading path (ToolSearch) — schemas load on demand; the parameter-encoding layer may not be applying the loaded schema when deciding whether to parse model-emitted values into JSON types.
- Happy to provide the project-scoped mcp-logs jsonl (4 failed calls) on request.