From 50f6ec321948434d4f21cf3cfda9d559314d7bcf Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Tue, 28 Oct 2025 15:50:44 +0100 Subject: [PATCH 01/10] Add _meta to Ressource --- src/Capability/Attribute/McpResource.php | 3 +++ src/Capability/Discovery/Discoverer.php | 4 +++- src/Capability/Registry/Loader/ArrayLoader.php | 3 ++- src/Capability/Registry/ResourceReference.php | 12 ++++++------ src/Schema/Content/ResourceContents.php | 5 +++++ src/Schema/Content/TextResourceContents.php | 5 +++-- src/Schema/Resource.php | 8 +++++++- src/Server/Handler/Request/ReadResourceHandler.php | 8 +++----- 8 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/Capability/Attribute/McpResource.php b/src/Capability/Attribute/McpResource.php index 873d485c..d0d2fdde 100644 --- a/src/Capability/Attribute/McpResource.php +++ b/src/Capability/Attribute/McpResource.php @@ -29,7 +29,9 @@ final class McpResource * @param ?string $mimeType the MIME type, if known and constant for this resource * @param ?int $size the size in bytes, if known and constant * @param Annotations|null $annotations optional annotations describing the resource + * @param ?array $_meta optional metadata */ + public function __construct( public string $uri, public ?string $name = null, @@ -37,6 +39,7 @@ public function __construct( public ?string $mimeType = null, public ?int $size = null, public ?Annotations $annotations = null, + public ?array $_meta = null ) { } } diff --git a/src/Capability/Discovery/Discoverer.php b/src/Capability/Discovery/Discoverer.php index e6cc328f..f8e64aca 100644 --- a/src/Capability/Discovery/Discoverer.php +++ b/src/Capability/Discovery/Discoverer.php @@ -234,8 +234,10 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $mimeType = $instance->mimeType; $size = $instance->size; $annotations = $instance->annotations; - $resource = new Resource($instance->uri, $name, $description, $mimeType, $annotations, $size); + $_meta = $instance->_meta; + $resource = new Resource($instance->uri, $name, $description, $mimeType, $annotations, $size, $_meta); $resources[$instance->uri] = new ResourceReference($resource, [$className, $methodName], false); + ++$discoveredCount['resources']; break; diff --git a/src/Capability/Registry/Loader/ArrayLoader.php b/src/Capability/Registry/Loader/ArrayLoader.php index 7420bc75..266b7753 100644 --- a/src/Capability/Registry/Loader/ArrayLoader.php +++ b/src/Capability/Registry/Loader/ArrayLoader.php @@ -137,8 +137,9 @@ public function load(ReferenceRegistryInterface $registry): void $mimeType = $data['mimeType']; $size = $data['size']; $annotations = $data['annotations']; + $_meta = $data['_meta']; - $resource = new Resource($uri, $name, $description, $mimeType, $annotations, $size); + $resource = new Resource($uri, $name, $description, $mimeType, $annotations, $size, $_meta); $registry->registerResource($resource, $data['handler'], true); $handlerDesc = $this->getHandlerDescription($data['handler']); diff --git a/src/Capability/Registry/ResourceReference.php b/src/Capability/Registry/ResourceReference.php index c93d5a14..68825245 100644 --- a/src/Capability/Registry/ResourceReference.php +++ b/src/Capability/Registry/ResourceReference.php @@ -58,7 +58,7 @@ public function __construct( * - array: Converted to JSON if MIME type is application/json or contains 'json' * For other MIME types, will try to convert to JSON with a warning */ - public function formatResult(mixed $readResult, string $uri, ?string $mimeType = null): array + public function formatResult(mixed $readResult, string $uri, ?string $mimeType = null, ?array $_meta = null): array { if ($readResult instanceof ResourceContents) { return [$readResult]; @@ -118,7 +118,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_string($readResult)) { $mimeType = $mimeType ?? $this->guessMimeTypeFromString($readResult); - return [new TextResourceContents($uri, $mimeType, $readResult)]; + return [new TextResourceContents($uri, $mimeType, $readResult, $_meta)]; } if (\is_resource($readResult) && 'stream' === get_resource_type($readResult)) { @@ -142,12 +142,12 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_array($readResult) && isset($readResult['text']) && \is_string($readResult['text'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'text/plain'; - return [new TextResourceContents($uri, $mimeType, $readResult['text'])]; + return [new TextResourceContents($uri, $mimeType, $readResult['text'], $_meta)]; } if ($readResult instanceof \SplFileInfo && $readResult->isFile() && $readResult->isReadable()) { if ($mimeType && str_contains(strtolower($mimeType), 'text')) { - return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()))]; + return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $_meta)]; } return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType)]; @@ -159,7 +159,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = try { $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); - return [new TextResourceContents($uri, $mimeType, $jsonString)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; } catch (\JsonException $e) { throw new RuntimeException(\sprintf('Failed to encode array as JSON for URI "%s": %s', $uri, $e->getMessage())); } @@ -169,7 +169,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); $mimeType = $mimeType ?? 'application/json'; - return [new TextResourceContents($uri, $mimeType, $jsonString)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; } catch (\JsonException $e) { throw new RuntimeException(\sprintf('Failed to encode array as JSON for URI "%s": %s', $uri, $e->getMessage())); } diff --git a/src/Schema/Content/ResourceContents.php b/src/Schema/Content/ResourceContents.php index d4c7733b..834516d7 100644 --- a/src/Schema/Content/ResourceContents.php +++ b/src/Schema/Content/ResourceContents.php @@ -30,6 +30,7 @@ abstract class ResourceContents implements \JsonSerializable public function __construct( public readonly string $uri, public readonly ?string $mimeType = null, + public readonly ?array $_meta = null, ) { } @@ -43,6 +44,10 @@ public function jsonSerialize(): array $data['mimeType'] = $this->mimeType; } + if (null !== $this->_meta) { + $data['_meta'] = $this->_meta; + } + return $data; } } diff --git a/src/Schema/Content/TextResourceContents.php b/src/Schema/Content/TextResourceContents.php index 04880f59..39d62362 100644 --- a/src/Schema/Content/TextResourceContents.php +++ b/src/Schema/Content/TextResourceContents.php @@ -35,8 +35,9 @@ public function __construct( string $uri, ?string $mimeType, public readonly string $text, + ?array $_meta ) { - parent::__construct($uri, $mimeType); + parent::__construct($uri, $mimeType, $_meta); } /** @@ -51,7 +52,7 @@ public static function fromArray(array $data): self throw new InvalidArgumentException('Missing or invalid "text" for TextResourceContents.'); } - return new self($data['uri'], $data['mimeType'] ?? null, $data['text']); + return new self($data['uri'], $data['mimeType'] ?? null, $data['text'], $data['_meta'] ?? null); } /** diff --git a/src/Schema/Resource.php b/src/Schema/Resource.php index ca6fa11a..3a2052e8 100644 --- a/src/Schema/Resource.php +++ b/src/Schema/Resource.php @@ -49,6 +49,7 @@ class Resource implements \JsonSerializable * @param string|null $mimeType the MIME type of this resource, if known * @param Annotations|null $annotations optional annotations for the client * @param int|null $size The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. + * @param array|null $_meta optional for additional metadata * * This can be used by Hosts to display file sizes and estimate context window usage. */ @@ -59,6 +60,7 @@ public function __construct( public readonly ?string $mimeType = null, public readonly ?Annotations $annotations = null, public readonly ?int $size = null, + public readonly ?array $_meta = null ) { if (!preg_match(self::RESOURCE_NAME_PATTERN, $name)) { throw new InvalidArgumentException('Invalid resource name: must contain only alphanumeric characters, underscores, and hyphens.'); @@ -86,7 +88,8 @@ public static function fromArray(array $data): self description: $data['description'] ?? null, mimeType: $data['mimeType'] ?? null, annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null, - size: isset($data['size']) ? (int) $data['size'] : null + size: isset($data['size']) ? (int) $data['size'] : null, + _meta: isset($data['_meta']) ? (int) $data['_meta'] : null ); } @@ -118,6 +121,9 @@ public function jsonSerialize(): array if (null !== $this->size) { $data['size'] = $this->size; } + if (null !== $this->_meta) { + $data['_meta'] = $this->_meta; + } return $data; } diff --git a/src/Server/Handler/Request/ReadResourceHandler.php b/src/Server/Handler/Request/ReadResourceHandler.php index 19e426aa..a2175c80 100644 --- a/src/Server/Handler/Request/ReadResourceHandler.php +++ b/src/Server/Handler/Request/ReadResourceHandler.php @@ -51,9 +51,7 @@ public function handle(Request $request, SessionInterface $session): Response|Er \assert($request instanceof ReadResourceRequest); $uri = $request->uri; - - $this->logger->debug('Reading resource', ['uri' => $uri]); - + try { $reference = $this->referenceProvider->getResource($uri); if (null === $reference) { @@ -64,7 +62,7 @@ public function handle(Request $request, SessionInterface $session): Response|Er 'uri' => $uri, '_session' => $session, ]; - + $this->logger->debug(var_export($reference, true)); if ($reference instanceof ResourceTemplateReference) { $variables = $reference->extractVariables($uri); $arguments = array_merge($arguments, $variables); @@ -73,7 +71,7 @@ public function handle(Request $request, SessionInterface $session): Response|Er $formatted = $reference->formatResult($result, $uri, $reference->resourceTemplate->mimeType); } else { $result = $this->referenceHandler->handle($reference, $arguments); - $formatted = $reference->formatResult($result, $uri, $reference->schema->mimeType); + $formatted = $reference->formatResult($result, $uri, $reference->schema->mimeType, $reference->schema->_meta); } return new Response($request->getId(), new ReadResourceResult($formatted)); From cbae9b97700bf25abc62eb90dde6b6830c91b2c7 Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Tue, 28 Oct 2025 15:59:58 +0100 Subject: [PATCH 02/10] Correction --- src/Server/Handler/Request/ReadResourceHandler.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Server/Handler/Request/ReadResourceHandler.php b/src/Server/Handler/Request/ReadResourceHandler.php index a2175c80..0d8945e6 100644 --- a/src/Server/Handler/Request/ReadResourceHandler.php +++ b/src/Server/Handler/Request/ReadResourceHandler.php @@ -51,7 +51,9 @@ public function handle(Request $request, SessionInterface $session): Response|Er \assert($request instanceof ReadResourceRequest); $uri = $request->uri; - + + $this->logger->debug('Reading resource', ['uri' => $uri]); + try { $reference = $this->referenceProvider->getResource($uri); if (null === $reference) { @@ -62,7 +64,7 @@ public function handle(Request $request, SessionInterface $session): Response|Er 'uri' => $uri, '_session' => $session, ]; - $this->logger->debug(var_export($reference, true)); + if ($reference instanceof ResourceTemplateReference) { $variables = $reference->extractVariables($uri); $arguments = array_merge($arguments, $variables); From 86cad84f7d91fc451ba5cf6e3a1f7f4b057719eb Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Thu, 30 Oct 2025 16:37:58 +0100 Subject: [PATCH 03/10] Add _meta field for Tool --- src/Capability/Attribute/McpTool.php | 1 + src/Capability/Discovery/Discoverer.php | 3 ++- src/Capability/Registry/Loader/ArrayLoader.php | 2 +- src/Schema/Tool.php | 7 ++++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Capability/Attribute/McpTool.php b/src/Capability/Attribute/McpTool.php index d4af3e6c..bc3355b0 100644 --- a/src/Capability/Attribute/McpTool.php +++ b/src/Capability/Attribute/McpTool.php @@ -28,6 +28,7 @@ public function __construct( public ?string $name = null, public ?string $description = null, public ?ToolAnnotations $annotations = null, + public ?array $_meta = null, ) { } } diff --git a/src/Capability/Discovery/Discoverer.php b/src/Capability/Discovery/Discoverer.php index f8e64aca..17faf30a 100644 --- a/src/Capability/Discovery/Discoverer.php +++ b/src/Capability/Discovery/Discoverer.php @@ -222,7 +222,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $name = $instance->name ?? ('__invoke' === $methodName ? $classShortName : $methodName); $description = $instance->description ?? $this->docBlockParser->getSummary($docBlock) ?? null; $inputSchema = $this->schemaGenerator->generate($method); - $tool = new Tool($name, $inputSchema, $description, $instance->annotations); + $_meta = $instance->_meta ?? null; + $tool = new Tool($name, $inputSchema, $description, $instance->annotations, $_meta); $tools[$name] = new ToolReference($tool, [$className, $methodName], false); ++$discoveredCount['tools']; break; diff --git a/src/Capability/Registry/Loader/ArrayLoader.php b/src/Capability/Registry/Loader/ArrayLoader.php index 266b7753..369c0b0f 100644 --- a/src/Capability/Registry/Loader/ArrayLoader.php +++ b/src/Capability/Registry/Loader/ArrayLoader.php @@ -102,7 +102,7 @@ public function load(ReferenceRegistryInterface $registry): void $inputSchema = $data['inputSchema'] ?? $schemaGenerator->generate($reflection); - $tool = new Tool($name, $inputSchema, $description, $data['annotations']); + $tool = new Tool($name, $inputSchema, $description, $data['annotations'], $data['_meta'] ?? null); $registry->registerTool($tool, $data['handler'], true); $handlerDesc = $this->getHandlerDescription($data['handler']); diff --git a/src/Schema/Tool.php b/src/Schema/Tool.php index 29646efc..663a560f 100644 --- a/src/Schema/Tool.php +++ b/src/Schema/Tool.php @@ -47,6 +47,7 @@ public function __construct( public readonly array $inputSchema, public readonly ?string $description, public readonly ?ToolAnnotations $annotations, + public readonly ?array $_meta = null, ) { if (!isset($inputSchema['type']) || 'object' !== $inputSchema['type']) { throw new InvalidArgumentException('Tool inputSchema must be a JSON Schema of type "object".'); @@ -75,7 +76,8 @@ public static function fromArray(array $data): self $data['name'], $data['inputSchema'], isset($data['description']) && \is_string($data['description']) ? $data['description'] : null, - isset($data['annotations']) && \is_array($data['annotations']) ? ToolAnnotations::fromArray($data['annotations']) : null + isset($data['annotations']) && \is_array($data['annotations']) ? ToolAnnotations::fromArray($data['annotations']) : null, + isset($data['_meta']) && \is_array($data['_meta']) ? $data['_meta'] : null ); } @@ -99,6 +101,9 @@ public function jsonSerialize(): array if (null !== $this->annotations) { $data['annotations'] = $this->annotations; } + if (null !== $this->_meta) { + $data['_meta'] = $this->_meta; + } return $data; } From 6b88994978db068ce2a4d73ccbdcef4902717c7a Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Fri, 31 Oct 2025 13:07:07 +0100 Subject: [PATCH 04/10] Add _meta field --- src/Capability/Attribute/McpPrompt.php | 4 +++- .../Attribute/McpResourceTemplate.php | 2 ++ src/Capability/Attribute/McpTool.php | 1 + src/Capability/Discovery/Discoverer.php | 6 ++++-- .../Registry/Loader/ArrayLoader.php | 7 ++++--- src/Capability/Registry/ResourceReference.php | 13 +++++++----- .../Registry/ResourceTemplateReference.php | 21 +++++++++++-------- src/Schema/Content/BlobResourceContents.php | 14 +++++++------ src/Schema/Content/ResourceContents.php | 3 ++- src/Schema/Content/TextResourceContents.php | 3 ++- src/Schema/Prompt.php | 10 +++++++-- src/Schema/ResourceTemplate.php | 10 +++++++-- src/Schema/Tool.php | 3 ++- .../Handler/Request/ReadResourceHandler.php | 2 +- 14 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/Capability/Attribute/McpPrompt.php b/src/Capability/Attribute/McpPrompt.php index 73677e33..7372ed5e 100644 --- a/src/Capability/Attribute/McpPrompt.php +++ b/src/Capability/Attribute/McpPrompt.php @@ -23,10 +23,12 @@ final class McpPrompt /** * @param ?string $name overrides the prompt name (defaults to method name) * @param ?string $description Optional description of the prompt. Defaults to method DocBlock summary. - */ + * @param ?array $_meta Optional metadata + */ public function __construct( public ?string $name = null, public ?string $description = null, + public ?array $_meta = null ) { } } diff --git a/src/Capability/Attribute/McpResourceTemplate.php b/src/Capability/Attribute/McpResourceTemplate.php index 9b8887f1..8db69d8c 100644 --- a/src/Capability/Attribute/McpResourceTemplate.php +++ b/src/Capability/Attribute/McpResourceTemplate.php @@ -28,6 +28,7 @@ final class McpResourceTemplate * @param ?string $description Optional description. Defaults to class DocBlock summary. * @param ?string $mimeType optional default MIME type for matching resources * @param ?Annotations $annotations optional annotations describing the resource template + * @param ?array $_meta optional metadata */ public function __construct( public string $uriTemplate, @@ -35,6 +36,7 @@ public function __construct( public ?string $description = null, public ?string $mimeType = null, public ?Annotations $annotations = null, + public ?array $_meta = null ) { } } diff --git a/src/Capability/Attribute/McpTool.php b/src/Capability/Attribute/McpTool.php index bc3355b0..6ba24ffb 100644 --- a/src/Capability/Attribute/McpTool.php +++ b/src/Capability/Attribute/McpTool.php @@ -23,6 +23,7 @@ class McpTool * @param string|null $name The name of the tool (defaults to the method name) * @param string|null $description The description of the tool (defaults to the DocBlock/inferred) * @param ToolAnnotations|null $annotations Optional annotations describing tool behavior + * @param ?array $_meta Optional metadata */ public function __construct( public ?string $name = null, diff --git a/src/Capability/Discovery/Discoverer.php b/src/Capability/Discovery/Discoverer.php index 17faf30a..6701e693 100644 --- a/src/Capability/Discovery/Discoverer.php +++ b/src/Capability/Discovery/Discoverer.php @@ -256,7 +256,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $paramTag = $paramTags['$'.$param->getName()] ?? null; $arguments[] = new PromptArgument($param->getName(), $paramTag ? trim((string) $paramTag->getDescription()) : null, !$param->isOptional() && !$param->isDefaultValueAvailable()); } - $prompt = new Prompt($name, $description, $arguments); + $_meta = $instance->_meta ?? null; + $prompt = new Prompt($name, $description, $arguments, $_meta); $completionProviders = $this->getCompletionProviders($method); $prompts[$name] = new PromptReference($prompt, [$className, $methodName], false, $completionProviders); ++$discoveredCount['prompts']; @@ -268,7 +269,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $description = $instance->description ?? $this->docBlockParser->getSummary($docBlock) ?? null; $mimeType = $instance->mimeType; $annotations = $instance->annotations; - $resourceTemplate = new ResourceTemplate($instance->uriTemplate, $name, $description, $mimeType, $annotations); + $_meta = $instance->_meta ?? null; + $resourceTemplate = new ResourceTemplate($instance->uriTemplate, $name, $description, $mimeType, $annotations, $_meta); $completionProviders = $this->getCompletionProviders($method); $resourceTemplates[$instance->uriTemplate] = new ResourceTemplateReference($resourceTemplate, [$className, $methodName], false, $completionProviders); ++$discoveredCount['resourceTemplates']; diff --git a/src/Capability/Registry/Loader/ArrayLoader.php b/src/Capability/Registry/Loader/ArrayLoader.php index 369c0b0f..bd0b0e9c 100644 --- a/src/Capability/Registry/Loader/ArrayLoader.php +++ b/src/Capability/Registry/Loader/ArrayLoader.php @@ -173,8 +173,9 @@ public function load(ReferenceRegistryInterface $registry): void $uriTemplate = $data['uriTemplate']; $mimeType = $data['mimeType']; $annotations = $data['annotations']; + $_meta = $data['_meta']; - $template = new ResourceTemplate($uriTemplate, $name, $description, $mimeType, $annotations); + $template = new ResourceTemplate($uriTemplate, $name, $description, $mimeType, $annotations, $_meta); $completionProviders = $this->getCompletionProviders($reflection); $registry->registerResourceTemplate($template, $data['handler'], $completionProviders, true); @@ -225,8 +226,8 @@ public function load(ReferenceRegistryInterface $registry): void !$param->isOptional() && !$param->isDefaultValueAvailable(), ); } - - $prompt = new Prompt($name, $description, $arguments); + $_meta = $data['_meta']; + $prompt = new Prompt($name, $description, $arguments, $_meta); $completionProviders = $this->getCompletionProviders($reflection); $registry->registerPrompt($prompt, $data['handler'], $completionProviders, true); diff --git a/src/Capability/Registry/ResourceReference.php b/src/Capability/Registry/ResourceReference.php index 68825245..c80cade8 100644 --- a/src/Capability/Registry/ResourceReference.php +++ b/src/Capability/Registry/ResourceReference.php @@ -58,7 +58,7 @@ public function __construct( * - array: Converted to JSON if MIME type is application/json or contains 'json' * For other MIME types, will try to convert to JSON with a warning */ - public function formatResult(mixed $readResult, string $uri, ?string $mimeType = null, ?array $_meta = null): array + public function formatResult(mixed $readResult, string $uri, ?string $mimeType = null): array { if ($readResult instanceof ResourceContents) { return [$readResult]; @@ -68,9 +68,11 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = return [$readResult->resource]; } + $_meta = $this->schema->_meta; + if (\is_array($readResult)) { if (empty($readResult)) { - return [new TextResourceContents($uri, 'application/json', '[]')]; + return [new TextResourceContents($uri, 'application/json', '[]', $_meta)]; } $allAreResourceContents = true; @@ -125,7 +127,8 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $result = BlobResourceContents::fromStream( $uri, $readResult, - $mimeType ?? 'application/octet-stream' + $mimeType ?? 'application/octet-stream', + $_meta ); @fclose($readResult); @@ -136,7 +139,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_array($readResult) && isset($readResult['blob']) && \is_string($readResult['blob'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'application/octet-stream'; - return [new BlobResourceContents($uri, $mimeType, $readResult['blob'])]; + return [new BlobResourceContents($uri, $mimeType, $readResult['blob'], $_meta)]; } if (\is_array($readResult) && isset($readResult['text']) && \is_string($readResult['text'])) { @@ -150,7 +153,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $_meta)]; } - return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType)]; + return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType, $_meta)]; } if (\is_array($readResult)) { diff --git a/src/Capability/Registry/ResourceTemplateReference.php b/src/Capability/Registry/ResourceTemplateReference.php index b71a943a..03448b96 100644 --- a/src/Capability/Registry/ResourceTemplateReference.php +++ b/src/Capability/Registry/ResourceTemplateReference.php @@ -101,9 +101,11 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = return [$readResult->resource]; } + $_meta = $this->resourceTemplate->_meta; + if (\is_array($readResult)) { if (empty($readResult)) { - return [new TextResourceContents($uri, 'application/json', '[]')]; + return [new TextResourceContents($uri, 'application/json', '[]', $_meta)]; } $allAreResourceContents = true; @@ -151,14 +153,15 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_string($readResult)) { $mimeType = $mimeType ?? $this->guessMimeTypeFromString($readResult); - return [new TextResourceContents($uri, $mimeType, $readResult)]; + return [new TextResourceContents($uri, $mimeType, $readResult, $_meta)]; } if (\is_resource($readResult) && 'stream' === get_resource_type($readResult)) { $result = BlobResourceContents::fromStream( $uri, $readResult, - $mimeType ?? 'application/octet-stream' + $mimeType ?? 'application/octet-stream', + $_meta ); @fclose($readResult); @@ -169,21 +172,21 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_array($readResult) && isset($readResult['blob']) && \is_string($readResult['blob'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'application/octet-stream'; - return [new BlobResourceContents($uri, $mimeType, $readResult['blob'])]; + return [new BlobResourceContents($uri, $mimeType, $readResult['blob'], $_meta)]; } if (\is_array($readResult) && isset($readResult['text']) && \is_string($readResult['text'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'text/plain'; - return [new TextResourceContents($uri, $mimeType, $readResult['text'])]; + return [new TextResourceContents($uri, $mimeType, $readResult['text'], $_meta)]; } if ($readResult instanceof \SplFileInfo && $readResult->isFile() && $readResult->isReadable()) { if ($mimeType && str_contains(strtolower($mimeType), 'text')) { - return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()))]; + return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $_meta)]; } - return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType)]; + return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType, $_meta)]; } if (\is_array($readResult)) { @@ -192,7 +195,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = try { $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); - return [new TextResourceContents($uri, $mimeType, $jsonString)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; } catch (\JsonException $e) { throw new RuntimeException("Failed to encode array as JSON for URI '{$uri}': {$e->getMessage()}"); } @@ -202,7 +205,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); $mimeType = $mimeType ?? 'application/json'; - return [new TextResourceContents($uri, $mimeType, $jsonString)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; } catch (\JsonException $e) { throw new RuntimeException("Failed to encode array as JSON for URI '{$uri}': {$e->getMessage()}"); } diff --git a/src/Schema/Content/BlobResourceContents.php b/src/Schema/Content/BlobResourceContents.php index c8b07b05..bcce55ec 100644 --- a/src/Schema/Content/BlobResourceContents.php +++ b/src/Schema/Content/BlobResourceContents.php @@ -30,13 +30,15 @@ class BlobResourceContents extends ResourceContents * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource * @param string $blob a base64-encoded string representing the binary data of the item + * @param ?array $_meta Optional metadata */ public function __construct( string $uri, ?string $mimeType, public readonly string $blob, + ?array $_meta ) { - parent::__construct($uri, $mimeType); + parent::__construct($uri, $mimeType, $_meta); } /** @@ -51,25 +53,25 @@ public static function fromArray(array $data): self throw new InvalidArgumentException('Missing or invalid "blob" for BlobResourceContents.'); } - return new self($data['uri'], $data['mimeType'] ?? null, $data['blob']); + return new self($data['uri'], $data['mimeType'] ?? null, $data['blob'], $data['_meta'] ?? null); } /** * @param resource $stream */ - public static function fromStream(string $uri, $stream, string $mimeType): self + public static function fromStream(string $uri, $stream, string $mimeType, ?array $_meta = null): self { $blob = stream_get_contents($stream); - return new self($uri, $mimeType, base64_encode($blob)); + return new self($uri, $mimeType, base64_encode($blob), $_meta); } - public static function fromSplFileInfo(string $uri, \SplFileInfo $file, ?string $explicitMimeType = null): self + public static function fromSplFileInfo(string $uri, \SplFileInfo $file, ?string $explicitMimeType = null, ?array $_meta = null): self { $mimeType = $explicitMimeType ?? mime_content_type($file->getPathname()); $blob = file_get_contents($file->getPathname()); - return new self($uri, $mimeType, base64_encode($blob)); + return new self($uri, $mimeType, base64_encode($blob), $_meta); } /** diff --git a/src/Schema/Content/ResourceContents.php b/src/Schema/Content/ResourceContents.php index 834516d7..cd30493e 100644 --- a/src/Schema/Content/ResourceContents.php +++ b/src/Schema/Content/ResourceContents.php @@ -26,7 +26,8 @@ abstract class ResourceContents implements \JsonSerializable /** * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource - */ + * @param ?array $_meta Optional metadata + */ public function __construct( public readonly string $uri, public readonly ?string $mimeType = null, diff --git a/src/Schema/Content/TextResourceContents.php b/src/Schema/Content/TextResourceContents.php index 39d62362..c1532636 100644 --- a/src/Schema/Content/TextResourceContents.php +++ b/src/Schema/Content/TextResourceContents.php @@ -30,7 +30,8 @@ class TextResourceContents extends ResourceContents * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource * @param string $text The text of the item. This must only be set if the item can actually be represented as text (not binary data). - */ + * @param ?array $_meta Optional metadata + */ public function __construct( string $uri, ?string $mimeType, diff --git a/src/Schema/Prompt.php b/src/Schema/Prompt.php index 96cffcd9..b201a491 100644 --- a/src/Schema/Prompt.php +++ b/src/Schema/Prompt.php @@ -32,11 +32,13 @@ class Prompt implements \JsonSerializable * @param string $name the name of the prompt or prompt template * @param string|null $description an optional description of what this prompt provides * @param PromptArgument[]|null $arguments A list of arguments for templating. Null if not a template. - */ + * @param array|null $_meta optional for additional metadata + */ public function __construct( public readonly string $name, public readonly ?string $description = null, public readonly ?array $arguments = null, + public readonly ?array $_meta = null ) { if (null !== $this->arguments) { foreach ($this->arguments as $arg) { @@ -63,7 +65,8 @@ public static function fromArray(array $data): self return new self( name: $data['name'], description: $data['description'] ?? null, - arguments: $arguments + arguments: $arguments, + _meta: isset($data['_meta']) ? (int) $data['_meta'] : null ); } @@ -83,6 +86,9 @@ public function jsonSerialize(): array if (null !== $this->arguments) { $data['arguments'] = $this->arguments; } + if (null !== $this->_meta) { + $data['_meta'] = $this->_meta; + } return $data; } diff --git a/src/Schema/ResourceTemplate.php b/src/Schema/ResourceTemplate.php index 796b3e22..d90a7c85 100644 --- a/src/Schema/ResourceTemplate.php +++ b/src/Schema/ResourceTemplate.php @@ -47,13 +47,15 @@ class ResourceTemplate implements \JsonSerializable * @param string|null $description This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. * @param string|null $mimeType The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type. * @param Annotations|null $annotations optional annotations for the client - */ + * @param array|null $_meta optional for additional metadata + */ public function __construct( public readonly string $uriTemplate, public readonly string $name, public readonly ?string $description = null, public readonly ?string $mimeType = null, public readonly ?Annotations $annotations = null, + public readonly ?array $_meta = null ) { if (!preg_match(self::RESOURCE_NAME_PATTERN, $name)) { throw new InvalidArgumentException('Invalid resource name: must contain only alphanumeric characters, underscores, and hyphens.'); @@ -80,7 +82,8 @@ public static function fromArray(array $data): self name: $data['name'], description: $data['description'] ?? null, mimeType: $data['mimeType'] ?? null, - annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null + annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null, + _meta: isset($data['_meta']) ? (int) $data['_meta'] : null ); } @@ -108,6 +111,9 @@ public function jsonSerialize(): array if (null !== $this->annotations) { $data['annotations'] = $this->annotations; } + if (null !== $this->_meta) { + $data['_meta'] = $this->_meta; + } return $data; } diff --git a/src/Schema/Tool.php b/src/Schema/Tool.php index 663a560f..9e3b3027 100644 --- a/src/Schema/Tool.php +++ b/src/Schema/Tool.php @@ -41,7 +41,8 @@ class Tool implements \JsonSerializable * available tools. It can be thought of like a "hint" to the model. * @param ToolInputSchema $inputSchema a JSON Schema object (as a PHP array) defining the expected 'arguments' for the tool * @param ToolAnnotations|null $annotations optional additional tool information - */ + * @param array|null $_meta optional for additional metadata + */ public function __construct( public readonly string $name, public readonly array $inputSchema, diff --git a/src/Server/Handler/Request/ReadResourceHandler.php b/src/Server/Handler/Request/ReadResourceHandler.php index 0d8945e6..19e426aa 100644 --- a/src/Server/Handler/Request/ReadResourceHandler.php +++ b/src/Server/Handler/Request/ReadResourceHandler.php @@ -73,7 +73,7 @@ public function handle(Request $request, SessionInterface $session): Response|Er $formatted = $reference->formatResult($result, $uri, $reference->resourceTemplate->mimeType); } else { $result = $this->referenceHandler->handle($reference, $arguments); - $formatted = $reference->formatResult($result, $uri, $reference->schema->mimeType, $reference->schema->_meta); + $formatted = $reference->formatResult($result, $uri, $reference->schema->mimeType); } return new Response($request->getId(), new ReadResourceResult($formatted)); From af83f9f01ba7fd64216e50933f5dee9c2ed88122 Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Sat, 1 Nov 2025 15:28:33 +0100 Subject: [PATCH 05/10] CS Fixer --- src/Capability/Attribute/McpPrompt.php | 4 ++-- src/Capability/Attribute/McpResource.php | 3 +-- src/Capability/Attribute/McpResourceTemplate.php | 4 ++-- src/Capability/Attribute/McpTool.php | 2 +- src/Capability/Registry/ResourceReference.php | 4 ++-- src/Schema/Content/BlobResourceContents.php | 2 +- src/Schema/Content/ResourceContents.php | 2 +- src/Schema/Content/TextResourceContents.php | 4 ++-- src/Schema/Prompt.php | 6 +++--- src/Schema/Resource.php | 4 ++-- src/Schema/ResourceTemplate.php | 6 +++--- src/Schema/Tool.php | 2 +- 12 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/Capability/Attribute/McpPrompt.php b/src/Capability/Attribute/McpPrompt.php index 7372ed5e..8a81c2de 100644 --- a/src/Capability/Attribute/McpPrompt.php +++ b/src/Capability/Attribute/McpPrompt.php @@ -24,11 +24,11 @@ final class McpPrompt * @param ?string $name overrides the prompt name (defaults to method name) * @param ?string $description Optional description of the prompt. Defaults to method DocBlock summary. * @param ?array $_meta Optional metadata - */ + */ public function __construct( public ?string $name = null, public ?string $description = null, - public ?array $_meta = null + public ?array $_meta = null, ) { } } diff --git a/src/Capability/Attribute/McpResource.php b/src/Capability/Attribute/McpResource.php index d0d2fdde..2bfd89f1 100644 --- a/src/Capability/Attribute/McpResource.php +++ b/src/Capability/Attribute/McpResource.php @@ -31,7 +31,6 @@ final class McpResource * @param Annotations|null $annotations optional annotations describing the resource * @param ?array $_meta optional metadata */ - public function __construct( public string $uri, public ?string $name = null, @@ -39,7 +38,7 @@ public function __construct( public ?string $mimeType = null, public ?int $size = null, public ?Annotations $annotations = null, - public ?array $_meta = null + public ?array $_meta = null, ) { } } diff --git a/src/Capability/Attribute/McpResourceTemplate.php b/src/Capability/Attribute/McpResourceTemplate.php index 8db69d8c..3a03e724 100644 --- a/src/Capability/Attribute/McpResourceTemplate.php +++ b/src/Capability/Attribute/McpResourceTemplate.php @@ -28,7 +28,7 @@ final class McpResourceTemplate * @param ?string $description Optional description. Defaults to class DocBlock summary. * @param ?string $mimeType optional default MIME type for matching resources * @param ?Annotations $annotations optional annotations describing the resource template - * @param ?array $_meta optional metadata + * @param ?array $_meta optional metadata */ public function __construct( public string $uriTemplate, @@ -36,7 +36,7 @@ public function __construct( public ?string $description = null, public ?string $mimeType = null, public ?Annotations $annotations = null, - public ?array $_meta = null + public ?array $_meta = null, ) { } } diff --git a/src/Capability/Attribute/McpTool.php b/src/Capability/Attribute/McpTool.php index 6ba24ffb..4eb6033c 100644 --- a/src/Capability/Attribute/McpTool.php +++ b/src/Capability/Attribute/McpTool.php @@ -23,7 +23,7 @@ class McpTool * @param string|null $name The name of the tool (defaults to the method name) * @param string|null $description The description of the tool (defaults to the DocBlock/inferred) * @param ToolAnnotations|null $annotations Optional annotations describing tool behavior - * @param ?array $_meta Optional metadata + * @param ?array $_meta Optional metadata */ public function __construct( public ?string $name = null, diff --git a/src/Capability/Registry/ResourceReference.php b/src/Capability/Registry/ResourceReference.php index c80cade8..7104b85a 100644 --- a/src/Capability/Registry/ResourceReference.php +++ b/src/Capability/Registry/ResourceReference.php @@ -162,7 +162,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = try { $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); - return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; } catch (\JsonException $e) { throw new RuntimeException(\sprintf('Failed to encode array as JSON for URI "%s": %s', $uri, $e->getMessage())); } @@ -172,7 +172,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); $mimeType = $mimeType ?? 'application/json'; - return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; } catch (\JsonException $e) { throw new RuntimeException(\sprintf('Failed to encode array as JSON for URI "%s": %s', $uri, $e->getMessage())); } diff --git a/src/Schema/Content/BlobResourceContents.php b/src/Schema/Content/BlobResourceContents.php index bcce55ec..56f6e085 100644 --- a/src/Schema/Content/BlobResourceContents.php +++ b/src/Schema/Content/BlobResourceContents.php @@ -36,7 +36,7 @@ public function __construct( string $uri, ?string $mimeType, public readonly string $blob, - ?array $_meta + ?array $_meta, ) { parent::__construct($uri, $mimeType, $_meta); } diff --git a/src/Schema/Content/ResourceContents.php b/src/Schema/Content/ResourceContents.php index cd30493e..631b9f90 100644 --- a/src/Schema/Content/ResourceContents.php +++ b/src/Schema/Content/ResourceContents.php @@ -27,7 +27,7 @@ abstract class ResourceContents implements \JsonSerializable * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource * @param ?array $_meta Optional metadata - */ + */ public function __construct( public readonly string $uri, public readonly ?string $mimeType = null, diff --git a/src/Schema/Content/TextResourceContents.php b/src/Schema/Content/TextResourceContents.php index c1532636..54737f7d 100644 --- a/src/Schema/Content/TextResourceContents.php +++ b/src/Schema/Content/TextResourceContents.php @@ -31,12 +31,12 @@ class TextResourceContents extends ResourceContents * @param string|null $mimeType the MIME type of the resource or sub-resource * @param string $text The text of the item. This must only be set if the item can actually be represented as text (not binary data). * @param ?array $_meta Optional metadata - */ + */ public function __construct( string $uri, ?string $mimeType, public readonly string $text, - ?array $_meta + ?array $_meta, ) { parent::__construct($uri, $mimeType, $_meta); } diff --git a/src/Schema/Prompt.php b/src/Schema/Prompt.php index b201a491..c2acf48b 100644 --- a/src/Schema/Prompt.php +++ b/src/Schema/Prompt.php @@ -33,12 +33,12 @@ class Prompt implements \JsonSerializable * @param string|null $description an optional description of what this prompt provides * @param PromptArgument[]|null $arguments A list of arguments for templating. Null if not a template. * @param array|null $_meta optional for additional metadata - */ + */ public function __construct( public readonly string $name, public readonly ?string $description = null, public readonly ?array $arguments = null, - public readonly ?array $_meta = null + public readonly ?array $_meta = null, ) { if (null !== $this->arguments) { foreach ($this->arguments as $arg) { @@ -66,7 +66,7 @@ public static function fromArray(array $data): self name: $data['name'], description: $data['description'] ?? null, arguments: $arguments, - _meta: isset($data['_meta']) ? (int) $data['_meta'] : null + _meta: isset($data['_meta']) ? (int) $data['_meta'] : null ); } diff --git a/src/Schema/Resource.php b/src/Schema/Resource.php index 3a2052e8..5b19519f 100644 --- a/src/Schema/Resource.php +++ b/src/Schema/Resource.php @@ -51,7 +51,7 @@ class Resource implements \JsonSerializable * @param int|null $size The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. * @param array|null $_meta optional for additional metadata * - * This can be used by Hosts to display file sizes and estimate context window usage. + * This can be used by Hosts to display file sizes and estimate context window usage */ public function __construct( public readonly string $uri, @@ -60,7 +60,7 @@ public function __construct( public readonly ?string $mimeType = null, public readonly ?Annotations $annotations = null, public readonly ?int $size = null, - public readonly ?array $_meta = null + public readonly ?array $_meta = null, ) { if (!preg_match(self::RESOURCE_NAME_PATTERN, $name)) { throw new InvalidArgumentException('Invalid resource name: must contain only alphanumeric characters, underscores, and hyphens.'); diff --git a/src/Schema/ResourceTemplate.php b/src/Schema/ResourceTemplate.php index d90a7c85..809d0b4d 100644 --- a/src/Schema/ResourceTemplate.php +++ b/src/Schema/ResourceTemplate.php @@ -47,15 +47,15 @@ class ResourceTemplate implements \JsonSerializable * @param string|null $description This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. * @param string|null $mimeType The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type. * @param Annotations|null $annotations optional annotations for the client - * @param array|null $_meta optional for additional metadata - */ + * @param array|null $_meta optional for additional metadata + */ public function __construct( public readonly string $uriTemplate, public readonly string $name, public readonly ?string $description = null, public readonly ?string $mimeType = null, public readonly ?Annotations $annotations = null, - public readonly ?array $_meta = null + public readonly ?array $_meta = null, ) { if (!preg_match(self::RESOURCE_NAME_PATTERN, $name)) { throw new InvalidArgumentException('Invalid resource name: must contain only alphanumeric characters, underscores, and hyphens.'); diff --git a/src/Schema/Tool.php b/src/Schema/Tool.php index 9e3b3027..df8a7d7a 100644 --- a/src/Schema/Tool.php +++ b/src/Schema/Tool.php @@ -42,7 +42,7 @@ class Tool implements \JsonSerializable * @param ToolInputSchema $inputSchema a JSON Schema object (as a PHP array) defining the expected 'arguments' for the tool * @param ToolAnnotations|null $annotations optional additional tool information * @param array|null $_meta optional for additional metadata - */ + */ public function __construct( public readonly string $name, public readonly array $inputSchema, From 52a4736431405feb729128674276dc97fe9a0eec Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Sat, 1 Nov 2025 15:57:14 +0100 Subject: [PATCH 06/10] Php Stan Test --- src/Capability/Attribute/McpPrompt.php | 6 +++--- src/Capability/Attribute/McpResource.php | 14 +++++++------- .../Attribute/McpResourceTemplate.php | 12 ++++++------ src/Capability/Attribute/McpTool.php | 8 ++++---- src/Capability/Registry/Loader/ArrayLoader.php | 4 ++++ src/Schema/Content/BlobResourceContents.php | 18 +++++++++++------- src/Schema/Content/ResourceContents.php | 6 +++--- src/Schema/Content/TextResourceContents.php | 10 +++++----- src/Schema/Prompt.php | 2 +- src/Schema/Resource.php | 14 +++++++------- src/Schema/ResourceTemplate.php | 12 ++++++------ src/Schema/Tool.php | 14 +++++++------- src/Server/Builder.php | 4 ++++ 13 files changed, 68 insertions(+), 56 deletions(-) diff --git a/src/Capability/Attribute/McpPrompt.php b/src/Capability/Attribute/McpPrompt.php index 8a81c2de..dfb05654 100644 --- a/src/Capability/Attribute/McpPrompt.php +++ b/src/Capability/Attribute/McpPrompt.php @@ -21,9 +21,9 @@ final class McpPrompt { /** - * @param ?string $name overrides the prompt name (defaults to method name) - * @param ?string $description Optional description of the prompt. Defaults to method DocBlock summary. - * @param ?array $_meta Optional metadata + * @param ?string $name overrides the prompt name (defaults to method name) + * @param ?string $description Optional description of the prompt. Defaults to method DocBlock summary. + * @param ?array $_meta Optional metadata */ public function __construct( public ?string $name = null, diff --git a/src/Capability/Attribute/McpResource.php b/src/Capability/Attribute/McpResource.php index 2bfd89f1..5f2cb36e 100644 --- a/src/Capability/Attribute/McpResource.php +++ b/src/Capability/Attribute/McpResource.php @@ -23,13 +23,13 @@ final class McpResource { /** - * @param string $uri The specific URI identifying this resource instance. Must be unique within the server. - * @param ?string $name A human-readable name for this resource. If null, a default might be generated from the method name. - * @param ?string $description An optional description of the resource. Defaults to class DocBlock summary. - * @param ?string $mimeType the MIME type, if known and constant for this resource - * @param ?int $size the size in bytes, if known and constant - * @param Annotations|null $annotations optional annotations describing the resource - * @param ?array $_meta optional metadata + * @param string $uri The specific URI identifying this resource instance. Must be unique within the server. + * @param ?string $name A human-readable name for this resource. If null, a default might be generated from the method name. + * @param ?string $description An optional description of the resource. Defaults to class DocBlock summary. + * @param ?string $mimeType the MIME type, if known and constant for this resource + * @param ?int $size the size in bytes, if known and constant + * @param Annotations|null $annotations optional annotations describing the resource + * @param ?array $_meta Optional metadata */ public function __construct( public string $uri, diff --git a/src/Capability/Attribute/McpResourceTemplate.php b/src/Capability/Attribute/McpResourceTemplate.php index 3a03e724..16fa6031 100644 --- a/src/Capability/Attribute/McpResourceTemplate.php +++ b/src/Capability/Attribute/McpResourceTemplate.php @@ -23,12 +23,12 @@ final class McpResourceTemplate { /** - * @param string $uriTemplate the URI template string (RFC 6570) - * @param ?string $name A human-readable name for the template type. If null, a default might be generated from the method name. - * @param ?string $description Optional description. Defaults to class DocBlock summary. - * @param ?string $mimeType optional default MIME type for matching resources - * @param ?Annotations $annotations optional annotations describing the resource template - * @param ?array $_meta optional metadata + * @param string $uriTemplate the URI template string (RFC 6570) + * @param ?string $name A human-readable name for the template type. If null, a default might be generated from the method name. + * @param ?string $description Optional description. Defaults to class DocBlock summary. + * @param ?string $mimeType optional default MIME type for matching resources + * @param ?Annotations $annotations optional annotations describing the resource template + * @param ?array $_meta Optional metadata */ public function __construct( public string $uriTemplate, diff --git a/src/Capability/Attribute/McpTool.php b/src/Capability/Attribute/McpTool.php index 4eb6033c..1190b30b 100644 --- a/src/Capability/Attribute/McpTool.php +++ b/src/Capability/Attribute/McpTool.php @@ -20,10 +20,10 @@ class McpTool { /** - * @param string|null $name The name of the tool (defaults to the method name) - * @param string|null $description The description of the tool (defaults to the DocBlock/inferred) - * @param ToolAnnotations|null $annotations Optional annotations describing tool behavior - * @param ?array $_meta Optional metadata + * @param string|null $name The name of the tool (defaults to the method name) + * @param string|null $description The description of the tool (defaults to the DocBlock/inferred) + * @param ToolAnnotations|null $annotations Optional annotations describing tool behavior + * @param ?array $_meta Optional metadata */ public function __construct( public ?string $name = null, diff --git a/src/Capability/Registry/Loader/ArrayLoader.php b/src/Capability/Registry/Loader/ArrayLoader.php index bd0b0e9c..5ab120d0 100644 --- a/src/Capability/Registry/Loader/ArrayLoader.php +++ b/src/Capability/Registry/Loader/ArrayLoader.php @@ -45,6 +45,7 @@ final class ArrayLoader implements LoaderInterface * name: ?string, * description: ?string, * annotations: ?ToolAnnotations, + * _meta: ?array * }[] $tools * @param array{ * handler: Handler, @@ -54,6 +55,7 @@ final class ArrayLoader implements LoaderInterface * mimeType: ?string, * size: int|null, * annotations: ?Annotations, + * _meta: ?array * }[] $resources * @param array{ * handler: Handler, @@ -62,11 +64,13 @@ final class ArrayLoader implements LoaderInterface * description: ?string, * mimeType: ?string, * annotations: ?Annotations, + * _meta: ?array * }[] $resourceTemplates * @param array{ * handler: Handler, * name: ?string, * description: ?string, + * _meta: ?array * }[] $prompts */ public function __construct( diff --git a/src/Schema/Content/BlobResourceContents.php b/src/Schema/Content/BlobResourceContents.php index 56f6e085..2b5b7e30 100644 --- a/src/Schema/Content/BlobResourceContents.php +++ b/src/Schema/Content/BlobResourceContents.php @@ -27,16 +27,16 @@ class BlobResourceContents extends ResourceContents { /** - * @param string $uri the URI of the resource or sub-resource - * @param string|null $mimeType the MIME type of the resource or sub-resource - * @param string $blob a base64-encoded string representing the binary data of the item - * @param ?array $_meta Optional metadata + * @param string $uri the URI of the resource or sub-resource + * @param string|null $mimeType the MIME type of the resource or sub-resource + * @param string $blob a base64-encoded string representing the binary data of the item + * @param ?array $_meta Optional metadata */ public function __construct( string $uri, ?string $mimeType, public readonly string $blob, - ?array $_meta, + ?array $_meta = null, ) { parent::__construct($uri, $mimeType, $_meta); } @@ -57,8 +57,9 @@ public static function fromArray(array $data): self } /** - * @param resource $stream - */ + * @param resource $stream + * @param ?array $_meta Optional metadata + * */ public static function fromStream(string $uri, $stream, string $mimeType, ?array $_meta = null): self { $blob = stream_get_contents($stream); @@ -66,6 +67,9 @@ public static function fromStream(string $uri, $stream, string $mimeType, ?array return new self($uri, $mimeType, base64_encode($blob), $_meta); } + /** + * @param ?array $_meta Optional metadata + * */ public static function fromSplFileInfo(string $uri, \SplFileInfo $file, ?string $explicitMimeType = null, ?array $_meta = null): self { $mimeType = $explicitMimeType ?? mime_content_type($file->getPathname()); diff --git a/src/Schema/Content/ResourceContents.php b/src/Schema/Content/ResourceContents.php index 631b9f90..e705f58d 100644 --- a/src/Schema/Content/ResourceContents.php +++ b/src/Schema/Content/ResourceContents.php @@ -24,9 +24,9 @@ abstract class ResourceContents implements \JsonSerializable { /** - * @param string $uri the URI of the resource or sub-resource - * @param string|null $mimeType the MIME type of the resource or sub-resource - * @param ?array $_meta Optional metadata + * @param string $uri the URI of the resource or sub-resource + * @param string|null $mimeType the MIME type of the resource or sub-resource + * @param ?array $_meta Optional metadata */ public function __construct( public readonly string $uri, diff --git a/src/Schema/Content/TextResourceContents.php b/src/Schema/Content/TextResourceContents.php index 54737f7d..8327533c 100644 --- a/src/Schema/Content/TextResourceContents.php +++ b/src/Schema/Content/TextResourceContents.php @@ -27,16 +27,16 @@ class TextResourceContents extends ResourceContents { /** - * @param string $uri the URI of the resource or sub-resource - * @param string|null $mimeType the MIME type of the resource or sub-resource - * @param string $text The text of the item. This must only be set if the item can actually be represented as text (not binary data). - * @param ?array $_meta Optional metadata + * @param string $uri the URI of the resource or sub-resource + * @param string|null $mimeType the MIME type of the resource or sub-resource + * @param string $text The text of the item. This must only be set if the item can actually be represented as text (not binary data). + * @param ?array $_meta Optional metadata */ public function __construct( string $uri, ?string $mimeType, public readonly string $text, - ?array $_meta, + ?array $_meta = null, ) { parent::__construct($uri, $mimeType, $_meta); } diff --git a/src/Schema/Prompt.php b/src/Schema/Prompt.php index c2acf48b..4d371cb1 100644 --- a/src/Schema/Prompt.php +++ b/src/Schema/Prompt.php @@ -32,7 +32,7 @@ class Prompt implements \JsonSerializable * @param string $name the name of the prompt or prompt template * @param string|null $description an optional description of what this prompt provides * @param PromptArgument[]|null $arguments A list of arguments for templating. Null if not a template. - * @param array|null $_meta optional for additional metadata + * @param ?array $_meta Optional metadata */ public function __construct( public readonly string $name, diff --git a/src/Schema/Resource.php b/src/Schema/Resource.php index 5b19519f..fb648bca 100644 --- a/src/Schema/Resource.php +++ b/src/Schema/Resource.php @@ -43,13 +43,13 @@ class Resource implements \JsonSerializable private const URI_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^\s]*$/'; /** - * @param string $uri the URI of this resource - * @param string $name A human-readable name for this resource. This can be used by clients to populate UI elements. - * @param string|null $description A description of what this resource represents. This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. - * @param string|null $mimeType the MIME type of this resource, if known - * @param Annotations|null $annotations optional annotations for the client - * @param int|null $size The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. - * @param array|null $_meta optional for additional metadata + * @param string $uri the URI of this resource + * @param string $name A human-readable name for this resource. This can be used by clients to populate UI elements. + * @param string|null $description A description of what this resource represents. This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. + * @param string|null $mimeType the MIME type of this resource, if known + * @param Annotations|null $annotations optional annotations for the client + * @param int|null $size The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. + * @param ?array $_meta Optional metadata * * This can be used by Hosts to display file sizes and estimate context window usage */ diff --git a/src/Schema/ResourceTemplate.php b/src/Schema/ResourceTemplate.php index 809d0b4d..d38f2064 100644 --- a/src/Schema/ResourceTemplate.php +++ b/src/Schema/ResourceTemplate.php @@ -42,12 +42,12 @@ class ResourceTemplate implements \JsonSerializable private const URI_TEMPLATE_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/.*{[^{}]+}.*/'; /** - * @param string $uriTemplate a URI template (according to RFC 6570) that can be used to construct resource URIs - * @param string $name A human-readable name for the type of resource this template refers to. This can be used by clients to populate UI elements. - * @param string|null $description This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. - * @param string|null $mimeType The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type. - * @param Annotations|null $annotations optional annotations for the client - * @param array|null $_meta optional for additional metadata + * @param string $uriTemplate a URI template (according to RFC 6570) that can be used to construct resource URIs + * @param string $name A human-readable name for the type of resource this template refers to. This can be used by clients to populate UI elements. + * @param string|null $description This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. + * @param string|null $mimeType The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type. + * @param Annotations|null $annotations optional annotations for the client + * @param ?array $_meta Optional metadata */ public function __construct( public readonly string $uriTemplate, diff --git a/src/Schema/Tool.php b/src/Schema/Tool.php index df8a7d7a..53cbf044 100644 --- a/src/Schema/Tool.php +++ b/src/Schema/Tool.php @@ -35,13 +35,13 @@ class Tool implements \JsonSerializable { /** - * @param string $name the name of the tool - * @param string|null $description A human-readable description of the tool. - * This can be used by clients to improve the LLM's understanding of - * available tools. It can be thought of like a "hint" to the model. - * @param ToolInputSchema $inputSchema a JSON Schema object (as a PHP array) defining the expected 'arguments' for the tool - * @param ToolAnnotations|null $annotations optional additional tool information - * @param array|null $_meta optional for additional metadata + * @param string $name the name of the tool + * @param string|null $description A human-readable description of the tool. + * This can be used by clients to improve the LLM's understanding of + * available tools. It can be thought of like a "hint" to the model. + * @param ToolInputSchema $inputSchema a JSON Schema object (as a PHP array) defining the expected 'arguments' for the tool + * @param ToolAnnotations|null $annotations optional additional tool information + * @param ?array $_meta Optional metadata */ public function __construct( public readonly string $name, diff --git a/src/Server/Builder.php b/src/Server/Builder.php index f309a3d4..066bf3f8 100644 --- a/src/Server/Builder.php +++ b/src/Server/Builder.php @@ -78,6 +78,7 @@ final class Builder * name: ?string, * description: ?string, * annotations: ?ToolAnnotations, + * _meta: ?array * }[] */ private array $tools = []; @@ -91,6 +92,7 @@ final class Builder * mimeType: ?string, * size: int|null, * annotations: ?Annotations, + * _meta: ?array * }[] */ private array $resources = []; @@ -103,6 +105,7 @@ final class Builder * description: ?string, * mimeType: ?string, * annotations: ?Annotations, + * _meta: ?array * }[] */ private array $resourceTemplates = []; @@ -112,6 +115,7 @@ final class Builder * handler: Handler, * name: ?string, * description: ?string, + * _meta: ?array * }[] */ private array $prompts = []; From 548ea51b6afc8d46ccc0e39fb719afc355aaed4a Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Sat, 1 Nov 2025 19:19:56 +0100 Subject: [PATCH 07/10] Remove int cast and check _meta is an array --- src/Schema/Prompt.php | 6 +++++- src/Schema/Resource.php | 6 +++++- src/Schema/ResourceTemplate.php | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Schema/Prompt.php b/src/Schema/Prompt.php index 4d371cb1..91b0105b 100644 --- a/src/Schema/Prompt.php +++ b/src/Schema/Prompt.php @@ -62,11 +62,15 @@ public static function fromArray(array $data): self $arguments = array_map(fn (array $argData) => PromptArgument::fromArray($argData), $data['arguments']); } + if (!empty($data['_meta']) && !\is_array($data['_meta'])) { + throw new InvalidArgumentException('Invalid "_meta" in Prompt data.'); + } + return new self( name: $data['name'], description: $data['description'] ?? null, arguments: $arguments, - _meta: isset($data['_meta']) ? (int) $data['_meta'] : null + _meta: isset($data['_meta']) ? $data['_meta'] : null ); } diff --git a/src/Schema/Resource.php b/src/Schema/Resource.php index fb648bca..e677d607 100644 --- a/src/Schema/Resource.php +++ b/src/Schema/Resource.php @@ -82,6 +82,10 @@ public static function fromArray(array $data): self throw new InvalidArgumentException('Invalid or missing "name" in Resource data.'); } + if (!empty($data['_meta']) && !\is_array($data['_meta'])) { + throw new InvalidArgumentException('Invalid "_meta" in Resource data.'); + } + return new self( uri: $data['uri'], name: $data['name'], @@ -89,7 +93,7 @@ public static function fromArray(array $data): self mimeType: $data['mimeType'] ?? null, annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null, size: isset($data['size']) ? (int) $data['size'] : null, - _meta: isset($data['_meta']) ? (int) $data['_meta'] : null + _meta: isset($data['_meta']) ? $data['_meta'] : null ); } diff --git a/src/Schema/ResourceTemplate.php b/src/Schema/ResourceTemplate.php index d38f2064..e845a85e 100644 --- a/src/Schema/ResourceTemplate.php +++ b/src/Schema/ResourceTemplate.php @@ -77,13 +77,17 @@ public static function fromArray(array $data): self throw new InvalidArgumentException('Invalid or missing "name" in ResourceTemplate data.'); } + if (!empty($data['_meta']) && !\is_array($data['_meta'])) { + throw new InvalidArgumentException('Invalid "_meta" in ResourceTemplate data.'); + } + return new self( uriTemplate: $data['uriTemplate'], name: $data['name'], description: $data['description'] ?? null, mimeType: $data['mimeType'] ?? null, annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null, - _meta: isset($data['_meta']) ? (int) $data['_meta'] : null + _meta: isset($data['_meta']) ? $data['_meta'] : null ); } From ae47b54fb3b558646f5b9dea2c1d1ee4246f677a Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Wed, 5 Nov 2025 11:36:49 +0100 Subject: [PATCH 08/10] Php Stan Type with _meta --- src/Schema/Content/BlobResourceContents.php | 3 ++- src/Schema/Content/ResourceContents.php | 3 ++- src/Schema/Content/TextResourceContents.php | 3 ++- src/Schema/Prompt.php | 4 +++- src/Schema/Resource.php | 2 ++ src/Schema/ResourceTemplate.php | 2 ++ src/Schema/Tool.php | 2 ++ 7 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Schema/Content/BlobResourceContents.php b/src/Schema/Content/BlobResourceContents.php index 2b5b7e30..853ebcb4 100644 --- a/src/Schema/Content/BlobResourceContents.php +++ b/src/Schema/Content/BlobResourceContents.php @@ -19,7 +19,8 @@ * @phpstan-type BlobResourceContentsData array{ * uri: string, * mimeType?: string|null, - * blob: string + * blob: string, + * _meta?: array * } * * @author Kyrian Obikwelu diff --git a/src/Schema/Content/ResourceContents.php b/src/Schema/Content/ResourceContents.php index e705f58d..eb008a34 100644 --- a/src/Schema/Content/ResourceContents.php +++ b/src/Schema/Content/ResourceContents.php @@ -16,7 +16,8 @@ * * @phpstan-type ResourceContentsData = array{ * uri: string, - * mimeType?: string|null + * mimeType?: string|null, + * _meta?: array * } * * @author Kyrian Obikwelu diff --git a/src/Schema/Content/TextResourceContents.php b/src/Schema/Content/TextResourceContents.php index 8327533c..fe55de71 100644 --- a/src/Schema/Content/TextResourceContents.php +++ b/src/Schema/Content/TextResourceContents.php @@ -19,7 +19,8 @@ * @phpstan-type TextResourceContentsData array{ * uri: string, * mimeType?: string|null, - * text: string + * text: string, + * _meta?: array * } * * @author Kyrian Obikwelu diff --git a/src/Schema/Prompt.php b/src/Schema/Prompt.php index 91b0105b..d4493640 100644 --- a/src/Schema/Prompt.php +++ b/src/Schema/Prompt.php @@ -22,6 +22,7 @@ * name: string, * description?: string, * arguments?: PromptArgumentData[], + * _meta?: array * } * * @author Kyrian Obikwelu @@ -78,7 +79,8 @@ public static function fromArray(array $data): self * @return array{ * name: string, * description?: string, - * arguments?: array + * arguments?: array, + * _meta?: array * } */ public function jsonSerialize(): array diff --git a/src/Schema/Resource.php b/src/Schema/Resource.php index e677d607..07fe3a21 100644 --- a/src/Schema/Resource.php +++ b/src/Schema/Resource.php @@ -25,6 +25,7 @@ * mimeType?: string|null, * annotations?: AnnotationsData|null, * size?: int|null, + * _meta?: array * } * * @author Kyrian Obikwelu @@ -105,6 +106,7 @@ public static function fromArray(array $data): self * mimeType?: string, * annotations?: Annotations, * size?: int, + * _meta?: array * } */ public function jsonSerialize(): array diff --git a/src/Schema/ResourceTemplate.php b/src/Schema/ResourceTemplate.php index e845a85e..5701aa03 100644 --- a/src/Schema/ResourceTemplate.php +++ b/src/Schema/ResourceTemplate.php @@ -24,6 +24,7 @@ * description?: string|null, * mimeType?: string|null, * annotations?: AnnotationsData|null, + * _meta?: array * } * * @author Kyrian Obikwelu @@ -98,6 +99,7 @@ public static function fromArray(array $data): self * description?: string, * mimeType?: string, * annotations?: Annotations, + * _meta?: array * } */ public function jsonSerialize(): array diff --git a/src/Schema/Tool.php b/src/Schema/Tool.php index 53cbf044..3be8ddbb 100644 --- a/src/Schema/Tool.php +++ b/src/Schema/Tool.php @@ -28,6 +28,7 @@ * inputSchema: ToolInputSchema, * description?: string|null, * annotations?: ToolAnnotationsData, + * _meta?: array * } * * @author Kyrian Obikwelu @@ -88,6 +89,7 @@ public static function fromArray(array $data): self * inputSchema: ToolInputSchema, * description?: string, * annotations?: ToolAnnotations, + * _meta?: array * } */ public function jsonSerialize(): array From 59095eaf78d2bd7ac637e7f8040a7036201276b1 Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Wed, 5 Nov 2025 12:49:34 +0100 Subject: [PATCH 09/10] _meta to meta --- src/Capability/Attribute/McpPrompt.php | 4 ++-- src/Capability/Attribute/McpResource.php | 4 ++-- .../Attribute/McpResourceTemplate.php | 4 ++-- src/Capability/Attribute/McpTool.php | 4 ++-- src/Capability/Discovery/Discoverer.php | 16 +++++++------- .../Registry/Loader/ArrayLoader.php | 22 +++++++++---------- src/Capability/Registry/ResourceReference.php | 20 ++++++++--------- .../Registry/ResourceTemplateReference.php | 20 ++++++++--------- src/Schema/Content/BlobResourceContents.php | 18 +++++++-------- src/Schema/Content/ResourceContents.php | 8 +++---- src/Schema/Content/TextResourceContents.php | 6 ++--- src/Schema/Prompt.php | 10 ++++----- src/Schema/Resource.php | 10 ++++----- src/Schema/ResourceTemplate.php | 10 ++++----- src/Schema/Tool.php | 8 +++---- src/Server/Builder.php | 8 +++---- 16 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/Capability/Attribute/McpPrompt.php b/src/Capability/Attribute/McpPrompt.php index dfb05654..8488e608 100644 --- a/src/Capability/Attribute/McpPrompt.php +++ b/src/Capability/Attribute/McpPrompt.php @@ -23,12 +23,12 @@ final class McpPrompt /** * @param ?string $name overrides the prompt name (defaults to method name) * @param ?string $description Optional description of the prompt. Defaults to method DocBlock summary. - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public ?string $name = null, public ?string $description = null, - public ?array $_meta = null, + public ?array $meta = null, ) { } } diff --git a/src/Capability/Attribute/McpResource.php b/src/Capability/Attribute/McpResource.php index 5f2cb36e..86b33078 100644 --- a/src/Capability/Attribute/McpResource.php +++ b/src/Capability/Attribute/McpResource.php @@ -29,7 +29,7 @@ final class McpResource * @param ?string $mimeType the MIME type, if known and constant for this resource * @param ?int $size the size in bytes, if known and constant * @param Annotations|null $annotations optional annotations describing the resource - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public string $uri, @@ -38,7 +38,7 @@ public function __construct( public ?string $mimeType = null, public ?int $size = null, public ?Annotations $annotations = null, - public ?array $_meta = null, + public ?array $meta = null, ) { } } diff --git a/src/Capability/Attribute/McpResourceTemplate.php b/src/Capability/Attribute/McpResourceTemplate.php index 16fa6031..14e66c5f 100644 --- a/src/Capability/Attribute/McpResourceTemplate.php +++ b/src/Capability/Attribute/McpResourceTemplate.php @@ -28,7 +28,7 @@ final class McpResourceTemplate * @param ?string $description Optional description. Defaults to class DocBlock summary. * @param ?string $mimeType optional default MIME type for matching resources * @param ?Annotations $annotations optional annotations describing the resource template - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public string $uriTemplate, @@ -36,7 +36,7 @@ public function __construct( public ?string $description = null, public ?string $mimeType = null, public ?Annotations $annotations = null, - public ?array $_meta = null, + public ?array $meta = null, ) { } } diff --git a/src/Capability/Attribute/McpTool.php b/src/Capability/Attribute/McpTool.php index 1190b30b..e5cab26b 100644 --- a/src/Capability/Attribute/McpTool.php +++ b/src/Capability/Attribute/McpTool.php @@ -23,13 +23,13 @@ class McpTool * @param string|null $name The name of the tool (defaults to the method name) * @param string|null $description The description of the tool (defaults to the DocBlock/inferred) * @param ToolAnnotations|null $annotations Optional annotations describing tool behavior - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public ?string $name = null, public ?string $description = null, public ?ToolAnnotations $annotations = null, - public ?array $_meta = null, + public ?array $meta = null, ) { } } diff --git a/src/Capability/Discovery/Discoverer.php b/src/Capability/Discovery/Discoverer.php index 6701e693..e8f32940 100644 --- a/src/Capability/Discovery/Discoverer.php +++ b/src/Capability/Discovery/Discoverer.php @@ -222,8 +222,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $name = $instance->name ?? ('__invoke' === $methodName ? $classShortName : $methodName); $description = $instance->description ?? $this->docBlockParser->getSummary($docBlock) ?? null; $inputSchema = $this->schemaGenerator->generate($method); - $_meta = $instance->_meta ?? null; - $tool = new Tool($name, $inputSchema, $description, $instance->annotations, $_meta); + $meta = $instance->meta ?? null; + $tool = new Tool($name, $inputSchema, $description, $instance->annotations, $meta); $tools[$name] = new ToolReference($tool, [$className, $methodName], false); ++$discoveredCount['tools']; break; @@ -235,8 +235,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $mimeType = $instance->mimeType; $size = $instance->size; $annotations = $instance->annotations; - $_meta = $instance->_meta; - $resource = new Resource($instance->uri, $name, $description, $mimeType, $annotations, $size, $_meta); + $meta = $instance->meta; + $resource = new Resource($instance->uri, $name, $description, $mimeType, $annotations, $size, $meta); $resources[$instance->uri] = new ResourceReference($resource, [$className, $methodName], false); ++$discoveredCount['resources']; @@ -256,8 +256,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $paramTag = $paramTags['$'.$param->getName()] ?? null; $arguments[] = new PromptArgument($param->getName(), $paramTag ? trim((string) $paramTag->getDescription()) : null, !$param->isOptional() && !$param->isDefaultValueAvailable()); } - $_meta = $instance->_meta ?? null; - $prompt = new Prompt($name, $description, $arguments, $_meta); + $meta = $instance->meta ?? null; + $prompt = new Prompt($name, $description, $arguments, $meta); $completionProviders = $this->getCompletionProviders($method); $prompts[$name] = new PromptReference($prompt, [$className, $methodName], false, $completionProviders); ++$discoveredCount['prompts']; @@ -269,8 +269,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun $description = $instance->description ?? $this->docBlockParser->getSummary($docBlock) ?? null; $mimeType = $instance->mimeType; $annotations = $instance->annotations; - $_meta = $instance->_meta ?? null; - $resourceTemplate = new ResourceTemplate($instance->uriTemplate, $name, $description, $mimeType, $annotations, $_meta); + $meta = $instance->meta ?? null; + $resourceTemplate = new ResourceTemplate($instance->uriTemplate, $name, $description, $mimeType, $annotations, $meta); $completionProviders = $this->getCompletionProviders($method); $resourceTemplates[$instance->uriTemplate] = new ResourceTemplateReference($resourceTemplate, [$className, $methodName], false, $completionProviders); ++$discoveredCount['resourceTemplates']; diff --git a/src/Capability/Registry/Loader/ArrayLoader.php b/src/Capability/Registry/Loader/ArrayLoader.php index 5ab120d0..a826bf6d 100644 --- a/src/Capability/Registry/Loader/ArrayLoader.php +++ b/src/Capability/Registry/Loader/ArrayLoader.php @@ -45,7 +45,7 @@ final class ArrayLoader implements LoaderInterface * name: ?string, * description: ?string, * annotations: ?ToolAnnotations, - * _meta: ?array + * meta: ?array * }[] $tools * @param array{ * handler: Handler, @@ -55,7 +55,7 @@ final class ArrayLoader implements LoaderInterface * mimeType: ?string, * size: int|null, * annotations: ?Annotations, - * _meta: ?array + * meta: ?array * }[] $resources * @param array{ * handler: Handler, @@ -64,13 +64,13 @@ final class ArrayLoader implements LoaderInterface * description: ?string, * mimeType: ?string, * annotations: ?Annotations, - * _meta: ?array + * meta: ?array * }[] $resourceTemplates * @param array{ * handler: Handler, * name: ?string, * description: ?string, - * _meta: ?array + * meta: ?array * }[] $prompts */ public function __construct( @@ -106,7 +106,7 @@ public function load(ReferenceRegistryInterface $registry): void $inputSchema = $data['inputSchema'] ?? $schemaGenerator->generate($reflection); - $tool = new Tool($name, $inputSchema, $description, $data['annotations'], $data['_meta'] ?? null); + $tool = new Tool($name, $inputSchema, $description, $data['annotations'], $data['meta'] ?? null); $registry->registerTool($tool, $data['handler'], true); $handlerDesc = $this->getHandlerDescription($data['handler']); @@ -141,9 +141,9 @@ public function load(ReferenceRegistryInterface $registry): void $mimeType = $data['mimeType']; $size = $data['size']; $annotations = $data['annotations']; - $_meta = $data['_meta']; + $meta = $data['meta']; - $resource = new Resource($uri, $name, $description, $mimeType, $annotations, $size, $_meta); + $resource = new Resource($uri, $name, $description, $mimeType, $annotations, $size, $meta); $registry->registerResource($resource, $data['handler'], true); $handlerDesc = $this->getHandlerDescription($data['handler']); @@ -177,9 +177,9 @@ public function load(ReferenceRegistryInterface $registry): void $uriTemplate = $data['uriTemplate']; $mimeType = $data['mimeType']; $annotations = $data['annotations']; - $_meta = $data['_meta']; + $meta = $data['meta']; - $template = new ResourceTemplate($uriTemplate, $name, $description, $mimeType, $annotations, $_meta); + $template = new ResourceTemplate($uriTemplate, $name, $description, $mimeType, $annotations, $meta); $completionProviders = $this->getCompletionProviders($reflection); $registry->registerResourceTemplate($template, $data['handler'], $completionProviders, true); @@ -230,8 +230,8 @@ public function load(ReferenceRegistryInterface $registry): void !$param->isOptional() && !$param->isDefaultValueAvailable(), ); } - $_meta = $data['_meta']; - $prompt = new Prompt($name, $description, $arguments, $_meta); + $meta = $data['meta']; + $prompt = new Prompt($name, $description, $arguments, $meta); $completionProviders = $this->getCompletionProviders($reflection); $registry->registerPrompt($prompt, $data['handler'], $completionProviders, true); diff --git a/src/Capability/Registry/ResourceReference.php b/src/Capability/Registry/ResourceReference.php index 7104b85a..d9b6a7e4 100644 --- a/src/Capability/Registry/ResourceReference.php +++ b/src/Capability/Registry/ResourceReference.php @@ -68,11 +68,11 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = return [$readResult->resource]; } - $_meta = $this->schema->_meta; + $meta = $this->schema->meta; if (\is_array($readResult)) { if (empty($readResult)) { - return [new TextResourceContents($uri, 'application/json', '[]', $_meta)]; + return [new TextResourceContents($uri, 'application/json', '[]', $meta)]; } $allAreResourceContents = true; @@ -120,7 +120,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_string($readResult)) { $mimeType = $mimeType ?? $this->guessMimeTypeFromString($readResult); - return [new TextResourceContents($uri, $mimeType, $readResult, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $readResult, $meta)]; } if (\is_resource($readResult) && 'stream' === get_resource_type($readResult)) { @@ -128,7 +128,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $uri, $readResult, $mimeType ?? 'application/octet-stream', - $_meta + $meta ); @fclose($readResult); @@ -139,21 +139,21 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_array($readResult) && isset($readResult['blob']) && \is_string($readResult['blob'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'application/octet-stream'; - return [new BlobResourceContents($uri, $mimeType, $readResult['blob'], $_meta)]; + return [new BlobResourceContents($uri, $mimeType, $readResult['blob'], $meta)]; } if (\is_array($readResult) && isset($readResult['text']) && \is_string($readResult['text'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'text/plain'; - return [new TextResourceContents($uri, $mimeType, $readResult['text'], $_meta)]; + return [new TextResourceContents($uri, $mimeType, $readResult['text'], $meta)]; } if ($readResult instanceof \SplFileInfo && $readResult->isFile() && $readResult->isReadable()) { if ($mimeType && str_contains(strtolower($mimeType), 'text')) { - return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $_meta)]; + return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $meta)]; } - return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType, $_meta)]; + return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType, $meta)]; } if (\is_array($readResult)) { @@ -162,7 +162,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = try { $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); - return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $meta)]; } catch (\JsonException $e) { throw new RuntimeException(\sprintf('Failed to encode array as JSON for URI "%s": %s', $uri, $e->getMessage())); } @@ -172,7 +172,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); $mimeType = $mimeType ?? 'application/json'; - return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $meta)]; } catch (\JsonException $e) { throw new RuntimeException(\sprintf('Failed to encode array as JSON for URI "%s": %s', $uri, $e->getMessage())); } diff --git a/src/Capability/Registry/ResourceTemplateReference.php b/src/Capability/Registry/ResourceTemplateReference.php index 03448b96..88104c9d 100644 --- a/src/Capability/Registry/ResourceTemplateReference.php +++ b/src/Capability/Registry/ResourceTemplateReference.php @@ -101,11 +101,11 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = return [$readResult->resource]; } - $_meta = $this->resourceTemplate->_meta; + $meta = $this->resourceTemplate->meta; if (\is_array($readResult)) { if (empty($readResult)) { - return [new TextResourceContents($uri, 'application/json', '[]', $_meta)]; + return [new TextResourceContents($uri, 'application/json', '[]', $meta)]; } $allAreResourceContents = true; @@ -153,7 +153,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_string($readResult)) { $mimeType = $mimeType ?? $this->guessMimeTypeFromString($readResult); - return [new TextResourceContents($uri, $mimeType, $readResult, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $readResult, $meta)]; } if (\is_resource($readResult) && 'stream' === get_resource_type($readResult)) { @@ -161,7 +161,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $uri, $readResult, $mimeType ?? 'application/octet-stream', - $_meta + $meta ); @fclose($readResult); @@ -172,21 +172,21 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = if (\is_array($readResult) && isset($readResult['blob']) && \is_string($readResult['blob'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'application/octet-stream'; - return [new BlobResourceContents($uri, $mimeType, $readResult['blob'], $_meta)]; + return [new BlobResourceContents($uri, $mimeType, $readResult['blob'], $meta)]; } if (\is_array($readResult) && isset($readResult['text']) && \is_string($readResult['text'])) { $mimeType = $readResult['mimeType'] ?? $mimeType ?? 'text/plain'; - return [new TextResourceContents($uri, $mimeType, $readResult['text'], $_meta)]; + return [new TextResourceContents($uri, $mimeType, $readResult['text'], $meta)]; } if ($readResult instanceof \SplFileInfo && $readResult->isFile() && $readResult->isReadable()) { if ($mimeType && str_contains(strtolower($mimeType), 'text')) { - return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $_meta)]; + return [new TextResourceContents($uri, $mimeType, file_get_contents($readResult->getPathname()), $meta)]; } - return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType, $_meta)]; + return [BlobResourceContents::fromSplFileInfo($uri, $readResult, $mimeType, $meta)]; } if (\is_array($readResult)) { @@ -195,7 +195,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = try { $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); - return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $meta)]; } catch (\JsonException $e) { throw new RuntimeException("Failed to encode array as JSON for URI '{$uri}': {$e->getMessage()}"); } @@ -205,7 +205,7 @@ public function formatResult(mixed $readResult, string $uri, ?string $mimeType = $jsonString = json_encode($readResult, \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT); $mimeType = $mimeType ?? 'application/json'; - return [new TextResourceContents($uri, $mimeType, $jsonString, $_meta)]; + return [new TextResourceContents($uri, $mimeType, $jsonString, $meta)]; } catch (\JsonException $e) { throw new RuntimeException("Failed to encode array as JSON for URI '{$uri}': {$e->getMessage()}"); } diff --git a/src/Schema/Content/BlobResourceContents.php b/src/Schema/Content/BlobResourceContents.php index 853ebcb4..52850392 100644 --- a/src/Schema/Content/BlobResourceContents.php +++ b/src/Schema/Content/BlobResourceContents.php @@ -31,15 +31,15 @@ class BlobResourceContents extends ResourceContents * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource * @param string $blob a base64-encoded string representing the binary data of the item - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( string $uri, ?string $mimeType, public readonly string $blob, - ?array $_meta = null, + ?array $meta = null, ) { - parent::__construct($uri, $mimeType, $_meta); + parent::__construct($uri, $mimeType, $meta); } /** @@ -59,24 +59,24 @@ public static function fromArray(array $data): self /** * @param resource $stream - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata * */ - public static function fromStream(string $uri, $stream, string $mimeType, ?array $_meta = null): self + public static function fromStream(string $uri, $stream, string $mimeType, ?array $meta = null): self { $blob = stream_get_contents($stream); - return new self($uri, $mimeType, base64_encode($blob), $_meta); + return new self($uri, $mimeType, base64_encode($blob), $meta); } /** - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata * */ - public static function fromSplFileInfo(string $uri, \SplFileInfo $file, ?string $explicitMimeType = null, ?array $_meta = null): self + public static function fromSplFileInfo(string $uri, \SplFileInfo $file, ?string $explicitMimeType = null, ?array $meta = null): self { $mimeType = $explicitMimeType ?? mime_content_type($file->getPathname()); $blob = file_get_contents($file->getPathname()); - return new self($uri, $mimeType, base64_encode($blob), $_meta); + return new self($uri, $mimeType, base64_encode($blob), $meta); } /** diff --git a/src/Schema/Content/ResourceContents.php b/src/Schema/Content/ResourceContents.php index eb008a34..ffd5599b 100644 --- a/src/Schema/Content/ResourceContents.php +++ b/src/Schema/Content/ResourceContents.php @@ -27,12 +27,12 @@ abstract class ResourceContents implements \JsonSerializable /** * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public readonly string $uri, public readonly ?string $mimeType = null, - public readonly ?array $_meta = null, + public readonly ?array $meta = null, ) { } @@ -46,8 +46,8 @@ public function jsonSerialize(): array $data['mimeType'] = $this->mimeType; } - if (null !== $this->_meta) { - $data['_meta'] = $this->_meta; + if (null !== $this->meta) { + $data['_meta'] = $this->meta; } return $data; diff --git a/src/Schema/Content/TextResourceContents.php b/src/Schema/Content/TextResourceContents.php index fe55de71..47ee31fd 100644 --- a/src/Schema/Content/TextResourceContents.php +++ b/src/Schema/Content/TextResourceContents.php @@ -31,15 +31,15 @@ class TextResourceContents extends ResourceContents * @param string $uri the URI of the resource or sub-resource * @param string|null $mimeType the MIME type of the resource or sub-resource * @param string $text The text of the item. This must only be set if the item can actually be represented as text (not binary data). - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( string $uri, ?string $mimeType, public readonly string $text, - ?array $_meta = null, + ?array $meta = null, ) { - parent::__construct($uri, $mimeType, $_meta); + parent::__construct($uri, $mimeType, $meta); } /** diff --git a/src/Schema/Prompt.php b/src/Schema/Prompt.php index d4493640..c61efcd1 100644 --- a/src/Schema/Prompt.php +++ b/src/Schema/Prompt.php @@ -33,13 +33,13 @@ class Prompt implements \JsonSerializable * @param string $name the name of the prompt or prompt template * @param string|null $description an optional description of what this prompt provides * @param PromptArgument[]|null $arguments A list of arguments for templating. Null if not a template. - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public readonly string $name, public readonly ?string $description = null, public readonly ?array $arguments = null, - public readonly ?array $_meta = null, + public readonly ?array $meta = null, ) { if (null !== $this->arguments) { foreach ($this->arguments as $arg) { @@ -71,7 +71,7 @@ public static function fromArray(array $data): self name: $data['name'], description: $data['description'] ?? null, arguments: $arguments, - _meta: isset($data['_meta']) ? $data['_meta'] : null + meta: isset($data['_meta']) ? $data['_meta'] : null ); } @@ -92,8 +92,8 @@ public function jsonSerialize(): array if (null !== $this->arguments) { $data['arguments'] = $this->arguments; } - if (null !== $this->_meta) { - $data['_meta'] = $this->_meta; + if (null !== $this->meta) { + $data['_meta'] = $this->meta; } return $data; diff --git a/src/Schema/Resource.php b/src/Schema/Resource.php index 07fe3a21..36ac5938 100644 --- a/src/Schema/Resource.php +++ b/src/Schema/Resource.php @@ -50,7 +50,7 @@ class Resource implements \JsonSerializable * @param string|null $mimeType the MIME type of this resource, if known * @param Annotations|null $annotations optional annotations for the client * @param int|null $size The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata * * This can be used by Hosts to display file sizes and estimate context window usage */ @@ -61,7 +61,7 @@ public function __construct( public readonly ?string $mimeType = null, public readonly ?Annotations $annotations = null, public readonly ?int $size = null, - public readonly ?array $_meta = null, + public readonly ?array $meta = null, ) { if (!preg_match(self::RESOURCE_NAME_PATTERN, $name)) { throw new InvalidArgumentException('Invalid resource name: must contain only alphanumeric characters, underscores, and hyphens.'); @@ -94,7 +94,7 @@ public static function fromArray(array $data): self mimeType: $data['mimeType'] ?? null, annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null, size: isset($data['size']) ? (int) $data['size'] : null, - _meta: isset($data['_meta']) ? $data['_meta'] : null + meta: isset($data['_meta']) ? $data['_meta'] : null ); } @@ -127,8 +127,8 @@ public function jsonSerialize(): array if (null !== $this->size) { $data['size'] = $this->size; } - if (null !== $this->_meta) { - $data['_meta'] = $this->_meta; + if (null !== $this->meta) { + $data['_meta'] = $this->meta; } return $data; diff --git a/src/Schema/ResourceTemplate.php b/src/Schema/ResourceTemplate.php index 5701aa03..136b8b6e 100644 --- a/src/Schema/ResourceTemplate.php +++ b/src/Schema/ResourceTemplate.php @@ -48,7 +48,7 @@ class ResourceTemplate implements \JsonSerializable * @param string|null $description This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model. * @param string|null $mimeType The MIME type for all resources that match this template. This should only be included if all resources matching this template have the same type. * @param Annotations|null $annotations optional annotations for the client - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public readonly string $uriTemplate, @@ -56,7 +56,7 @@ public function __construct( public readonly ?string $description = null, public readonly ?string $mimeType = null, public readonly ?Annotations $annotations = null, - public readonly ?array $_meta = null, + public readonly ?array $meta = null, ) { if (!preg_match(self::RESOURCE_NAME_PATTERN, $name)) { throw new InvalidArgumentException('Invalid resource name: must contain only alphanumeric characters, underscores, and hyphens.'); @@ -88,7 +88,7 @@ public static function fromArray(array $data): self description: $data['description'] ?? null, mimeType: $data['mimeType'] ?? null, annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null, - _meta: isset($data['_meta']) ? $data['_meta'] : null + meta: isset($data['_meta']) ? $data['_meta'] : null ); } @@ -117,8 +117,8 @@ public function jsonSerialize(): array if (null !== $this->annotations) { $data['annotations'] = $this->annotations; } - if (null !== $this->_meta) { - $data['_meta'] = $this->_meta; + if (null !== $this->meta) { + $data['_meta'] = $this->meta; } return $data; diff --git a/src/Schema/Tool.php b/src/Schema/Tool.php index 3be8ddbb..c3613074 100644 --- a/src/Schema/Tool.php +++ b/src/Schema/Tool.php @@ -42,14 +42,14 @@ class Tool implements \JsonSerializable * available tools. It can be thought of like a "hint" to the model. * @param ToolInputSchema $inputSchema a JSON Schema object (as a PHP array) defining the expected 'arguments' for the tool * @param ToolAnnotations|null $annotations optional additional tool information - * @param ?array $_meta Optional metadata + * @param ?array $meta Optional metadata */ public function __construct( public readonly string $name, public readonly array $inputSchema, public readonly ?string $description, public readonly ?ToolAnnotations $annotations, - public readonly ?array $_meta = null, + public readonly ?array $meta = null, ) { if (!isset($inputSchema['type']) || 'object' !== $inputSchema['type']) { throw new InvalidArgumentException('Tool inputSchema must be a JSON Schema of type "object".'); @@ -104,8 +104,8 @@ public function jsonSerialize(): array if (null !== $this->annotations) { $data['annotations'] = $this->annotations; } - if (null !== $this->_meta) { - $data['_meta'] = $this->_meta; + if (null !== $this->meta) { + $data['_meta'] = $this->meta; } return $data; diff --git a/src/Server/Builder.php b/src/Server/Builder.php index 066bf3f8..77effae4 100644 --- a/src/Server/Builder.php +++ b/src/Server/Builder.php @@ -78,7 +78,7 @@ final class Builder * name: ?string, * description: ?string, * annotations: ?ToolAnnotations, - * _meta: ?array + * meta: ?array * }[] */ private array $tools = []; @@ -92,7 +92,7 @@ final class Builder * mimeType: ?string, * size: int|null, * annotations: ?Annotations, - * _meta: ?array + * meta: ?array * }[] */ private array $resources = []; @@ -105,7 +105,7 @@ final class Builder * description: ?string, * mimeType: ?string, * annotations: ?Annotations, - * _meta: ?array + * meta: ?array * }[] */ private array $resourceTemplates = []; @@ -115,7 +115,7 @@ final class Builder * handler: Handler, * name: ?string, * description: ?string, - * _meta: ?array + * meta: ?array * }[] */ private array $prompts = []; From 358f6c1e73f3721d9b9fe82b4152e31f796d6091 Mon Sep 17 00:00:00 2001 From: Kaipi Yann Date: Wed, 5 Nov 2025 13:43:13 +0100 Subject: [PATCH 10/10] Correct Issue 130 https://github.com/modelcontextprotocol/php-sdk/issues/130 --- src/Schema/Content/BlobResourceContents.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema/Content/BlobResourceContents.php b/src/Schema/Content/BlobResourceContents.php index 52850392..0d6016d5 100644 --- a/src/Schema/Content/BlobResourceContents.php +++ b/src/Schema/Content/BlobResourceContents.php @@ -86,7 +86,7 @@ public function jsonSerialize(): array { return [ 'blob' => $this->blob, - ...$this->jsonSerialize(), + ...parent::jsonSerialize(), ]; } }