From 526285bcde982fa98897a862f70f2cd3b823d705 Mon Sep 17 00:00:00 2001 From: Tac Tacelosky Date: Wed, 4 Nov 2026 09:13:42 -0500 Subject: [PATCH 1/2] fix(mcp): support MCP SDK 0.9 registry capabilities (#8758) * fix(mcp): support MCP SDK 0.9 registry capabilities * test(mcp): exercise capability forwarding with both SDK versions * test(mcp): apply review, widen mcp-bundle to sdk 0.9 * chore(mcp): ignore sdk 0.9 narrowed method_exists --------- Co-authored-by: soyuka (cherry picked from commit ba3d61f66a2cec281f578ff30af07393f9c69a3c) Co-Authored-By: Claude Opus 5.5 --- composer.json | 4 ++-- .../Capability/Registry/SecureRegistry.php | 6 ++++++ .../Registry/SecureRegistryTest.php | 14 +++++++++++++ .../ListChangePublishingRegistryInterface.php | 21 +++++++++++++++++++ src/Mcp/composer.json | 2 +- 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/Mcp/Tests/Fixtures/ListChangePublishingRegistryInterface.php diff --git a/composer.json b/composer.json index 13946a83607..4c8dea29155 100644 --- a/composer.json +++ b/composer.json @@ -143,7 +143,7 @@ "jangregor/phpstan-prophecy": "^2.1.11", "justinrainbow/json-schema": "^6.5.2", "laravel/framework": "^11.0 || ^12.0 || ^13.0", - "mcp/sdk": "^0.8", + "mcp/sdk": "^0.8 || ^0.9", "orchestra/testbench": "^10.9 || ^11.0", "phpspec/prophecy-phpunit": "^2.2", "phpstan/extension-installer": "^1.1", @@ -176,7 +176,7 @@ "symfony/intl": "^7.4 || ^8.0", "symfony/json-streamer": "^7.4 || ^8.0", "symfony/maker-bundle": "^1.24", - "symfony/mcp-bundle": "^0.13", + "symfony/mcp-bundle": "^0.13 || ^0.15", "symfony/mercure-bundle": "^0.5", "symfony/messenger": "^7.4 || ^8.0", "symfony/object-mapper": "^7.4 || ^8.0", diff --git a/src/Mcp/Capability/Registry/SecureRegistry.php b/src/Mcp/Capability/Registry/SecureRegistry.php index 946d9181411..f81c1e0cf1c 100644 --- a/src/Mcp/Capability/Registry/SecureRegistry.php +++ b/src/Mcp/Capability/Registry/SecureRegistry.php @@ -103,6 +103,12 @@ public function unregisterPrompt(string $name): void $this->inner->unregisterPrompt($name); } + public function publishesListChanges(): bool + { + // MCP SDK 0.8 does not expose this capability. + return method_exists($this->inner, 'publishesListChanges') && $this->inner->publishesListChanges(); // @phpstan-ignore function.alreadyNarrowedType + } + public function hasTool(string $name): bool { $this->load(); diff --git a/src/Mcp/Tests/Capability/Registry/SecureRegistryTest.php b/src/Mcp/Tests/Capability/Registry/SecureRegistryTest.php index e01bf390b9f..d7217c5ea8c 100644 --- a/src/Mcp/Tests/Capability/Registry/SecureRegistryTest.php +++ b/src/Mcp/Tests/Capability/Registry/SecureRegistryTest.php @@ -18,6 +18,7 @@ use ApiPlatform\Mcp\Capability\Registry\Loader; use ApiPlatform\Mcp\Capability\Registry\SecureRegistry; use ApiPlatform\Mcp\Security\ElementAccessCheckerInterface; +use ApiPlatform\Mcp\Tests\Fixtures\ListChangePublishingRegistryInterface; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\McpResource; use ApiPlatform\Metadata\McpTool; @@ -34,6 +35,19 @@ class SecureRegistryTest extends TestCase { + public function testListChangePublishingCapabilityIsForwarded(): void + { + $inner = $this->createMock(ListChangePublishingRegistryInterface::class); + $inner->expects($this->exactly(2))->method('publishesListChanges')->willReturn(true, false); + $loader = $this->createMock(LoaderInterface::class); + $loader->expects($this->never())->method('load'); + + $registry = new SecureRegistry($inner, $loader); + + $this->assertTrue($registry->publishesListChanges()); + $this->assertFalse($registry->publishesListChanges()); + } + public function testToolsAreLoadedIntoTheRegistryOnFirstRead(): void { $inputSchema = new Schema(Schema::VERSION_JSON_SCHEMA); diff --git a/src/Mcp/Tests/Fixtures/ListChangePublishingRegistryInterface.php b/src/Mcp/Tests/Fixtures/ListChangePublishingRegistryInterface.php new file mode 100644 index 00000000000..7b6433a01d9 --- /dev/null +++ b/src/Mcp/Tests/Fixtures/ListChangePublishingRegistryInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Mcp\Tests\Fixtures; + +use Mcp\Capability\RegistryInterface; + +interface ListChangePublishingRegistryInterface extends RegistryInterface +{ + public function publishesListChanges(): bool; +} diff --git a/src/Mcp/composer.json b/src/Mcp/composer.json index 66dc51b7186..00b9f5d3851 100644 --- a/src/Mcp/composer.json +++ b/src/Mcp/composer.json @@ -31,7 +31,7 @@ "api-platform/metadata": "^4.4", "api-platform/json-schema": "^4.4", "api-platform/state": "^4.4", - "mcp/sdk": "^0.8", + "mcp/sdk": "^0.8 || ^0.9", "psr/log": "^1.0 || ^2.0 || ^3.0", "symfony/http-foundation": "^7.4 || ^8.0", "symfony/object-mapper": "^7.4 || ^8.0", From 0ca57d52fdb2beeea43a0c1200b0eb58d3ddbc62 Mon Sep 17 00:00:00 2001 From: soyuka Date: Thu, 12 Nov 2026 11:35:33 +0100 Subject: [PATCH 2/2] fix(laravel): allow symfony/mcp-bundle 0.15 --- src/Laravel/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Laravel/composer.json b/src/Laravel/composer.json index f30f059ddd8..f91c052ccf9 100644 --- a/src/Laravel/composer.json +++ b/src/Laravel/composer.json @@ -65,7 +65,7 @@ "phpstan/phpdoc-parser": "^1.29 || ^2.0", "phpunit/phpunit": "^11.5 || ^12.2", "symfony/http-client": "^7.4 || ^8.0", - "symfony/mcp-bundle": "^0.13", + "symfony/mcp-bundle": "^0.13 || ^0.15", "symfony/object-mapper": "^7.4 || ^8.0" }, "autoload": {