Skip to main content
Glama
bssth

telegram-mcp

by bssth
README.md
# telegram-mcp

**Локальный MCP-сервер для работы с Telegram через userbot-сессию.**

Даёт агентам ([Claude Code](https://docs.claude.com/en/docs/claude-code) и любым
другим MCP-клиентам) набор инструментов для чтения и отправки сообщений, поиска,
работы с чатами, контактами и медиа — от лица вашего Telegram-аккаунта, через
[Telethon](https://docs.telethon.dev/) (MTProto, а не Bot API).

Работает **только по stdio** и держит сессию **локально в зашифрованном виде** —
наружу уходит лишь трафик к серверам Telegram.

---

## Зачем

Bot API умеет мало и требует бота. Userbot-сессия — это полноценный клиент: он
видит все ваши диалоги, историю, участников групп, умеет искать по всему
Telegram, слать файлы и кружки, ставить реакции. Этот сервер аккуратно
оборачивает такие возможности в 28 MCP-тулз, чтобы агент мог работать с
Telegram так же, как вы сами из приложения.

## Возможности

- **Диалоги и чаты** — список диалогов с непрочитанными, инфо о чате/канале/пользователе
  (включая bio/описание), папки, вступление и выход из групп.
- **Сообщения** — история с пагинацией, поиск (глобальный и по чату), отправка,
  правка, удаление, пересылка, закрепление, реакции, отметка о прочтении.
- **Медиа** — отправка файлов (фото/видео/документ/голосовое/кружок; для видео
  подставляются размеры и длительность через `ffprobe`), скачивание вложений.
- **Контакты и люди** — свой профиль, адресная книга, разрешение
  `@username`/телефона/ссылки в сущность, глобальный поиск людей и каналов,
  участники групп.
- **Вход** — по номеру телефона (код + 2FA) или по QR-коду, прямо из тулз или из CLI.

## Безопасность

Userbot-сессия — это **полный доступ к аккаунту**, поэтому:

- **Только stdio.** Сервер не открывает сетевой порт: общение с MCP-клиентом идёт
  через стандартный ввод/вывод. За пределы машины уходит только трафик к Telegram.
- **Сессия шифруется на диске** (Fernet). Строка сессии = ключ от аккаунта, и на
  диск она кладётся только зашифрованной, в `~/.telegram-mcp/session.enc`. Ключ
  берётся из `TELEGRAM_MCP_ENC_KEY` либо генерируется один раз в `~/.telegram-mcp/enc.key`
  с правами `0600`.
- **Режим только-чтение.** Запуск с `TELEGRAM_MCP_READONLY=1` отключает все
  изменяющие тулзы (отправка/правка/удаление/пересылка/вступление/реакции) —
  удобно для наблюдения и аудита.
- **Действия от вашего имени.** Всё, что отправляет/удаляет сервер, происходит от
  лица владельца аккаунта. Держите это в голове, давая агенту доступ.
- Первый вход лучше делать через CLI `telegram-mcp-login`: код и пароль 2FA
  вводятся в терминале и не проходят через контекст агента.

## Установка

Нужен Python ≥ 3.10.

```bash
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]"
```

Опциональные экстры:

| Экстра | Что даёт |
|---|---|
| `speed` | `cryptg` — заметно быстрее шифрование MTProto (особенно на медиа) |
| `qr` | ASCII-QR прямо в терминале при входе по QR-коду |
| `dev` | `pytest` для офлайн-тестов |

Для корректных размеров/длительности отправляемого **видео** желателен `ffmpeg`
(утилита `ffprobe`) в `PATH` — опционально, без него видео тоже отправляется.

## Настройка и вход

1. Получите `api_id` / `api_hash` на <https://my.telegram.org> →
   *API development tools*.
2. Скопируйте `.env.example` в `.env` и заполните:

   ```env
   TELEGRAM_API_ID=1234567
   TELEGRAM_API_HASH=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
   # пусто = ключ шифрования сгенерируется в ~/.telegram-mcp/enc.key
   TELEGRAM_MCP_ENC_KEY=
   ```

3. Войдите в аккаунт (один раз):

   ```bash
   telegram-mcp-login
   ```

   Спросит номер → код из Telegram → пароль 2FA (если включён), либо предложит
   вход по QR. Зашифрованная сессия ляжет в `~/.telegram-mcp/session.enc`, и
   дальше сервер поднимается уже авторизованным.

   > Вход возможен и без CLI — через тулзы `login_send_code` / `login_complete` /
   > `login_qr`. Но CLI безопаснее: секреты не попадают в контекст агента.

## Подключение к Claude Code

`.mcp.json` в проекте (или пользовательский конфиг MCP-клиента):

```json
{
  "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` — путь к `python` из вашего venv (в нём установлен пакет).
- Блок `env` можно опустить, если переменные уже заданы в системном окружении
  или в `~/.telegram-mcp/.env`.
- Проверить без клиента можно через инспектор:
  `npx @modelcontextprotocol/inspector <путь>\python.exe -m telegram_mcp`.

## Тулзы

Аргумент `chat` почти везде — строка: числовой `id`, `@username`, ссылка
`t.me/...`, номер телефона, либо `me` / `self` для «Избранного».

### Вход
| Тулза | Назначение |
|---|---|
| `auth_status` | Статус подключения и входа, кто авторизован |
| `login_send_code(phone)` | Отправить код входа на номер |
| `login_complete(code?, password?)` | Завершить вход кодом и/или паролем 2FA (или дожать QR без аргументов) |
| `login_qr()` | Начать вход по QR — вернёт ссылку `tg://login` |
| `logout(confirm)` | Выйти и удалить локальную сессию |

### Чаты
| Тулза | Назначение |
|---|---|
| `list_dialogs(limit?, archived?, query?)` | Последние диалоги с непрочитанными и последним сообщением |
| `get_chat(chat)` | Инфо о чате/пользователе/канале (+ bio/about, число участников) |
| `get_chat_folders()` | Папки аккаунта |
| `join_chat(link)` ✱ | Вступить по `@username`, ссылке или приглашению `t.me/+hash` |
| `leave_chat(chat, confirm)` ✱ | Покинуть группу/канал |

### Сообщения
| Тулза | Назначение |
|---|---|
| `get_history(chat, limit?, before_id?, from_user?)` | История сообщений (пагинация) |
| `get_message(chat, message_id)` | Одно сообщение с деталями вложения |
| `search_messages(query, chat?, from_user?, limit?)` | Поиск (глобально или по чату) |
| `send_message(chat, text, reply_to?, parse_mode?, link_preview?, silent?)` ✱ | Отправить текст |
| `edit_message(chat, message_id, text, parse_mode?)` ✱ | Изменить своё сообщение |
| `delete_messages(chat, message_ids, revoke?)` ✱ | Удалить (у всех / у себя) |
| `forward_messages(from_chat, message_ids, to_chat, drop_author?)` ✱ | Переслать |
| `pin_message` / `unpin_message` ✱ | Закрепить / открепить |
| `send_reaction(chat, message_id, emoji?, big?)` ✱ | Поставить/снять реакцию |
| `mark_read(chat, max_id?)` ✱ | Отметить прочитанным |

### Медиа
| Тулза | Назначение |
|---|---|
| `send_file(chat, path, caption?, as_voice?, as_video_note?, force_document?)` ✱ | Отправить локальный файл |
| `download_media(chat, message_id, out_dir?)` | Скачать вложение, вернуть путь |

### Контакты и люди
| Тулза | Назначение |
|---|---|
| `get_me()` | Свой профиль |
| `resolve_chat(query)` | Разрешить `@username`/телефон/ссылку/id в сущность |
| `search_public(query, limit?)` | Глобальный поиск людей и публичных чатов/каналов |
| `get_participants(chat, limit?, query?)` | Участники группы/канала |
| `get_contacts()` | Адресная книга аккаунта |

✱ — изменяющая тулза, отключается флагом `TELEGRAM_MCP_READONLY=1`.

## Конфигурация (переменные окружения)

| Переменная | Назначение |
|---|---|
| `TELEGRAM_API_ID`, `TELEGRAM_API_HASH` | **Обязательно.** Креды с my.telegram.org |
| `TELEGRAM_MCP_HOME` | Каталог состояния (по умолчанию `~/.telegram-mcp`) |
| `TELEGRAM_MCP_SESSION` | Путь к файлу сессии (по умолчанию `<HOME>/session.enc`) |
| `TELEGRAM_MCP_ENC_KEY` | Ключ Fernet; пусто = автоген в `<HOME>/enc.key` |
| `TELEGRAM_MCP_ENC_KEY_FILE` | Путь к файлу автосгенерированного ключа |
| `TELEGRAM_MCP_READONLY` | `1` = только чтение (изменяющие тулзы выключены) |
| `TELEGRAM_MCP_DOWNLOAD_DIR` | Куда скачивать вложения |
| `TELEGRAM_MCP_FLOOD_SLEEP_THRESHOLD` | Порог авто-ожидания FloodWait, сек (по умолчанию 60) |

Переменные читаются из окружения и из `.env` в текущей директории.

## Как устроено

```
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, contacts
```

Один общий `TelegramClient` поднимается в lifespan сервера (внутри его event
loop, как требует Telethon) и переиспользуется всеми тулзами. Пиры разрешаются с
прогревом кэша диалогов, ошибки Telegram переводятся в понятный текст, а сессия
между запусками читается из зашифрованного файла.

## Разработка

```bash
.venv\Scripts\python -m telegram_mcp --self-check   # собрать и показать список тулз
.venv\Scripts\pytest                                # офлайн-тесты (без сети и Telegram)
```

Тесты не ходят в сеть: покрывают шифрование сессии, разбор ссылок в
`resolve`, сериализацию, конфиг, гард режима только-чтение и регистрацию всех
тулз через реальный stdio-протокол MCP.

## Лицензия

MIT.

TDQS

B3.2/5.0

Scored across 28 tools

Disambiguation4/5

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.

Naming Consistency4/5

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.

Tool Count3/5

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.

Completeness4/5

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

ActivityMaintained
ResponsivenessNo issues