From a64fd6c9a282c1fdc60bffb69f2e8f22e6abc915 Mon Sep 17 00:00:00 2001 From: Igor Markin Date: Tue, 9 Sep 2025 13:04:51 +0300 Subject: [PATCH 1/3] Change return type of abstract request methods --- src/Schema/JsonRpc/Request.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Schema/JsonRpc/Request.php b/src/Schema/JsonRpc/Request.php index a4d0c0f4..6807930b 100644 --- a/src/Schema/JsonRpc/Request.php +++ b/src/Schema/JsonRpc/Request.php @@ -36,7 +36,7 @@ abstract public static function getMethod(): string; /** * @param RequestData $data */ - public static function fromArray(array $data): self + public static function fromArray(array $data): static { if (($data['jsonrpc'] ?? null) !== MessageInterface::JSONRPC_VERSION) { throw new InvalidArgumentException('Invalid or missing "jsonrpc" version for Request.'); @@ -68,7 +68,7 @@ public static function fromArray(array $data): self /** * @param array|null $params */ - abstract protected static function fromParams(?array $params): self; + abstract protected static function fromParams(?array $params): static; public function getId(): string|int { From 207befdb6f695d200b93864b9d1a0fee396d0d24 Mon Sep 17 00:00:00 2001 From: Igor Markin Date: Tue, 9 Sep 2025 17:07:57 +0300 Subject: [PATCH 2/3] Change return type of `fromParams` method to `static` in request classes (cherry picked from commit 94799ab66ff60d4b2305aadb6b73aaa4c805221e) --- src/Schema/Request/CallToolRequest.php | 2 +- src/Schema/Request/CompletionCompleteRequest.php | 2 +- src/Schema/Request/CreateSamplingMessageRequest.php | 2 +- src/Schema/Request/GetPromptRequest.php | 2 +- src/Schema/Request/InitializeRequest.php | 2 +- src/Schema/Request/ListPromptsRequest.php | 2 +- src/Schema/Request/ListResourceTemplatesRequest.php | 2 +- src/Schema/Request/ListResourcesRequest.php | 2 +- src/Schema/Request/ListRootsRequest.php | 2 +- src/Schema/Request/ListToolsRequest.php | 2 +- src/Schema/Request/PingRequest.php | 2 +- src/Schema/Request/ReadResourceRequest.php | 2 +- src/Schema/Request/ResourceSubscribeRequest.php | 2 +- src/Schema/Request/ResourceUnsubscribeRequest.php | 2 +- src/Schema/Request/SetLogLevelRequest.php | 2 +- tests/Schema/JsonRpc/RequestTest.php | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Schema/Request/CallToolRequest.php b/src/Schema/Request/CallToolRequest.php index 0bc7fcf3..50bbd421 100644 --- a/src/Schema/Request/CallToolRequest.php +++ b/src/Schema/Request/CallToolRequest.php @@ -36,7 +36,7 @@ public static function getMethod(): string return 'tools/call'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['name']) || !\is_string($params['name'])) { throw new InvalidArgumentException('Missing or invalid "name" parameter for tools/call.'); diff --git a/src/Schema/Request/CompletionCompleteRequest.php b/src/Schema/Request/CompletionCompleteRequest.php index 324b0041..1ae6433c 100644 --- a/src/Schema/Request/CompletionCompleteRequest.php +++ b/src/Schema/Request/CompletionCompleteRequest.php @@ -38,7 +38,7 @@ public static function getMethod(): string return 'completion/complete'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['ref']) || !\is_array($params['ref'])) { throw new InvalidArgumentException('Missing or invalid "ref" parameter for completion/complete.'); diff --git a/src/Schema/Request/CreateSamplingMessageRequest.php b/src/Schema/Request/CreateSamplingMessageRequest.php index ae9ea39c..82ef54ed 100644 --- a/src/Schema/Request/CreateSamplingMessageRequest.php +++ b/src/Schema/Request/CreateSamplingMessageRequest.php @@ -59,7 +59,7 @@ public static function getMethod(): string return 'sampling/createMessage'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['messages']) || !\is_array($params['messages'])) { throw new InvalidArgumentException('Missing or invalid "messages" parameter for sampling/createMessage.'); diff --git a/src/Schema/Request/GetPromptRequest.php b/src/Schema/Request/GetPromptRequest.php index 68954e9c..fe17d1bd 100644 --- a/src/Schema/Request/GetPromptRequest.php +++ b/src/Schema/Request/GetPromptRequest.php @@ -36,7 +36,7 @@ public static function getMethod(): string return 'prompts/get'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['name']) || !\is_string($params['name']) || empty($params['name'])) { throw new InvalidArgumentException('Missing or invalid "name" parameter for prompts/get.'); diff --git a/src/Schema/Request/InitializeRequest.php b/src/Schema/Request/InitializeRequest.php index 702aa7b3..4365358a 100644 --- a/src/Schema/Request/InitializeRequest.php +++ b/src/Schema/Request/InitializeRequest.php @@ -40,7 +40,7 @@ public static function getMethod(): string return 'initialize'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['protocolVersion'])) { throw new InvalidArgumentException('protocolVersion is required'); diff --git a/src/Schema/Request/ListPromptsRequest.php b/src/Schema/Request/ListPromptsRequest.php index 5f388d66..d16e3ec2 100644 --- a/src/Schema/Request/ListPromptsRequest.php +++ b/src/Schema/Request/ListPromptsRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'prompts/list'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { return new self($params['cursor'] ?? null); } diff --git a/src/Schema/Request/ListResourceTemplatesRequest.php b/src/Schema/Request/ListResourceTemplatesRequest.php index bf6da924..67dba430 100644 --- a/src/Schema/Request/ListResourceTemplatesRequest.php +++ b/src/Schema/Request/ListResourceTemplatesRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'resources/templates/list'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { return new self($params['cursor'] ?? null); } diff --git a/src/Schema/Request/ListResourcesRequest.php b/src/Schema/Request/ListResourcesRequest.php index 85527dff..9eee6f3e 100644 --- a/src/Schema/Request/ListResourcesRequest.php +++ b/src/Schema/Request/ListResourcesRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'resources/list'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { return new self($params['cursor'] ?? null); } diff --git a/src/Schema/Request/ListRootsRequest.php b/src/Schema/Request/ListRootsRequest.php index 3e8fd9fe..542ee43a 100644 --- a/src/Schema/Request/ListRootsRequest.php +++ b/src/Schema/Request/ListRootsRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'roots/list'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { return new self(); } diff --git a/src/Schema/Request/ListToolsRequest.php b/src/Schema/Request/ListToolsRequest.php index 56ed591a..641fcac3 100644 --- a/src/Schema/Request/ListToolsRequest.php +++ b/src/Schema/Request/ListToolsRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'tools/list'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { return new self($params['cursor'] ?? null); } diff --git a/src/Schema/Request/PingRequest.php b/src/Schema/Request/PingRequest.php index 13e13202..a40d87ce 100644 --- a/src/Schema/Request/PingRequest.php +++ b/src/Schema/Request/PingRequest.php @@ -26,7 +26,7 @@ public static function getMethod(): string return 'ping'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { return new self(); } diff --git a/src/Schema/Request/ReadResourceRequest.php b/src/Schema/Request/ReadResourceRequest.php index 4aadbe8d..3bdd6c1c 100644 --- a/src/Schema/Request/ReadResourceRequest.php +++ b/src/Schema/Request/ReadResourceRequest.php @@ -34,7 +34,7 @@ public static function getMethod(): string return 'resources/read'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['uri']) || !\is_string($params['uri']) || empty($params['uri'])) { throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/read.'); diff --git a/src/Schema/Request/ResourceSubscribeRequest.php b/src/Schema/Request/ResourceSubscribeRequest.php index 0b17b6c1..2ff66e12 100644 --- a/src/Schema/Request/ResourceSubscribeRequest.php +++ b/src/Schema/Request/ResourceSubscribeRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'resources/subscribe'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['uri']) || !\is_string($params['uri']) || empty($params['uri'])) { throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/subscribe.'); diff --git a/src/Schema/Request/ResourceUnsubscribeRequest.php b/src/Schema/Request/ResourceUnsubscribeRequest.php index 54349ae8..f89c030c 100644 --- a/src/Schema/Request/ResourceUnsubscribeRequest.php +++ b/src/Schema/Request/ResourceUnsubscribeRequest.php @@ -35,7 +35,7 @@ public static function getMethod(): string return 'resources/unsubscribe'; } - protected static function fromParams(?array $params): Request + protected static function fromParams(?array $params): static { if (!isset($params['uri']) || !\is_string($params['uri']) || empty($params['uri'])) { throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/unsubscribe.'); diff --git a/src/Schema/Request/SetLogLevelRequest.php b/src/Schema/Request/SetLogLevelRequest.php index 610c241d..8595ef08 100644 --- a/src/Schema/Request/SetLogLevelRequest.php +++ b/src/Schema/Request/SetLogLevelRequest.php @@ -37,7 +37,7 @@ public static function getMethod(): string return 'logging/setLevel'; } - protected static function fromParams(?array $params): self + protected static function fromParams(?array $params): static { if (!isset($params['level']) || !\is_string($params['level']) || empty($params['level'])) { throw new InvalidArgumentException('Missing or invalid "level" parameter for "logging/setLevel".'); diff --git a/tests/Schema/JsonRpc/RequestTest.php b/tests/Schema/JsonRpc/RequestTest.php index a22b9272..279d0953 100644 --- a/tests/Schema/JsonRpc/RequestTest.php +++ b/tests/Schema/JsonRpc/RequestTest.php @@ -24,7 +24,7 @@ public static function getMethod(): string return 'foo/bar'; } - public static function fromParams(?array $params): self + public static function fromParams(?array $params): static { return new self(); } From 2516d4cd5afee097a6157c07f42422cd02e8c2bf Mon Sep 17 00:00:00 2001 From: Igor Markin Date: Tue, 9 Sep 2025 18:39:00 +0300 Subject: [PATCH 3/3] Make request classes final and update `getParams` return types for improved type safety (cherry picked from commit d6be496f89cc0e6d30f519792d0dc902685c4178) --- src/Schema/JsonRpc/Request.php | 2 +- src/Schema/Request/CallToolRequest.php | 7 +++++-- src/Schema/Request/CompletionCompleteRequest.php | 10 ++++++++-- .../Request/CreateSamplingMessageRequest.php | 16 ++++++++++++++-- src/Schema/Request/GetPromptRequest.php | 7 +++++-- src/Schema/Request/InitializeRequest.php | 7 +++++-- src/Schema/Request/ListPromptsRequest.php | 5 ++++- .../Request/ListResourceTemplatesRequest.php | 5 ++++- src/Schema/Request/ListResourcesRequest.php | 5 ++++- src/Schema/Request/ListRootsRequest.php | 2 +- src/Schema/Request/ListToolsRequest.php | 5 ++++- src/Schema/Request/PingRequest.php | 2 +- src/Schema/Request/ReadResourceRequest.php | 9 ++++++--- src/Schema/Request/ResourceSubscribeRequest.php | 9 ++++++--- .../Request/ResourceUnsubscribeRequest.php | 9 ++++++--- src/Schema/Request/SetLogLevelRequest.php | 7 +++++-- 16 files changed, 79 insertions(+), 28 deletions(-) diff --git a/src/Schema/JsonRpc/Request.php b/src/Schema/JsonRpc/Request.php index 6807930b..22083c75 100644 --- a/src/Schema/JsonRpc/Request.php +++ b/src/Schema/JsonRpc/Request.php @@ -97,7 +97,7 @@ public function jsonSerialize(): array } /** - * @return array|null + * @return array|null */ abstract protected function getParams(): ?array; } diff --git a/src/Schema/Request/CallToolRequest.php b/src/Schema/Request/CallToolRequest.php index 50bbd421..49bcd0d8 100644 --- a/src/Schema/Request/CallToolRequest.php +++ b/src/Schema/Request/CallToolRequest.php @@ -19,7 +19,7 @@ * * @author Kyrian Obikwelu */ -class CallToolRequest extends Request +final class CallToolRequest extends Request { /** * @param string $name the name of the tool to invoke @@ -58,7 +58,10 @@ protected static function fromParams(?array $params): static ); } - protected function getParams(): ?array + /** + * @return array{name: string, arguments: array} + */ + protected function getParams(): array { return [ 'name' => $this->name, diff --git a/src/Schema/Request/CompletionCompleteRequest.php b/src/Schema/Request/CompletionCompleteRequest.php index 1ae6433c..467bb97c 100644 --- a/src/Schema/Request/CompletionCompleteRequest.php +++ b/src/Schema/Request/CompletionCompleteRequest.php @@ -21,7 +21,7 @@ * * @author Kyrian Obikwelu */ -class CompletionCompleteRequest extends Request +final class CompletionCompleteRequest extends Request { /** * @param PromptReference|ResourceReference $ref the prompt or resource to complete @@ -57,7 +57,13 @@ protected static function fromParams(?array $params): static return new self($ref, $params['argument']); } - protected function getParams(): ?array + /** + * @return array{ + * ref: PromptReference|ResourceReference, + * argument: array{ name: string, value: string } + * } + */ + protected function getParams(): array { return [ 'ref' => $this->ref, diff --git a/src/Schema/Request/CreateSamplingMessageRequest.php b/src/Schema/Request/CreateSamplingMessageRequest.php index 82ef54ed..f07a632b 100644 --- a/src/Schema/Request/CreateSamplingMessageRequest.php +++ b/src/Schema/Request/CreateSamplingMessageRequest.php @@ -23,7 +23,7 @@ * * @author Kyrian Obikwelu */ -class CreateSamplingMessageRequest extends Request +final class CreateSamplingMessageRequest extends Request { /** * @param SamplingMessage[] $messages the messages to send to the model @@ -86,7 +86,19 @@ protected static function fromParams(?array $params): static ); } - protected function getParams(): ?array + /** + * @return array{ + * messages: SamplingMessage[], + * maxTokens: int, + * preferences?: ModelPreferences, + * systemPrompt?: string, + * includeContext?: string, + * temperature?: float, + * stopSequences?: string[], + * metadata?: array + * } + */ + protected function getParams(): array { $params = [ 'messages' => $this->messages, diff --git a/src/Schema/Request/GetPromptRequest.php b/src/Schema/Request/GetPromptRequest.php index fe17d1bd..bc6903f3 100644 --- a/src/Schema/Request/GetPromptRequest.php +++ b/src/Schema/Request/GetPromptRequest.php @@ -19,7 +19,7 @@ * * @author Kyrian Obikwelu */ -class GetPromptRequest extends Request +final class GetPromptRequest extends Request { /** * @param string $name the name of the prompt to get @@ -55,7 +55,10 @@ protected static function fromParams(?array $params): static return new self($params['name'], $arguments); } - protected function getParams(): ?array + /** + * @return array{name: string, arguments?: array} + */ + protected function getParams(): array { $params = ['name' => $this->name]; diff --git a/src/Schema/Request/InitializeRequest.php b/src/Schema/Request/InitializeRequest.php index 4365358a..04db317c 100644 --- a/src/Schema/Request/InitializeRequest.php +++ b/src/Schema/Request/InitializeRequest.php @@ -21,7 +21,7 @@ * * @author Kyrian Obikwelu */ -class InitializeRequest extends Request +final class InitializeRequest extends Request { /** * @param string $protocolVersion The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well. @@ -59,7 +59,10 @@ protected static function fromParams(?array $params): static return new self($params['protocolVersion'], $capabilities, $clientInfo); } - protected function getParams(): ?array + /** + * @return array{protocolVersion: string, capabilities: ClientCapabilities, clientInfo: Implementation} + */ + protected function getParams(): array { return [ 'protocolVersion' => $this->protocolVersion, diff --git a/src/Schema/Request/ListPromptsRequest.php b/src/Schema/Request/ListPromptsRequest.php index d16e3ec2..8c627999 100644 --- a/src/Schema/Request/ListPromptsRequest.php +++ b/src/Schema/Request/ListPromptsRequest.php @@ -18,7 +18,7 @@ * * @author Kyrian Obikwelu */ -class ListPromptsRequest extends Request +final class ListPromptsRequest extends Request { /** * If provided, the server should return results starting after this cursor. @@ -40,6 +40,9 @@ protected static function fromParams(?array $params): static return new self($params['cursor'] ?? null); } + /** + * @return array{cursor:string}|null + */ protected function getParams(): ?array { $params = []; diff --git a/src/Schema/Request/ListResourceTemplatesRequest.php b/src/Schema/Request/ListResourceTemplatesRequest.php index 67dba430..4ce4dfd9 100644 --- a/src/Schema/Request/ListResourceTemplatesRequest.php +++ b/src/Schema/Request/ListResourceTemplatesRequest.php @@ -18,7 +18,7 @@ * * @author Kyrian Obikwelu */ -class ListResourceTemplatesRequest extends Request +final class ListResourceTemplatesRequest extends Request { /** * @param string|null $cursor An opaque token representing the current pagination position. @@ -40,6 +40,9 @@ protected static function fromParams(?array $params): static return new self($params['cursor'] ?? null); } + /** + * @return array{cursor:string}|null + */ protected function getParams(): ?array { $params = []; diff --git a/src/Schema/Request/ListResourcesRequest.php b/src/Schema/Request/ListResourcesRequest.php index 9eee6f3e..30c00418 100644 --- a/src/Schema/Request/ListResourcesRequest.php +++ b/src/Schema/Request/ListResourcesRequest.php @@ -18,7 +18,7 @@ * * @author Kyrian Obikwelu */ -class ListResourcesRequest extends Request +final class ListResourcesRequest extends Request { /** * @param string|null $cursor An opaque token representing the current pagination position. @@ -40,6 +40,9 @@ protected static function fromParams(?array $params): static return new self($params['cursor'] ?? null); } + /** + * @return array{cursor:string}|null + */ protected function getParams(): ?array { $params = []; diff --git a/src/Schema/Request/ListRootsRequest.php b/src/Schema/Request/ListRootsRequest.php index 542ee43a..35c8a009 100644 --- a/src/Schema/Request/ListRootsRequest.php +++ b/src/Schema/Request/ListRootsRequest.php @@ -24,7 +24,7 @@ * * @author Kyrian Obikwelu */ -class ListRootsRequest extends Request +final class ListRootsRequest extends Request { public function __construct( ) { diff --git a/src/Schema/Request/ListToolsRequest.php b/src/Schema/Request/ListToolsRequest.php index 641fcac3..00af2863 100644 --- a/src/Schema/Request/ListToolsRequest.php +++ b/src/Schema/Request/ListToolsRequest.php @@ -18,7 +18,7 @@ * * @author Kyrian Obikwelu */ -class ListToolsRequest extends Request +final class ListToolsRequest extends Request { /** * @param string|null $cursor An opaque token representing the current pagination position. @@ -40,6 +40,9 @@ protected static function fromParams(?array $params): static return new self($params['cursor'] ?? null); } + /** + * @return array{cursor:string}|null + */ protected function getParams(): ?array { $params = []; diff --git a/src/Schema/Request/PingRequest.php b/src/Schema/Request/PingRequest.php index a40d87ce..31fe64bb 100644 --- a/src/Schema/Request/PingRequest.php +++ b/src/Schema/Request/PingRequest.php @@ -19,7 +19,7 @@ * * @author Kyrian Obikwelu */ -class PingRequest extends Request +final class PingRequest extends Request { public static function getMethod(): string { diff --git a/src/Schema/Request/ReadResourceRequest.php b/src/Schema/Request/ReadResourceRequest.php index 3bdd6c1c..69523eff 100644 --- a/src/Schema/Request/ReadResourceRequest.php +++ b/src/Schema/Request/ReadResourceRequest.php @@ -19,10 +19,10 @@ * * @author Kyrian Obikwelu */ -class ReadResourceRequest extends Request +final class ReadResourceRequest extends Request { /** - * @param string $uri the URI of the resource to read + * @param non-empty-string $uri the URI of the resource to read */ public function __construct( public readonly string $uri, @@ -43,7 +43,10 @@ protected static function fromParams(?array $params): static return new self($params['uri']); } - protected function getParams(): ?array + /** + * @return array{uri: non-empty-string} + */ + protected function getParams(): array { return [ 'uri' => $this->uri, diff --git a/src/Schema/Request/ResourceSubscribeRequest.php b/src/Schema/Request/ResourceSubscribeRequest.php index 2ff66e12..036785a2 100644 --- a/src/Schema/Request/ResourceSubscribeRequest.php +++ b/src/Schema/Request/ResourceSubscribeRequest.php @@ -20,10 +20,10 @@ * * @author Kyrian Obikwelu */ -class ResourceSubscribeRequest extends Request +final class ResourceSubscribeRequest extends Request { /** - * @param string $uri the URI of the resource to subscribe to + * @param non-empty-string $uri the URI of the resource to subscribe to */ public function __construct( public readonly string $uri, @@ -44,7 +44,10 @@ protected static function fromParams(?array $params): static return new self($params['uri']); } - protected function getParams(): ?array + /** + * @return array{uri: non-empty-string} + */ + protected function getParams(): array { return ['uri' => $this->uri]; } diff --git a/src/Schema/Request/ResourceUnsubscribeRequest.php b/src/Schema/Request/ResourceUnsubscribeRequest.php index f89c030c..fd93727b 100644 --- a/src/Schema/Request/ResourceUnsubscribeRequest.php +++ b/src/Schema/Request/ResourceUnsubscribeRequest.php @@ -20,10 +20,10 @@ * * @author Kyrian Obikwelu */ -class ResourceUnsubscribeRequest extends Request +final class ResourceUnsubscribeRequest extends Request { /** - * @param string $uri the URI of the resource to unsubscribe from + * @param non-empty-string $uri the URI of the resource to unsubscribe from */ public function __construct( public readonly string $uri, @@ -44,7 +44,10 @@ protected static function fromParams(?array $params): static return new self($params['uri']); } - protected function getParams(): ?array + /** + * @return array{uri: non-empty-string} + */ + protected function getParams(): array { return ['uri' => $this->uri]; } diff --git a/src/Schema/Request/SetLogLevelRequest.php b/src/Schema/Request/SetLogLevelRequest.php index 8595ef08..ad7bee68 100644 --- a/src/Schema/Request/SetLogLevelRequest.php +++ b/src/Schema/Request/SetLogLevelRequest.php @@ -20,7 +20,7 @@ * * @author Kyrian Obikwelu */ -class SetLogLevelRequest extends Request +final class SetLogLevelRequest extends Request { /** * @param LoggingLevel $level The level of logging that the client wants to receive from the server. The server @@ -46,7 +46,10 @@ protected static function fromParams(?array $params): static return new self(LoggingLevel::from($params['level'])); } - protected function getParams(): ?array + /** + * @return array{level: value-of} + */ + protected function getParams(): array { return [ 'level' => $this->level->value,