diff --git a/demo/config/services.yaml b/demo/config/services.yaml index c7b0bc68..8ba8eec0 100644 --- a/demo/config/services.yaml +++ b/demo/config/services.yaml @@ -19,10 +19,10 @@ services: - '../src/Entity/' - '../src/Kernel.php' - Symfony\AI\McpSdk\Capability\Tool\ToolExecutorInterface: + mcp.tool_executor: class: Symfony\AI\McpSdk\Capability\ToolChain arguments: - ['@App\MCP\Tools\CurrentTimeTool'] - Symfony\AI\McpSdk\Capability\Tool\CollectionInterface: - alias: Symfony\AI\McpSdk\Capability\Tool\ToolExecutorInterface + mcp.tool_collection: + alias: mcp.tool_executor diff --git a/src/mcp-bundle/config/services.php b/src/mcp-bundle/config/services.php index 2ce8fadb..96130e0a 100644 --- a/src/mcp-bundle/config/services.php +++ b/src/mcp-bundle/config/services.php @@ -15,46 +15,55 @@ use Symfony\AI\McpSdk\Server; use Symfony\AI\McpSdk\Server\JsonRpcHandler; use Symfony\AI\McpSdk\Server\NotificationHandler\InitializedHandler; -use Symfony\AI\McpSdk\Server\NotificationHandlerInterface; use Symfony\AI\McpSdk\Server\RequestHandler\InitializeHandler; use Symfony\AI\McpSdk\Server\RequestHandler\PingHandler; use Symfony\AI\McpSdk\Server\RequestHandler\ToolCallHandler; use Symfony\AI\McpSdk\Server\RequestHandler\ToolListHandler; -use Symfony\AI\McpSdk\Server\RequestHandlerInterface; use Symfony\AI\McpSdk\Server\Transport\Sse\Store\CachePoolStore; return static function (ContainerConfigurator $container): void { $container->services() - ->defaults() - ->autowire() - ->autoconfigure() - ->instanceof(NotificationHandlerInterface::class) + ->set('mcp.server.notification_handler.initialized', InitializedHandler::class) + ->args([]) ->tag('mcp.server.notification_handler') - ->instanceof(RequestHandlerInterface::class) + ->set('mcp.server.request_handler.initialize', InitializeHandler::class) + ->args([ + param('mcp.app'), + param('mcp.version'), + ]) ->tag('mcp.server.request_handler') - - ->set(InitializedHandler::class) - ->set(InitializeHandler::class) - ->args([ - '$name' => param('mcp.app'), - '$version' => param('mcp.version'), - ]) - ->set(PingHandler::class) - ->set(ToolCallHandler::class) - ->set(ToolListHandler::class) + ->set('mcp.server.request_handler.ping', PingHandler::class) + ->args([]) + ->tag('mcp.server.request_handler') + ->set('mcp.server.request_handler.tool_call', ToolCallHandler::class) + ->args([ + service('mcp.tool_executor'), + ]) + ->tag('mcp.server.request_handler') + ->set('mcp.server.request_handler.tool_list', ToolListHandler::class) + ->args([ + service('mcp.tool_collection'), + 20, + ]) ->set('mcp.message_factory', Factory::class) + ->args([]) ->set('mcp.server.json_rpc', JsonRpcHandler::class) ->args([ - '$messageFactory' => service('mcp.message_factory'), - '$requestHandlers' => tagged_iterator('mcp.server.request_handler'), - '$notificationHandlers' => tagged_iterator('mcp.server.notification_handler'), + service('mcp.message_factory'), + tagged_iterator('mcp.server.request_handler'), + tagged_iterator('mcp.server.notification_handler'), + service('logger')->ignoreOnInvalid(), ]) ->set('mcp.server', Server::class) ->args([ - '$jsonRpcHandler' => service('mcp.server.json_rpc'), + service('mcp.server.json_rpc'), + service('logger')->ignoreOnInvalid(), ]) ->alias(Server::class, 'mcp.server') - ->set(CachePoolStore::class) + ->set('mcp.server.sse.store.cache_pool', CachePoolStore::class) + ->args([ + service('cache.app'), + ]) ; }; diff --git a/src/mcp-bundle/src/McpBundle.php b/src/mcp-bundle/src/McpBundle.php index 44a11c49..f8eb4ce0 100644 --- a/src/mcp-bundle/src/McpBundle.php +++ b/src/mcp-bundle/src/McpBundle.php @@ -14,9 +14,12 @@ use Symfony\AI\McpBundle\Command\McpCommand; use Symfony\AI\McpBundle\Controller\McpController; use Symfony\AI\McpBundle\Routing\RouteLoader; +use Symfony\AI\McpSdk\Server\NotificationHandlerInterface; +use Symfony\AI\McpSdk\Server\RequestHandlerInterface; use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Bundle\AbstractBundle; final class McpBundle extends AbstractBundle @@ -50,21 +53,32 @@ private function configureClient(array $transports, ContainerBuilder $container) return; } + $container->registerForAutoconfiguration(NotificationHandlerInterface::class) + ->addTag('mcp.server.notification_handler'); + $container->registerForAutoconfiguration(RequestHandlerInterface::class) + ->addTag('mcp.server.request_handler'); + if ($transports['stdio']) { $container->register('mcp.server.command', McpCommand::class) - ->setAutowired(true) + ->setArguments([ + new Reference('mcp.server'), + ]) ->addTag('console.command'); } if ($transports['sse']) { $container->register('mcp.server.controller', McpController::class) - ->setAutowired(true) + ->setArguments([ + new Reference('mcp.server'), + new Reference('mcp.server.sse.store.cache_pool'), + new Reference('router'), + ]) ->setPublic(true) ->addTag('controller.service_arguments'); } $container->register('mcp.server.route_loader', RouteLoader::class) - ->setArgument('$sseTransportEnabled', $transports['sse']) + ->setArgument(0, $transports['sse']) ->addTag('routing.route_loader'); } } diff --git a/src/mcp-sdk/src/Server/JsonRpcHandler.php b/src/mcp-sdk/src/Server/JsonRpcHandler.php index 8278e3b5..76d84a18 100644 --- a/src/mcp-sdk/src/Server/JsonRpcHandler.php +++ b/src/mcp-sdk/src/Server/JsonRpcHandler.php @@ -12,6 +12,7 @@ namespace Symfony\AI\McpSdk\Server; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use Symfony\AI\McpSdk\Exception\ExceptionInterface; use Symfony\AI\McpSdk\Exception\HandlerNotFoundException; use Symfony\AI\McpSdk\Exception\InvalidInputMessageException; @@ -45,7 +46,7 @@ public function __construct( private Factory $messageFactory, iterable $requestHandlers, iterable $notificationHandlers, - private LoggerInterface $logger, + private LoggerInterface $logger = new NullLogger(), ) { $this->requestHandlers = $requestHandlers instanceof \Traversable ? iterator_to_array($requestHandlers) : $requestHandlers; $this->notificationHandlers = $notificationHandlers instanceof \Traversable ? iterator_to_array($notificationHandlers) : $notificationHandlers;