From e1c2bf0f5338a3962db01dd9b78487009a802e5b Mon Sep 17 00:00:00 2001 From: Illia Vasylevskyi Date: Sun, 5 Oct 2025 16:55:52 -0400 Subject: [PATCH] Added possibility to set custom ServerCapabilities. --- .../stdio-explicit-registration/server.php | 12 +++++++ src/Capability/Registry.php | 9 ++++- src/Server/Builder.php | 12 +++++++ .../Unit/Capability/Registry/RegistryTest.php | 36 +++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/examples/stdio-explicit-registration/server.php b/examples/stdio-explicit-registration/server.php index f225f98..81678d9 100644 --- a/examples/stdio-explicit-registration/server.php +++ b/examples/stdio-explicit-registration/server.php @@ -14,6 +14,7 @@ chdir(__DIR__); use Mcp\Example\StdioExplicitRegistration\SimpleHandlers; +use Mcp\Schema\ServerCapabilities; use Mcp\Server; use Mcp\Server\Transport\StdioTransport; @@ -27,6 +28,17 @@ ->addResource([SimpleHandlers::class, 'getAppVersion'], 'app://version', 'application_version', mimeType: 'text/plain') ->addPrompt([SimpleHandlers::class, 'greetingPrompt'], 'personalized_greeting') ->addResourceTemplate([SimpleHandlers::class, 'getItemDetails'], 'item://{itemId}/details', 'get_item_details', mimeType: 'application/json') + ->setServerCapabilities(new ServerCapabilities( + tools: true, + toolsListChanged: false, + resources: true, + resourcesSubscribe: false, + resourcesListChanged: false, + prompts: true, + promptsListChanged: false, + logging: false, + completions: false, + )) ->build(); $transport = new StdioTransport(logger: logger()); diff --git a/src/Capability/Registry.php b/src/Capability/Registry.php index 6e54cfc..94db079 100644 --- a/src/Capability/Registry.php +++ b/src/Capability/Registry.php @@ -63,6 +63,8 @@ final class Registry implements ReferenceProviderInterface, ReferenceRegistryInt */ private array $resourceTemplates = []; + private ServerCapabilities $serverCapabilities; + public function __construct( private readonly ?EventDispatcherInterface $eventDispatcher = null, private readonly LoggerInterface $logger = new NullLogger(), @@ -75,7 +77,7 @@ public function getCapabilities(): ServerCapabilities $this->logger->info('No capabilities registered on server.'); } - return new ServerCapabilities( + return $this->serverCapabilities ?? new ServerCapabilities( tools: [] !== $this->tools, toolsListChanged: $this->eventDispatcher instanceof EventDispatcherInterface, resources: [] !== $this->resources || [] !== $this->resourceTemplates, @@ -453,4 +455,9 @@ private function paginateResults(array $items, int $limit, ?string $cursor = nul return array_values(\array_slice($items, $offset, $limit)); } + + public function setServerCapabilities(ServerCapabilities $serverCapabilities): void + { + $this->serverCapabilities = $serverCapabilities; + } } diff --git a/src/Server/Builder.php b/src/Server/Builder.php index 8ac2dc4..39f2cb8 100644 --- a/src/Server/Builder.php +++ b/src/Server/Builder.php @@ -138,6 +138,8 @@ final class Builder */ private array $discoveryExcludeDirs = []; + private ?ServerCapabilities $serverCapabilities = null; + /** * Sets the server's identity. Required. */ @@ -264,6 +266,13 @@ public function setDiscovery( return $this; } + public function setServerCapabilities(ServerCapabilities $serverCapabilities): self + { + $this->serverCapabilities = $serverCapabilities; + + return $this; + } + /** * Manually registers a tool handler. * @@ -348,6 +357,9 @@ public function build(): Server $registry = new Registry($this->eventDispatcher, $logger); $this->registerCapabilities($registry, $logger); + if ($this->serverCapabilities) { + $registry->setServerCapabilities($this->serverCapabilities); + } if (null !== $this->discoveryBasePath) { $this->performDiscovery($registry, $logger); diff --git a/tests/Unit/Capability/Registry/RegistryTest.php b/tests/Unit/Capability/Registry/RegistryTest.php index e18f9d1..e1f4768 100644 --- a/tests/Unit/Capability/Registry/RegistryTest.php +++ b/tests/Unit/Capability/Registry/RegistryTest.php @@ -80,6 +80,42 @@ public function testGetCapabilitiesWhenPopulated(): void $this->assertFalse($capabilities->logging); } + public function testSetCustomCapabilities(): void + { + $serverCapabilities = new ServerCapabilities( + tools: false, + toolsListChanged: true, + resources: false, + resourcesSubscribe: false, + resourcesListChanged: false, + prompts: false, + promptsListChanged: false, + logging: true, + completions: true, + ); + $tool = $this->createValidTool('test_tool'); + $resource = $this->createValidResource('test://resource'); + $prompt = $this->createValidPrompt('test_prompt'); + $template = $this->createValidResourceTemplate('test://{id}'); + + $this->registry->registerTool($tool, fn () => 'result'); + $this->registry->registerResource($resource, fn () => 'content'); + $this->registry->registerPrompt($prompt, fn () => []); + $this->registry->registerResourceTemplate($template, fn () => 'template'); + + $this->registry->setServerCapabilities($serverCapabilities); + + $capabilities = $this->registry->getCapabilities(); + + $this->assertFalse($capabilities->tools); + $this->assertFalse($capabilities->resources); + $this->assertFalse($capabilities->prompts); + $this->assertTrue($capabilities->completions); + $this->assertFalse($capabilities->resourcesSubscribe); + $this->assertTrue($capabilities->logging); + $this->assertTrue($capabilities->toolsListChanged); + } + public function testRegisterToolWithManualFlag(): void { $tool = $this->createValidTool('test_tool');