php-sdk/tests/Unit
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
..
Capability [Capability] Cast variadic tool parameters element-by-element (#465) 2026-08-29 15:46:40 +02:00
Client [Server][Client] Bridge W3C trace context between HTTP headers and _meta (SEP-414) (#473) 2026-08-24 01:26:22 +02:00
Fixtures [Server] Handle malformed JSON-RPC input graceful (#412) 2026-08-14 22:34:01 +02:00
JsonRpc [Schema] Omit the id of an error response that never had one (#442) 2026-08-18 15:24:19 +02:00
Schema [Client] Speak the 2026-07-28 lifecycle (#456) 2026-08-19 02:41:02 +02:00
Server [Server] Restrict FileSessionStore::gc() to owned session files (#479) 2026-08-25 00:43:08 +02:00
ClientTest.php [Client] Implement setMaxRetries connection retries (#413) 2026-08-15 02:43:50 +02:00
ServerTest.php Update codestyle based on updated Symfony rules (#229) 2026-02-01 11:54:31 +01:00