Skip to main content
Glama
telegram-mcp-server

telegram-mcp-server

by Schimmilab

telegram-mcp-server

MCP-Server für Telegram über einen User-Account (MTProto/Telethon). Liest Chats/Nachrichten/Medien und sendet Nachrichten/Dateien. Läuft lokal über stdio.

Warum User-Account statt Bot?

Ein Bot kann keine Gruppen-Historie und keine vor seinem Beitritt geposteten Medien lesen (und hat ein 20-MB-Download-Limit). Für „hol mir die Bilder aus der Gruppe" braucht es einen User-Client. Session-Datei = voller Account-Zugriff → lokal halten, chmod 600, nie committen.

Related MCP server: Telegram MCP Server

Setup

  1. API-Credentials auf https://my.telegram.org (API development tools) erzeugen.

  2. Repo installieren (venv + editierbar; Python ≥3.10):

    python3 -m venv .venv
    .venv/bin/pip install -e .
  3. Environment setzen:

    export TELEGRAM_API_ID=...
    export TELEGRAM_API_HASH=...
    export TELEGRAM_PHONE=+49...        # nur für den Login nötig
    # optional:
    export TELEGRAM_SESSION="$HOME/.telegram-mcp/telegram.session"
    export TELEGRAM_DOWNLOAD_DIR="$HOME/Downloads/telegram-mcp"
  4. Einmalig einloggen (erzeugt die Session-Datei, fragt Code + ggf. 2FA):

    .venv/bin/python -m telegram_mcp_server.login

In Claude Code registrieren

claude mcp add telegram \
  -e TELEGRAM_API_ID=... \
  -e TELEGRAM_API_HASH=... \
  -e TELEGRAM_SESSION="$HOME/.telegram-mcp/telegram.session" \
  -- /ABSOLUTER/PFAD/telegram-mcp-server/.venv/bin/telegram-mcp-server

Die -e-Flags sind nötig, weil ein von Claude Code gestarteter MCP-Server die Shell-exports aus dem Setup NICHT erbt. Alternativ die env-Sektion in der MCP-Konfiguration nutzen. TELEGRAM_DOWNLOAD_DIR optional per weiterem -e setzen. Nach dem Registrieren eine neue Claude-Code-Session starten, damit der Server erscheint.

Tools

Tool

Zweck

get_me

Whoami / Session-Check

list_chats(query?, limit)

Chats auflisten (Gruppe/Kanal/DM)

get_messages(chat, limit, before_id?, search?)

Nachrichten eines Chats lesen

search_messages(query, chat?, limit)

Nachrichten suchen (global oder im Chat)

download_media(chat, message_ids[], dest_dir?)

Medien gezielter Nachrichten laden

get_recent_media(chat, limit, kind?, dest_dir?)

Letzte N Medien eines Chats laden

send_message(chat, text)

Textnachricht senden

send_file(chat, file_path, caption?)

Datei/Bild senden

chat akzeptiert Chat-id, @username oder (Teil-)Titel; bei mehrdeutigem Titel kommt ein Fehler mit den Treffern statt einer Rate-Auflösung.

get_messages/search_messages liefern pro Nachricht auch chat_id mit — Treffer aus der globalen Suche sind damit direkt in weiteren Tool-Aufrufen (z.B. download_media) verwendbar.

Mehrere gleichzeitige Sessions

Jeder MCP-Client startet einen eigenen Serverprozess. Alle zeigen auf dieselbe Session-Datei, und Telethon legt darin veraenderlichen Zustand ab — vor allem update_state. SQLiteSession.set_update_state schreibt mit insert or replace, also ein blindes Ueberschreiben ohne Vergleich.

Gemessen am 14.09.2026 an einer Kopie einer echten Session: Zwei Schreiber verwerfen gegenseitig ihren Stand — 4997 Update-Positionen still verloren, kein Fehler. Dazu nutzt die Datei journal_mode=delete (kein WAL), ein Schreiber sperrt also die ganze Datei; ein konkurrierender Schreibvorgang scheitert nach dem 5-s-Standardtimeout mit database is locked.

Deshalb liest der Server aus einer prozesseigenen Kopie und schreibt nie zurueck (_private_session_copy). Kopiert wird ueber SQLites Backup-API, nicht per Dateikopie: Ein anderer Prozess kann mitten im Schreiben sein, und eine einfache Kopie kann eine halb geschriebene Seite erwischen.

Was das kostet: Der Entitaeten-Cache waechst nicht mehr ueber Prozesse hinweg, es gibt also etwas mehr Aufloese-Aufrufe. Fuer Lesen und Senden wird nur der auth_key gebraucht; update_state und der Cache sind Beschleuniger.

login.py ist davon nicht betroffen und schreibt weiterhin die echte Datei.

⚠️ Der naheliegende Fix receive_updates=False traegt nicht: Er schaltet nur den Zufluss ab. Der set_update_state-Aufruf in Telethons telegrambaseclient.py laeuft beim Disconnect und ist nicht von _no_updates geschuetzt — geschrieben wird trotzdem.

Entwicklung / Tests

python3 -m venv .venv && .venv/bin/pip install -e ".[test]"
.venv/bin/python -m pytest tests/ -v

Tests laufen ohne Live-Account (Client wird gemockt).

Smoke-Test (einmalig nach Login, mit echtem Account)

