# Symfony MCP Bundle The Symfony MCP Bundle provides integration between Symfony applications and the Model Context Protocol (MCP), enabling applications to expose AI capabilities through a standardized protocol. This bundle wraps the official PHP MCP SDK and provides a Symfony-native way to define and expose tools, prompts, resources, and resource templates to MCP clients. It is an experimental feature designed to make Symfony applications AI-ready by providing a server implementation that can communicate with AI models and agents. The bundle supports two transport mechanisms: STDIO for command-line interactions and HTTP for web-based connections. It includes automatic discovery of MCP capabilities through PHP attributes, dependency injection integration for service management, session handling for stateful interactions, and a Symfony Profiler integration for debugging. The bundle handles all the complexity of protocol implementation, allowing developers to focus on defining their AI capabilities using simple PHP attributes and methods. ## Bundle Installation and Configuration Install the bundle via Composer and configure transport options, discovery settings, and server metadata. ```bash composer require symfony/mcp-bundle ``` ```yaml # config/packages/mcp.yaml mcp: app: 'my-mcp-app' version: '1.0.0' pagination_limit: 50 instructions: 'This server provides weather and calendar tools' # Enable transports client_transports: stdio: true http: true # HTTP transport configuration http: path: '/_mcp' session: store: 'file' # or 'memory' directory: '%kernel.cache_dir%/mcp-sessions' ttl: 3600 # Capability discovery discovery: scan_dirs: ['src', 'lib'] exclude_dirs: ['src/DataFixtures', 'tests'] ``` ## MCP Tool Definition Define AI-callable tools using the McpTool attribute to expose functions that can be executed by AI models. ```php 'object', 'properties' => [ 'city' => [ 'type' => 'string', 'description' => 'City name', ], 'units' => [ 'type' => 'string', 'enum' => ['celsius', 'fahrenheit'], 'description' => 'Temperature units', 'default' => 'celsius', ], ], 'required' => ['city'], ] )] public function getWeather(string $city, string $units = 'celsius'): array { // Fetch weather data $temperature = 22; $condition = 'sunny'; return [ new TextContent( text: "Weather in {$city}: {$temperature}°" . ($units === 'celsius' ? 'C' : 'F') . ", {$condition}" ), ]; } } ``` ## MCP Prompt Definition Create reusable prompt templates that AI models can invoke with dynamic arguments. ```php 'language', 'description' => 'Programming language', 'required' => true, ], [ 'name' => 'code', 'description' => 'Code to review', 'required' => true, ], [ 'name' => 'focus', 'description' => 'Review focus area', 'required' => false, ], ] )] public function codeReview(string $language, string $code, ?string $focus = null): PromptMessage { $focusText = $focus ? " Focus on: {$focus}." : ''; return new PromptMessage( messages: [ new Message( role: 'user', content: new TextContent( text: "Please review this {$language} code:{$focusText}\n\n```{$language}\n{$code}\n```" ) ), ], description: "Code review prompt for {$language} code" ); } } ``` ## MCP Resource Definition Expose static or dynamic resources that AI models can read and reference. ```php DOC; return [ new TextContent(text: $documentation), ]; } #[McpResource( uri: 'docs://api/rate-limits', name: 'Rate Limiting Information', description: 'API rate limit policies', mimeType: 'application/json' )] public function getRateLimitInfo(): array { return [ new TextContent( text: json_encode([ 'free_tier' => 100, 'pro_tier' => 1000, 'enterprise' => 'unlimited', 'window' => '1 hour', ]) ), ]; } } ``` ## MCP Resource Template Definition Create URI templates for dynamic resource access with parameterized URIs. ```php $userId, 'username' => 'john_doe', 'email' => 'john@example.com', 'created_at' => '2024-01-15', ]; return [ new TextContent(text: json_encode($userData)), ]; } #[McpResourceTemplate( uriTemplate: 'logs://{service}/{date}', name: 'Service Logs', description: 'Access service logs by service name and date', mimeType: 'text/plain' )] public function getServiceLogs(string $service, string $date): array { // Fetch logs from log storage $logs = "[$date] Service: $service\n" . "[10:00] INFO: Service started\n" . "[10:05] DEBUG: Processing request\n" . "[10:10] INFO: Request completed"; return [ new TextContent(text: $logs), ]; } } ``` ## STDIO Server Command Start the MCP server using STDIO transport for command-line interactions with AI clients. ```bash # Start STDIO MCP server php bin/console mcp:server # The server will communicate via standard input/output # Typically used by desktop AI applications or Claude CLI # Example output: # [INFO] MCP Server started # [INFO] Listening on STDIO # [INFO] Available capabilities: 5 tools, 3 prompts, 2 resources ``` ## HTTP Server Endpoint The HTTP transport automatically creates a route for MCP client connections over HTTP. ```bash # The endpoint is available at the configured path (default: /_mcp) curl -X POST http://localhost:8000/_mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "tools/list", "id": 1 }' # Response: # { # "jsonrpc": "2.0", # "result": { # "tools": [ # { # "name": "get_weather", # "description": "Get current weather for a city", # "inputSchema": { # "type": "object", # "properties": { # "city": {"type": "string"} # } # } # } # ] # }, # "id": 1 # } # Call a tool via HTTP curl -X POST http://localhost:8000/_mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "get_weather", "arguments": {"city": "Paris", "units": "celsius"} }, "id": 2 }' ``` ## Custom Request Handler Implement custom request handlers to extend MCP protocol capabilities. ```php logger->info('Handling custom analyze request', $params); // Perform custom analysis $input = $params['input'] ?? ''; $analysis = [ 'length' => strlen($input), 'words' => str_word_count($input), 'sentiment' => 'neutral', ]; return [ 'result' => $analysis, 'timestamp' => time(), ]; } } ``` ## Custom Notification Handler Create notification handlers to respond to client-sent notifications. ```php logger->info('Progress notification received', [ 'progress' => $progress, 'message' => $message, ]); // Handle progress update (e.g., update cache, notify websockets) } } ``` ## Custom Capability Loader Implement custom loaders for programmatic capability registration beyond attribute discovery. ```php fetchToolsFromDatabase(); foreach ($tools as $toolData) { $tool = new Tool( name: $toolData['name'], description: $toolData['description'], inputSchema: json_decode($toolData['schema'], true) ); $registry->registerTool( $tool, fn(array $args) => $this->executeTool($toolData['id'], $args), isManual: true ); } } private function fetchToolsFromDatabase(): array { // Fetch from database return [ [ 'id' => 1, 'name' => 'query_database', 'description' => 'Execute database queries', 'schema' => '{"type":"object","properties":{"query":{"type":"string"}}}', ], ]; } private function executeTool(int $toolId, array $args): array { // Execute tool logic return [new TextContent(text: 'Query executed')]; } } ``` ## Profiler Integration The bundle provides Symfony Profiler integration for debugging MCP capabilities in development mode. ```php getTools(); // [ // ['name' => 'get_weather', 'description' => '...', 'inputSchema' => [...]] // ] $prompts = $collector->getPrompts(); $resources = $collector->getResources(); $templates = $collector->getResourceTemplates(); $totalCount = $collector->getTotalCount(); return $this->json([ 'tools' => count($tools), 'prompts' => count($prompts), 'resources' => count($resources), 'templates' => count($templates), 'total' => $totalCount, ]); } } ``` ## Summary The Symfony MCP Bundle enables Symfony applications to serve as MCP servers, exposing AI capabilities through tools, prompts, resources, and resource templates. The bundle's primary use cases include building AI-powered APIs that expose business logic to AI models, creating documentation and knowledge bases that AI agents can query, implementing custom AI assistants with domain-specific capabilities, and integrating Symfony applications into AI agent workflows. The attribute-based capability definition makes it simple to annotate existing methods, while the automatic discovery mechanism eliminates boilerplate configuration. Integration patterns include embedding the MCP server directly in Symfony applications using HTTP transport for web-based AI interactions, running standalone MCP servers via STDIO for desktop AI applications and CLI tools, combining both transports to support multiple client types simultaneously, and extending the protocol with custom handlers for specialized use cases. The bundle's dependency injection integration ensures all capabilities have access to Symfony services like databases, caches, and external APIs. Session management supports stateful interactions, while the profiler integration provides visibility into registered capabilities during development. The bundle bridges Symfony's powerful web framework with the emerging ecosystem of AI agents and models through standardized protocol implementation.