Le mois dernier, j’ai fait passer le serveur MCP de Kookee aux tokens personnels. Chacun crée le sien, l’assistant agit au nom de cette personne, et chaque modification qu’il fait indique qui l’a faite. Dans Claude Code et Cursor, cela fonctionne bien : vous collez votre token dans une commande ou un fichier de configuration, et c’est terminé.
Essayez maintenant d’expliquer cela à quelqu’un qui rédige ses notes de version dans Claude sur un portable, ou qui trie les retours sur son téléphone. Les applications de chat de Claude et ChatGPT n’ont aucun champ pour un en-tête Authorization. Elles se connectent à un serveur MCP distant d’une seule façon : vous leur donnez une URL, elles vous redirigent vers une page de connexion, et elles gardent la session. C’est OAuth, et jusqu’à cette semaine, Kookee ne le gérait pas.
Maintenant, c’est le cas. Vous ajoutez https://api.kookee.dev/api/mcp dans Claude, ChatGPT ou VS Code, vous vous connectez à Kookee, vous choisissez « Lecture et écriture » ou « Lecture seule », et la configuration s’arrête là. Voici ce que j’ai livré, et les décisions qui ont pris plus de temps que le code.
À quoi ressemble la connexion maintenant
La page Serveur MCP de chaque projet a une nouvelle carte avec l’URL et les étapes pour chaque application. Pour Claude, il y a un bouton Ajouter à Claude. Il ouvre la boîte de dialogue Add custom connector de Claude avec le nom et l’URL déjà remplis : il ne vous reste qu’à cliquer sur Add.

Claude ouvre ensuite une page Kookee. Vous vous connectez, ou créez un compte, et décidez de ce que l’application a le droit de faire :

