MCP Telegram
Назад в Quickstart

OAuth для собственных MCP-клиентов

Если ты пишешь свой MCP-клиент (CLI, SDK, плагин для IDE), эта страница описывает нашу реализацию OAuth: какие стандарты мы поддерживаем, endpoint'ы, правила matching'а redirect_uri и как чинить типичные ошибки. Пользователям Claude.ai и ChatGPT эта страница не нужна — смотри Quickstart.

Какие стандарты мы реализуем

mcp-telegram.com полностью соответствует OAuth-спекам, на которые опирается экосистема MCP — без проприетарных расширений и без захардкоженных в клиентах секретов.

Endpoint'ы

Метаданные authorization-сервера (RFC 8414)
Динамическая регистрация клиента (RFC 7591)
Authorization endpoint
Token endpoint
MCP-ресурс (Streamable HTTP)

Authorization code flow с PKCE

Стандартный поток RFC 6749 §4.1 + RFC 7636. Никаких сюрпризов — если твоя OAuth-библиотека умеет «authorization code + PKCE», всё заработает.

1

Зарегистрируй клиент

POST /oauth/register с { redirect_uris: ["http://127.0.0.1:<порт>/callback"], client_name: "имя-клиента" }. Сервер вернёт client_id и client_secret (секрет необязателен для публичных PKCE-клиентов, но получить его не помешает).

2

Сгенерируй PKCE-пару

Сделай случайный code_verifier (43–128 символов), затем посчитай code_challenge = BASE64URL(SHA256(code_verifier)). Сохрани verifier локально для шага 4.

3

Открой /oauth/authorize в браузере

Перенаправь юзера на /oauth/authorize?response_type=code&client_id=...&redirect_uri=...&state=...&code_challenge=...&code_challenge_method=S256. Сервер покажет QR-код; юзер сканит его в Telegram-приложении и аутентифицируется.

4

Получи authorization code

После сканирования QR сервер редиректит на твой redirect_uri с ?code=...&state=.... Проверь, что state совпадает с тем, что ты отправлял.

5

Обменяй 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.

Правила matching'а redirect_uri

Мы строго следуем RFC 8252 §7.3 и §8.4. Алгоритм matching'а зависит от того, является ли зарегистрированный URI loopback IP-литералом.

Loopback (http://127.0.0.1 или http://[::1])

Если ты зарегистрировал loopback URI, то на /authorize redirect_uri должен точно совпадать по scheme, host, path и query — но порт может отличаться. Этого требует RFC 8252 §7.3, потому что нативные клиенты биндят OS-assigned эфемерный порт, который может меняться между запусками.

HTTPS (https://your-domain.example/...)

Точное побайтовое совпадение, включая path, query и порт (RFC 6749 §3.1.2). Без гибкости.

localhost (НЕ рекомендуется)

http://localhost мы рассматриваем как обычное hostname — нужен точный match, гибкости по порту нет. RFC 8252 §8.3 рекомендует использовать IP-литералы (127.0.0.1 / [::1]) вместо localhost, потому что разрешение DNS зависит от реализации.

PKCE обязателен

code_challenge_method=S256 нужен в каждом authorize-запросе. Plain method отклоняется. Если совсем пропустить code_challenge, обмен на /token упадёт на валидации code_verifier.

Время жизни токена

TTL access_token намеренно большой (10 лет), потому что не все MCP-клиенты надёжно сохраняют refresh_token. refresh_token всё равно выдаётся и ротируется на каждом refresh (RFC 6819 §5.2.2.3). Юзер может отозвать все токены в любой момент на /my/sessions или через logout в Telegram. Также можно явно сделать POST /oauth/revoke (RFC 7009), чтобы завершить сессию.

Типичные ошибки

HTTP 400 «Invalid redirect_uri» на /oauth/authorize

Параметр 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 лет специально, чтобы это смягчить, но если твой клиент сам пер-expir'ит токены раньше, нужно либо сохранять refresh_token, либо вызывать /oauth/revoke + повторный auth по требованию.

Проверенные клиенты

Подтверждённая совместимость. Если ты собрал что-то новое и оно работает — пришли PR, добавим в этот список.

Несколько Telegram-аккаунтов на одном OAuth-подключении

С версии v2.32.0 одно OAuth-подключение может держать несколько Telegram-идентичностей и переключаться между ними одним tool-вызовом — без цикла Disconnect/Connect, без регистрации нового клиента.

1

Посмотреть что привязано

Вызовите telegram-accounts-list. Вы увидите основной (OAuth-bound) аккаунт со значком ⭐ если он активный, плюс любые вторичные, которые вы добавили.

2

Привязать ещё один аккаунт

Вызовите telegram-accounts-add с опциональной меткой (например, "testing"). Tool вернёт одноразовую ссылку (TTL 10 минут) — откройте её на любом устройстве и сосканируйте QR Telegram-аккаунтом, который хотите добавить.

3

Переключить активный аккаунт

Вызовите telegram-accounts-switch с identifier=label, @username, account_id или 'primary'. Следующий telegram-* вызов сразу пойдёт от выбранного аккаунта. Без переподключения.

4

Отвязать вторичный аккаунт

Вызовите telegram-accounts-remove identifier=… для вторичного. Сам Telegram-аккаунт НЕ выходит из системы — отвязывается только привязка здесь. Основной аккаунт так удалить нельзя; используйте Disconnect в клиенте для полного выхода.

Каждое OAuth-подключение изолировано: аккаунты, которые вы добавили через Hermes, не видны Claude.ai или ChatGPT, даже если это та же Telegram-идентичность. Чтобы подключить разные аккаунты к разным MCP-клиентам, зарегистрируйте каждый клиент отдельно и используйте telegram-accounts-add внутри его сессии.