OAuth dla własnych klientów MCP
Jeśli budujesz własnego klienta MCP (CLI, SDK, wtyczkę do IDE), na tej stronie znajdziesz opis naszej implementacji OAuth: jakie standardy wspieramy, jakie są endpointy, reguły redirect_uri oraz jak debugować typowe błędy. Użytkownicy Claude.ai i ChatGPT nie potrzebują tej strony — skorzystaj z Quickstart.
Standardy, które wdrażamy
mcp-telegram.com jest w pełni zgodny ze specyfikacjami OAuth, na których opiera się ekosystem MCP — bez własnościowych rozszerzeń, bez współdzielonych sekretów zaszytych w klientach.
- RFC 6749 — OAuth 2.0 Authorization Framework — bazowy authorization code grant z refresh tokenami
- RFC 7591 — Dynamic Client Registration — każdy klient może sam się zarejestrować pod /oauth/register, bez wcześniejszej koordynacji
- RFC 7636 — PKCE (Proof Key for Code Exchange) — challenge S256 wymagany dla klientów publicznych
- RFC 8252 — OAuth 2.0 for Native Apps — redirect URI z loopback IP i elastycznością efemerycznego portu
- RFC 8414 — OAuth 2.0 Authorization Server Metadata — dokument discovery pod /.well-known/oauth-authorization-server
- RFC 9728 — OAuth 2.0 Protected Resource Metadata — discovery granicy zasobu MCP
Endpointy
Authorization code flow z PKCE
Standardowy przepływ RFC 6749 §4.1 + RFC 7636. Bez niespodzianek — jeśli twoja biblioteka OAuth obsługuje "authorization code + PKCE", zadziała.
Zarejestruj swojego klienta
POST /oauth/register z { redirect_uris: ["http://127.0.0.1:<port>/callback"], client_name: "nazwa-twojego-klienta" }. Serwer zwraca client_id + client_secret (secret jest opcjonalny dla publicznych klientów PKCE, ale jego otrzymanie nie zaszkodzi).
Wygeneruj parę PKCE
Wygeneruj losowy code_verifier o długości 43–128 znaków, następnie policz code_challenge = BASE64URL(SHA256(code_verifier)). Zapisz verifier lokalnie na potrzeby kroku 4.
Otwórz /oauth/authorize w przeglądarce
Przekieruj użytkownika na /oauth/authorize?response_type=code&client_id=...&redirect_uri=...&state=...&code_challenge=...&code_challenge_method=S256. Serwer wyświetla kod QR; użytkownik skanuje go w aplikacji Telegram, żeby się uwierzytelnić.
Odbierz authorization code
Po zeskanowaniu QR serwer przekierowuje na twój redirect_uri z ?code=...&state=.... Sprawdź, czy parametr state zgadza się z tym, który wysłałeś.
Wymień code na token
POST /oauth/token z grant_type=authorization_code, code, redirect_uri, code_verifier, client_id. Otrzymujesz access_token (TTL 10 lat — zobacz Token lifetime poniżej) oraz refresh_token. Używaj access_token jako Authorization: Bearer ... w żądaniach do /mcp.
Reguły matchingu redirect_uri
Ściśle stosujemy RFC 8252 §7.3 i §8.4. Algorytm matchingu zależy od tego, czy zarejestrowany URI jest literałem IP loopback.
Loopback (http://127.0.0.1 lub http://[::1])
Jeśli zarejestrowałeś URI loopback, to redirect_uri w momencie authorize musi się zgadzać dokładnie pod względem scheme, host, path i query — ale port może być inny. Wymaga tego RFC 8252 §7.3, ponieważ klienty natywne bindują efemeryczny port przyznany przez system operacyjny, który może się zmieniać między uruchomieniami.
- Zarejestrowane http://127.0.0.1:36201/callback pasuje przy authorize do http://127.0.0.1:50000/callback ✅
- Zarejestrowane http://127.0.0.1:36201/callback NIE pasuje do http://127.0.0.1:50000/different-path — path musi się zgadzać dokładnie
- Zarejestrowane http://[::1]:36201/cb NIE pasuje do http://127.0.0.1:36201/cb — loopback IPv4 i IPv6 to oddzielne identyfikatory
HTTPS (https://twoja-domena.example/...)
Wymagana dokładna zgodność bajt po bajcie, włącznie z path, query i portem (RFC 6749 §3.1.2). Żadnej elastyczności.
localhost (NIE polecane)
http://localhost traktujemy jako zwykły hostname — wymagany jest dokładny match, bez elastyczności portu. RFC 8252 §8.3 zaleca używanie literałów IP (127.0.0.1 / [::1]) zamiast localhost, ponieważ rozwiązywanie DNS zależy od implementacji.
PKCE jest obowiązkowe
code_challenge_method=S256 jest wymagany w każdym żądaniu authorize. Metoda plain jest odrzucana. Jeśli całkowicie pominiesz code_challenge, wymiana na /token padnie na walidacji code_verifier.
Czas życia tokena
TTL access_token jest celowo długi (10 lat), ponieważ niektóre klienty MCP nie zapisują refresh_token w sposób niezawodny. refresh_token i tak jest wydawany i rotowany przy każdym odświeżeniu (RFC 6819 §5.2.2.3). Użytkownik może w każdej chwili odwołać wszystkie tokeny na /my/sessions albo wylogowując się z Telegrama. Może też jawnie zrobić POST na /oauth/revoke (RFC 7009), żeby zakończyć sesję.
Typowe błędy
HTTP 400 "Invalid redirect_uri" na /oauth/authorize
Parametr redirect_uri nie pasuje do żadnego URI zarejestrowanego dla tego client_id. Dla klientów loopback: sprawdź, czy scheme + host + path + query zgadzają się dokładnie (elastyczny jest tylko port). Dla klientów HTTPS: wymagana jest pełna równość bajt-w-bajt — uważaj na końcowe slashe i różnice w URL-encodingu.
HTTP 400 "Unknown client"
client_id nie istnieje w naszej bazie. Albo pominąłeś krok /oauth/register, albo odpowiedź z rejestracji zgubiła się, zanim zapisałeś client_id, albo klient został odwołany przez użytkownika przez /my/clients.
Klient ciągle pokazuje "Needs Auth"
Jeśli twój klient zapisuje access_token, ale nie refresh_token, zobaczysz to, gdy access_token wygaśnie. Nasze access tokeny mają TTL 10 lat właśnie po to, żeby to złagodzić, ale jeśli twój klient sam wygasza tokeny po krótszym czasie, musisz albo zapisywać refresh_token, albo wywoływać /oauth/revoke + ponowną autoryzację na żądanie.
Sprawdzeni klienci
Potwierdzona współpraca z naszym serwerem. Jeśli zbudujesz coś nowego i zadziała, przyślij PR, żebyśmy mogli to tu dodać.
- Claude.ai web — przez wbudowany konektor MCP
- ChatGPT Apps — przez wbudowany konektor MCP
- Hermes Agent — open-source'owy klient MCP CLI (RFC 8252 loopback flow)
- Cursor MCP — wtyczka do IDE (RFC 8252 loopback flow)
- Każdy klient zgodny z RFC 6749 + RFC 7591 + RFC 7636 + RFC 8252 powinien działać bez zmian w kodzie po naszej stronie.
Wiele kont Telegram w jednym połączeniu OAuth
Od wersji v2.32.0 pojedyncze połączenie OAuth może obsługiwać kilka tożsamości Telegram i przełączać się między nimi jednym wywołaniem narzędzia — bez cyklu Disconnect/Connect i bez rejestrowania nowego klienta.
Wyświetlić podłączone konta
Wywołać telegram-accounts-list. Zostanie wyświetlone konto primary (powiązane z OAuth) oznaczone symbolem ⭐, jeśli jest aktywne, wraz z dodanymi kontami pomocniczymi.
Podłączyć kolejne konto
Wywołać telegram-accounts-add z opcjonalnym label (np. "testing"). Narzędzie zwróci jednorazowy URL (TTL 10 minutes) — należy otworzyć go na dowolnym urządzeniu i zeskanować QR za pomocą konta Telegram, które ma zostać dodane.
Przełączyć aktywne konto
Wywołać telegram-accounts-switch z identifier=label, @username, account_id lub 'primary'. Następne wywołanie telegram-* zostanie natychmiast wykonane z poziomu tego konta. Bez ponownego łączenia.
Odłączyć konto pomocnicze
Wywołać telegram-accounts-remove identifier=… na koncie pomocniczym. Samo konto Telegram NIE zostanie wylogowane — usuwane jest tylko powiązanie w tym miejscu. Konta primary nie można w ten sposób usunąć; aby całkowicie się wylogować, należy użyć Disconnect w kliencie.
Każde połączenie OAuth jest odizolowane: konta podłączone przez Hermes są niewidoczne dla Claude.ai ani ChatGPT, nawet jeśli chodzi o tę samą tożsamość Telegram. Aby podłączyć różne konta do różnych klientów MCP, należy zarejestrować każdego klienta osobno i użyć telegram-accounts-add w obrębie jego własnej sesji.