Serveur MCP¶
Le serveur MCP (security-review-mcp) est le processus des agents IA : il leur fournit les
prompts de revue, les checklists, le scan par motifs et les normes de développement, et
enregistre leurs rapports. Il n'appelle jamais le contrôleur : les deux
partagent la base (voir Architecture).
Ce qu'il sert¶
| Route | Utilisée par | Identifiant |
|---|---|---|
/mcp |
les agents : prompts, outils et ressources | jeton mcp (personnel ou non) ou jeton admin |
/mcp sans jeton |
un agent pas encore connecté : serveur d'enrôlement | aucun |
POST /api/v1/enroll |
security-review-mcp enroll et les scripts : enrôlement |
aucun |
/healthz |
sondes (HEALTHCHECK Docker, Kubernetes) |
aucun |
Il ne sert aucune page web ni aucune autre route de l'API REST.
Deux transports¶
| Transport | Commande | Usage |
|---|---|---|
| HTTP streamable | security-review-mcp serve (défaut de l'image, port 8000) |
mode partagé : tous les agents de l'équipe, avec un jeton |
| stdio | security-review-mcp local |
mode local : lancé par l'hôte sur un poste, base SQLite locale, sans jeton |
Démarrage¶
En HTTP, security-review-mcp serve :
- vérifie le schéma de la base et refuse de démarrer (code
2) tant que le contrôleur ne l'a pas migré : il ne migre jamais (voir Migrations du schéma) ; - vérifie les réglages TLS, charge les règles de la base ;
- sert
/mcp. Tant qu'aucun jeton n'existe, il reste fermé : un client n'atteint que l'enrôlement, sauf si le serveur écoute sur localhost ou avecSECREVIEW_ALLOW_UNAUTHENTICATED=true(voir Jetons Bearer).
En stdio, security-review-mcp local migre lui-même sa base locale.
Ce que reçoit un agent¶
| Client | Réponse |
|---|---|
| Sans jeton | le serveur d'enrôlement : request_enrollment et des prompts qui expliquent comment obtenir un jeton ; 401 avec SECREVIEW_ENROLLMENT=false |
| Jeton inconnu, révoqué ou expiré | 401 qui indique à l'utilisateur où créer un nouveau jeton (jeton refusé) |
Jeton mcp ou admin valide |
tous les prompts, outils et ressources, sur les projets du jeton (jetons restreints à un projet) |
Les jetons et les règles sont lus en base : un jeton créé ou révoqué sur le contrôleur s'applique à la requête suivante, une règle modifiée en 5 secondes.
Ce qu'il ne fait jamais¶
- Il ne fait aucune connexion sortante (la base OSV est importée par le contrôleur), et ne charge aucun module du contrôleur.
- Ses outils ne lisent jamais le disque à partir d'un chemin donné par le client : ils travaillent sur le contenu transmis.
- Toute entrée est bornée (
SECREVIEW_MAX_CONTENT_CHARS,SECREVIEW_MAX_FINDINGS_PER_REPORT,SECREVIEW_MAX_MCP_REQUEST_MB, 64 Kio pour un client sans jeton), et les secrets sont masqués avant stockage. - Il ne change jamais le statut d'un finding :
propose_finding_statusenregistre seulement une proposition, qu'une personne valide dans l'interface web. - En stdio, stdout est réservé au protocole MCP : les journaux vont sur stderr.
Voir Sécurité et limites.
Exposition et réplicas¶
Exposez le serveur MCP avec TLS (intégré ou reverse proxy) aux postes des
développeurs. Derrière un reverse proxy ou un Ingress, réglez SECREVIEW_FORWARDED_ALLOW_IPS,
sinon tous les clients partagent l'adresse du proxy pour les limites d'enrôlement.
Les sessions MCP (HTTP streamable) vivent dans la mémoire du processus qui les a ouvertes : avant
de lancer plusieurs réplicas, envoyez toutes les requêtes d'une session au même réplica
(affinité sur l'en-tête Mcp-Session-Id, voir Kubernetes).
Les variables du serveur MCP : Configuration. Ses
commandes (serve, local, enroll) : Ligne de commande.
Enrôlement : demander le projet¶
L'enrôlement ne crée jamais de jeton : il demande le projet, qu'un administrateur valide, et
le développeur crée un jeton MCP personnel dans l'interface web. Il est activé par défaut
(SECREVIEW_ENROLLMENT=true), même avant la création du premier jeton (sauf sur un
serveur ouvert, qui n'a pas besoin de jeton).
-
Demande. Le client donne le nom de son projet (en général le nom du dépôt). Un nouveau projet est en attente : ce n'est pas encore un projet et il ne donne aucun accès. Un projet qui existe déjà, ou déjà en attente, reste inchangé, et la réponse est la même dans tous les cas, pour ne pas révéler quels projets existent. Trois façons de s'enrôler :
- Depuis l'agent, à la première revue. Un client MCP qui se connecte sans en-tête
Authorizationn'est pas rejeté : il atteint un serveur MCP restreint (même nomsecurity-review) qui n'expose que l'outilrequest_enrollment, et des prompts nommés comme les revues (security-review,codebase-review…) qui expliquent la marche à suivre. L'agent appellerequest_enrollmentavec le nom du projet. -
En ligne de commande, depuis le poste du développeur ou la CI :
security-review-mcp enroll --url https://secreview.example.internal:8443 \ --project shop-api --requested-by "alice (équipe shop)" # {"project": "shop-api", "web_url": "https://secreview.example.internal/ui", "next_steps": "…"} -
Par l'API du serveur MCP :
POST /api/v1/enroll(sans jeton) avec{"project": "shop-api"}, qui répond202. Le contrôleur ne sert pas cet endpoint : il n'expose aucune route d'écriture non authentifiée. - Validation. Un utilisateur qui porte
projects.create(entre autres le rôleadmin) valide ou refuse la demande dans la section Projets en attente de l'écran Projets, ou en CLI :
security-review-controller project list # demandeur, adresse, expiration security-review-controller project approve 3 # id de la liste security-review-controller project reject 4La validation crée le projet, avec son groupe
project:<projet>sans aucun membre : personne n'obtient d'accès, pas même le validateur. Une demande que personne n'a validée sousSECREVIEW_PROJECT_ENROLLMENT_TTL_DAYS(7 jours par défaut) est supprimée. 3. Jeton personnel. La réponse de l'enrôlement donne l'URL de l'interface web (web_url, issue deSECREVIEW_WEB_URL) et la marche à suivre : l'utilisateur se connecte, crée un jeton MCP personnel dans Mon compte (voir jetons MCP personnels) et le place dans la configuration de l'hôte. Le jeton atteint les projets que l'utilisateur peut lire, relus à chaque requête. 4. Accès. Un administrateur donne à l'utilisateur l'accès au projet en l'ajoutant au groupeproject:<projet>(écran Groupes, voir contrôle d'accès) ; le jeton personnel atteint le projet dès la requête suivante, sans reconfiguration. - Depuis l'agent, à la première revue. Un client MCP qui se connecte sans en-tête
Un agent qui a déjà un jeton peut aussi appeler request_enrollment (par exemple quand
save_security_report refuse un projet que son jeton n'atteint pas) : le projet est demandé de
la même façon, et le jeton ne gagne aucun projet. Un utilisateur portant projects.create qui
crée le projet lui-même solde sa demande en attente.
Jeton refusé : se reconnecter¶
Un client dont le jeton est inconnu, révoqué ou expiré reçoit 401 sur /mcp
(error="invalid_token") : la description invite l'utilisateur à se connecter à l'interface web
(avec son URL quand SECREVIEW_WEB_URL est défini) et à créer un nouveau jeton MCP personnel,
puis à le remplacer dans la configuration de l'hôte.
Un tel client n'atteint jamais les outils de revue ni le serveur d'enrôlement. Le refus est
journalisé en avertissement par le serveur MCP (Rejected unauthenticated request /
Rejected expired token).
Garde-fous : quiconque atteint le serveur peut s'enrôler, donc au plus 20 projets sont en
attente à la fois, une adresse cliente s'enrôle au plus 5 fois par heure (429 au-delà ;
derrière un reverse proxy, définissez
SECREVIEW_FORWARDED_ALLOW_IPS), et un projet en attente
expire après SECREVIEW_PROJECT_ENROLLMENT_TTL_DAYS. Chaque demande, validation, refus et
expiration est écrit dans le journal d'audit
(enrollment.requested, enrollment.approved, enrollment.rejected, avec le demandeur et
l'adresse cliente). Pour désactiver l'enrôlement :
SECREVIEW_ENROLLMENT=false (les clients sans jeton reçoivent alors 401, avec le même conseil).
--url est l'URL du serveur MCP (avec ou sans /mcp) : c'est lui qui reçoit les demandes.