Describe the bug
When a sub-agent launched via the task tool calls an MCP tool that returns a JSON array, the call fails with a Zod validation error. The exact same tool with the exact same parameters works fine when called from the primary/orchestrator agent.
The error is:
MCP server 'my-mcp-server': [{"expected":"record","code":"invalid_type","path":["structuredContent"],"message":"Invalid input: expected record, received array"}]
The root cause is in sdk/index.js where the CallToolResult schema defines structuredContent: z.record(z.string(), z.unknown()).optional(). z.record() only accepts plain objects, so when an MCP server returns a JSON array, the Zod validation rejects it. This validation only runs in the sub-agent code path, not the primary agent path.
| Context |
Response type |
Result |
| Primary agent |
JSON array |
Works |
| Primary agent |
String |
Works |
| Primary agent |
JSON object |
Works |
Sub-agent (via task) |
String |
Works |
Sub-agent (via task) |
JSON object |
Works |
Sub-agent (via task) |
JSON array |
Fails |
Affected version
Reproduced on 1.0.36 and 1.0.39 (latest as of 2026-04-29). Using @github/copilot-sdk 0.3.0.
Steps to reproduce the behavior
-
Register a stdio MCP server with a tool that returns a JSON array:
[
{ "id": "abc-123", "status": "Succeeded", "startTime": "2026-04-27T10:00:00Z" },
{ "id": "def-456", "status": "Running", "startTime": "2026-04-28T01:00:00Z" }
]
-
Configure a custom sub-agent with access to that tool:
name: my-agent
tools:
- my-mcp-server/list_items
-
Create a session with sub-agents enabled and have the orchestrator delegate to my-agent via the task tool
-
The sub-agent calls my-mcp-server/list_items and gets the error above
A tool on the same server that returns a string (e.g., "No items found") succeeds in the same sub-agent session, confirming the issue is specifically with array responses.
Expected behavior
MCP tool calls returning JSON arrays should work the same way in sub-agents as they do in the primary agent. A few possible fixes:
- Accept arrays in
structuredContent: z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())])
- Normalize array responses before validation by wrapping
[...] into { items: [...] }
- Apply the same lenient parsing that the primary agent uses to sub-agent MCP responses as well
Additional context
Describe the bug
When a sub-agent launched via the
tasktool calls an MCP tool that returns a JSON array, the call fails with a Zod validation error. The exact same tool with the exact same parameters works fine when called from the primary/orchestrator agent.The error is:
The root cause is in
sdk/index.jswhere theCallToolResultschema definesstructuredContent: z.record(z.string(), z.unknown()).optional().z.record()only accepts plain objects, so when an MCP server returns a JSON array, the Zod validation rejects it. This validation only runs in the sub-agent code path, not the primary agent path.task)task)task)Affected version
Reproduced on 1.0.36 and 1.0.39 (latest as of 2026-04-29). Using @github/copilot-sdk 0.3.0.
Steps to reproduce the behavior
Register a stdio MCP server with a tool that returns a JSON array:
[ { "id": "abc-123", "status": "Succeeded", "startTime": "2026-04-27T10:00:00Z" }, { "id": "def-456", "status": "Running", "startTime": "2026-04-28T01:00:00Z" } ]Configure a custom sub-agent with access to that tool:
Create a session with sub-agents enabled and have the orchestrator delegate to
my-agentvia thetasktoolThe sub-agent calls
my-mcp-server/list_itemsand gets the error aboveA tool on the same server that returns a string (e.g.,
"No items found") succeeds in the same sub-agent session, confirming the issue is specifically with array responses.Expected behavior
MCP tool calls returning JSON arrays should work the same way in sub-agents as they do in the primary agent. A few possible fixes:
structuredContent:z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())])[...]into{ items: [...] }Additional context
onPostToolUsesession hook fires after the Zod validation, so there is no way to intercept the response before rejection.