Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/Capability/Attribute/McpResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,20 @@
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 $uri the specific URI identifying this resource instance
* @param ?string $name a short identifier for this resource; defaults to the method name
* @param ?string $title optional human-readable title for display in UI
* @param ?string $description optional description; 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 ?Icon[] $icons Optional list of icon URLs representing the resource
* @param ?array<string, mixed> $meta Optional metadata
* @param ?Annotations $annotations optional annotations describing the resource
* @param ?Icon[] $icons optional icons representing the resource
* @param ?array<string, mixed> $meta optional metadata
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why all the changes, can't you just add the title?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docblock changes align $name with the spec distinction between name (machine identifier) and title (display label). The old docblock said "human-readable name" which is now what $title is for. The other adjustments are just consistency: lowercase param descriptions and Annotations|null -> ?Annotations to match the type declaration. Happy to revert the style changes to a separate commit if you prefer a minimal diff.

*/
public function __construct(
public string $uri,
public ?string $name = null,
public ?string $title = null,
public ?string $description = null,
public ?string $mimeType = null,
public ?int $size = null,
Expand Down
8 changes: 5 additions & 3 deletions src/Capability/Attribute/McpResourceTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ 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 $name a short identifier for the template type; defaults to the method name
* @param ?string $title optional human-readable title for display in UI
* @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<string, mixed> $meta Optional metadata
* @param ?array<string, mixed> $meta optional metadata
*/
public function __construct(
public string $uriTemplate,
public ?string $name = null,
public ?string $title = null,
public ?string $description = null,
public ?string $mimeType = null,
public ?Annotations $annotations = null,
Expand Down
3 changes: 2 additions & 1 deletion src/Capability/Discovery/Discoverer.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun
$resource = new Resource(
$instance->uri,
$name,
$instance->title,
$description,
$instance->mimeType,
$instance->annotations,
Expand Down Expand Up @@ -293,7 +294,7 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun
$mimeType = $instance->mimeType;
$annotations = $instance->annotations;
$meta = $instance->meta ?? null;
$resourceTemplate = new ResourceTemplate($instance->uriTemplate, $name, $description, $mimeType, $annotations, $meta);
$resourceTemplate = new ResourceTemplate($instance->uriTemplate, $name, $instance->title, $description, $mimeType, $annotations, $meta);
$completionProviders = $this->getCompletionProviders($method);
$resourceTemplates[$instance->uriTemplate] = new ResourceTemplateReference($resourceTemplate, [$className, $methodName], false, $completionProviders);
++$discoveredCount['resourceTemplates'];
Expand Down
18 changes: 12 additions & 6 deletions src/Schema/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @phpstan-type ResourceData array{
* uri: string,
* name: string,
* title?: string,
* description?: string,
* mimeType?: string,
* annotations?: AnnotationsData,
Expand All @@ -47,19 +48,19 @@ class Resource implements \JsonSerializable

/**
* @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 $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 $name a short identifier for this resource
* @param ?string $title optional human-readable title for display in UI
* @param ?string $description A description of what this resource represents. This can be used by clients to improve the LLM's understanding of available resources.
* @param ?string $mimeType the MIME type of this resource, if known
* @param ?Annotations $annotations optional annotations for the client
* @param ?int $size The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.
* @param ?int $size the size of the raw resource content, in bytes (before base64 encoding or any tokenization), if known
* @param ?Icon[] $icons optional icons representing the resource
* @param ?array<string, mixed> $meta Optional metadata
*
* This can be used by Hosts to display file sizes and estimate context window usage
* @param ?array<string, mixed> $meta optional metadata
*/
public function __construct(
public readonly string $uri,
public readonly string $name,
public readonly ?string $title = null,
public readonly ?string $description = null,
public readonly ?string $mimeType = null,
public readonly ?Annotations $annotations = null,
Expand Down Expand Up @@ -94,6 +95,7 @@ public static function fromArray(array $data): self
return new self(
uri: $data['uri'],
name: $data['name'],
title: isset($data['title']) && \is_string($data['title']) ? $data['title'] : null,
description: $data['description'] ?? null,
mimeType: $data['mimeType'] ?? null,
annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null,
Expand All @@ -107,6 +109,7 @@ public static function fromArray(array $data): self
* @return array{
* uri: string,
* name: string,
* title?: string,
* description?: string,
* mimeType?: string,
* annotations?: Annotations,
Expand All @@ -121,6 +124,9 @@ public function jsonSerialize(): array
'uri' => $this->uri,
'name' => $this->name,
];
if (null !== $this->title) {
$data['title'] = $this->title;
}
if (null !== $this->description) {
$data['description'] = $this->description;
}
Expand Down
18 changes: 13 additions & 5 deletions src/Schema/ResourceTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @phpstan-type ResourceTemplateData array{
* uriTemplate: string,
* name: string,
* title?: string,
* description?: string|null,
* mimeType?: string|null,
* annotations?: AnnotationsData|null,
Expand All @@ -44,15 +45,17 @@ class ResourceTemplate implements \JsonSerializable

/**
* @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<string, mixed> $meta Optional metadata
* @param string $name a short identifier for this resource template type
* @param ?string $title optional human-readable title for display in UI
* @param ?string $description a description to help the LLM understand available resources
* @param ?string $mimeType the MIME type for all resources that match this template, if uniform
* @param ?Annotations $annotations optional annotations for the client
* @param ?array<string, mixed> $meta optional metadata
*/
public function __construct(
public readonly string $uriTemplate,
public readonly string $name,
public readonly ?string $title = null,
public readonly ?string $description = null,
public readonly ?string $mimeType = null,
public readonly ?Annotations $annotations = null,
Expand Down Expand Up @@ -85,6 +88,7 @@ public static function fromArray(array $data): self
return new self(
uriTemplate: $data['uriTemplate'],
name: $data['name'],
title: isset($data['title']) && \is_string($data['title']) ? $data['title'] : null,
description: $data['description'] ?? null,
mimeType: $data['mimeType'] ?? null,
annotations: isset($data['annotations']) ? Annotations::fromArray($data['annotations']) : null,
Expand All @@ -96,6 +100,7 @@ public static function fromArray(array $data): self
* @return array{
* uriTemplate: string,
* name: string,
* title?: string,
* description?: string,
* mimeType?: string,
* annotations?: Annotations,
Expand All @@ -108,6 +113,9 @@ public function jsonSerialize(): array
'uriTemplate' => $this->uriTemplate,
'name' => $this->name,
];
if (null !== $this->title) {
$data['title'] = $this->title;
}
if (null !== $this->description) {
$data['description'] = $this->description;
}
Expand Down
35 changes: 35 additions & 0 deletions tests/Unit/Schema/ResourceTemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,45 @@ public function testFromArrayValid(): void
$this->assertInstanceOf(ResourceTemplate::class, $resource);
$this->assertSame(self::VALID_URI, $resource->uriTemplate);
$this->assertSame('list-books', $resource->name);
$this->assertNull($resource->title);
$this->assertNull($resource->description);
$this->assertNull($resource->meta);
}

public function testTitleFromArray(): void
{
$resource = ResourceTemplate::fromArray([
'uriTemplate' => self::VALID_URI,
'name' => 'list-books',
'title' => 'Book Listing',
]);

$this->assertSame('Book Listing', $resource->title);
}

public function testTitleSerialization(): void
{
$resource = new ResourceTemplate(
uriTemplate: self::VALID_URI,
name: 'list-books',
title: 'Book Listing',
);

$data = $resource->jsonSerialize();
$this->assertSame('Book Listing', $data['title']);
}

public function testTitleOmittedWhenNull(): void
{
$resource = new ResourceTemplate(
uriTemplate: self::VALID_URI,
name: 'list-books',
);

$data = $resource->jsonSerialize();
$this->assertArrayNotHasKey('title', $data);
}

#[DataProvider('provideInvalidResources')]
public function testFromArrayInvalid(array $input, string $expectedExceptionMessage): void
{
Expand Down
35 changes: 35 additions & 0 deletions tests/Unit/Schema/ResourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,45 @@ public function testFromArrayValid(): void
$this->assertInstanceOf(Resource::class, $resource);
$this->assertSame(self::VALID_URI, $resource->uri);
$this->assertSame('list-books', $resource->name);
$this->assertNull($resource->title);
$this->assertNull($resource->description);
$this->assertNull($resource->meta);
}

public function testTitleFromArray(): void
{
$resource = Resource::fromArray([
'uri' => self::VALID_URI,
'name' => 'list-books',
'title' => 'Book Listing',
]);

$this->assertSame('Book Listing', $resource->title);
}

public function testTitleSerialization(): void
{
$resource = new Resource(
uri: self::VALID_URI,
name: 'list-books',
title: 'Book Listing',
);

$data = $resource->jsonSerialize();
$this->assertSame('Book Listing', $data['title']);
}

public function testTitleOmittedWhenNull(): void
{
$resource = new Resource(
uri: self::VALID_URI,
name: 'list-books',
);

$data = $resource->jsonSerialize();
$this->assertArrayNotHasKey('title', $data);
}

#[DataProvider('provideInvalidResources')]
public function testFromArrayInvalid(array $input, string $expectedExceptionMessage): void
{
Expand Down