From 9fa5c11364477c5ee6e729df3c7feed4d0540fd0 Mon Sep 17 00:00:00 2001 From: camilleislasse Date: Thu, 13 Nov 2025 08:40:47 +0100 Subject: [PATCH 1/3] Make MonologBundle optional in McpBundle Fixes #830 - Wrap monolog.logger.mcp service creation in class_exists() check - Add ->nullOnInvalid() to setLogger() call - Uniformize logger references in McpCommand and McpController - Update test to skip when MonologBundle is not installed Builds on #849 by @WebMamba --- src/mcp-bundle/config/services.php | 17 +++++++++++------ src/mcp-bundle/src/McpBundle.php | 2 +- .../tests/DependencyInjection/McpBundleTest.php | 5 +++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/mcp-bundle/config/services.php b/src/mcp-bundle/config/services.php index 9f836a81b..ae9e08490 100644 --- a/src/mcp-bundle/config/services.php +++ b/src/mcp-bundle/config/services.php @@ -13,20 +13,25 @@ use Mcp\Server; use Mcp\Server\Builder; +use Symfony\Bundle\MonologBundle\MonologBundle; return static function (ContainerConfigurator $container): void { - $container->services() - ->set('monolog.logger.mcp') - ->parent('monolog.logger_prototype') - ->args(['mcp']) - ->tag('monolog.logger', ['channel' => 'mcp']) + if (class_exists(MonologBundle::class)) { + $container->services() + ->set('monolog.logger.mcp') + ->parent('monolog.logger_prototype') + ->args(['mcp']) + ->tag('monolog.logger', ['channel' => 'mcp']) + ; + } + $container->services() ->set('mcp.server.builder', Builder::class) ->factory([Server::class, 'builder']) ->call('setServerInfo', [param('mcp.app'), param('mcp.version')]) ->call('setPaginationLimit', [param('mcp.pagination_limit')]) ->call('setInstructions', [param('mcp.instructions')]) - ->call('setLogger', [service('monolog.logger.mcp')]) + ->call('setLogger', [service('monolog.logger.mcp')->nullOnInvalid()]) ->call('setEventDispatcher', [service('event_dispatcher')]) ->call('setSession', [service('mcp.session.store')]) ->call('setDiscovery', [param('kernel.project_dir'), param('mcp.discovery.scan_dirs'), param('mcp.discovery.exclude_dirs')]) diff --git a/src/mcp-bundle/src/McpBundle.php b/src/mcp-bundle/src/McpBundle.php index bec84d4fd..25080dddf 100644 --- a/src/mcp-bundle/src/McpBundle.php +++ b/src/mcp-bundle/src/McpBundle.php @@ -114,7 +114,7 @@ private function configureClient(array $transports, array $httpConfig, Container $container->register('mcp.server.command', McpCommand::class) ->setArguments([ new Reference('mcp.server'), - new Reference('logger'), + new Reference('monolog.logger.mcp', ContainerInterface::NULL_ON_INVALID_REFERENCE), ]) ->addTag('console.command'); } diff --git a/src/mcp-bundle/tests/DependencyInjection/McpBundleTest.php b/src/mcp-bundle/tests/DependencyInjection/McpBundleTest.php index 976811ba4..2b456051b 100644 --- a/src/mcp-bundle/tests/DependencyInjection/McpBundleTest.php +++ b/src/mcp-bundle/tests/DependencyInjection/McpBundleTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\AI\McpBundle\McpBundle; +use Symfony\Bundle\MonologBundle\MonologBundle; use Symfony\Component\DependencyInjection\ContainerBuilder; class McpBundleTest extends TestCase @@ -49,6 +50,10 @@ public function testCustomConfiguration() public function testMcpLoggerServiceIsCreated() { + if (!class_exists(MonologBundle::class)) { + $this->markTestSkipped('MonologBundle is not installed'); + } + $container = $this->buildContainer([]); $this->assertTrue($container->hasDefinition('monolog.logger.mcp')); From ecea6d676b4ea9e35ade883bda281ef1d113879d Mon Sep 17 00:00:00 2001 From: camilleislasse Date: Fri, 14 Nov 2025 18:16:40 +0100 Subject: [PATCH 2/3] Conditionally call Builder->setLogger() only when MonologBundle exists, and handle nullable logger in McpCommand/McpController by conditionally passing it to Transports. When MonologBundle is absent, Server and Transports use their default NullLogger. --- src/mcp-bundle/config/services.php | 10 +++++++--- src/mcp-bundle/src/Command/McpCommand.php | 6 ++++-- .../src/Controller/McpController.php | 18 ++++++++++++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/mcp-bundle/config/services.php b/src/mcp-bundle/config/services.php index ae9e08490..9bf56d7e2 100644 --- a/src/mcp-bundle/config/services.php +++ b/src/mcp-bundle/config/services.php @@ -25,17 +25,21 @@ ; } - $container->services() + $builderDefinition = $container->services() ->set('mcp.server.builder', Builder::class) ->factory([Server::class, 'builder']) ->call('setServerInfo', [param('mcp.app'), param('mcp.version')]) ->call('setPaginationLimit', [param('mcp.pagination_limit')]) ->call('setInstructions', [param('mcp.instructions')]) - ->call('setLogger', [service('monolog.logger.mcp')->nullOnInvalid()]) ->call('setEventDispatcher', [service('event_dispatcher')]) ->call('setSession', [service('mcp.session.store')]) - ->call('setDiscovery', [param('kernel.project_dir'), param('mcp.discovery.scan_dirs'), param('mcp.discovery.exclude_dirs')]) + ->call('setDiscovery', [param('kernel.project_dir'), param('mcp.discovery.scan_dirs'), param('mcp.discovery.exclude_dirs')]); + if (class_exists(MonologBundle::class)) { + $builderDefinition->call('setLogger', [service('monolog.logger.mcp')]); + } + + $container->services() ->set('mcp.server', Server::class) ->factory([service('mcp.server.builder'), 'build']) diff --git a/src/mcp-bundle/src/Command/McpCommand.php b/src/mcp-bundle/src/Command/McpCommand.php index f939ffc10..5abf26dff 100644 --- a/src/mcp-bundle/src/Command/McpCommand.php +++ b/src/mcp-bundle/src/Command/McpCommand.php @@ -24,14 +24,16 @@ class McpCommand extends Command { public function __construct( private readonly Server $server, - private readonly LoggerInterface $logger, + private readonly ?LoggerInterface $logger = null, ) { parent::__construct(); } protected function execute(InputInterface $input, OutputInterface $output): int { - $transport = new StdioTransport(logger: $this->logger); + $transport = $this->logger + ? new StdioTransport(logger: $this->logger) + : new StdioTransport(); $this->server->run($transport); return Command::SUCCESS; diff --git a/src/mcp-bundle/src/Controller/McpController.php b/src/mcp-bundle/src/Controller/McpController.php index 54d19df3d..7e5d891f6 100644 --- a/src/mcp-bundle/src/Controller/McpController.php +++ b/src/mcp-bundle/src/Controller/McpController.php @@ -35,12 +35,18 @@ public function __construct( public function handle(Request $request): Response { - $transport = new StreamableHttpTransport( - $this->httpMessageFactory->createRequest($request), - $this->responseFactory, - $this->streamFactory, - logger: $this->logger, - ); + $transport = $this->logger + ? new StreamableHttpTransport( + $this->httpMessageFactory->createRequest($request), + $this->responseFactory, + $this->streamFactory, + logger: $this->logger, + ) + : new StreamableHttpTransport( + $this->httpMessageFactory->createRequest($request), + $this->responseFactory, + $this->streamFactory, + ); return $this->httpFoundationFactory->createResponse( $this->server->run($transport), From a8500cab5c1bd00b6f797f23920c8196cb202ced Mon Sep 17 00:00:00 2001 From: camilleislasse Date: Sat, 15 Nov 2025 09:04:27 +0100 Subject: [PATCH 3/3] Add MonologBundle to require-dev to ensure tests run in CI --- src/mcp-bundle/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mcp-bundle/composer.json b/src/mcp-bundle/composer.json index 2bf13ec11..bf05aa7dc 100644 --- a/src/mcp-bundle/composer.json +++ b/src/mcp-bundle/composer.json @@ -24,7 +24,8 @@ "require-dev": { "phpstan/phpstan": "^2.1", "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^11.5" + "phpunit/phpunit": "^11.5", + "symfony/monolog-bundle": "^3.10" }, "minimum-stability": "dev", "prefer-stable": true,