Symfony MCP Bundle : Intégrez le Model Context Protocol dans vos applications
Découvrez comment le Symfony MCP Bundle permet d'intégrer facilement le Model Context Protocol d'Anthropic dans vos applications Symfony pour créer des agents IA intelligents et contextuels.
Qu'est-ce que le Model Context Protocol (MCP) ?
Le Model Context Protocol est un standard ouvert développé par Anthropic pour permettre aux applications IA d'accéder de manière sécurisée et structurée à des contextes externes : bases de données, APIs, systèmes de fichiers, outils métier, etc.
🤖 En résumé : MCP permet à Claude (et autres LLM) d'interagir avec vos données et systèmes de manière contrôlée, sans exposer directement vos credentials ou votre logique métier.
Le Symfony MCP Bundle simplifie l'intégration de ce protocole dans vos applications Symfony, vous permettant de créer des serveurs MCP personnalisés en quelques lignes de code.
Installation et configuration
Installation via Composer
composer require anthropic/symfony-mcp-bundle
# Si ce n'est pas fait automatiquement
php bin/console mcp:install
Configuration de base
Créez le fichier de configuration config/packages/mcp.yaml :
mcp:
# Nom de votre serveur MCP
server_name: "my-symfony-app"
# Version du protocole
protocol_version: "2024-11-05"
# Configuration des transports
transports:
stdio:
enabled: true
sse:
enabled: true
path: /mcp/events
# Sécurité
security:
enabled: true
api_keys:
- "%env(MCP_API_KEY)%"
Créer votre premier outil MCP
1. Définir un outil avec l'attribut PHP
Les outils MCP sont de simples services Symfony annotés :
namespace App\Mcp\Tool;
use Anthropic\Mcp\Attribute\McpTool;
use Anthropic\Mcp\Attribute\McpParameter;
class UserSearchTool
{
public function __construct(
private UserRepository $userRepository
) {}
#[McpTool(
name: 'search_users',
description: 'Recherche des utilisateurs par email ou nom'
)]
public function search(
#[McpParameter(
description: 'Terme de recherche',
required: true
)]
string $query,
#[McpParameter(
description: 'Nombre maximum de résultats',
required: false,
default: 10
)]
int $limit = 10
): array {
$users = $this->userRepository->search($query, $limit);
return array_map(fn($user) => [
'id' => $user->getId(),
'email' => $user->getEmail(),
'name' => $user->getFullName(),
'created_at' => $user->getCreatedAt()->format('Y-m-d'),
], $users);
}
}
2. Enregistrer l'outil
Si vous utilisez l'autoconfiguration Symfony (par défaut), c'est automatique ! Sinon :
# config/services.yaml
services:
App\Mcp\Tool\UserSearchTool:
tags: ['mcp.tool']
Types d'outils disponibles
Outils de lecture de données
#[McpTool(
name: 'get_order_details',
description: 'Récupère les détails d\'une commande'
)]
public function getOrderDetails(
#[McpParameter(description: 'ID de la commande')]
int $orderId
): array {
$order = $this->orderRepository->find($orderId);
if (!$order) {
throw new McpToolException("Commande #{$orderId} introuvable");
}
return [
'id' => $order->getId(),
'customer' => [
'name' => $order->getCustomer()->getName(),
'email' => $order->getCustomer()->getEmail(),
],
'items' => array_map(fn($item) => [
'product' => $item->getProduct()->getName(),
'quantity' => $item->getQuantity(),
'price' => $item->getPrice(),
], $order->getItems()->toArray()),
'total' => $order->getTotal(),
'status' => $order->getStatus()->value,
];
}
Outils d'écriture avec validation
#[McpTool(
name: 'create_support_ticket',
description: 'Crée un ticket de support client'
)]
public function createTicket(
#[McpParameter(description: 'Email du client')]
string $email,
#[McpParameter(description: 'Sujet du ticket')]
string $subject,
#[McpParameter(description: 'Description du problème')]
string $description,
#[McpParameter(
description: 'Priorité',
enum: ['low', 'medium', 'high', 'urgent']
)]
string $priority = 'medium'
): array {
// Validation
$user = $this->userRepository->findByEmail($email);
if (!$user) {
throw new McpToolException("Utilisateur avec email {$email} introuvable");
}
// Création
$ticket = new SupportTicket();
$ticket->setUser($user);
$ticket->setSubject($subject);
$ticket->setDescription($description);
$ticket->setPriority(Priority::from($priority));
$ticket->setStatus(TicketStatus::OPEN);
$this->entityManager->persist($ticket);
$this->entityManager->flush();
// Notification
$this->notificationService->notifySupportTeam($ticket);
return [
'ticket_id' => $ticket->getId(),
'reference' => $ticket->getReference(),
'status' => 'created',
'message' => 'Ticket créé avec succès',
];
}
Resources : Exposer des données contextuelles
Les resources permettent d'exposer des données que l'IA peut lire pour comprendre le contexte :
namespace App\Mcp\Resource;
use Anthropic\Mcp\Attribute\McpResource;
class ProductCatalogResource
{
public function __construct(
private ProductRepository $productRepository
) {}
#[McpResource(
uri: 'catalog://products',
name: 'Product Catalog',
description: 'Liste complète des produits disponibles',
mimeType: 'application/json'
)]
public function getProducts(): array {
$products = $this->productRepository->findAvailable();
return [
'total' => count($products),
'products' => array_map(fn($p) => [
'id' => $p->getId(),
'name' => $p->getName(),
'price' => $p->getPrice(),
'stock' => $p->getStock(),
'category' => $p->getCategory()->getName(),
], $products)
];
}
#[McpResource(
uri: 'catalog://product/{id}',
name: 'Product Details',
description: 'Détails complets d\'un produit spécifique'
)]
public function getProductDetails(int $id): array {
$product = $this->productRepository->find($id);
return [
'id' => $product->getId(),
'name' => $product->getName(),
'description' => $product->getDescription(),
'price' => $product->getPrice(),
'reviews' => array_map(fn($r) => [
'rating' => $r->getRating(),
'comment' => $r->getComment(),
'author' => $r->getAuthor()->getName(),
], $product->getReviews()->toArray()),
];
}
}
Prompts : Templates réutilisables
Créez des templates de prompts que l'IA peut utiliser :
namespace App\Mcp\Prompt;
use Anthropic\Mcp\Attribute\McpPrompt;
use Anthropic\Mcp\Attribute\McpPromptArgument;
class CustomerServicePrompts
{
#[McpPrompt(
name: 'respond_to_complaint',
description: 'Générer une réponse professionnelle à une réclamation client'
)]
public function respondToComplaint(
#[McpPromptArgument(description: 'Réclamation du client')]
string $complaint,
#[McpPromptArgument(description: 'Contexte de la commande')]
array $orderContext
): string {
return <<
Sécurité et permissions
1. Authentication avec API Keys
# .env
MCP_API_KEY=mcp_sk_1234567890abcdef
# config/packages/mcp.yaml
mcp:
security:
enabled: true
api_keys:
- "%env(MCP_API_KEY)%"
2. Permissions par outil
#[McpTool(
name: 'delete_user',
description: 'Supprime un utilisateur',
permissions: ['ROLE_ADMIN']
)]
public function deleteUser(int $userId): array {
$this->denyAccessUnlessGranted('ROLE_ADMIN');
// Logique de suppression
}
3. Rate limiting
mcp:
rate_limiting:
enabled: true
requests_per_minute: 60
burst: 10
Tests automatisés
namespace App\Tests\Mcp;
use Anthropic\Mcp\Test\McpTestCase;
class UserSearchToolTest extends McpTestCase
{
public function testSearchUsers(): void
{
$client = $this->createMcpClient();
// Appeler l'outil
$response = $client->callTool('search_users', [
'query' => 'john',
'limit' => 5,
]);
// Assertions
$this->assertCount(5, $response['content']);
$this->assertArrayHasKey('id', $response['content'][0]);
$this->assertArrayHasKey('email', $response['content'][0]);
}
public function testSearchUsersWithInvalidQuery(): void
{
$client = $this->createMcpClient();
$this->expectException(McpToolException::class);
$client->callTool('search_users', [
'query' => '', // Query vide
]);
}
}
Monitoring et logging
Le bundle intègre automatiquement le logging des opérations MCP :
mcp:
logging:
enabled: true
channel: 'mcp'
level: 'info'
metrics:
enabled: true
provider: 'prometheus'
Exemple de logs
[2024-01-15 10:23:45] mcp.INFO: Tool called []
{"tool": "search_users", "params": {"query": "john"}, "duration_ms": 45}
[2024-01-15 10:23:50] mcp.INFO: Resource accessed []
{"uri": "catalog://products", "duration_ms": 120}
[2024-01-15 10:24:10] mcp.ERROR: Tool execution failed []
{"tool": "create_ticket", "error": "User not found"}
Architecture complète d'un projet
src/
├── Mcp/
│ ├── Tool/ # Outils MCP
│ │ ├── UserSearchTool.php
│ │ ├── OrderManagementTool.php
│ │ └── SupportTicketTool.php
│ │
│ ├── Resource/ # Resources MCP
│ │ ├── ProductCatalogResource.php
│ │ └── DocumentationResource.php
│ │
│ ├── Prompt/ # Templates de prompts
│ │ └── CustomerServicePrompts.php
│ │
│ └── Security/ # Sécurité custom
│ └── McpVoter.php
│
├── Controller/
│ └── McpController.php # Endpoints HTTP
│
└── EventSubscriber/
└── McpEventSubscriber.php # Événements MCP
Cas d'usage réels
| Secteur | Use Case | Outils MCP |
|---|---|---|
| E-commerce | Assistant d'achat IA | Recherche produits, Gestion panier, Suivi commande |
| Support client | Chatbot intelligent | Base de connaissances, Création tickets, Historique client |
| RH | Assistant recrutement | Recherche candidats, Analyse CV, Planification entretiens |
| Finance | Analyse financière | Extraction données, Calculs, Génération rapports |
Déploiement en production
Configuration Nginx
location /mcp/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# SSE support
proxy_buffering off;
proxy_cache off;
}
Docker Compose
version: '3.8'
services:
app:
build: .
environment:
MCP_API_KEY: ${MCP_API_KEY}
DATABASE_URL: ${DATABASE_URL}
ports:
- "8000:8000"
volumes:
- ./:/app
command: php bin/console server:run 0.0.0.0:8000
Avantages du Symfony MCP Bundle
- ✅ Intégration native avec l'écosystème Symfony
- ✅ Type-safe grâce aux attributs PHP 8
- ✅ Sécurité intégrée avec authentication et permissions
- ✅ Testabilité avec des outils de test dédiés
- ✅ Performance optimisée avec cache et async
- ✅ Monitoring complet avec metrics et logs
💡 Conseil : Commencez petit avec 2-3 outils simples, testez-les bien, puis étendez progressivement vos capacités MCP. La clé est d'avoir des outils fiables et bien documentés.
Ressources et communauté
Pour aller plus loin :
- Repository GitHub officiel
- Spécification MCP
- Documentation Symfony Bundles
- Rejoignez le #mcp channel sur le Slack Symfony
Conclusion
Le Symfony MCP Bundle ouvre des possibilités infinies pour intégrer l'intelligence artificielle dans vos applications Symfony de manière structurée et sécurisée. Que vous créiez un chatbot, un assistant virtuel ou un système d'automatisation, MCP fournit le cadre idéal pour exposer vos données et logique métier à des modèles de langage.
La combinaison de la robustesse de Symfony et de la puissance de Claude via MCP permet de construire des applications IA de niveau professionnel, prêtes pour la production.