Skip to content

[Schema] Fix Implementation::fromArray rejecting falsy-but-valid name/version#393

Merged
chr-hertel merged 2 commits into
modelcontextprotocol:mainfrom
DevkumarPatel:fix/implementation-falsy-string-validation
Jul 14, 2026
Merged

[Schema] Fix Implementation::fromArray rejecting falsy-but-valid name/version#393
chr-hertel merged 2 commits into
modelcontextprotocol:mainfrom
DevkumarPatel:fix/implementation-falsy-string-validation

Conversation

@DevkumarPatel

Copy link
Copy Markdown
Contributor

Fixes #392.

Problem

Implementation::fromArray() validates the required name and version fields with empty(). Because empty('0') === true in PHP, a perfectly valid clientInfo/serverInfo carrying "version": "0" (or "name": "0") is rejected with an InvalidArgumentException.

During the initialize handshake this is especially confusing: the exception aborts parsing of the InitializeRequest, and Protocol::resolveSession() then reports the misleading error:

A valid session id is REQUIRED for non-initialize requests.

…which points nowhere near the actual cause.

Change

Replace the empty() guards with explicit checks:

if (!isset($data['name']) || !\is_string($data['name']) || '' === $data['name']) {
if (!isset($data['version']) || !\is_string($data['version']) || '' === $data['version']) {

This keeps rejecting the cases that should fail — missing, non-string, and genuinely empty ("") — while accepting falsy-but-valid strings like "0". Behavior is strictly widened; nothing previously valid is now rejected.

Tests

Adds tests/Unit/Schema/ImplementationTest.php (there was no existing test for this class), covering:

  • Regression: "version": "0" and "name": "0" are accepted.
  • Rejection of missing / empty-string / non-string name and version.
  • Constructor defaults, minimal & full fromArray, non-array icons, and jsonSerialize round-trip.
OK (14 tests, 34 assertions)

vendor/bin/phpstan reports no errors on the changed file.

Scope note

The same empty()-on-required-string pattern exists in several sibling schema DTOs (Icon, Prompt, PromptArgument, ResourceDefinition, ResourceTemplate, Root, Tool) — e.g. a tool literally named "0" would hit the identical bug. I've kept this PR scoped to the reported issue; happy to follow up with a sweep (single PR or per-DTO) if you'd prefer.

…/version

`empty()` treats the string "0" as empty, so a valid clientInfo/serverInfo
with `"version": "0"` (or `"name": "0"`) was rejected with an
InvalidArgumentException. During initialize this aborted request parsing and
surfaced as a misleading "A valid session id is REQUIRED" error.

Replace the `empty()` guards with explicit isset/is_string/empty-string checks
so genuinely missing, non-string, and empty values are still rejected while
"0" is accepted. Adds ImplementationTest covering the regression and the
existing validation paths.

Fixes modelcontextprotocol#392

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chr-hertel chr-hertel added bug Something isn't working Schema Issues & PRs related to the Schema component labels Jul 14, 2026
@chr-hertel

Copy link
Copy Markdown
Member

Thanks @DevkumarPatel for that patch - and follow-up for the broader scope very much welcome! 👍

@chr-hertel chr-hertel added this to the 0.7.0 milestone Jul 14, 2026
@chr-hertel chr-hertel merged commit 206aa9d into modelcontextprotocol:main Jul 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 Schema Issues & PRs related to the Schema component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implementation::fromArray rejects clientInfo version "0" (empty() on a falsy string)

2 participants