OAuth per client MCP personalizzati
Se stai costruendo il tuo client MCP (CLI, SDK, plugin per IDE), questa pagina descrive la nostra implementazione OAuth: gli standard che supportiamo, gli endpoint, le regole su redirect_uri e come fare il debug degli errori più comuni. Gli utenti di Claude.ai e ChatGPT non hanno bisogno di questa pagina — usa il Quickstart.
Standard che implementiamo
mcp-telegram.com è pienamente conforme alle specifiche OAuth su cui si basa l'ecosistema MCP — niente estensioni proprietarie, niente segreti condivisi cablati nei client.
- RFC 6749 — OAuth 2.0 Authorization Framework — authorization code grant di base con refresh token
- RFC 7591 — Dynamic Client Registration — qualunque client può registrarsi da solo su /oauth/register senza coordinamento preventivo
- RFC 7636 — PKCE (Proof Key for Code Exchange) — challenge S256 obbligatorio per i client pubblici
- RFC 8252 — OAuth 2.0 for Native Apps — redirect URI con IP loopback e flessibilità sulla porta effimera
- RFC 8414 — OAuth 2.0 Authorization Server Metadata — documento di discovery su /.well-known/oauth-authorization-server
- RFC 9728 — OAuth 2.0 Protected Resource Metadata — discovery del confine della risorsa MCP
Endpoint
Authorization code flow con PKCE
Flusso standard RFC 6749 §4.1 + RFC 7636. Nessuna sorpresa — se la tua libreria OAuth gestisce "authorization code + PKCE", funzionerà.
Registra il tuo client
POST /oauth/register con { redirect_uris: ["http://127.0.0.1:<porta>/callback"], client_name: "nome-del-tuo-client" }. Il server restituisce client_id + client_secret (il secret è opzionale per i client PKCE pubblici, ma riceverlo non fa male).
Genera la coppia PKCE
Genera un code_verifier casuale di 43-128 caratteri, poi calcola code_challenge = BASE64URL(SHA256(code_verifier)). Conserva il verifier in locale per il passo 4.
Apri /oauth/authorize nel browser
Reindirizza l'utente a /oauth/authorize?response_type=code&client_id=...&redirect_uri=...&state=...&code_challenge=...&code_challenge_method=S256. Il server mostra un codice QR; l'utente lo scansiona nell'app Telegram per autenticarsi.
Ricevi l'authorization code
Dopo la scansione del QR, il server reindirizza al tuo redirect_uri con ?code=...&state=.... Verifica che il parametro state corrisponda a quello che hai inviato.
Scambia il code per un token
POST /oauth/token con grant_type=authorization_code, code, redirect_uri, code_verifier, client_id. Ricevi un access_token (TTL di 10 anni — vedi Token lifetime sotto) e un refresh_token. Usa l'access_token come Authorization: Bearer ... nelle richieste a /mcp.
Regole di matching del redirect_uri
Seguiamo rigorosamente RFC 8252 §7.3 e §8.4. L'algoritmo di matching dipende dal fatto che l'URI registrato sia o meno un letterale IP loopback.
Loopback (http://127.0.0.1 o http://[::1])
Se hai registrato un URI loopback, il redirect_uri al momento dell'authorize deve combaciare esattamente in scheme, host, path e query — ma la porta può essere diversa. Lo richiede RFC 8252 §7.3 perché i client nativi si legano a una porta effimera assegnata dal sistema operativo, che può cambiare tra un'esecuzione e l'altra.
- Registrato http://127.0.0.1:36201/callback combacia all'authorize con http://127.0.0.1:50000/callback ✅
- Registrato http://127.0.0.1:36201/callback NON combacia con http://127.0.0.1:50000/different-path — il path deve essere esatto
- Registrato http://[::1]:36201/cb NON combacia con http://127.0.0.1:36201/cb — i loopback IPv4 e IPv6 sono identificatori separati
HTTPS (https://tuo-dominio.example/...)
Corrispondenza byte-per-byte esatta, inclusi path, query e porta (RFC 6749 §3.1.2). Nessuna flessibilità.
localhost (NON consigliato)
Trattiamo http://localhost come un normale hostname — match esatto obbligatorio, nessuna flessibilità sulla porta. RFC 8252 §8.3 consiglia di usare letterali IP (127.0.0.1 / [::1]) invece di localhost perché la risoluzione DNS dipende dall'implementazione.
PKCE è obbligatorio
code_challenge_method=S256 è richiesto in ogni richiesta di authorize. Il metodo plain viene rifiutato. Se salti del tutto code_challenge, lo scambio su /token fallirà alla validazione del code_verifier.
Durata del token
Il TTL dell'access_token è volutamente lungo (10 anni) perché alcuni client MCP non persistono il refresh_token in modo affidabile. Un refresh_token viene comunque emesso e ruotato ad ogni refresh (RFC 6819 §5.2.2.3). L'utente può revocare tutti i token in qualsiasi momento da /my/sessions o facendo logout da Telegram. L'utente può anche fare esplicitamente POST su /oauth/revoke (RFC 7009) per terminare una sessione.
Errori comuni
HTTP 400 "Invalid redirect_uri" su /oauth/authorize
Il parametro redirect_uri non corrisponde a nessun URI registrato per questo client_id. Per i client loopback: controlla che scheme + host + path + query combacino esattamente (solo la porta è flessibile). Per i client HTTPS: serve l'uguaglianza byte-per-byte totale — attenzione agli slash finali e alle differenze di URL-encoding.
HTTP 400 "Unknown client"
Il client_id non esiste nel nostro database. O hai saltato il passo /oauth/register, o la risposta della registrazione è andata persa prima che salvassi il client_id, oppure il client è stato revocato dall'utente via /my/clients.
Il client mostra "Needs Auth" ripetutamente
Se il tuo client persiste l'access_token ma non il refresh_token, vedrai questo quando l'access_token scade. I nostri access token hanno TTL di 10 anni proprio per mitigare questa cosa, ma se il tuo client fa scadere i token lato client su una finestra più corta, dovrai o persistere il refresh_token o chiamare /oauth/revoke + ri-autenticarti su richiesta.
Client testati
Confermati come interoperanti con il nostro server. Se costruisci qualcosa di nuovo e funziona, mandaci una PR per aggiungerlo qui.
- Claude.ai web — tramite connettore MCP integrato
- ChatGPT Apps — tramite connettore MCP integrato
- Hermes Agent — client MCP CLI open-source (RFC 8252 loopback flow)
- Cursor MCP — plugin per IDE (RFC 8252 loopback flow)
- Qualunque client conforme a RFC 6749 + RFC 7591 + RFC 7636 + RFC 8252 dovrebbe funzionare senza modifiche al codice dal nostro lato.
Più account Telegram su un'unica connessione OAuth
Dalla v2.32.0 una singola connessione OAuth può contenere diverse identità Telegram e passare dall'una all'altra con una sola chiamata di tool — senza ciclo Disconnect/Connect, senza registrare un nuovo client.
Elencare gli account collegati
Chiamare telegram-accounts-list. Apparirà il Suo account primary (legato all'OAuth) contrassegnato con ⭐ se attivo, insieme a eventuali account secondari aggiunti.
Collegare un altro account
Chiamare telegram-accounts-add con un label opzionale (es. "testing"). Il tool restituisce un URL monouso (TTL 10 minutes) — lo apra su un qualsiasi dispositivo e scansioni il QR con l'account Telegram che desidera aggiungere.
Cambiare l'account attivo
Chiamare telegram-accounts-switch con identifier=label, @username, account_id oppure 'primary'. La successiva chiamata telegram-* userà immediatamente quell'account. Senza riconnessione.
Scollegare un account secondario
Chiamare telegram-accounts-remove identifier=… su un account secondario. L'account Telegram in sé NON viene disconnesso — viene rimosso solo il collegamento qui. L'account primary non può essere rimosso in questo modo; utilizzi il flusso di Disconnect del Suo client per uscire completamente.
Ogni connessione OAuth è isolata: gli account che collega tramite Hermes sono invisibili a Claude.ai o ChatGPT, anche se si tratta della stessa identità Telegram. Per collegare account diversi a client MCP diversi, registri ciascun client separatamente e usi telegram-accounts-add all'interno della relativa sessione.