Backoffice MCP — administration des clients et audit
Contexte : le serveur MCP (
tlr-mcp) est opérationnel. Les tokens sont émis en CLI (app:mcp:seed) mais leur gestion quotidienne (voir qui est actif, révoquer, consulter l'activité) passe par du SQL brut — ce n'est pas tenable. Cette spec couvre la page d'administration qui résout ce problème.
1. Périmètre
Dans la spec :
- Liste des clients MCP actifs/révoqués avec leurs scopes et leur dernière activité
- Révocation et restauration d'un client en un clic
- Log d'audit paginé des appels outils
Hors de la spec :
- Création de token via BO — reste CLI (
app:mcp:seed) ; le token brut ne peut être affiché qu'une fois et de façon sécurisée, le terminal est le bon endroit pour ça - Modification des scopes d'un client existant — cas rare, SQL direct acceptable
- Gestion des tenants et des projets — idem
2. Accès
- Route parente :
/admin/mcp - RĂ´le requis :
ROLE_ADMIN - Entrée dans le menu admin : MCP (sous-section IA ou section dédiée selon l'organisation du menu existant)
3. Vue principale — /admin/mcp
Page unique avec deux blocs verticaux : Clients en haut, Audit en bas.
3.1 Bloc Clients
Tableau listant tous les ApiClient du tenant courant.
| Colonne | Source | Détail |
|---|---|---|
| ID | mcp_api_client.id |
Référence interne |
| Scopes | mcp_api_client.scopes |
Affichés en badges, un par scope |
| Statut | mcp_api_client.revoked |
Badge Actif (vert) ou Révoqué (rouge) |
| Expiration | mcp_api_client.expires_at |
Date ou « Aucune » |
| Dernier appel | MAX(mcp_tool_audit_log.timestamp) WHERE api_client_id |
Date relative (ex. « il y a 2h ») ou « Jamais » |
| Actions | — | Bouton Révoquer (si actif) ou Restaurer (si révoqué) |
Tri par défaut : ID décroissant (plus récent en premier).
Pas de pagination — le nombre de clients restera faible (< 20 sur toute la durée de vie de l'écosystème).
3.2 Bloc Audit
Log des 100 derniers appels tous clients confondus.
| Colonne | Source | Détail |
|---|---|---|
| Date | mcp_tool_audit_log.timestamp |
Format YYYY-MM-DD HH:mm:ss UTC |
| Client | mcp_tool_audit_log.api_client_id |
Lien vers la ligne correspondante du bloc Clients |
| Outil | mcp_tool_audit_log.tool_name |
list_docs, read_doc ou search_docs |
| Statut | mcp_tool_audit_log.status |
Badge success (vert), refused (orange), error (rouge) |
| Code erreur | mcp_tool_audit_log.error_code |
Affiché uniquement si non null — ex. FORBIDDEN_TOOL, RATE_LIMIT |
Tri : timestamp décroissant. Pas de filtre en V1 — le log brut suffit pour un usage d'audit ponctuel.
4. Actions
Révoquer un client
- Bouton Révoquer sur la ligne du client actif
- Confirmation modale : « Révoquer ce client MCP ? Les appels en cours seront rejetés immédiatement. »
- Action :
POST /admin/mcp/clients/{id}/revoke - Effet :
UPDATE mcp_api_client SET revoked = 1 WHERE id = :id - Retour : rechargement de la page, flash de confirmation, ligne passe en statut Révoqué
Restaurer un client
- Bouton Restaurer sur la ligne d'un client révoqué
- Pas de confirmation modale (action réversible)
- Action :
POST /admin/mcp/clients/{id}/restore - Effet :
UPDATE mcp_api_client SET revoked = 0 WHERE id = :id - Retour : rechargement de la page, flash de confirmation, ligne passe en statut Actif
5. Implémentation Symfony
ContrĂ´leur
src/Controller/Admin/McpController.php
Méthodes :
| Méthode | Route | HTTP |
|---|---|---|
index() |
/admin/mcp |
GET |
revoke() |
/admin/mcp/clients/{id}/revoke |
POST |
restore() |
/admin/mcp/clients/{id}/restore |
POST |
Toutes les routes sous l'attribut #[IsGranted('ROLE_ADMIN')].
RequĂŞtes
Clients avec dernier appel :
SELECT c.id, c.scopes, c.revoked, c.expires_at, MAX(l.timestamp) AS last_call FROM mcp_api_client c LEFT JOIN mcp_tool_audit_log l ON l.api_client_id = c.id JOIN mcp_tenant t ON c.tenant_id = t.id WHERE t.name = 'telaria' GROUP BY c.id ORDER BY c.id DESC
En Doctrine, via un QueryBuilder sur ApiClientRepository avec leftJoin sur ToolAuditLog.
Audit récent :
$repo->findBy([], ['timestamp' => 'DESC'], 100)
Template
templates/admin/mcp/index.html.twig
Étend le layout admin existant. Deux sections : <section id="clients"> et <section id="audit">.
6. Ce que ça ne remplace pas
La création d'un nouveau token reste impérativement CLI :
php bin/console app:mcp:seed --tenant="telaria" --project="telaria-doc" \ --root="C:/src/telaria-doc" \ --scopes="tool:list_docs,tool:read_doc,tool:search_docs,project:telaria-doc"
Le BO ne peut pas afficher un token brut de façon sécurisée — le terminal est le seul endroit où ce flux est maîtrisé.
7. Évolutions possibles (hors V1)
- Filtre par outil ou par statut dans le log d'audit
- Pagination du log au-delà de 100 entrées
- Export CSV de l'audit
- Affichage du projet associé au client (jointure
mcp_project)
Références
- Guide mise en service : mcp-mise-en-service.md
- Gouvernance tokens/scopes : mcp-gouvernance-instances.md
- Spec serveur MCP : ia-mcp.md
- Backoffice existant : telaria-admin.md