Fix return type in abstract methods from self to static (#53)

* Change return type of abstract request methods

* Change return type of `fromParams` method to `static` in request classes

(cherry picked from commit 94799ab66ff60d4b2305aadb6b73aaa4c805221e)

* Make request classes final and update `getParams` return types for improved type safety

(cherry picked from commit d6be496f89cc0e6d30f519792d0dc902685c4178)
This commit is contained in:
Igor Markin 2025-09-09 19:22:29 +03:00 • committed by GitHub
commit 20e789d402
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 97 additions and 46 deletions

View file

@ -36,7 +36,7 @@ abstract class Request implements HasMethodInterface, MessageInterface
/** /**
* @param RequestData $data * @param RequestData $data
*/ */
public static function fromArray(array $data): self public static function fromArray(array $data): static
{ {
if (($data['jsonrpc'] ?? null) !== MessageInterface::JSONRPC_VERSION) { if (($data['jsonrpc'] ?? null) !== MessageInterface::JSONRPC_VERSION) {
throw new InvalidArgumentException('Invalid or missing "jsonrpc" version for Request.'); throw new InvalidArgumentException('Invalid or missing "jsonrpc" version for Request.');
@ -68,7 +68,7 @@ abstract class Request implements HasMethodInterface, MessageInterface
/** /**
* @param array<string, mixed>|null $params * @param array<string, mixed>|null $params
*/ */
abstract protected static function fromParams(?array $params): self; abstract protected static function fromParams(?array $params): static;
public function getId(): string|int public function getId(): string|int
{ {
@ -97,7 +97,7 @@ abstract class Request implements HasMethodInterface, MessageInterface
} }
/** /**
* @return array<string, mixed>|null * @return array<non-empty-string, mixed>|null
*/ */
abstract protected function getParams(): ?array; abstract protected function getParams(): ?array;
} }

View file

@ -19,7 +19,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class CallToolRequest extends Request final class CallToolRequest extends Request
{ {
/** /**
* @param string $name the name of the tool to invoke * @param string $name the name of the tool to invoke
@ -36,7 +36,7 @@ class CallToolRequest extends Request
return 'tools/call'; 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'])) { if (!isset($params['name']) || !\is_string($params['name'])) {
throw new InvalidArgumentException('Missing or invalid "name" parameter for tools/call.'); throw new InvalidArgumentException('Missing or invalid "name" parameter for tools/call.');
@ -58,7 +58,10 @@ class CallToolRequest extends Request
); );
} }
protected function getParams(): ?array /**
* @return array{name: string, arguments: array<string, mixed>}
*/
protected function getParams(): array
{ {
return [ return [
'name' => $this->name, 'name' => $this->name,

View file

@ -21,7 +21,7 @@ use Mcp\Schema\ResourceReference;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class CompletionCompleteRequest extends Request final class CompletionCompleteRequest extends Request
{ {
/** /**
* @param PromptReference|ResourceReference $ref the prompt or resource to complete * @param PromptReference|ResourceReference $ref the prompt or resource to complete
@ -38,7 +38,7 @@ class CompletionCompleteRequest extends Request
return 'completion/complete'; 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'])) { if (!isset($params['ref']) || !\is_array($params['ref'])) {
throw new InvalidArgumentException('Missing or invalid "ref" parameter for completion/complete.'); throw new InvalidArgumentException('Missing or invalid "ref" parameter for completion/complete.');
@ -57,7 +57,13 @@ class CompletionCompleteRequest extends Request
return new self($ref, $params['argument']); 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 [ return [
'ref' => $this->ref, 'ref' => $this->ref,

View file

@ -23,7 +23,7 @@ use Mcp\Schema\ModelPreferences;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class CreateSamplingMessageRequest extends Request final class CreateSamplingMessageRequest extends Request
{ {
/** /**
* @param SamplingMessage[] $messages the messages to send to the model * @param SamplingMessage[] $messages the messages to send to the model
@ -59,7 +59,7 @@ class CreateSamplingMessageRequest extends Request
return 'sampling/createMessage'; 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'])) { if (!isset($params['messages']) || !\is_array($params['messages'])) {
throw new InvalidArgumentException('Missing or invalid "messages" parameter for sampling/createMessage.'); throw new InvalidArgumentException('Missing or invalid "messages" parameter for sampling/createMessage.');
@ -86,7 +86,19 @@ class CreateSamplingMessageRequest extends Request
); );
} }
protected function getParams(): ?array /**
* @return array{
* messages: SamplingMessage[],
* maxTokens: int,
* preferences?: ModelPreferences,
* systemPrompt?: string,
* includeContext?: string,
* temperature?: float,
* stopSequences?: string[],
* metadata?: array<string, mixed>
* }
*/
protected function getParams(): array
{ {
$params = [ $params = [
'messages' => $this->messages, 'messages' => $this->messages,

View file

@ -19,7 +19,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class GetPromptRequest extends Request final class GetPromptRequest extends Request
{ {
/** /**
* @param string $name the name of the prompt to get * @param string $name the name of the prompt to get
@ -36,7 +36,7 @@ class GetPromptRequest extends Request
return 'prompts/get'; 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'])) { if (!isset($params['name']) || !\is_string($params['name']) || empty($params['name'])) {
throw new InvalidArgumentException('Missing or invalid "name" parameter for prompts/get.'); throw new InvalidArgumentException('Missing or invalid "name" parameter for prompts/get.');
@ -55,7 +55,10 @@ class GetPromptRequest extends Request
return new self($params['name'], $arguments); return new self($params['name'], $arguments);
} }
protected function getParams(): ?array /**
* @return array{name: string, arguments?: array<string, mixed>}
*/
protected function getParams(): array
{ {
$params = ['name' => $this->name]; $params = ['name' => $this->name];

View file

@ -21,7 +21,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
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. * @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.
@ -40,7 +40,7 @@ class InitializeRequest extends Request
return 'initialize'; return 'initialize';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
if (!isset($params['protocolVersion'])) { if (!isset($params['protocolVersion'])) {
throw new InvalidArgumentException('protocolVersion is required'); throw new InvalidArgumentException('protocolVersion is required');
@ -59,7 +59,10 @@ class InitializeRequest extends Request
return new self($params['protocolVersion'], $capabilities, $clientInfo); return new self($params['protocolVersion'], $capabilities, $clientInfo);
} }
protected function getParams(): ?array /**
* @return array{protocolVersion: string, capabilities: ClientCapabilities, clientInfo: Implementation}
*/
protected function getParams(): array
{ {
return [ return [
'protocolVersion' => $this->protocolVersion, 'protocolVersion' => $this->protocolVersion,

View file

@ -18,7 +18,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class ListPromptsRequest extends Request final class ListPromptsRequest extends Request
{ {
/** /**
* If provided, the server should return results starting after this cursor. * If provided, the server should return results starting after this cursor.
@ -35,11 +35,14 @@ class ListPromptsRequest extends Request
return 'prompts/list'; return 'prompts/list';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
return new self($params['cursor'] ?? null); return new self($params['cursor'] ?? null);
} }
/**
* @return array{cursor:string}|null
*/
protected function getParams(): ?array protected function getParams(): ?array
{ {
$params = []; $params = [];

View file

@ -18,7 +18,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class ListResourceTemplatesRequest extends Request final class ListResourceTemplatesRequest extends Request
{ {
/** /**
* @param string|null $cursor An opaque token representing the current pagination position. * @param string|null $cursor An opaque token representing the current pagination position.
@ -35,11 +35,14 @@ class ListResourceTemplatesRequest extends Request
return 'resources/templates/list'; return 'resources/templates/list';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
return new self($params['cursor'] ?? null); return new self($params['cursor'] ?? null);
} }
/**
* @return array{cursor:string}|null
*/
protected function getParams(): ?array protected function getParams(): ?array
{ {
$params = []; $params = [];

View file

@ -18,7 +18,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class ListResourcesRequest extends Request final class ListResourcesRequest extends Request
{ {
/** /**
* @param string|null $cursor An opaque token representing the current pagination position. * @param string|null $cursor An opaque token representing the current pagination position.
@ -35,11 +35,14 @@ class ListResourcesRequest extends Request
return 'resources/list'; return 'resources/list';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
return new self($params['cursor'] ?? null); return new self($params['cursor'] ?? null);
} }
/**
* @return array{cursor:string}|null
*/
protected function getParams(): ?array protected function getParams(): ?array
{ {
$params = []; $params = [];

View file

@ -24,7 +24,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class ListRootsRequest extends Request final class ListRootsRequest extends Request
{ {
public function __construct( public function __construct(
) { ) {
@ -35,7 +35,7 @@ class ListRootsRequest extends Request
return 'roots/list'; return 'roots/list';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
return new self(); return new self();
} }

View file

@ -18,7 +18,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class ListToolsRequest extends Request final class ListToolsRequest extends Request
{ {
/** /**
* @param string|null $cursor An opaque token representing the current pagination position. * @param string|null $cursor An opaque token representing the current pagination position.
@ -35,11 +35,14 @@ class ListToolsRequest extends Request
return 'tools/list'; return 'tools/list';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
return new self($params['cursor'] ?? null); return new self($params['cursor'] ?? null);
} }
/**
* @return array{cursor:string}|null
*/
protected function getParams(): ?array protected function getParams(): ?array
{ {
$params = []; $params = [];

View file

@ -19,14 +19,14 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
class PingRequest extends Request final class PingRequest extends Request
{ {
public static function getMethod(): string public static function getMethod(): string
{ {
return 'ping'; return 'ping';
} }
protected static function fromParams(?array $params): Request protected static function fromParams(?array $params): static
{ {
return new self(); return new self();
} }

View file

@ -19,10 +19,10 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
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 function __construct(
public readonly string $uri, public readonly string $uri,
@ -34,7 +34,7 @@ class ReadResourceRequest extends Request
return 'resources/read'; 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'])) { if (!isset($params['uri']) || !\is_string($params['uri']) || empty($params['uri'])) {
throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/read.'); throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/read.');
@ -43,7 +43,10 @@ class ReadResourceRequest extends Request
return new self($params['uri']); return new self($params['uri']);
} }
protected function getParams(): ?array /**
* @return array{uri: non-empty-string}
*/
protected function getParams(): array
{ {
return [ return [
'uri' => $this->uri, 'uri' => $this->uri,

View file

@ -20,10 +20,10 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
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 function __construct(
public readonly string $uri, public readonly string $uri,
@ -35,7 +35,7 @@ class ResourceSubscribeRequest extends Request
return 'resources/subscribe'; 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'])) { if (!isset($params['uri']) || !\is_string($params['uri']) || empty($params['uri'])) {
throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/subscribe.'); throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/subscribe.');
@ -44,7 +44,10 @@ class ResourceSubscribeRequest extends Request
return new self($params['uri']); return new self($params['uri']);
} }
protected function getParams(): ?array /**
* @return array{uri: non-empty-string}
*/
protected function getParams(): array
{ {
return ['uri' => $this->uri]; return ['uri' => $this->uri];
} }

View file

@ -20,10 +20,10 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
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 function __construct(
public readonly string $uri, public readonly string $uri,
@ -35,7 +35,7 @@ class ResourceUnsubscribeRequest extends Request
return 'resources/unsubscribe'; 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'])) { if (!isset($params['uri']) || !\is_string($params['uri']) || empty($params['uri'])) {
throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/unsubscribe.'); throw new InvalidArgumentException('Missing or invalid "uri" parameter for resources/unsubscribe.');
@ -44,7 +44,10 @@ class ResourceUnsubscribeRequest extends Request
return new self($params['uri']); return new self($params['uri']);
} }
protected function getParams(): ?array /**
* @return array{uri: non-empty-string}
*/
protected function getParams(): array
{ {
return ['uri' => $this->uri]; return ['uri' => $this->uri];
} }

View file

@ -20,7 +20,7 @@ use Mcp\Schema\JsonRpc\Request;
* *
* @author Kyrian Obikwelu <koshnawaza@gmail.com> * @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/ */
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 * @param LoggingLevel $level The level of logging that the client wants to receive from the server. The server
@ -37,7 +37,7 @@ class SetLogLevelRequest extends Request
return 'logging/setLevel'; 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'])) { if (!isset($params['level']) || !\is_string($params['level']) || empty($params['level'])) {
throw new InvalidArgumentException('Missing or invalid "level" parameter for "logging/setLevel".'); throw new InvalidArgumentException('Missing or invalid "level" parameter for "logging/setLevel".');
@ -46,7 +46,10 @@ class SetLogLevelRequest extends Request
return new self(LoggingLevel::from($params['level'])); return new self(LoggingLevel::from($params['level']));
} }
protected function getParams(): ?array /**
* @return array{level: value-of<LoggingLevel>}
*/
protected function getParams(): array
{ {
return [ return [
'level' => $this->level->value, 'level' => $this->level->value,

View file

@ -24,7 +24,7 @@ final class RequestTest extends TestCase
return 'foo/bar'; return 'foo/bar';
} }
public static function fromParams(?array $params): self public static function fromParams(?array $params): static
{ {
return new self(); return new self();
} }