OAuth pour clients MCP personnalisés
Si tu construis ton propre client MCP (CLI, SDK, plugin d'IDE), cette page décrit notre implémentation OAuth : les standards que nous supportons, les endpoints, les règles de redirect_uri et comment déboguer les erreurs courantes. Les utilisateurs de Claude.ai et ChatGPT n'ont pas besoin de cette page — utilise plutôt le Quickstart.
Standards que nous implémentons
mcp-telegram.com est entièrement conforme aux spécifications OAuth sur lesquelles repose l'écosystème MCP — sans extensions propriétaires ni secrets partagés intégrés dans les clients.
- RFC 6749 — OAuth 2.0 Authorization Framework — authorization code grant de base avec refresh tokens
- RFC 7591 — Dynamic Client Registration — n'importe quel client peut s'enregistrer lui-même via /oauth/register, sans coordination préalable
- RFC 7636 — PKCE (Proof Key for Code Exchange) — challenge S256 obligatoire pour les clients publics
- RFC 8252 — OAuth 2.0 for Native Apps — redirect URIs avec IP loopback et flexibilité de port éphémère
- RFC 8414 — OAuth 2.0 Authorization Server Metadata — document de discovery sur /.well-known/oauth-authorization-server
- RFC 9728 — OAuth 2.0 Protected Resource Metadata — discovery de la frontière de la ressource MCP
Endpoints
Authorization code flow avec PKCE
Flux standard RFC 6749 §4.1 + RFC 7636. Aucune surprise — si ta bibliothèque OAuth gère « authorization code + PKCE », ça marchera.
Enregistre ton client
POST /oauth/register avec { redirect_uris: ["http://127.0.0.1:<port>/callback"], client_name: "nom-de-ton-client" }. Le serveur renvoie client_id + client_secret (le secret est optionnel pour les clients publics PKCE, mais le recevoir ne pose pas de problème).
Génère la paire PKCE
Génère un code_verifier aléatoire de 43-128 caractères, puis calcule code_challenge = BASE64URL(SHA256(code_verifier)). Conserve le verifier en local pour l'étape 4.
Ouvre /oauth/authorize dans un navigateur
Redirige l'utilisateur vers /oauth/authorize?response_type=code&client_id=...&redirect_uri=...&state=...&code_challenge=...&code_challenge_method=S256. Le serveur affiche un code QR ; l'utilisateur le scanne dans l'app Telegram pour s'authentifier.
Reçois le code d'autorisation
Après le scan du QR, le serveur redirige vers ton redirect_uri avec ?code=...&state=.... Vérifie que le paramètre state correspond à celui que tu as envoyé.
Échange le code contre un token
POST /oauth/token avec grant_type=authorization_code, code, redirect_uri, code_verifier, client_id. Tu recevras un access_token (TTL de 10 ans — voir Token Lifetime ci-dessous) et un refresh_token. Utilise l'access_token en Authorization: Bearer ... sur les requêtes /mcp.
Règles de correspondance du redirect_uri
Nous suivons strictement RFC 8252 §7.3 et §8.4. L'algorithme de correspondance dépend du fait que l'URI enregistré soit ou non un littéral d'IP loopback.
Loopback (http://127.0.0.1 ou http://[::1])
Si tu as enregistré un URI loopback, le redirect_uri au moment de l'authorize doit correspondre exactement en scheme, host, path et query — mais le port peut différer. C'est ce qu'exige RFC 8252 §7.3, parce que les clients natifs s'attachent à un port éphémère assigné par l'OS qui peut changer entre les exécutions.
- Enregistré http://127.0.0.1:36201/callback correspond à http://127.0.0.1:50000/callback au moment de l'authorize ✅
- Enregistré http://127.0.0.1:36201/callback ne correspond PAS à http://127.0.0.1:50000/different-path — le path doit être exact
- Enregistré http://[::1]:36201/cb ne correspond PAS à http://127.0.0.1:36201/cb — IPv4 et IPv6 loopback sont des identifiants distincts
HTTPS (https://your-domain.example/...)
Correspondance exacte octet par octet exigée, incluant path, query et port (RFC 6749 §3.1.2). Aucune flexibilité.
localhost (NON recommandé)
Nous traitons http://localhost comme un hostname normal — correspondance exacte exigée, pas de flexibilité sur le port. RFC 8252 §8.3 recommande d'utiliser des littéraux IP (127.0.0.1 / [::1]) plutôt que localhost parce que la résolution DNS dépend de l'implémentation.
PKCE est obligatoire
code_challenge_method=S256 est obligatoire sur chaque requête authorize. La méthode plain est rejetée. Si tu omets complètement code_challenge, l'échange /token échouera à la validation du code_verifier.
Durée de vie du token
La TTL de l'access_token est volontairement longue (10 ans) parce que certains clients MCP ne persistent pas le refresh_token de manière fiable. Un refresh_token est tout de même émis et tourne à chaque refresh (RFC 6819 §5.2.2.3). L'utilisateur peut révoquer tous les tokens à tout moment depuis /my/sessions ou en se déconnectant de Telegram. Il peut aussi faire un POST explicite vers /oauth/revoke (RFC 7009) pour terminer une session.
Erreurs courantes
HTTP 400 « Invalid redirect_uri » sur /oauth/authorize
Le paramètre de requête redirect_uri ne correspond à aucun URI enregistré pour ce client_id. Pour les clients loopback : vérifie que scheme + host + path + query correspondent exactement (seul le port est flexible). Pour les clients HTTPS : égalité octet par octet exigée — attention aux barres obliques finales et aux différences d'URL-encoding.
HTTP 400 « Unknown client »
Le client_id n'existe pas dans notre base. Soit tu as sauté l'étape /oauth/register, soit la réponse d'enregistrement a été perdue avant que tu ne sauvegardes le client_id, soit le client a été révoqué par l'utilisateur via /my/clients.
Le client affiche « Needs Auth » de façon répétée
Si ton client persiste l'access_token mais pas le refresh_token, tu verras cela quand l'access_token expirera. Nos access tokens ont une TTL de 10 ans précisément pour atténuer cela, mais si ton client expire les tokens côté client après une fenêtre plus courte, il te faudra soit persister le refresh_token, soit appeler /oauth/revoke + ré-authentifier à la demande.
Clients testés
Interopérabilité confirmée avec notre serveur. Si tu construis quelque chose de nouveau et que ça marche, envoie-nous une PR pour l'ajouter ici.
- Claude.ai web — via le connector MCP intégré
- ChatGPT Apps — via le connector MCP intégré
- Hermes Agent — client MCP open-source en CLI (flux loopback RFC 8252)
- Cursor MCP — plugin d'IDE (flux loopback RFC 8252)
- Tout client conforme à RFC 6749 + RFC 7591 + RFC 7636 + RFC 8252 devrait fonctionner sans changement de code de notre côté.
Plusieurs comptes Telegram sur une seule connexion OAuth
Depuis v2.32.0, une seule connexion OAuth peut héberger plusieurs identités Telegram et basculer entre elles avec un seul appel d'outil — pas de cycle Disconnect/Connect, pas de nouvel enregistrement de client.
Listez ce qui est rattaché
Appelez telegram-accounts-list. Vous verrez votre compte primary (lié à OAuth) marqué d'un ⭐ s'il est actif, ainsi que toutes les comptes secondaires que vous avez ajoutés.
Rattachez un autre compte
Appelez telegram-accounts-add avec un label optionnel (par ex. "testing"). L'outil renvoie une URL à usage unique (TTL 10 minutes) — ouvrez-la sur n'importe quel appareil et scannez le QR avec le compte Telegram que vous souhaitez ajouter.
Changez de compte actif
Appelez telegram-accounts-switch avec identifier=label, @username, account_id ou 'primary'. Le prochain appel d'outil telegram-* utilisera ce compte immédiatement. Aucune reconnexion.
Détachez un compte secondaire
Appelez telegram-accounts-remove identifier=… sur un compte secondaire. Le compte Telegram lui-même n'est PAS déconnecté — seul le lien ici est supprimé. Le compte primary ne peut pas être retiré de cette manière ; utilisez le flux Disconnect de votre client pour vous déconnecter complètement.
Chaque connexion OAuth est isolée : les comptes que vous rattachez via Hermes sont invisibles pour Claude.ai ou ChatGPT, même s'il s'agit de la même identité Telegram. Pour connecter des comptes différents à des clients MCP différents, enregistrez chaque client séparément et utilisez telegram-accounts-add à l'intérieur de sa propre session.