Skip to content
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ All notable changes to `mcp/sdk` will be documented in this file.
* [BC Break] `RegistryInterface::registerTool()`, `registerResource()`, `registerResourceTemplate()`, `registerPrompt()` lost their trailing `bool $isManual = false` parameter. Callers using positional arguments must drop the flag.
* [BC Break] Removed `RegistryInterface::clear()`, `getDiscoveryState()`, `setDiscoveryState()`. Rediscovery now goes through `DiscoveryLoader::load()` directly.
* `Registry::register*()` semantics changed to plain last-write-wins (overwrites silently) and the methods now return the stored `*Reference`. The previous "discovered registration is ignored when a manual one already exists" precedence rule still applies, but is now enforced by `DiscoveryLoader` via reference-identity tracking — and still emits a debug log when a discovery is skipped due to a conflicting registration.
* Add optional `title` parameter to `Builder::addResource()` and `Builder::addResourceTemplate()` for MCP spec compliance
* [BC Break] `Builder::addResource()` signature changed — `$title` parameter added between `$name` and `$description`. Callers using positional arguments must switch to named arguments.
* [BC Break] `Builder::addResourceTemplate()` signature changed — `$title` parameter added between `$name` and `$description`. Callers using positional arguments must switch to named arguments.

0.5.0
-----
Expand Down
4 changes: 4 additions & 0 deletions src/Capability/Registry/Loader/ArrayLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ final class ArrayLoader implements LoaderInterface
* handler: Handler,
* uri: string,
* name: ?string,
* title: ?string,
* description: ?string,
* mimeType: ?string,
* size: int|null,
Expand All @@ -67,6 +68,7 @@ final class ArrayLoader implements LoaderInterface
* handler: Handler,
* uriTemplate: string,
* name: ?string,
* title: ?string,
* description: ?string,
* mimeType: ?string,
* annotations: ?Annotations,
Expand Down Expand Up @@ -157,6 +159,7 @@ public function load(RegistryInterface $registry): void
$resource = new Resource(
uri: $data['uri'],
name: $name,
title: $data['title'] ?? null,
description: $description,
mimeType: $data['mimeType'] ?? null,
annotations: $data['annotations'] ?? null,
Expand Down Expand Up @@ -197,6 +200,7 @@ public function load(RegistryInterface $registry): void
$template = new ResourceTemplate(
uriTemplate: $data['uriTemplate'],
name: $name,
title: $data['title'] ?? null,
description: $description,
mimeType: $data['mimeType'] ?? null,
annotations: $data['annotations'] ?? null,
Expand Down
8 changes: 8 additions & 0 deletions src/Server/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ final class Builder
* handler: Handler,
* uri: string,
* name: ?string,
* title: ?string,
* description: ?string,
* mimeType: ?string,
* size: int|null,
Expand All @@ -134,6 +135,7 @@ final class Builder
* handler: Handler,
* uriTemplate: string,
* name: ?string,
* title: ?string,
* description: ?string,
* mimeType: ?string,
* annotations: ?Annotations,
Expand Down Expand Up @@ -433,13 +435,15 @@ public function addTool(
* Manually registers a resource handler.
*
* @param Handler $handler
* @param ?string $title Optional human-readable title for display in UI
* @param ?Icon[] $icons
* @param array<string, mixed>|null $meta
*/
public function addResource(
\Closure|array|string $handler,
string $uri,
?string $name = null,
?string $title = null,
?string $description = null,
?string $mimeType = null,
?int $size = null,
Expand All @@ -451,6 +455,7 @@ public function addResource(
'handler',
'uri',
'name',
'title',
'description',
'mimeType',
'size',
Expand All @@ -466,12 +471,14 @@ public function addResource(
* Manually registers a resource template handler.
*
* @param Handler $handler
* @param ?string $title Optional human-readable title for display in UI
* @param array<string, mixed>|null $meta
*/
public function addResourceTemplate(
\Closure|array|string $handler,
string $uriTemplate,
?string $name = null,
?string $title = null,
?string $description = null,
?string $mimeType = null,
?Annotations $annotations = null,
Expand All @@ -481,6 +488,7 @@ public function addResourceTemplate(
'handler',
'uriTemplate',
'name',
'title',
'description',
'mimeType',
'annotations',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/*
* This file is part of the official PHP MCP SDK.
*
* A collaboration between Symfony and the PHP Foundation.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Mcp\Tests\Unit\Capability\Registry\Loader;

use Mcp\Capability\Registry;
use Mcp\Capability\Registry\Loader\ArrayLoader;
use PHPUnit\Framework\TestCase;

class ArrayLoaderResourceTitleTest extends TestCase
{
public function testLoadPropagatesResourceTitleToRegisteredResource(): void
{
$resources = [
[
'handler' => static fn (): string => 'ok',
'uri' => 'config://app/settings',
'name' => 'app_settings',
'title' => 'Application Settings',
'description' => null,
'mimeType' => null,
'size' => null,
'annotations' => null,
'icons' => null,
'meta' => null,
],
];

$loader = new ArrayLoader([], $resources);
$registry = new Registry();

$loader->load($registry);

$resourceRef = $registry->getResource('config://app/settings');
$this->assertSame('Application Settings', $resourceRef->resource->title);
}

public function testLoadPropagatesResourceTemplateTitleToRegisteredTemplate(): void
{
$resourceTemplates = [
[
'handler' => static fn (): string => 'ok',
'uriTemplate' => 'user://{userId}/profile',
'name' => 'user_profile',
'title' => 'User Profile',
'description' => null,
'mimeType' => null,
'annotations' => null,
'meta' => null,
],
];

$loader = new ArrayLoader([], [], $resourceTemplates);
$registry = new Registry();

$loader->load($registry);

$templateRef = $registry->getResourceTemplate('user://{userId}/profile');
$this->assertSame('User Profile', $templateRef->resourceTemplate->title);
}
}