From b3406409d8c8279156370c44c8f8ec3a4f2b716e Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 14 Aug 2026 18:57:05 +0200 Subject: [PATCH] chore(deps): bump mcp/sdk to ^0.7.1 for GHSA-7m52-jw36-44r3 CVE-2026-53965 affects mcp/sdk >=0.5.0,<0.7.1: the client HttpTransport's SSE buffer grows unbounded when a server withholds the event delimiter. composer audit has failed the "Lint & Static Analysis" job on every run since the advisory was published. ^0.6 cannot reach the fix (a caret on a 0.x version pins the minor), so the constraint moves to ^0.7.1. symfony/mcp-bundle v0.10 requires mcp/sdk ^0.6 and therefore has to move too; v0.11 is the first release accepting ^0.7, and its changes are additive (an http.allowed_hosts option, an MCP Apps attribute, and a middleware factory passed to the bundle's own controller). Compatibility of the SDK surface this application uses: - The McpTool/Schema attributes, ToolCallException, Mcp\Server and the three HTTP middleware classes are unchanged. - StreamableHttpTransport gained a trailing $maxBodyBytes parameter; McpEndpointController passes $logger and $middleware by name, so the call site is unaffected. - 0.7.0 made element loading lazy (a documented BC break): the registry loads on the first read instead of at Builder::build(). Nothing covered that path, because the tool tests call the tool services directly, so McpHttpEndpointTest gained a tools/list case over the real /mcp endpoint. Claude-Session: https://claude.ai/code/session_01AcqcEjgwcQfp3vpnFa3gh6 Signed-off-by: Sebastian Mendel --- composer.json | 4 ++-- composer.lock | 32 ++++++++++++++++--------------- tests/Mcp/McpHttpEndpointTest.php | 26 +++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 1e4eb6c02..d87d0d8ac 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,7 @@ "guzzlehttp/guzzle": "^7.9", "guzzlehttp/oauth-subscriber": "^0.9.1", "laminas/laminas-ldap": "^2.19", - "mcp/sdk": "^0.6", + "mcp/sdk": "^0.7.1", "pentatrion/vite-bundle": "^8.2", "phpoffice/phpspreadsheet": "^5.0", "phpstan/phpdoc-parser": "^2.2", @@ -60,7 +60,7 @@ "symfony/dotenv": "^8.1", "symfony/flex": "^2.8", "symfony/framework-bundle": "^8.1", - "symfony/mcp-bundle": "^0.10", + "symfony/mcp-bundle": "^0.11", "symfony/monolog-bundle": "^3.10|^4.0", "symfony/object-mapper": "^8.1", "symfony/polyfill-mbstring": "^1.33", diff --git a/composer.lock b/composer.lock index 5baacab17..348da44f0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c6b56c13d86288093f2068cee65e45f7", + "content-hash": "64fd2b6607cb15b577038547305134b2", "packages": [ { "name": "brick/math", @@ -2000,16 +2000,16 @@ }, { "name": "mcp/sdk", - "version": "v0.6.0", + "version": "v0.7.1", "source": { "type": "git", "url": "https://github.com/modelcontextprotocol/php-sdk.git", - "reference": "433c84b58af346dd32f15f9909679e96a46ebe23" + "reference": "785fc3b9b7006ecc8a73322c939d96a4a7154345" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/modelcontextprotocol/php-sdk/zipball/433c84b58af346dd32f15f9909679e96a46ebe23", - "reference": "433c84b58af346dd32f15f9909679e96a46ebe23", + "url": "https://api.github.com/repos/modelcontextprotocol/php-sdk/zipball/785fc3b9b7006ecc8a73322c939d96a4a7154345", + "reference": "785fc3b9b7006ecc8a73322c939d96a4a7154345", "shasum": "" }, "require": { @@ -2078,9 +2078,9 @@ "description": "Model Context Protocol SDK for Client and Server applications in PHP", "support": { "issues": "https://github.com/modelcontextprotocol/php-sdk/issues", - "source": "https://github.com/modelcontextprotocol/php-sdk/tree/v0.6.0" + "source": "https://github.com/modelcontextprotocol/php-sdk/tree/v0.7.1" }, - "time": "2026-06-02T15:47:04+00:00" + "time": "2026-08-10T20:09:23+00:00" }, { "name": "monolog/monolog", @@ -5961,20 +5961,20 @@ }, { "name": "symfony/mcp-bundle", - "version": "v0.10.0", + "version": "v0.11.0", "source": { "type": "git", "url": "https://github.com/symfony/mcp-bundle.git", - "reference": "b473eaee250c1e59d33487e6f3a41c35a1f02afb" + "reference": "f973cf4f146674d362da3258ba35629ad447ecb1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mcp-bundle/zipball/b473eaee250c1e59d33487e6f3a41c35a1f02afb", - "reference": "b473eaee250c1e59d33487e6f3a41c35a1f02afb", + "url": "https://api.github.com/repos/symfony/mcp-bundle/zipball/f973cf4f146674d362da3258ba35629ad447ecb1", + "reference": "f973cf4f146674d362da3258ba35629ad447ecb1", "shasum": "" }, "require": { - "mcp/sdk": "^0.6", + "mcp/sdk": "^0.6|^0.7", "php-http/discovery": "^1.20", "symfony/config": "^7.3|^8.0", "symfony/console": "^7.3|^8.0", @@ -5988,11 +5988,13 @@ "symfony/service-contracts": "^2.5|^3" }, "require-dev": { + "nyholm/psr7": "^1.8", "phpstan/phpstan": "^2.1", "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^11.5.53", - "symfony/monolog-bundle": "^3.10 || ^4.0" + "symfony/monolog-bundle": "^3.10 || ^4.0", + "symfony/twig-bundle": "^7.3|^8.0" }, "type": "symfony-bundle", "extra": { @@ -6022,7 +6024,7 @@ ], "description": "Symfony integration bundle for Model Context Protocol (via official mcp/sdk)", "support": { - "source": "https://github.com/symfony/mcp-bundle/tree/v0.10.0" + "source": "https://github.com/symfony/mcp-bundle/tree/v0.11.0" }, "funding": [ { @@ -6042,7 +6044,7 @@ "type": "tidelift" } ], - "time": "2026-06-15T19:39:32+00:00" + "time": "2026-07-15T00:43:00+00:00" }, { "name": "symfony/monolog-bridge", diff --git a/tests/Mcp/McpHttpEndpointTest.php b/tests/Mcp/McpHttpEndpointTest.php index 892a0b8b4..27534e0f5 100644 --- a/tests/Mcp/McpHttpEndpointTest.php +++ b/tests/Mcp/McpHttpEndpointTest.php @@ -14,6 +14,8 @@ use App\Service\ApiToken\ApiTokenService; use Tests\AbstractWebTestCase; +use const JSON_THROW_ON_ERROR; + /** * Functional tests for the /mcp HTTP endpoint (ADR-021 Phase 5), driving the full * stack — the Bearer-PAT firewall, our McpEndpointController, and the SDK's @@ -44,6 +46,30 @@ public function testDisallowedHostIsForbidden(): void self::assertSame(403, $this->client->getResponse()->getStatusCode()); } + public function testToolsListExposesTheRegisteredTools(): void + { + // The SDK loads its element registry lazily since v0.7.0, so the tools only + // materialise on the first registry read — tools/list, not the handshake. + // The direct tool tests fetch the services from the container and would not + // notice an empty registry here. + $server = $this->mcpServer('localhost'); + $this->client->request('POST', '/mcp', server: $server, content: self::INITIALIZE); + $sessionId = $this->client->getResponse()->headers->get('Mcp-Session-Id'); + self::assertNotNull($sessionId, 'the handshake did not open a session'); + + $server['HTTP_MCP_SESSION_ID'] = $sessionId; + $this->client->request('POST', '/mcp', server: $server, content: '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'); + + $response = $this->client->getResponse(); + self::assertSame(200, $response->getStatusCode()); + + /** @var array{result: array{tools: list}} $payload */ + $payload = json_decode((string) $response->getContent(), true, flags: JSON_THROW_ON_ERROR); + $names = array_column($payload['result']['tools'], 'name'); + self::assertContains('get_day', $names); + self::assertContains('log_time', $names); + } + public function testBogusTokenIsUnauthorized(): void { // A tt_pat_ Bearer is claimed by the stateless api firewall; an invalid one