Brouillon à relire par Paul
Ce texte est un brouillon. Paul Perigault le relira et le réécrira avant publication.
ADR-0003 — Serveur MCP du design system
- Statut : proposé (2026-10-21). Décision pour la version locale ; la version distante est planifiée, non construite.
- Référence : gap.md n° 28 à 30 (IA, L14) ; systems.md, section « Documentation et outillage IA ».
Contexte
Trois systèmes publiés exposent leur design system à un assistant IA par MCP (Model Context Protocol) :
- Primer, avec
@primer/mcp: tokens, composants, motifs. Données embarquées, serveur local (source : README de@primer/mcp0.3.4, cité dans systems.md). - Carbon, avec Carbon MCP : documentation, exemples, audit de code. Serveur hébergé, en aperçu public, avec authentification OAuth (source : carbondesignsystem.com, « Carbon MCP overview »).
- shadcn/ui, avec
shadcn mcp: parcourt tout registre compatible déclaré danscomponents.json(source : ui.shadcn.com/docs/mcp).
Aucun de ces points n’établit que le MCP améliore la qualité du code produit. C’est une convention de distribution : elle rend les règles du système lisibles par un outil, sans preuve de gain mesuré.
Décision maintenant
Nous construisons @paulperigault/mcp, un serveur MCP :
- en transport stdio, lancé localement par l’éditeur ou l’agent ;
- en lecture seule : aucun outil n’écrit de fichier, ne publie, ne modifie de configuration ;
- avec des données embarquées à la publication du paquet : composants, tokens, documentation, décisions. Le serveur n’ouvre aucune connexion réseau à l’exécution ;
- avec des entrées validées par zod, schéma par outil, rejet de tout champ inconnu.
Outils prévus :
list_components: liste des composants publiés, avec leur statut ;get_component: fiche d’un composant (usage, « quand ne pas l’utiliser », accessibilité, propriétés) ;get_tokens: tokens--pp-*par rôle et par thème ;check_contrast: contraste WCAG 2 entre deux couleurs, calculé par@paulperigault/tokens;validate_snippet: analyse statique d’un extrait de code (classes,styleen ligne, valeurs brutes). Le texte est analysé, jamais exécuté ;search_docs: recherche dans la documentation embarquée ;get_decision: lecture d’une ADR par numéro.
Le registre shadcn statique (/r/registry.json, gap n° 29) est publié en parallèle. Il rend
npx shadcn@latest mcp exploitable sans aucun code serveur de notre part.
Sécurité
La surface d’attaque d’un serveur MCP est le contenu qu’il renvoie à un modèle. Règles retenues :
- Injection par le contenu retourné : les réponses sont des données. Toute chaîne issue de la documentation est marquée comme donnée, jamais comme instruction. Un test vérifie qu’un texte contenant une consigne reste inerte.
- Chemins : aucun outil ne reçoit de chemin de fichier libre. Les identifiants passent par une liste blanche générée à la publication.
- Exécution : interdite. Aucune dépendance d’évaluation (
eval,Function, sous-processus).validate_snippetne fait que de l’analyse de texte. - Entrées : zod, longueur maximale par champ, types stricts (pas de
any). - Dépendances : versions exactes, aucune dépendance
file:oulink:(check:lockfile).
Plus tard : version distante (planifiée, non construite)
Aucune ressource n’est créée ni nommée à ce stade. Le plan en cinq étapes :
- Authentification : choisir OAuth 2.1 ou jeton, à trancher par ADR. Aucune route sans authentification.
- Limitation du débit : seuils à définir après mesure ; aucun chiffre n’est retenu aujourd’hui.
- Coût mesuré : requêtes, durée, journaux. Les coûts sont à mesurer sur le fournisseur choisi, non estimés ici.
- Sécurité du transport : CSP, CORS restreint à des origines listées, aucune donnée personnelle journalisée (RGPD par défaut), journal d’audit des appels d’outils sans contenu de requête.
- Infrastructure en OpenTofu, une ADR de plus pour le fournisseur, et un test de charge avant toute mise en service.
Conséquences
- Le serveur local est le seul livrable de cette ADR. Son code suit les limites d’AGENTS.md : fichiers de 120 lignes au plus, un test par brique.
- Les données embarquées peuvent diverger de la documentation publiée. Le contrôle
check:registrybloque la publication si un export n’a pas son fragment. - La version distante reste ouverte : les conditions préalables bloquent sa mise en service, pas sa planification.
Alternatives écartées
- Serveur distant d’emblée : authentification, débit, coût et RGPD à traiter avant la première ligne de code. Trop de surface pour un gain non mesuré.
- Seulement
llms.txt: utile et retenu (gap n° 30), mais sans outils, donc sans validation de contraste ni d’extrait. - Seulement shadcn MCP : ne couvre que les composants shadcn, pas les tokens, la charte ni les décisions.
- Pas de MCP : rien à maintenir, mais aucune interface lisible par un assistant. Les trois systèmes publiés cités plus haut en ont une.
Réserves
- « Prouvé » : rien dans cette ADR ne l’est. Le choix du MCP est une convention observée chez trois systèmes.
- Les délais, les volumes et les coûts ne sont pas connus : ils sont à mesurer.