Skip to content

[Server] Always emit items for array tool parameter schemas#378

Open
valeriudev wants to merge 1 commit into
modelcontextprotocol:mainfrom
valeriudev:fix/array-schema-missing-items
Open

[Server] Always emit items for array tool parameter schemas#378
valeriudev wants to merge 1 commit into
modelcontextprotocol:mainfrom
valeriudev:fix/array-schema-missing-items

Conversation

@valeriudev
Copy link
Copy Markdown

Problem

VS Code / Copilot and other strict MCP clients reject tools whose input schema declares an array parameter without an items keyword:

Failed to validate tool <name>: Error: tool parameters array type must have items. Please open a Github issue for the MCP server or extension which provides this tool

Any handler with an untyped array parameter (e.g. array $params = [], as in the report) generated {"type": "array"} with no items, so the tool was unusable in those clients.

Root cause

SchemaGenerator only set items when it could infer an element type:

  • Untyped arrays (array, array<string, mixed> maps, mixed) and untyped variadics emitted type: array with no items at all.
  • A nullable typed array (string[]|null) lost its element type entirely, because the |null suffix wasn't stripped before the T[] inference ran — so it too fell back to no items.

Fix

src/Capability/Discovery/SchemaGenerator.php, two parts:

  1. ensureArrayItems() runs after all schema merges (and on the variadic path). When the schema is array-typed and still has no items, it defaults to the empty schema — items: {} (a \stdClass, so it serializes to {} and not []), which matches any element. Running post-merge means a #[Schema] attribute that reshapes a parameter (e.g. to object) is respected and the invariant is only enforced on what is genuinely still an array.
  2. inferArrayItemsType() strips a top-level nullable union (string[]|null, null|int[]) before inference, so nullable typed arrays recover their element type. Inner unions like array<int|string> are left untouched (the strip is anchored to the start/end only); array nullability is still handled separately via allows_null.

No public API symbol changes — this corrects derived schema output to be spec-compliant, so it is a bugfix, not a [BC Break].

Verification

  • New unit tests testRecoversItemsTypeForNullableTypedArrays and testUntypedVariadicStillDeclaresItems; tightened the existing array-case assertions; new fixtures nullableTypedArrays / untypedVariadic.
  • make tests (unit + inspector), make phpstan, make cs, composer validate --strict, and make docs all green.
  • End-to-end: the committed HttpComplexToolSchemaTest snapshot now shows the nullable string[]|null attendee-emails parameter correctly carrying items: {type: string}.

Note for merge

A parallel branch of mine also opens a 0.6.1 CHANGELOG section. If it lands first, I'll rebase and move this bullet under the existing 0.6.1 heading rather than re-adding it.

Fixes #151

Array tool parameters without an inferable element type generated `{"type":"array"}` with no `items`, which strict MCP clients (VS Code / Copilot) reject. Always emit `items` (`{}` when the element type is unknown) and recover the element type for nullable typed arrays such as `string[]|null`.

Fixes modelcontextprotocol#151
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Failed to validate tool : Error: tool parameters array type must have items.

1 participant