Skip to content

McpServer emits structuredContent: null because typeof null is "object" #7494

Closed

Description

@grey-tsosie

What happens

packages/effect/src/unstable/ai/McpServer.ts builds every tool reply with:

structuredContent: typeof result.encodedResult === "object" ? result.encodedResult : undefined,

typeof reports "object" for null and for arrays. A handler that returns nothing therefore emits structuredContent: null, and one that returns a list emits an array.

Why that breaks callers

structuredContent is optional in CallToolResult. Optional means the key may be absent, not that it may be null, and the schema types it as an object. A client that validates its input rejects the whole reply, so the caller never sees the result at all.

Observed against a real server built on this code, every call to the affected tools failed with:

Invalid result for tools/call: [
  {
    "expected": "record",
    "code": "invalid_type",
    "path": [ "structuredContent" ],
    "message": "Invalid input: expected record, received null"
  }
]

The array case produces the same error with received array.

Note that the tool does not need an outputSchema for this to bite. validateToolOutput returns early when there is no output schema, so nothing on the server side ever looks at the value.

Reproduction

Register a tool whose handler returns void, or one whose success value encodes to an array. Call it from any client that validates CallToolResult against the schema.

Suggested fix

Test the value rather than its typeof, so null and arrays fall through to undefined.

Version

Found on effect 4.0.0-beta.103, and the line is unchanged on main as of 2026-08-27.

Related: #7072 fixed a different defect on the same expression.

Found with Claude Opus 5 in Claude Code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions