Authentification, RBAC et limites
Une connexion MCP est un acteur authentifié qui interroge vos données, et elle est traitée comme tel. Il n'existe aucune dérogation propre à l'IA sur ce chemin : un appel d'outil passe par les mêmes permissions de rôle et les mêmes règles au niveau ligne que la requête HTTP équivalente d'une session humaine.
Deux identifiants, choisis par l'en-tête
Il n'y a aucune stratégie à configurer. /mcp détermine le vérificateur à partir de l'en-tête que la requête présente réellement : les deux identifiants sont donc actifs en même temps — un utilisateur de Claude Desktop en OAuth et un job de CI porteur d'une clé d'API appellent la même instance, sans qu'aucun ne doive être activé.
| En-tête | Vérifié comme | Idéal pour |
|---|---|---|
x-api-key |
Une clé d'API en libre-service. | Scripts, jobs de CI, tout ce qui est automatisé. |
Authorization: Bearer |
Un jeton d'accès OAuth 2.1, vérifié en amont. | Clients de bureau et IDE capables de se connecter. |
Comme l'aiguillage se décide par requête, il n'existe aucune chaîne de repli dans laquelle l'échec d'un vérificateur masquerait silencieusement l'autre.
Les deux identifiants viennent de la couche d'authentification : MCP_ENABLED=true exige donc app.auth. Une application sans bloc d'authentification ne donne à personne un moyen d'entrer, et le démarrage refuse plutôt que de monter une route soit inaccessible, soit sans garde. Une requête sans aucun identifiant reçoit un 401 accompagné d'un défi WWW-Authenticate: Bearer conforme à la RFC 9728, de sorte qu'un client conforme peut engager le flux OAuth sans qu'on le lui explique.
Chaque appelant est un utilisateur
C'est le changement de fond, pas une simple question de vocabulaire. Les deux identifiants désignent un utilisateur réel, et le rôle de cet utilisateur est résolu en direct à chaque appel :
- Rétrogradez quelqu'un et toutes ses clés se restreignent avec lui — sans réémission ni redémarrage.
- Bannissez-le et ses clés cessent de fonctionner, dès la requête suivante.
- Une déconnexion désactive immédiatement un jeton d'accès OAuth, car chaque jeton est revérifié contre la session vivante au lieu d'être cru sur parole jusqu'à son expiration.
- Les clés sont hachées au repos, affichées une seule fois à la création, et révocables individuellement.
- Les permissions d'enregistrement au niveau ligne s'appliquent enfin. Une règle du type « les enregistrements dont cet utilisateur est propriétaire » a besoin d'un utilisateur auquel se rattacher. Les jetons statiques retirés n'en portaient aucun : ce palier ne s'exécutait donc jamais pour un appelant authentifié par jeton — le modèle voyait toutes les lignes visibles par le rôle, et non celles visibles par la personne.
Ce dernier point est la raison pour laquelle les variables statiques MCP_TOKEN_* ont été supprimées plutôt que dépréciées. Elles n'étaient pas seulement grossières : elles sautaient silencieusement un palier de permissions que la requête humaine équivalente traversait.
La clé voyage sur x-api-key, jamais sur Authorization: Bearer. C'est la règle qu'applique déjà /api/*, et la maintenir dans tout le produit est ce qui empêche un en-tête Authorization fuité de signifier une chose sur un chemin et autre chose ailleurs. Si une requête qui devrait marcher renvoie 401, vérifiez d'abord le nom de l'en-tête.
Migrer depuis MCP_TOKEN_*
Les jetons statiques ont disparu, et un reliquat refuse le démarrage quand MCP_ENABLED=true — délibérément, pour que l'échec survienne là où le changement a été fait plutôt que dans la CI de quelqu'un une semaine plus tard. Trois étapes :
- Retirez
MCP_TOKEN_ADMIN,MCP_TOKEN_MEMBER,MCP_TOKEN_VIEWERetMCP_AUTH_STRATEGY. - Assurez-vous que l'application a un bloc
app.auth, avecapiKeys: truepour les appelants automatisés. - Connectez-vous avec l'utilisateur dont le client doit hériter du rôle, émettez une clé, et envoyez-la sur
x-api-key.
Remplacez un rôle par un utilisateur : là où vous auriez émis MCP_TOKEN_VIEWER, créez un utilisateur portant le rôle viewer et émettez la clé de cet utilisateur. Voir Dépannage : exécution pour les messages de démarrage exacts.
Le RBAC est le plafond
Le rôle de l'utilisateur derrière l'identifiant borne tout ce qui suit. Une clé détenue par un viewer ne peut que lire et lister, même sur une table dont l'aiAccess.operations autorise l'écriture — aiAccess élargit ce qui est proposé, jamais ce qui est permis.
| Couche | Répond à |
|---|---|
aiAccess sur l'entité |
Cette entité est-elle éligible à devenir un outil ? |
MCP_ENABLED |
Le serveur tourne-t-il ? |
| Permissions de rôle | Cet acteur peut-il effectuer cette opération ? |
| Permissions de champ | Quelles colonnes apparaissent dans le schéma et dans le résultat ? |
| Règles au niveau ligne | Quels enregistrements sont visibles ? |
Les cinq doivent passer. Conséquence pratique : vous ne pouvez pas surexposer une table par accident en y écrivant aiAccess: true — le pire des cas est qu'un rôle voie exactement ce qu'il aurait déjà pu récupérer par l'API.
Audit
Avec MCP_AUDIT_ENABLED (défaut true), chaque appel d'outil est consigné dans system.ai_tool_calls et dans le flux d'activité. Les administrateurs peuvent relire cette table via MCP lui-même, sous le nom {app}_system_ai_tool_calls_list.
Désactiver l'audit est permis pour des cas de conformité particuliers, et c'est un mauvais réglage par défaut. Un acteur IA est précisément celui dont vous voudrez plus tard reconstituer les appels.
Limitation de débit
| Variable | Défaut | Portée |
|---|---|---|
MCP_RATE_LIMIT_PER_MINUTE |
60 |
Par identifiant. |
MCP_RATE_LIMIT_PER_DAY |
5000 |
Idem. |
Les requêtes au-delà répondent 429 avec les en-têtes de limitation standard. C'est le plafond journalier qui compte le plus : un modèle pris dans une boucle de reprise peut brûler le budget d'une minute et continuer, mais il ne peut pas tourner discrètement toute la nuit contre votre base.
Internes admin
MCP_EXPOSE_INTERNALS vaut true par défaut et donne au rôle administrateur des outils en lecture seule sur les tables auth et system — {app}_auth_*_read, {app}_system_*_list et ainsi de suite — avec les colonnes secrètes exclues.
C'est ce qui rend « quels utilisateurs se sont inscrits cette semaine ? » répondable sans client de base de données. Passez la variable à false pour retirer entièrement ces outils de tools/list, y compris pour les administrateurs ; faites-le quand la surface MCP vise uniquement des données métier et que les internes de la plateforme sortent du périmètre de celui qui se connecte.
Pages associées
- Présentation de MCP — les variables
MCP_*en contexte. - Mode serveur —
aiAccesset ce qu'il ne fait pas. - Connecter un client — transmettre l'identifiant.
- Rôles et RBAC — les permissions appliquées.
- Suivi d'activité — où remontent les appels d'outils.
- Serveur OAuth — le greffon qui émet l'identifiant Bearer.
- Clés d'API — émettre et révoquer l'identifiant
x-api-key.
Dernière mise à jour 1 septembre 2026
Cette documentation a été rédigée avec de l'IA : des erreurs ou du contenu obsolète sont donc possibles. Sovrium est en bêta. Les contributions et corrections sont les bienvenues.