Skip to content

[Schema] Always emit {} for empty tool schema properties - #407

Merged
chr-hertel merged 2 commits into
modelcontextprotocol:mainfrom
BrocksiNet:fix/405-normalize-empty-tool-schema-properties
Aug 14, 2026
Merged

[Schema] Always emit {} for empty tool schema properties#407
chr-hertel merged 2 commits into
modelcontextprotocol:mainfrom
BrocksiNet:fix/405-normalize-empty-tool-schema-properties

Conversation

@BrocksiNet

Copy link
Copy Markdown
Contributor

Summary

  • Move empty-properties normalization into Tool::__construct() so every construction path (not only fromArray / SchemaGenerator) emits JSON Schema objects as {} instead of [].
  • Make the walk recursive across nested property schemas, items, additionalProperties, and combinators, and apply it to outputSchema as well.
  • Add unit coverage for direct construction, json_decode round-trips, nested objects, array item schemas, and empty outputSchema.properties.

Fixes #405

Test plan

  • make unit-tests (834 tests)
  • make phpstan
  • make cs
  • make inspector-tests (95 tests, 7 skipped)
  • composer validate --strict
  • Confirm a parameterless tool serializes "properties":{} in tools/list against a strict client (e.g. OpenAI-compatible)

chr-hertel
chr-hertel previously approved these changes Aug 14, 2026

@chr-hertel chr-hertel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @BrocksiNet - will extend the list of supported keywords and rebase for v0.8.0 while merging. Thanks for the patch!

@chr-hertel chr-hertel added Schema Issues & PRs related to the Schema component P2 Moderate issues affecting some users, edge cases, potentially valuable feature labels Aug 14, 2026
BrocksiNet and others added 2 commits August 14, 2026 21:44
Normalize empty properties arrays (including nested object schemas and
outputSchema) in Tool::__construct so tools/list never serializes
invalid JSON Schema properties: [].

Fixes modelcontextprotocol#405
Walking into `items` and `additionalProperties` without normalizing an empty
sub-schema at those positions left the `[]`-instead-of-`{}` bug intact one
level down. Most notably it regressed modelcontextprotocol#151 on a `Tool::fromArray()`
round-trip: `SchemaGenerator` emits `items: {}` for untyped array parameters,
which decodes to `[]` and was re-serialized as `[]` — the exact schema strict
clients reject.

Empty sub-schemas are now replaced with a `\stdClass` at every schema
position, and the keyword list is completed to cover draft-07 through
2020-12: `$defs`, `definitions`, `dependentSchemas`, `patternProperties`,
`propertyNames`, `contains`, `not`, `if`/`then`/`else`, `additionalItems`,
and `unevaluatedItems`/`unevaluatedProperties`. Keywords holding plain JSON
arrays (`allOf: []`, `enum: []`, `dependentRequired`) keep encoding as `[]`.
@chr-hertel chr-hertel modified the milestones: 0.6.0, 0.8.0 Aug 14, 2026
@chr-hertel
chr-hertel force-pushed the fix/405-normalize-empty-tool-schema-properties branch from 3211fa1 to 05ac007 Compare August 14, 2026 19:46
@chr-hertel
chr-hertel merged commit 9236824 into modelcontextprotocol:main Aug 14, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working P2 Moderate issues affecting some users, edge cases, potentially valuable feature Schema Issues & PRs related to the Schema component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool serializes empty inputSchema.properties as [] instead of {}

2 participants