Skip to content

Reconsider the type-union schema-portability rule: providers recommend the array form for nullable fields #2286

Description

@cliffhall

Split out of #2205, which asked two independent things. The usability half — collapsing the Schema portability section — is #2285. This is the other half.

The argument

core/json/schemaLint.ts raises a type-union warning whenever a schema spells a type as an array:

type is an array (["string","null"]). The array form is legal JSON Schema, but several MCP clients read type as a single string and either reject the tool or drop the constraint.

The reporter of #2205 points out that this contradicts guidance from a major LLM provider. OpenAI's structured-outputs guide recommends exactly this construct for a nullable required field:

Although all fields must be required (and the model will return a value for each parameter), it is possible to emulate an optional parameter by using a union type with null.

with the example:

"unit": {
  "type": ["string", "null"],
  "description": "The unit to return the temperature in",
  "enum": ["F", "C"]
}

https://developers.openai.com/api/docs/guides/structured-outputs

What is actually in question

The rule is not obviously wrong — it is about what MCP clients accept, which is a different population from what a model provider's own API accepts, and the module's header is explicit that every rule encodes a construct known to be refused or mishandled by a real MCP client. But nothing in the repo records which clients those are for this particular rule, and that is what would settle it.

So the question to answer, in order:

  1. Which shipping MCP clients actually mishandle an array-form type? Name them, with a version. If the answer is "none any more", the rule has outlived its evidence.
  2. If some do, is warning still the right severity, given that a server author may be deliberately following provider guidance? A third tier below warning is one option; rewording the message to frame it as a portability caveat rather than a defect is another.
  3. If it stays, should the message acknowledge the tension — that the array form is what some providers recommend, and the trade is portability against that?

Why it is not part of #2285

The rule is shared by all three clients, so any change to it moves more than the web panel:

  • the CLI's --strict report and its exit code (mcp-inspector --cli … --strict exits 6 on findings — demoting or dropping the rule changes whether a CI job that runs it goes red)
  • the TUI's tool detail pane
  • ToolListItem's severity icon in the web sidebar

test-servers/configs/unportable-schemas-many-http.json exercises the rule heavily (7 of its 26 findings are type-union) if you want a server to look at while deciding.

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

    questionFurther information is requestedv2Issues and PRs for v2

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions