Skip to content

Cast variadic tool parameters element-by-element - #465

Open
Faneraiy14 wants to merge 1 commit into
modelcontextprotocol:mainfrom
Faneraiy14:fix/reference-handler-variadic-parameters
Open

Cast variadic tool parameters element-by-element#465
Faneraiy14 wants to merge 1 commit into
modelcontextprotocol:mainfrom
Faneraiy14:fix/reference-handler-variadic-parameters

Conversation

@Faneraiy14

Copy link
Copy Markdown

Summary

SchemaGenerator::buildVariadicParameterSchema() already advertises a variadic parameter (e.g. int ...$scores) as a JSON "array" schema, so a spec-conformant client sends an array for it. But ReferenceHandler::prepareArguments() never special-cased ReflectionParameter::isVariadic() — it fell through to the regular single-value branch and passed the whole array to castArgumentType(), which tried to cast it as one scalar and failed (e.g. "Cannot cast value to integer" for int ...$scores given [1, 2, 3]).

Any tool handler declaring a variadic parameter was therefore unreachable through the advertised schema — confirmed by direct reproduction against ReferenceHandler::handle() before this change:

EXCEPTION: Mcp\Exception\RegistryException: Cannot cast value to integer. Expected integer representation.

This resolves the // TODO: Handle variadic parameters. left in prepareArguments().

Fix

Casts each array element individually via the existing castArgumentType() (unchanged — it already inspects the variadic parameter's element type, not array, per PHP reflection semantics) and appends to the result in order. Variadic is always the last parameter, so this preserves correct positional ordering. A non-array value for a variadic argument now fails clearly with an invalid-params error instead of the confusing cast message.

Test plan

  • New unit tests: array argument cast element-by-element, omitted argument treated as zero elements, non-array argument rejected with a clear error
  • vendor/bin/phpunit --testsuite=unit — 1516 tests, 3923 assertions, all passing
  • vendor/bin/phpstan analyse (full repo, level 6 per phpstan.dist.neon) — no errors

SchemaGenerator::buildVariadicParameterSchema() already advertises a
variadic parameter (e.g. `int ...$scores`) as a JSON "array" schema, so
a spec-conformant client sends an array for it. But
ReferenceHandler::prepareArguments() never special-cased
ReflectionParameter::isVariadic(): it fell through to the regular
single-value branch and passed the whole array to castArgumentType(),
which tried to cast it as one scalar and failed - e.g. "Cannot cast
value to integer" for `int ...$scores` given [1, 2, 3].

Any tool handler declaring a variadic parameter was therefore
unreachable through the advertised schema, confirmed by direct
reproduction against ReferenceHandler::handle() before this change.

Casts each array element individually via the existing
castArgumentType() (unchanged - it already inspects the variadic
parameter's element type, not "array", per PHP reflection semantics)
and appends to the result in order; variadic is always the last
parameter, so this preserves correct positional ordering. A non-array
value for a variadic argument now fails clearly with an invalid-params
error instead of the confusing cast message.
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.

1 participant