.venv/bin/python -m telegram_mcp_server.login        # 1) Session erzeugen
# 2) get_me / list_chats / get_messages / download_media manuell über den
#    MCP-Client (Claude Code) prüfen:
#    - get_me                         -> zeigt deinen Account
#    - list_chats query="<gruppe>"    -> findet eine deiner Gruppen
#    - get_messages chat=<id> limit=5 -> liefert Nachrichten
#    - search_messages query="..."    -> globale Suche (übt _search_global live aus;
#                                         Treffer müssen chat_id tragen)
#    - get_recent_media chat=<id> kind="photo" -> lädt Fotos nach $TELEGRAM_DOWNLOAD_DIR

Erster echter Integrationstest = ein Medienabruf aus einer deiner Gruppen. Die globale search_messages (ohne chat) ist der einzige Pfad, der _search_global/SearchGlobalRequest real ausführt — im Smoke-Test nicht überspringen.

Maintainer

Schimmi — https://schimmilab.de Issues und Pull Requests willkommen.

Available Tools

8 tools
download_mediaA

Download media from specific messages to disk.

Args: chat: Chat id/@username/title. message_ids: Message ids whose media should be downloaded. dest_dir: Target directory (default TELEGRAM_DOWNLOAD_DIR).

Returns [{message_id, path}] for messages whose media downloaded successfully; non-media and undownloadable media are skipped. Paths are absolute.

Inputs: chat (required), message_ids (required), dest_dir. Returns: result

get_meA

Return the logged-in Telegram account (id, username, first_name, phone).

Doubles as a session check — errors if no valid session exists.

Inputs: no named parameters. Returns: object

get_messagesA

Read recent messages from one chat.

Args: chat: Chat id, @username, or exact/substring title. limit: Max messages (default 30, capped at 200). before_id: Only messages older than this message id (pagination). search: Optional full-text filter within the chat.

Returns message dicts (id, chat_id, date, sender_id, text, has_media, media_type).

Inputs: chat (required), limit, search, before_id. Returns: result

get_recent_mediaA

Download the most recent media items from a chat.

Args: chat: Chat id/@username/title. limit: How many recent messages to scan (default 20, capped at 200). kind: Optional filter — 'photo' / 'video' / 'document' / 'other'. dest_dir: Target directory (default TELEGRAM_DOWNLOAD_DIR).

Returns [{message_id, kind, path}] for successfully downloaded media. This is the fast path for pulling images out of a group (e.g. the Arcanara Juni-Treffen photos). Paths are absolute.

Inputs: chat (required), kind, limit, dest_dir. Returns: result

list_chatsA

List chats (groups, channels, direct messages).

Args: query: Optional case-insensitive substring filter on the chat title. When set, ALL dialogs are scanned so a match beyond the most-recent limit chats is still found (comparatively expensive, like title resolution); limit then caps the number of matches returned. limit: Max results (default 50, capped at 500). Without query this is also how many dialogs are fetched.

Returns objects with id, title, type ('group'/'channel'/'user'), unread. Use this to find a chat's id/title before calling other tools.

Inputs: limit, query. Returns: result

search_messagesA

Search messages by text — globally or within one chat.

Args: query: Non-empty search string. chat: Optional chat id/@username/title to scope the search. limit: Max results (default 30, capped at 200).

Returns message dicts (id, chat_id, date, sender_id, text, has_media, media_type).

Inputs: query (required), chat, limit. Returns: result

send_fileA

Send a local file (image/document) to a chat as the logged-in user.

This is a real, irreversible send, visible to the chat's members, and cannot be recalled via this API — confirm the chat and file before calling.

Args: chat: Chat id/@username/title. file_path: Absolute path to an existing local file. caption: Optional caption text.

Returns {"sent": True, "message_id": }.

Inputs: chat (required), file_path (required), caption. Returns: object

send_messageA

Send a text message to a chat as the logged-in user.

This is a real, irreversible send, visible to the chat's members, and cannot be recalled via this API — confirm the chat and text before calling.

Args: chat: Chat id/@username/title. text: Non-empty message text.

Returns {"sent": True, "message_id": }.

Inputs: chat (required), text (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.4/5.0

    Scored across 8 tools

    Disambiguation4/5

    Tools mostly have distinct purposes. download_media and get_recent_media both handle media downloads but are differentiated by targeted vs. bulk recent retrieval. All other tools are clearly distinct.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in snake_case (e.g., download_media, list_chats, send_message), making the set predictable and easy to navigate.

    Tool Count5/5

    8 tools is well-scoped for a Telegram messaging interface, covering essential operations like reading messages, searching, listing chats, sending messages/files, and downloading media without being overwhelming.

    Completeness4/5

    Core functionality is covered: read, search, send, download. Minor gaps such as no delete, edit, or forward tools, but these are optional for many use cases and the set feels complete for basic messaging automation.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to control a real Telegram user account via MTProto, allowing message sending, chat reading/searching, and message management through MCP tools.
      37 npm
      -
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI assistants to control a personal Telegram account for sending/reading messages, media, group management, and more via the MTProto API.
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Enables use of a personal Telegram account within MCP clients for reading and sending messages, searching chats, and managing media, all running locally.
      16
      12 npm
      MIT
    • A
      license
      B
      quality
      C
      maintenance
      Enables MCP clients to operate a Telegram account as a userbot, providing tools for reading and sending messages, searching chats and contacts, managing media, and performing other account actions via MTProto with a locally encrypted session.
      28
      MIT