[BUG] Cowork MCP client strips tool inputSchema properties typed as nullable unions (["string","null"]) — enums and nested schemas never reach the model

Open 💬 0 comments Opened Jul 13, 2026 by satrman1

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

In Cowork mode (Claude Desktop for Windows), for any MCP tool inputSchema property whose type is a union array containing null (the standard output of .NET/C#/Kotlin nullable types), the schema surfaced to the model is reduced to an empty objecttype, enum, and nested items/properties are all dropped. Only a stand-alone description survives.

What the MCP server sends (verbatim from a raw tools/list stdio capture — Sparx Systems Enterprise Architect MCP add-in MCP3.exe v2.8.4, tool create_or_update_connectors):

"direction": {
  "type": ["string","null"],
  "enum": ["Unspecified","FromSourceToTarget","FromTargetToSource","BothDirection", null]
}

What the model receives:

"direction": {}

More examples from the same tool, same pattern:

| Server sends | Model receives |
|---|---|
| "scope": {"type":["string","null"],"enum":["Public","Protected","Private","Package",null]} | "scope": {} |
| "routingStyle": {"description":"routing style in diagrams","type":["string","null"],"enum":["Default","OrthogonalSquare","OrthogonalRounded",null]} | "routingStyle": {"description":"routing style in diagrams"} |
| "taggedValues": {"description":"…","type":["array","null"],"items":{ …full nested object schema with its own enum… }} | "taggedValues": {"description":"…"} |

Simple-typed properties in the same tool are preserved correctly (e.g. "relatedElementID": {"type":"integer"} arrives typed; integer is normalized to number, which is harmless). The dropped properties are exactly those with union types.

Impact: the model cannot see the allowed enum values or nested structures, so it guesses — and every guess outside the invisible enum fails the tool call with the server's generic error. In our case this caused a three-email support exchange with the MCP server vendor (Sparx Systems Japan), where both sides were provably looking at different schemas: the vendor correctly claimed the enum is provided; our model never received it. Any MCP server whose schemas are generated from a language with nullable types is affected.

Related, but not duplicates: #5844 (display-level: anyOf-nullable params shown as unknown in /mcp), #31302 (large-schema truncation, closed as duplicate). This report is specifically about union-type properties arriving as {} in the model-facing schema, with a wire-level capture attached.

What Should Happen?

Nullable union types ("type": ["string","null"]) are valid JSON Schema (draft-07) and common in generated schemas. The client should preserve them as-is — or, if it must normalize for the API, keep the non-null member type together with enum and nested items/properties (e.g. {"type":"string","enum":[…]}), rather than dropping the property definition entirely. The model must see the same contract the server published.

Error Messages/Logs

No client-side error. Server-side consequence of the invisible enum: any guessed value fails with the server's generic error, e.g.:

request: {"connectorInfo":[{"connectorID":0,"type":"Dependency","direction":"Source -> Destination","sourceEnd":{"relatedElementID":1671},"targetEnd":{"relatedElementID":1672}}]}
response: "An error occurred invoking 'create_or_update_connectors'."

With the enum value from the raw schema (never shown to the model), the same call succeeds:
request: {"connectorInfo":[{"connectorID":0,"type":"Dependency","direction":"FromSourceToTarget",…}]}
response: {"Connectors":[{"connectorID":1177,"direction":"from source to target",…}]}

Steps to Reproduce

The MCP server used is the free official Sparx Systems EA MCP add-in (https://www.sparxsystems.jp/en/MCP), but any server declaring nullable union types reproduces it — a minimal FastMCP/TS server with one property "direction": {"type":["string","null"],"enum":["A","B",null]} is enough.

  1. Capture the server's raw tools/list: run the server binary manually and paste {"jsonrpc":"2.0","method":"tools/list","id":1} on stdin. Confirm the property carries type + enum (raw capture from our environment attached as file).
  2. Connect the same server in Claude Desktop → Cowork mode (STDIO, mcp.json).
  3. In a Cowork session, ask Claude to quote the tool definition of the affected property exactly as it appears in its tool list (or let it attempt a call — it cannot know the enum values).
  4. Compare: the property arrives as {} — no type, no enum; sibling properties with simple types ("type":"integer") arrive intact.
  5. Optional control proving it is client-side: send the call by hand with a value from the raw enum — the server accepts it (see Error Messages/Logs section).

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude Desktop for Windows 1.20186.0 (Cowork mode; no CLI — bundled Claude Code runtime version not user-visible)

Platform

Other

Operating System

Windows

Terminal/Shell

Other

Additional Information

Environment detail: Claude Desktop for Windows 1.20186.0, Cowork mode (no terminal involved - the 'Terminal' field does not apply). MCP server connected via STDIO from mcp.json. Reproduced identically with Claude Fable 5 and Claude Opus 4.8, and against MCP server versions 2.8.2 and 2.8.4 - the behavior is model- and server-version-independent, pointing at the client-side schema pipeline.

I will attach the full raw tools/list capture (tools-list-raw-2.8.4.json) to this issue - it contains the complete create_or_update_connectors inputSchema as sent by the server, for direct comparison with what the model receives.

View original on GitHub ↗