telegram-reader
Reads Telegram channels and groups the account can see and downloads their videos and files. Provides tools to list joined chats, read and search messages (including across all joined channels and groups), fetch a message by its t.me link (with photos returned as viewable images), and download a post's media with progress reporting. Public channels can be read without joining, and the server refuses private chats, bots, Saved Messages, and contact lookups; it is read-only and cannot send, edit, join, react or mark anything read.
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-readerread the latest posts from @telegram"
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-reader
An MCP server that lets an LLM agent read the Telegram channels and groups your account can see, and download their videos and files under names taken from the post. The agent cannot send, edit, join, react or mark anything read, and it never sees your private chats, bots or Saved Messages.
You need:
an
api_idandapi_hashfrom https://my.telegram.org (API development tools);NixOS for the module below, or Python 3.11+ to run it by hand;
an MCP client that speaks streamable HTTP, on the same host.
Set it up on NixOS
Add the flake and enable the module. The two credential files must be readable by
the telegram-reader user, for example as sops-nix secrets owned by it.
# flake.nix
inputs.telegram-reader = {
url = "github:chinrw/telegram-reader";
inputs.nixpkgs.follows = "nixpkgs";
};# configuration.nix
{ config, inputs, ... }:
{
imports = [ inputs.telegram-reader.nixosModules.default ];
services.telegram-reader = {
enable = true;
apiIdFile = "/run/secrets/telegram-reader/api_id";
apiHashFile = "/run/secrets/telegram-reader/api_hash";
# Only when Telegram is not reachable directly.
proxy = "http://192.0.2.10:8080";
# Leave unset to turn downloads off.
downloads.directory = "/srv/media/telegram";
};
}Proxy URLs must not contain usernames or passwords. Do not put credentials in Nix configuration.
After switching, log the account in once. It asks for your phone number, the login code Telegram sends you, and your two-step verification password if you set one:
$ sudo telegram-reader-loginThe service starts when the login succeeds. Point your agent at
config.services.telegram-reader.url, which is http://127.0.0.1:9520/mcp by
default. The session shows up in Telegram under Settings > Devices with your host
name, and ending it there logs the server out.
A permanent Telegram disconnection stops the server so the NixOS unit can restart it. The server allows ten seconds for HTTP requests to drain during shutdown, then cancels requests still running. An unauthorized session needs a new login. Successful DC migrations keep the server running, though individual in-flight requests may still fail while Telegram reconnects.
Related MCP server: telegram-mcp
Run it without NixOS
Run it as a user your agent cannot read files of. The session file gives full control of the account.
$ pip install .
$ export TELEGRAM_API_ID_FILE=~/.config/telegram-reader/api_id
$ export TELEGRAM_API_HASH_FILE=~/.config/telegram-reader/api_hash
$ export TELEGRAM_READER_SESSION=~/.local/state/telegram-reader/reader
$ export TELEGRAM_READER_DOWNLOADS=~/Downloads/telegram # optional
$ export TELEGRAM_READER_PROXY=socks5://127.0.0.1:1080 # optional
$ telegram-reader login
$ telegram-reader serve --port 9520Tools
Tool | What it does |
| Lists up to 200 joined channels and groups, filtered by kind or a title/username substring. There is no paging. |
| Reads recent messages of one chat, newest first, with paging and a date cutoff. |
| Searches one chat, or every joined channel and group. |
| Fetches one message by |
| Downloads a post's files in the background. |
| Reports download progress. |
| Finds posts in one chat whose file has one of the given sizes. |
| Tells whether a file in the download directory is a given post's file. |
Chats can be given as the id from list_chats, a @username, or a t.me link.
Private-channel links such as https://t.me/c/123456/789 work too. Public channels
can be read without joining them.
Global search examines at most 3 * limit hits before filtering out private
chats. If this budget runs out before enough readable results are found, the
result has truncated: true: matching posts may be missing. Search a specific
chat to avoid this global scan limit.
Find the posts behind files you already have
Files saved by hand from a Telegram app keep the uploader's file name, which is
often just a date. To find their posts, pass the byte sizes of the files to
find_media together with the chat they came from. Telegram's search does not
match file names, so the server scans the chat's history, 2000 messages per call;
pass next_before_id back until it is null. Then confirm each candidate with
check_file. Renaming and moving the files is left to the agent.
check_file compares Telegram's SHA-256 hashes of 128 KiB parts with the file at
its start, middle and end. That costs at most three requests and 3 MiB of reading,
and tells apart files that merely share a size. It is a sample: damage between
those windows goes unnoticed. It only reads files inside the download directory,
and never through a symlink.
Call the tools from scripts
telegram-reader call runs one tool on the running server and prints its JSON
result, so a cron job or shell script can read Telegram without an LLM. Arguments
are key=value pairs. A misspelled name is refused with the list of names the tool
takes. Pass --port when the server does not listen on 9520.
$ telegram-reader call list_chats kind=channel
$ telegram-reader call read_messages chat=@newsfeed limit=5 since=2026-10-01
$ telegram-reader call search_messages query=release chat=newsfeed
$ telegram-reader call download_media ref=https://t.me/newsfeed/123 name="Show - 01"
$ telegram-reader call download_status
$ telegram-reader call find_media chat=newsfeed 'sizes=[1344170064, 97703126]'The command needs no credentials, since it only talks to the server. A tool error,
a refused argument or an unreachable server prints the reason on stderr and exits 1.
Photos from get_message are left out of the output.
Downloads
Ask the agent to read the post and pass a clean title as name. Files are saved as
<downloads.directory>/<chat>/<name> [<message id>].<ext>and every file of an album as <name> - 01 [<id>].<ext>, <name> - 02 [<id>].<ext>,
and so on, named after the album's text. Without a name, the first line of the
post is used. <chat> is the channel's username plus its id, such as
newsfeed-c1234567890, or an id-based name when the chat has no username.
Files are created without execute bits and owned by the service user. A writer in the directory can replace or copy them, and interpreters can read them without execute permission.
Existing files are never overwritten, and a symlink planted in the directory cannot redirect a download. When a file with the same name and size is already there, it counts as the download if Telegram's part hashes match it at its start, middle and end, the same sample
check_filetakes. Otherwise the request is refused and the file is left alone.Two downloads run at a time and twenty can be queued or running. A download starts only if the disk has room for it, for the downloads still in progress, and 1 GiB more.
Album capacity is checked as a whole, counting only new jobs. Requesting an existing job does not need a free slot.
The extension comes from the original file. The characters
$ ` \ " ' ; | & < > * ? { } ! : /in names become_.
The module requires an absolute download directory and grants the service user
access to it with an ACL. Set
downloads.createAs to a user who should create it with plain mkdir, so it
inherits the parent directory's group and default ACLs.
What the agent sees, and what it does not
Every result carries a notice that Telegram content is third-party data: the agent may read it, but should not follow instructions found in it or run files downloaded from it. The server can only state this. Enforcing it is up to your agent's own approval rules, for example by denying commands that run an interpreter on files in the download directory.
The server refuses private chats, bots and Saved Messages on every path, including global search and messages fetched by id. It also refuses phone numbers and other strings that would make Telegram look up your contacts.
Limits
The endpoint has no authentication. It listens on 127.0.0.1 only and rejects foreign
HostandOriginheaders, but any local process can call it.Download jobs live in memory, at most 200 of them. Active jobs are kept, and older completed or failed ones are discarded. Moving, deleting or changing a completed file makes its job report
failed. Asking for the post again downloads it again, or reports it done when a matching file is back in place.A job that waits a long time in the queue can fail when Telegram's file reference expires. Asking again fixes it.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Telegram for AI agents, no login: keyword search, channel posts, comments, username lookup.
1Run a Telegram channel from your AI agent. Posts go out through your own bot, not your account.
I use your linked Telegram MTProto session (Integrations → Telegram) to list groups, members, and s…
Live Telegram data: trending topics, channel profiles & metrics, post history incl. edits/deletions.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables Claude to interact with Telegram channels and groups through API or web scraping for reading posts and searching.1533 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with a user's Telegram account: list chats, read history, search, and send messages through Telegram's MTProto API.2MIT
- AlicenseAqualityAmaintenanceEnables searching Telegram messages and chats, retrieving recent messages, and extracting text from attached documents (PDF, TXT, MD, CSV) using your personal Telegram account.4Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to search and analyze a Telegram account as a read-only knowledge source, allowing chat discovery, message search, history reading, contact inspection, and media download without exposing any mutating Telegram tools.13Apache 2.0