telegram-mcp-server
Use a logged-in Telegram user account to read chats/messages/media and send messages/files through MCP.
Verify the session/account with
get_me.List groups, channels, and DMs, optionally filtering by title.
Read recent messages or paginate through a chat, with optional in-chat text filtering.
Search messages globally or scoped to a specific chat.
Download media from specific messages or fetch recent media by type.
Send text messages and local files as the logged-in user.
Resolve chats by id,
@username, or title, with errors on ambiguous matches.
Provides tools for reading chats, messages, and media, and sending messages and files via Telegram using a user account.
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-server get last 5 messages in group 'Test Group'"
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-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
API-Credentials auf https://my.telegram.org (API development tools) erzeugen.
Repo installieren (venv + editierbar; Python ≥3.10):
python3 -m venv .venv .venv/bin/pip install -e .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"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-serverDie -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 |
| Whoami / Session-Check |
| Chats auflisten (Gruppe/Kanal/DM) |
| Nachrichten eines Chats lesen |
| Nachrichten suchen (global oder im Chat) |
| Medien gezielter Nachrichten laden |
| Letzte N Medien eines Chats laden |
| Textnachricht senden |
| 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/ -vTests 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_DIRErster 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 toolsdownload_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
Scored across 8 tools
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.
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.
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.
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
Related MCP Connectors
I use your linked Telegram MTProto session (Integrations → Telegram) to list groups, members, and s…
Read chats and members; send, edit and delete messages with a bot in Telegram.
Multi-tenant Telegram gateway for AI agents — HTTP+stdio, 8 tools, MTProto User API
Hosted Telegram MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables 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-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to control a personal Telegram account for sending/reading messages, media, group management, and more via the MTProto API.MIT
- 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
- AlicenseBqualityCmaintenanceEnables 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.28MIT