Skip to content

[Server] Accept nested empty objects in tool arguments - #609

Closed
chr-hertel wants to merge 1 commit into
modelcontextprotocol:mainfrom
chr-hertel:issue-586-schemavalidator-rejects-nested
Closed

chr-hertel wants to merge 1 commit into
modelcontextprotocol:mainfrom
chr-hertel:issue-586-schemavalidator-rejects-nested

Conversation

@chr-hertel

Copy link
Copy Markdown
Member

Tool arguments are decoded with assoc: true, so a nested {} arrives as [] and failed an object schema. Only the root was patched.

SchemaValidator::validateAgainstJsonSchema() now takes emptyArrayMayBeObject: true: an empty array that only failed for not being an object is turned into {} and validated again. Since opis resolves the schema, $ref, additionalProperties, items and oneOf/anyOf are covered; a branch that accepts [] keeps it an array. CallToolHandler uses it for arguments and drops its root special case. Output validation stays strict.

This is not #587: arguments are still decoded with assoc: true and handlers still get arrays, so nothing changes for them. It only stops valid {} from being rejected. What stays lossy until #587:

  • [] sent for an object-only parameter is accepted, as the root already was
  • {"0":"x"} and ["x"] can't be told apart

Fixes #586

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Conflicting branch repairs and union-type constraints still cause valid empty-object arguments to be rejected.

2 open issues
What changed in this PR

Adds opt-in handling of nested empty objects during tool argument validation, while preserving array-based handler inputs and strict output validation.

Changes:

  • Retry validation after converting eligible empty arrays to objects.
  • Enable this behavior for tool arguments.
  • Add regression tests and a changelog entry.
File Description
tests/​Unit/​Server/​Handler/​Request/​CallToolHandlerTest.php Tests nested empty-object arguments and unchanged handler inputs.
tests/​Unit/​Capability/​Discovery/​SchemaValidatorTest.php Tests opt-in conversion and strict validation.
src/​Server/​Handler/​Request/​CallToolHandler.php Enables conversion for input validation.
src/​Capability/​Discovery/​SchemaValidator.php Adds error-driven conversion and validation retries.
CHANGELOG.md Documents the fix and validator option.

Review effort: Balanced

{
$errors = [];
if (null !== $error) {
$this->collectLeafErrors($error, $errors);
Comment on lines +170 to +171
if ('type' !== $leaf->keyword() || [] !== $leaf->data()->value() || !\in_array('object', $expected, true) || \in_array('array', $expected, true)) {
continue;
@chr-hertel chr-hertel added bug Something isn't working Server Issues & PRs related to the Server component labels Oct 18, 2026
@chr-hertel

Copy link
Copy Markdown
Member Author

naah, not really

@chr-hertel chr-hertel closed this Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SchemaValidator rejects nested empty JSON objects as arrays

2 participants