php-sdk/tests/Unit/Capability
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Sviatoslav 46628fbe6a
[Capability] Cast variadic tool parameters element-by-element (#465)
* Cast variadic tool parameters element-by-element

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.

* Address chr-hertel's review: wrap scalars, reject objects, index cast errors

- Non-array variadic argument is now wrapped as a single-element list
  instead of being rejected: MCP prompt arguments are always
  Record<string,string> per protocol, so a variadic prompt parameter
  legitimately receives a plain string, not an array. Rejecting it
  regressed behaviour that worked on main.
- A JSON object (non-list array) is now explicitly rejected instead of
  being silently flattened into positional args by array_values().
- Cast-failure errors now include the parameter name and element index,
  so a failure inside a large array is actually actionable.
- Trimmed the inline rationale comment; the PR description already
  covers it.

Tests updated: replaced the "throws on non-array" test (no longer
correct) with tests for the wrap-as-single-element, reject-object, and
indexed-error-message behaviours.

* Pin argument order for an injectable before a variadic

---------

Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
2026-08-29 15:46:40 +02:00
..
Attribute [Schema][Server] Add top-level title to Tool (#288) 2026-04-26 15:37:40 +02:00
Discovery [Server] Keep injectable parameters out of the published inputSchema (#482) 2026-08-25 01:12:29 +02:00
Formatter [Capability] Harden structuredContent extraction (#417) 2026-08-15 04:03:20 +02:00
Logger style: apply php-cs-fixer and PHPStan fixes (#289) 2026-04-20 20:49:15 +02:00
Registry [Capability] Cast variadic tool parameters element-by-element (#465) 2026-08-29 15:46:40 +02:00
Tool Add tool name validation for SEP-986 (#140) 2025-11-13 21:42:30 +01:00
RegistryTest.php [Capability] Suppress list-changed events during the initial registry load (#480) 2026-08-25 00:45:00 +02:00