telegram-mcp
Provides tools for interacting with Telegram through a userbot session, including reading and sending messages, searching chats and messages, managing dialogs, contacts, media, reactions, and account authentication.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@telegram-mcp Send a Telegram message to Mom saying I'll be home late."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
telegram-mcp
Local MCP server for working with Telegram through a userbot session.
Gives agents (Claude Code and any other MCP clients) a set of tools for reading and sending messages, searching, working with chats, contacts, and media — on behalf of your Telegram account, via Telethon (MTProto, not Bot API).
Works via stdio only and keeps the session locally in encrypted form — the only traffic going out is to Telegram servers.
Why
The Bot API can do little and requires a bot. A userbot session is a full-fledged client: it sees all your dialogs, history, group members, can search across all of Telegram, send files and video notes, and add reactions. This server neatly wraps such capabilities into 28 MCP tools so an agent can work with Telegram the same way you do from the app.
Related MCP server: telegram-mcp
Features
Dialogs and chats — list of dialogs with unread counts, info about chat/channel/user (including bio/description), folders, joining and leaving groups.
Messages — history with pagination, search (global and per chat), sending, editing, deleting, forwarding, pinning, reactions, marking as read.
Media — sending files (photo/video/document/voice/video note; for video dimensions and duration are filled in via
ffprobe), downloading attachments.Contacts and people — your own profile, address book, resolving
@username/phone/link to an entity, global search for people and channels, group members.Login — by phone number (code + 2FA) or by QR code, directly from tools or from the CLI.
Security
A userbot session is full access to the account, therefore:
Stdio only. The server does not open a network port: communication with the MCP client goes through standard input/output. Only traffic to Telegram leaves the machine.
The session is encrypted on disk (Fernet). The session string is the key to the account, and it is placed on disk only encrypted, in
~/.telegram-mcp/session.enc. The key is taken fromTELEGRAM_MCP_ENC_KEYor generated once in~/.telegram-mcp/enc.keywith permissions0600.Read-only mode. Running with
TELEGRAM_MCP_READONLY=1disables all mutating tools (sending/editing/deleting/forwarding/joining/reactions) — convenient for monitoring and auditing.Actions on your behalf. Everything the server sends/deletes happens on behalf of the account owner. Keep this in mind when giving an agent access.
The first login is best done via the CLI
telegram-mcp-login: the code and 2FA password are entered in the terminal and do not pass through the agent's context.
Installation
Requires Python ≥ 3.10.
git clone git@github.com:bssth/telegram-mcp.git
cd telegram-mcp
python -m venv .venv
# Windows:
.venv\Scripts\pip install -e ".[speed,qr]"
# Linux/macOS:
# .venv/bin/pip install -e ".[speed,qr]"Optional extras:
Extra | What it provides |
|
|
| ASCII QR right in the terminal when logging in via QR code |
|
|
For correct dimensions/duration of sent video, ffmpeg
(the ffprobe utility) in PATH is desirable — optional, video is sent without it too.
Setup and login
Get
api_id/api_hashat https://my.telegram.org → API development tools.Copy
.env.exampleto.envand fill it in:TELEGRAM_API_ID=1234567 TELEGRAM_API_HASH=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # пусто = ключ шифрования сгенерируется в ~/.telegram-mcp/enc.key TELEGRAM_MCP_ENC_KEY=Log in to the account (once):
telegram-mcp-loginIt will ask for the number → the code from Telegram → the 2FA password (if enabled), or offer QR login. The encrypted session will be placed in
~/.telegram-mcp/session.enc, and from then on the server starts already authorized.Login is also possible without the CLI — via the
login_send_code/login_complete/login_qrtools. But the CLI is safer: secrets do not enter the agent's context.
Connecting to Claude Code
.mcp.json in the project (or the user MCP client config):
{
"mcpServers": {
"telegram": {
"command": "D:\\dev\\telegram-mcp\\.venv\\Scripts\\python.exe",
"args": ["-m", "telegram_mcp"],
"env": {
"TELEGRAM_API_ID": "1234567",
"TELEGRAM_API_HASH": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"TELEGRAM_MCP_ENC_KEY": "<ваш Fernet-ключ>"
}
}
}
}command— the path topythonfrom your venv (the package is installed in it).The
envblock can be omitted if the variables are already set in the system environment or in~/.telegram-mcp/.env.You can check without a client via the inspector:
npx @modelcontextprotocol/inspector <path>\python.exe -m telegram_mcp.
Tools
The chat argument almost everywhere is a string: a numeric id, @username, a link
t.me/..., a phone number, or me / self for Saved Messages.
Login
Tool | Purpose |
| Connection and login status, who is authorized |
| Send the login code to the number |
| Complete login with code and/or 2FA password (or finish QR with no arguments) |
| Start QR login — returns a |
| Log out and delete the local session |
Chats
Tool | Purpose |
| Recent dialogs with unread counts and last message |
| Info about chat/user/channel (+ bio/about, member count) |
| Account folders |
| Join via |
| Leave a group/channel |
Messages
Tool | Purpose |
| Message history (pagination) |
| A single message with attachment details |
| Search (global or per chat) |
| Send text |
| Edit your message |
| Delete (for everyone / for yourself) |
| Forward |
| Pin / unpin |
| Add/remove a reaction |
| Mark as read |
Media
Tool | Purpose |
| Send a local file |
| Download attachment, return path |
Contacts and people
Tool | Purpose |
| Your own profile |
| Resolve |
| Global search for people and public chats/channels |
| Group/channel members |
| Account address book |
✱ — mutating tool, disabled by the TELEGRAM_MCP_READONLY=1 flag.
Configuration (environment variables)
Variable | Purpose |
| Required. Credentials from my.telegram.org |
| State directory (default |
| Session file path (default |
| Fernet key; empty = auto-generated in |
| Path to the auto-generated key file |
|
|
| Where to download attachments |
| Auto-wait threshold for FloodWait, sec (default 60) |
Variables are read from the environment and from .env in the current directory.
How it works
src/telegram_mcp/
__main__.py # `python -m telegram_mcp` → stdio-сервер; флаг --self-check
app.py # сборка MCP-приложения: lifespan (один клиент на процесс) + тулзы
client.py # рантайм: подключение, вход, разрешение пиров, флуд-хендлинг
session.py # шифрование StringSession (Fernet) и хранение на диске
serialize.py # Telethon-объекты → компактный JSON для агента
errors.py # человекочитаемые ошибки входа/лимитов
login.py # интерактивный CLI первого входа
tools/ # auth, dialogs, messages, media, contactsA single shared TelegramClient is started in the server lifespan (inside its event
loop, as Telethon requires) and reused by all tools. Peers are resolved with
dialog cache warming, Telegram errors are translated into readable text, and the session
between runs is read from the encrypted file.
Development
.venv\Scripts\python -m telegram_mcp --self-check # собрать и показать список тулз
.venv\Scripts\pytest # офлайн-тесты (без сети и Telegram)Tests do not touch the network: they cover session encryption, link parsing in
resolve, serialization, config, the read-only mode guard, and registration of all
tools via the real MCP stdio protocol.
License
MIT.
Available Tools
28 toolsauth_statusA
Статус подключения и входа: подключён ли клиент, авторизован ли аккаунт, включён ли режим только-чтение, и кто вошёл (если вошёл).
Inputs: no named parameters. Returns: object
delete_messagesA
Удалить сообщения. revoke=true — у всех; false — только со своей стороны.
Inputs: chat (required), message_ids (required), revoke. Returns: object
download_mediaB
Скачать вложение сообщения в локальный файл. Возвращает путь. По умолчанию — в TELEGRAM_MCP_DOWNLOAD_DIR.
Inputs: chat (required), message_id (required), out_dir. Returns: object
edit_messageC
Изменить своё сообщение по id.
Inputs: chat (required), text (required), message_id (required), parse_mode, +1 more. Returns: object
forward_messagesB
Переслать сообщения из одного чата в другой. drop_author=true убирает шапку «Переслано от» — у получателя выглядит как обычное сообщение.
Inputs: to_chat (required), from_chat (required), message_ids (required), drop_author. Returns: object
get_chatA
Информация о чате/пользователе/канале: id, тип, название/@username, число участников и описание (bio/about), если доступны. chat — id, @username, ссылка t.me, телефон или me.
Inputs: chat (required). Returns: object
get_chat_foldersB
Папки (folders) аккаунта: их id и названия.
Inputs: no named parameters. Returns: result
get_contactsA
Список контактов аккаунта (адресная книга Telegram).
Inputs: no named parameters. Returns: result
get_historyA
Сообщения чата, новые первыми. before_id — брать сообщения старше этого id (пагинация вглубь истории). from_user — только от указанного отправителя.
Inputs: chat (required), limit, before_id, from_user. Returns: result
get_meB
Профиль текущего вошедшего аккаунта.
Inputs: no named parameters. Returns: object
get_messageA
Одно сообщение по id (с деталями вложения, если есть).
Inputs: chat (required), message_id (required). Returns: object
get_participantsA
Участники группы/канала. query — фильтр по имени/@username. Для больших каналов Telegram отдаёт участников не полностью — это ограничение Telegram.
Inputs: chat (required), limit, query. Returns: result
join_chatA
Вступить в группу/канал по @username, публичной ссылке t.me/name или ссылке-приглашению t.me/+hash (t.me/joinchat/hash).
Inputs: link (required). Returns: object
leave_chatA
Покинуть группу/канал. Требует confirm=true. chat — id, @username или ссылка.
Inputs: chat (required), confirm. Returns: object
list_dialogsB
Последние диалоги (чаты) с непрочитанными и последним сообщением, новые первыми. archived=true — папка «Архив». query — подстрока названия (без учёта регистра).
Inputs: limit, query, archived. Returns: result
login_completeA
Завершить вход. Передайте code из сообщения Telegram; если включена двухфакторная аутентификация — затем вызовите с password=... . Для входа по QR вызовите без аргументов после сканирования.
Inputs: code, password. Returns: object
login_qrA
Начать вход по QR-коду: вернёт ссылку tg://login. Отсканируйте её уже залогиненным Telegram (Настройки → Устройства → Подключить устройство), затем вызовите login_complete() без аргументов.
Inputs: no named parameters. Returns: object
login_send_codeA
Первый шаг входа по номеру: Telegram пришлёт код. phone — в международном формате, например +79991234567. Затем вызовите login_complete(code=...).
Inputs: phone (required). Returns: object
logoutA
Выйти из аккаунта в Telegram и удалить локальную сессию. Требует confirm=true, так как отменяет авторизацию userbot.
Inputs: confirm. Returns: object
mark_readA
Отметить чат прочитанным — до max_id включительно или весь.
Inputs: chat (required), max_id. Returns: object
pin_messageB
Закрепить сообщение. notify=false — без уведомления участникам.
Inputs: chat (required), message_id (required), notify. Returns: object
resolve_chatA
Разрешить ссылку в сущность Telegram: @username, телефон, ссылку t.me, числовой id или me. Возвращает id, тип и основные поля.
Inputs: query (required). Returns: object
search_messagesA
Поиск сообщений по тексту. Без chat — глобально по всем чатам; с chat — внутри него. from_user работает вместе с chat.
Inputs: query (required), chat, limit, from_user. Returns: result
search_publicA
Глобальный поиск в Telegram по людям, публичным группам и каналам (по имени/@username). Минимум 3 символа.
Inputs: query (required), limit. Returns: result
send_fileA
Отправить локальный файл (фото/видео/документ/аудио). caption — подпись (parse_mode: md|html|none). as_voice — как голосовое, as_video_note — как «кружок», force_document — как файл без предпросмотра. Для видео при наличии ffprobe проставляются размеры/длительность для нормального воспроизведения.
Inputs: chat (required), path (required), caption, as_voice, +3 more. Returns: object
send_messageB
Отправить текстовое сообщение. parse_mode: md | html | none. reply_to — id сообщения, на которое отвечаем. silent — без звука уведомления.
Inputs: chat (required), text (required), silent, reply_to, +2 more. Returns: object
send_reactionA
Поставить реакцию emoji на сообщение; emoji=None (или пусто) — снять реакцию. big=true — крупная анимация.
Inputs: chat (required), message_id (required), big, emoji. Returns: object
unpin_messageD
Снять закрепление с сообщения.
Inputs: chat (required), message_id (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 28 tools
Most tools map to distinct actions, but get_chat and resolve_chat both work with chat identifiers and return entity information, and get_me overlaps with get_chat(me). The detailed descriptions clarify the differences, so confusion is possible but not severe.
The dominant pattern is verb_noun (get_chat, send_message, list_dialogs, delete_messages). A few names break the pattern (auth_status is a noun phrase, login_send_code/login_complete are compound verbs), but the conventions are otherwise consistent and predictable.
At 28 tools, this is on the heavy side; Telegram's API is broad, and each tool covers a distinct operation, so there is little duplication. Still, the count exceeds the typical 3-15 range and feels somewhat bloated compared to more focused servers.
Core workflows are well covered: authentication, listing/searching chats and messages, and full message lifecycle (send, edit, delete, forward, pin, react). Gaps like creating chats, managing participants, or updating account profile are minor for a userbot-oriented server.
Maintenance
Related MCP Connectors
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Hosted Telegram MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Unofficial Telegram MCP server — read, search, reply and react in your own Telegram account.
Remote MCP server for AI.TV creators — delegate account operations to your AI agent over MCP.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables MCP clients to interact with Telegram user accounts, providing tools for messaging, contacts, groups, channels, and media management through the Telegram API.853-
- AlicenseAqualityDmaintenanceEnables use of a personal Telegram account within MCP clients for reading and sending messages, searching chats, and managing media, all running locally.1612 npmMIT
- FlicenseNot gradedqualityCmaintenanceEnables users to interact with their own Telegram account through MTProto, supporting chat listing, message reading and searching, sending messages, and fetching contacts via MCP tools.-
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to drive a real Telegram account, exposing chats, messages, media, secret chats, admin rights, invite links, Mini Apps, and multi-account routing as callable tools.32GPL 3.0