OAuth для власних MCP-клієнтів
Якщо ти пишеш свій MCP-клієнт (CLI, SDK, плагін для IDE), ця сторінка описує нашу реалізацію OAuth: які стандарти ми підтримуємо, точки доступу, правила зіставлення redirect_uri та як виправити типові помилки. Користувачам Claude.ai і ChatGPT ця сторінка не потрібна — переглянь натомість Quickstart.
Які стандарти ми реалізуємо
mcp-telegram.com повністю відповідає OAuth-специфікаціям, на які спирається екосистема MCP — без пропрієтарних розширень, без зашитих у клієнти спільних секретів.
- RFC 6749 — OAuth 2.0 Authorization Framework — базовий authorization code grant із refresh-токенами
- RFC 7591 — Dynamic Client Registration — будь-який клієнт може зареєструватися самостійно через /oauth/register, без попередніх домовленостей
- RFC 7636 — PKCE (Proof Key for Code Exchange) — S256 challenge обов'язковий для публічних клієнтів
- RFC 8252 — OAuth 2.0 for Native Apps — loopback IP redirect URI з гнучкістю ефемерного порту
- RFC 8414 — OAuth 2.0 Authorization Server Metadata — discovery-документ за адресою /.well-known/oauth-authorization-server
- RFC 9728 — OAuth 2.0 Protected Resource Metadata — discovery меж MCP-ресурсу
Точки доступу
Authorization code flow з PKCE
Стандартний потік RFC 6749 §4.1 + RFC 7636. Жодних сюрпризів — якщо твоя OAuth-бібліотека вміє «authorization code + PKCE», усе запрацює.
Зареєструй свій клієнт
POST /oauth/register із { redirect_uris: ["http://127.0.0.1:<port>/callback"], client_name: "назва-твого-клієнта" }. Сервер поверне client_id + client_secret (secret необов'язковий для публічних PKCE-клієнтів, але отримати його не зашкодить).
Згенеруй PKCE-пару
Згенеруй випадковий code_verifier на 43–128 символів, потім обчисли code_challenge = BASE64URL(SHA256(code_verifier)). Збережи verifier локально для кроку 4.
Відкрий /oauth/authorize у браузері
Перенаправ користувача на /oauth/authorize?response_type=code&client_id=...&redirect_uri=...&state=...&code_challenge=...&code_challenge_method=S256. Сервер покаже QR-код; користувач сканує його у застосунку Telegram, щоб автентифікуватися.
Отримай authorization code
Після сканування QR сервер перенаправляє на твій redirect_uri з ?code=...&state=.... Перевір, що параметр state збігається з тим, який ти надсилав.
Обміняй code на токен
POST /oauth/token із grant_type=authorization_code, code, redirect_uri, code_verifier, client_id. Отримаєш access_token (TTL 10 років — див. нижче Token Lifetime) та refresh_token. Використовуй access_token як Authorization: Bearer ... у запитах до /mcp.
Правила зіставлення redirect_uri
Ми суворо дотримуємося RFC 8252 §7.3 та §8.4. Алгоритм зіставлення залежить від того, чи є зареєстрований URI loopback IP-літералом.
Loopback (http://127.0.0.1 або http://[::1])
Якщо ти зареєстрував loopback URI, то redirect_uri на момент authorize має точно збігатися за scheme, host, path і query — але порт може відрізнятися. Цього вимагає RFC 8252 §7.3, бо нативні клієнти прив'язуються до ефемерного порту, призначеного ОС, який може змінюватися між запусками.
- Зареєстровано http://127.0.0.1:36201/callback — збігається з http://127.0.0.1:50000/callback на момент authorize ✅
- Зареєстровано http://127.0.0.1:36201/callback — НЕ збігається з http://127.0.0.1:50000/different-path: path має бути точним
- Зареєстровано http://[::1]:36201/cb — НЕ збігається з http://127.0.0.1:36201/cb: IPv4 та IPv6 loopback — це різні ідентифікатори
HTTPS (https://your-domain.example/...)
Потрібен точний побайтовий збіг, включно з path, query та портом (RFC 6749 §3.1.2). Без гнучкості.
localhost (НЕ рекомендовано)
Ми трактуємо http://localhost як звичайне ім'я хоста — потрібен точний збіг, гнучкості за портом немає. RFC 8252 §8.3 рекомендує використовувати IP-літерали (127.0.0.1 / [::1]) замість localhost, бо розв'язання DNS залежить від реалізації.
PKCE обов'язковий
code_challenge_method=S256 потрібен у кожному запиті до authorize. Метод Plain відхиляється. Якщо повністю пропустити code_challenge, обмін на /token впаде на перевірці code_verifier.
Час життя токена
TTL access_token навмисно великий (10 років), бо деякі MCP-клієнти ненадійно зберігають refresh_token. Тим не менш refresh_token усе одно видається й ротується під час кожного refresh (RFC 6819 §5.2.2.3). Користувач будь-коли може відкликати всі токени за адресою /my/sessions або виходом із Telegram. Також можна явно надіслати POST на /oauth/revoke (RFC 7009), щоб завершити сесію.
Типові помилки
HTTP 400 «Invalid redirect_uri» на /oauth/authorize
Query-параметр redirect_uri не збігається з жодним URI, зареєстрованим для цього client_id. Для loopback-клієнтів: перевір, що scheme + host + path + query збігаються точно (гнучкий лише порт). Для HTTPS-клієнтів: потрібна повна побайтова рівність — звертай увагу на trailing-слеші та різницю в URL-кодуванні.
HTTP 400 «Unknown client»
client_id не існує в нашій базі. Або ти пропустив крок /oauth/register, або відповідь із реєстрацією загубилася до того, як ти зберіг client_id, або клієнт був відкликаний користувачем через /my/clients.
Клієнт постійно показує «Needs Auth»
Якщо твій клієнт зберігає access_token, але не refresh_token, ти побачиш це, коли access_token завершить термін дії. Наші access-токени мають TTL у 10 років саме для того, щоб пом'якшити цю проблему, проте якщо твій клієнт сам завершує термін дії токенів раніше з боку клієнта, потрібно або зберігати refresh_token, або викликати /oauth/revoke + повторну автентифікацію на вимогу.
Перевірені клієнти
Підтверджена сумісність із нашим сервером. Якщо ти зібрав щось нове і воно працює — надішли нам PR, додамо сюди.
- Claude.ai web — через вбудований MCP connector
- ChatGPT Apps — через вбудований MCP connector
- Hermes Agent — open-source CLI MCP-клієнт (RFC 8252 loopback flow)
- Cursor MCP — плагін для IDE (RFC 8252 loopback flow)
- Будь-який клієнт, що відповідає RFC 6749 + RFC 7591 + RFC 7636 + RFC 8252, має працювати без змін у коді з нашого боку.
Кілька облікових записів Telegram на одному OAuth-з'єднанні
Починаючи з v2.32.0 одне OAuth-з'єднання може містити кілька ідентичностей Telegram і перемикатися між ними одним викликом інструмента — без циклу Disconnect/Connect, без реєстрації нового клієнта.
Перегляньте, що прив'язано
Викличте telegram-accounts-list. Ви побачите основний (прив'язаний до OAuth) акаунт, позначений ⭐, якщо він активний, а також будь-які вторинні, які ви додали.
Прив'яжіть ще один акаунт
Викличте telegram-accounts-add з опціональною міткою (наприклад, "testing"). Інструмент поверне одноразове посилання (TTL 10 minutes) — відкрийте його на будь-якому пристрої та відскануйте QR обліковим записом Telegram, який хочете додати.
Перемкніть активний акаунт
Викличте telegram-accounts-switch з identifier=label, @username, account_id або 'primary'. Наступний виклик telegram-* одразу використає цей акаунт. Без перепідключення.
Від'єднайте вторинний акаунт
Викличте telegram-accounts-remove identifier=… для вторинного. Сам обліковий запис Telegram НЕ виходить із системи — від'єднується лише прив'язка тут. Основний акаунт у такий спосіб видалити не можна; для повного виходу скористайтеся процесом Disconnect у вашому клієнті.
Кожне OAuth-з'єднання ізольоване: акаунти, які ви прив'язали через Hermes, невидимі для Claude.ai чи ChatGPT, навіть якщо це та сама ідентичність Telegram. Щоб під'єднати різні акаунти до різних MCP-клієнтів, зареєструйте кожен клієнт окремо та використовуйте telegram-accounts-add у межах його сесії.