Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
Symfony MCP Bundle
https://github.com/symfony/mcp-bundle
Admin
A Symfony integration bundle for the Model Context Protocol (MCP) that supports MCP capabilities
...
Tokens:
5,670
Snippets:
32
Trust Score:
9.3
Update:
4 months ago
Context
Skills
Chat
Benchmark
82.4
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# 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 <?php namespace App\Tool; use Mcp\Capability\Attribute\McpTool; use Mcp\Schema\Content\TextContent; class WeatherTool { #[McpTool( name: 'get_weather', description: 'Get current weather for a city', inputSchema: [ 'type' => '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 <?php namespace App\Prompt; use Mcp\Capability\Attribute\McpPrompt; use Mcp\Schema\Prompt\Message; use Mcp\Schema\Prompt\PromptMessage; use Mcp\Schema\Content\TextContent; class CodeReviewPrompt { #[McpPrompt( name: 'code_review', description: 'Generate a code review prompt for given code', arguments: [ [ 'name' => '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 <?php namespace App\Resource; use Mcp\Capability\Attribute\McpResource; use Mcp\Schema\Content\TextContent; class DocumentationResource { #[McpResource( uri: 'docs://api/authentication', name: 'API Authentication Documentation', description: 'Documentation for API authentication methods', mimeType: 'text/plain' )] public function getAuthDocs(): array { $documentation = <<<'DOC' # API Authentication Our API supports two authentication methods: 1. JWT Bearer tokens 2. API Key authentication To authenticate, include the Authorization header: Authorization: Bearer <your-token> 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 <?php namespace App\Resource; use Mcp\Capability\Attribute\McpResourceTemplate; use Mcp\Schema\Content\TextContent; class UserProfileResource { #[McpResourceTemplate( uriTemplate: 'user://{userId}/profile', name: 'User Profile', description: 'Access user profile information by user ID', mimeType: 'application/json' )] public function getUserProfile(string $userId): array { // Fetch user data from database $userData = [ 'id' => $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 <?php namespace App\Mcp\Handler; use Mcp\Server\Handler\Request\RequestHandlerInterface; use Psr\Log\LoggerInterface; class CustomRequestHandler implements RequestHandlerInterface { public function __construct( private LoggerInterface $logger, ) {} public function supportsMethod(string $method): bool { return $method === 'custom/analyze'; } public function handle(string $method, array $params): array { $this->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 <?php namespace App\Mcp\Handler; use Mcp\Server\Handler\Notification\NotificationHandlerInterface; use Psr\Log\LoggerInterface; class ProgressNotificationHandler implements NotificationHandlerInterface { public function __construct( private LoggerInterface $logger, ) {} public function supportsMethod(string $method): bool { return $method === 'notifications/progress'; } public function handle(string $method, array $params): void { $progress = $params['progress'] ?? 0; $message = $params['message'] ?? 'Processing'; $this->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 <?php namespace App\Mcp\Loader; use Mcp\Capability\Registry\Loader\LoaderInterface; use Mcp\Capability\RegistryInterface; use Mcp\Schema\Tool; use Mcp\Schema\Content\TextContent; class DatabaseToolLoader implements LoaderInterface { public function load(RegistryInterface $registry): void { // Dynamically load tools from database $tools = $this->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 <?php // The DataCollector automatically collects capability information // Access it in the Symfony Profiler toolbar under the MCP icon // Programmatic access to collected data: use Symfony\AI\McpBundle\Profiler\DataCollector; class DebugController { public function debug(DataCollector $collector): Response { $tools = $collector->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.