From 6b6c962feeb09e25f23eb7c61e1769549fd12690 Mon Sep 17 00:00:00 2001 From: Julien Duseyau Date: Wed, 23 Jul 2025 18:28:18 +0200 Subject: [PATCH 1/4] Normalize stdClass to array in Request::fromArray() for param type safety Converts stdClass to an associative array when decoding 'params' in JsonRpc\Request, ensuring type compliance with downstream DTOs. Fixes https://github.com/php-mcp/server/issues/53 See https://github.com/php-mcp/server/issues/53#issuecomment-3107833955 --- src/JsonRpc/Request.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/JsonRpc/Request.php b/src/JsonRpc/Request.php index 7b008f0..03298f9 100644 --- a/src/JsonRpc/Request.php +++ b/src/JsonRpc/Request.php @@ -42,6 +42,9 @@ public static function fromArray(array $data): static throw new \InvalidArgumentException('Invalid or missing "method" for Request.'); } $params = $data['params'] ?? null; + if ($params instanceof \stdClass) { + $params = (array) $params; + } if ($params !== null && !is_array($params)) { throw new \InvalidArgumentException('"params" for Request must be an array/object or null.'); } From 380c4a0747a331c1ebc606f7ed66ceb63cba1e81 Mon Sep 17 00:00:00 2001 From: Julien Duseyau Date: Wed, 23 Jul 2025 18:47:27 +0200 Subject: [PATCH 2/4] Normalize 'arguments' in CallToolRequest::fromRequest() Fixes runtime issue where 'arguments' could be a stdClass when omitted or sent as {}. Casts to array and defaults to [] to ensure strict constructor contract. Related to https://github.com/php-mcp/server/issues/53 --- src/Request/CallToolRequest.php | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Request/CallToolRequest.php b/src/Request/CallToolRequest.php index 487302d..c57c713 100644 --- a/src/Request/CallToolRequest.php +++ b/src/Request/CallToolRequest.php @@ -52,17 +52,27 @@ public static function fromRequest(Request $request): static throw new \InvalidArgumentException('Request is not a call tool request'); } - $params = $request->params; + $params = $request->params ?? []; - if (! isset($params['name']) || ! is_string($params['name'])) { + if (!isset($params['name']) || !is_string($params['name'])) { throw new \InvalidArgumentException("Missing or invalid 'name' parameter for tools/call."); } - $arguments = $params['arguments'] ?? new \stdClass(); - if (! is_array($arguments) && ! $arguments instanceof \stdClass) { - throw new \InvalidArgumentException("Parameter 'arguments' must be an object/array for tools/call."); + $arguments = $params['arguments'] ?? []; + + if ($arguments instanceof \stdClass) { + $arguments = (array) $arguments; + } + + if (!is_array($arguments)) { + throw new \InvalidArgumentException("Parameter 'arguments' must be an array."); } - return new static($request->id, $params['name'], $arguments, $params['_meta'] ?? null); + return new static( + $request->id, + $params['name'], + $arguments, + $params['_meta'] ?? null + ); } } From 2ede1b22f4fa014c2b90a33aea8db052a05a0df7 Mon Sep 17 00:00:00 2001 From: Kyrian Obikwelu Date: Fri, 25 Jul 2025 10:27:50 +0100 Subject: [PATCH 3/4] fix: add missing $rootsEnabled parameter to ClientCapabilities constructor --- src/ClientCapabilities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ClientCapabilities.php b/src/ClientCapabilities.php index f20417a..1b01083 100644 --- a/src/ClientCapabilities.php +++ b/src/ClientCapabilities.php @@ -62,6 +62,7 @@ public static function fromArray(array $data): static } return new static( + $rootsEnabled, $rootsListChanged, $sampling, $data['experimental'] ?? null From 18f9f09b1564dd222f59674249eb4aa43615afe7 Mon Sep 17 00:00:00 2001 From: Kyrian Obikwelu Date: Fri, 25 Jul 2025 10:41:08 +0100 Subject: [PATCH 4/4] fix: update condition for rootsListChanged in ClientCapabilities --- src/ClientCapabilities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ClientCapabilities.php b/src/ClientCapabilities.php index 1b01083..766f817 100644 --- a/src/ClientCapabilities.php +++ b/src/ClientCapabilities.php @@ -28,7 +28,7 @@ public function toArray(): array $data = []; if ($this->roots || $this->rootsListChanged) { $data['roots'] = new \stdClass(); - if ($this->rootsListChanged) { + if ($this->rootsListChanged !== null) { $data['roots']->listChanged = $this->rootsListChanged; } }