Aucun token à créer, copier, stocker ou renouveler. Le connecteur apparaît ensuite dans Claude sur le web, sur ordinateur et sur téléphone.
Sept décisions prises pour l’OAuth MCP de Kookee
1. Une connexion par personne, pas par projet
Mon premier plan copiait le modèle des tokens : un token appartient à un projet, donc une connexion aussi. Claude a enterré ce plan. Il refuse un second connecteur personnalisé avec la même URL : une connexion liée à un projet aurait donc limité chaque utilisateur de Claude à un seul projet. Une URL distincte par projet contourne le problème, mais laisse quelqu’un qui est dans cinq projets avec cinq connecteurs à configurer et à suivre.
Une connexion appartient donc à votre compte et donne accès à tous les projets dont vous êtes membre, avec votre rôle dans chacun. Tous les outils sauf list_projects acceptent un argument project facultatif. Si vous êtes dans un seul projet, l’assistant n’en a jamais besoin. Si vous êtes dans plusieurs, vous dites « dans le projet Lumen » et il passe le slug. list_projects couvre le cas où il doit demander.
Quand le projet manque ou est erroné, le serveur ne répond pas par une erreur HTTP. Il renvoie un résultat d’outil ordinaire qui dit ce qui ne va pas et liste vos projets :
{
"error": "MCP_PROJECT_REQUIRED",
"message": "This account belongs to several projects. Pass `project` with the slug of the one the user means.",
"projects": [
{ "slug": "lumen", "name": "Lumen", "role": "OWNER" },
{ "slug": "lumen-docs", "name": "Lumen Docs", "role": "MEMBER" }
]
}
Un modèle lit cela et réessaie avec le bon slug. Une erreur 400 renvoyée par le transport, en revanche, ressemble pour lui à un serveur cassé.
2. La lecture seule se choisit sur l’écran de consentement
Avec les tokens, vous choisissez l’accès en créant le token. Avec OAuth, il n’y a pas de page de token : le choix se fait donc au moment où vous approuvez l’application.
En coulisse, les deux options sont des scopes OAuth, read et write, et choisir « Lecture seule » retire write avant que l’application reçoive son code. Comme avec les tokens, une connexion en lecture seule ne se contente pas de refuser les écritures : elle ne liste jamais les outils d’écriture. Un modèle qui voit move_feedback planifie tout un tri autour de cet outil et échoue à la dernière étape. Un modèle qui ne le voit pas vous dit que la connexion est en lecture seule.
3. Déconnecter doit vouloir dire déconnecté
C’est ce qui a pris le plus de temps. Une application OAuth détient deux tokens : un access token valable une heure, et un refresh token qu’elle échange contre de nouveaux access tokens. Par défaut, le refresh grant du serveur OAuth sur lequel je me suis appuyé ne vérifiait pas si vous autorisiez toujours l’application. Si vous retiriez son consentement, elle pouvait continuer à obtenir de nouveaux access tokens.
Désormais, deux choses se produisent. Chaque requête MCP vérifie l’access token, le consentement derrière lui et le compte, en une seule requête à la base, et refuse la requête si l’un d’eux a disparu ou si le compte est désactivé. Et la déconnexion supprime ensemble le consentement, les refresh tokens et les access tokens, dans une seule transaction. Déconnectez une application dans Kookee, et sa toute prochaine requête est refusée.
Changer ou réinitialiser votre mot de passe déconnecte aussi toutes les applications. Si vous réinitialisez un mot de passe parce que quelque chose s’est mal passé, un assistant quelque part avec une session active est bien la dernière chose que vous voulez. Les comptes invités ne peuvent pas se connecter du tout.
4. Des tokens qu’on peut révoquer, pas des tokens dont on attend l’expiration
Un choix courant pour les access tokens OAuth, ce sont les JWT : signés, autonomes, vérifiés sans consulter la base. En revanche, ils ne peuvent pas être révoqués avant d’expirer. Pour un assistant capable de publier sous votre nom, « ça cessera de fonctionner dans l’heure » ne suffit pas.
Ceux de Kookee sont des chaînes aléatoires, stockées uniquement sous forme de hash SHA-256, avec leurs propres préfixes : mcpa_ pour les access tokens et mcpr_ pour les refresh tokens. Un scanner de secrets, ou une personne qui lit un log, peut les distinguer d’un token personnel (kkm_) ou d’une clé API (kk_). Le prix, c’est une requête à la base par appel, et cette requête existait déjà.
5. Uniquement des applications connues
Les clients MCP s’identifient avec un document de métadonnées (client ID metadata document) : le client ID est une URL, et le serveur la télécharge pour connaître le nom de l’application et l’adresse vers laquelle elle peut vous renvoyer. La conception est propre. Elle signifie aussi qu’un serveur qui accepte n’importe quelle URL ira chercher tout ce qu’on lui indique, et enregistrera un client pour cela, avant même que quelqu’un se soit connecté.
Kookee accepte plutôt une courte liste : Claude, Claude Code, ChatGPT et VS Code, chacun reconnu à l’adresse où se trouve son document de métadonnées. L’écran de consentement peut alors dire « Autoriser Claude » à bon droit, et personne ne peut héberger ailleurs un document qui se fait passer pour Claude.
Cela a un coût. Cursor s’enregistre via l’enregistrement dynamique de clients (dynamic client registration), que j’ai laissé désactivé : les utilisateurs de Cursor continuent donc d’utiliser des tokens personnels. Ceux-ci fonctionnent exactement comme avant.
6. La page de consentement ne peut pas être chargée dans un cadre
Une page avec un bouton Autoriser est la cible classique du clickjacking : on la charge dans un cadre invisible et on place quelque chose d’alléchant sous le bouton. Celle de Kookee envoie Content-Security-Policy: frame-ancestors 'none' et X-Frame-Options: DENY, donc aucun autre site ne peut l’afficher dans un cadre. Deux en-têtes, faciles à oublier jusqu’à ce que quelqu’un vous écrive à ce sujet.
7. La même attribution qu’avant
La connexion par compte change la façon de se connecter, pas ce qui est enregistré. Une modification faite depuis Claude est enregistrée sous votre nom, comme une modification faite avec un token, et le log du serveur note quelle application l’a faite. Sur le tableau de retours, ses changements de colonne, réattributions et réponses portent la mention via MCP : vos coéquipiers voient qui a déplacé le retour, et qu’un assistant l’a fait.
Ce que vous voyez dans Kookee
Tout ce que vous avez connecté est listé dans les paramètres de votre compte, sous Sécurité → Applications connectées, avec son accès et la date de connexion. Déconnecter une application demande un clic et une confirmation.

Les tokens personnels n’ont pas disparu. Ils restent le bon outil pour Cursor, pour les scripts et la CI, et pour un .mcp.json que toute l’équipe commite, et ils se trouvent désormais dans une seule carte sur la page du serveur MCP, sous la nouvelle.
Si vous gérez un serveur MCP
Prenez en charge OAuth. Les utilisateurs de Claude, de ChatGPT et des autres applications de chat ne peuvent pas coller un en-tête.
Faites une connexion par personne, et prenez l’espace de travail comme argument d’outil. Claude n’accepte pas deux fois la même URL.
Mettez le choix de la lecture seule sur l’écran de consentement, et ne listez pas les outils que l’autorisation accordée ne couvre pas.
Vérifiez le consentement à chaque requête, et supprimez les refresh tokens quand quelqu’un se déconnecte. Ne comptez pas sur le refresh grant pour le faire à votre place.
Préférez des tokens opaques révocables à des JWT dont il faut attendre l’expiration.
Acceptez une liste d’URL de métadonnées de clients connues plutôt que de télécharger tout ce qu’un client envoie.
Gardez la page de consentement hors des cadres.
Répondez à « quel projet ? » par un résultat d’outil sur lequel le modèle peut agir, pas par une erreur HTTP.
Le serveur MCP de Kookee fonctionne désormais avec Claude, ChatGPT et VS Code par simple connexion au compte. Consultez Connecter Claude, ChatGPT ou VS Code à Kookee pour les étapes, ou Gérer votre contenu depuis un assistant IA (MCP) pour ce qu’un assistant peut faire une fois connecté.