tdl-mcp
Provides read-only access to a personal Telegram account, enabling listing chats, reading recent messages, and downloading media files, without sending or modifying any data.
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., "@tdl-mcpShow the last 10 messages from @technews"
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.
tdl-mcp
Read-only Telegram access for Claude and other MCP hosts, powered by the
tdl CLI.
List your chats, read recent messages, and download media β from your own Telegram account β with five simple tools. It never sends messages, never modifies anything, and never touches your login.
π°π· νκ΅μ΄ λ¬Έμλ μ¬κΈ° μμ΅λλ€ β README.ko.md
Why tdl-mcp?
Most Telegram MCP servers embed an MTProto library (Telethon, gramjs, β¦),
ask you to create your own Telegram application at my.telegram.org to get an
api_id/api_hash, and many of them can send messages on your behalf.
tdl-mcp takes a different, deliberately boring approach:
Read-only by design. The server can list chats, export messages and download files. That's all. There is no code path that sends, edits, deletes, or logs in.
No
api_id/api_hashsetup. Login is handled once, by you, in your terminal withtdl login -T qrβ scan a QR code with your phone and you're done. No Telegram app registration needed.Built on a battle-tested downloader.
tdl(7.5k+ β) does the heavy lifting: fast parallel downloads, resume,--skip-samededuplication.Tiny and auditable. One plain-JavaScript file, two dependencies (
@modelcontextprotocol/sdk,zod), no build step. You can read the whole server in five minutes.
Claude / MCP host βstdioβ tdl-mcp (Node) βsubprocessβ tdl CLI βMTProtoβ TelegramRelated MCP server: Telegram MCP Server
Quick start
1. Install tdl
# macOS
brew install telegram-downloader
# Linux / WSL
curl -sSL https://docs.iyear.me/tdl/install.sh | sudo bash
# Windows (PowerShell)
iwr -useb https://docs.iyear.me/tdl/install.ps1 | iexAny version from the one pinned in .tdl-version upward
should work β CI continuously tests against that pin (see
Compatibility).
2. Log in to Telegram (once)
tdl login -T qrScan the QR code with the Telegram mobile app
(Settings β Devices β Link Desktop Device). The session is stored in
~/.tdl on your machine and shared by every MCP host β you log in exactly
once. tdl-mcp itself never performs or refreshes logins.
3. Add the server to your MCP host
You need Node.js β₯ 18.
Claude Code:
claude mcp add --scope user telegram -- npx -y tdl-mcpClaude Desktop / any other MCP host (generic mcpServers JSON):
{
"mcpServers": {
"telegram": {
"command": "npx",
"args": ["-y", "tdl-mcp"]
}
}
}4. Try it
Ask your assistant things like:
"What Telegram chats do I have? Find the one about quant trading."
"Show me the last 20 messages in @some_channel."
"Download every PDF posted in that channel since message 1500 to ~/Papers."
If a tool reports that you are not logged in, run tdl login -T qr in a
terminal and retry β that's the only manual step there is.
Tools
Tool | Arguments | What it does |
| β | Checks whether the tdl session is logged in. Never errors: returns |
|
| Lists dialogs as |
|
| Exports recent media messages from a chat as compact |
|
| Downloads media from a chat with |
|
| Downloads the media of specific messages by link. Validates every url starts with |
chat accepts either a numeric id or an @username/domain, exactly as shown
by tg_chats.
Environment variables
Variable | Effect |
| Path to the tdl binary. Default: |
| tdl namespace, passed as |
Set them in your host's server config, e.g.:
{
"mcpServers": {
"telegram": {
"command": "npx",
"args": ["-y", "tdl-mcp"],
"env": { "TDL_NS": "work" }
}
}
}Compatibility & staying up to date
tdl-mcp shells out to the tdl CLI, so its real dependency is tdl's
command-line surface. That surface is guarded automatically:
.tdl-versionpins the tdl release this package is tested against.scripts/contract.mjsverifies β without logging in β that every flag the server uses (chat ls -o json,chat export -c/-T/-i/-o/--with-content,dl -f/-u/-i/-d/--skip-same, global-n) still exists in that tdl binary. CI runs it on every push and PR.A scheduled workflow watches tdl releases. When a new version appears it runs the contract test against the new binary and scans the release notes for breaking-change markers. Routine updates become a simple version-bump PR; anything suspicious is escalated to an AI-assisted upgrade PR that adapts the wrapper code.
So if you're on a newer tdl than the pin, chances are excellent everything just works β and if it ever wouldn't, this repo finds out before you do.
Development
git clone https://github.com/rixile9999/tdl-mcp.git
cd tdl-mcp
npm install
npm test # smoke (MCP protocol, login-free) + contract (tdl CLI surface)npm run smokespawns the server over stdio and checks the tool catalog,tg_statusshape, and input validation β passes whether or not you are logged in.npm run contractchecks the installed tdl binary against the CLI surface the server uses.scripts/install-tdl.sh [vX.Y.Z]installs a specific (checksum-verified) tdl release if you want to test against another version.
PRs welcome. Please keep the server read-only β tools that send, edit or delete are out of scope for this project.
Security notes
The tdl session in
~/.tdlis a full user-account credential β anyone who can read it can act as your Telegram account. Protect it like an SSH key: don't copy it into repos, shared backups, or other machines.tdl-mcpnever reads or transmits the session itself; it only runs thetdlbinary locally. Nothing leaves your machine except tdl's own Telegram traffic.Downloads go to a directory you choose (
dest), defaulting to~/Downloads/telegram.
Telegram terms-of-service note
tdl drives a regular user session (MTProto), not a bot. Quiet, read-only,
personal-use automation of your own account is generally tolerated, but
aggressive crawling can get an account limited: keep ranges modest
(last_n, since_id), avoid large parallel pulls, and let --skip-same do
its job instead of re-downloading.
License
MIT for everything in this repository.
tdl itself is a separate project licensed under
AGPL-3.0. tdl-mcp does
not bundle, link, or modify tdl β it invokes the binary you installed as a
separate process, so the AGPL applies to tdl, not to this wrapper. You install
tdl yourself through official channels (step 1 above).
Available Tools
5 toolstg_chatsList Telegram chatsA
List the Telegram dialogs (chats/channels/groups/users) visible to the logged-in session, as [{id, type, name, username}]. Use it to find the chat id or @username to pass as chat to tg_messages / tg_download. Optional filter does a case-insensitive substring match on name/username/id.
| Name | Required | Description | Default |
|---|---|---|---|
| filter | No | Case-insensitive substring to match against chat name, username or id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description bears full burden. Discloses output format and that it lists dialogs visible to the logged-in session. No mention of destructive actions, appropriate for a read-only tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with core purpose and output, second sentence adds usage and parameter detail. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a simple list tool with one optional parameter and no output schema, the description covers all necessary aspects: purpose, output format, usage, and parameter behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (one parameter fully described in schema). Description restates the filter purpose: 'case-insensitive substring match on name/username/id.' Adds minimal value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it lists Telegram dialogs visible to the session and specifies output format. Distinguishes from sibling tools like tg_messages and tg_download by clarifying its role in finding chat IDs or usernames for use with those tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use: to find chat id or @username for tg_messages/tg_download. Mentions optional filter for matching. Lacks explicit when-not-to-use statements, but context is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tg_downloadDownload Telegram media from a chatA
Download media files from one chat (by id or @username) to a local directory and return the absolute paths of newly downloaded files. Use extensions (csv, e.g. 'xlsx,pdf') to fetch only certain file types; since_id for 'everything new after message X'; last_n for 'the latest N media messages' (default 100). Already-present files are skipped (--skip-same).
| Name | Required | Description | Default |
|---|---|---|---|
| chat | Yes | Chat id or @username/domain (as shown by tg_chats) | |
| dest | No | Destination directory (default ~/Downloads/telegram) | |
| last_n | No | How many recent media messages to consider (default 100) | |
| since_id | No | Only messages with id > since_id (overrides last_n) | |
| extensions | No | Comma-separated file extensions to include, e.g. 'xlsx,pdf' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full disclosure burden. It explains the tool returns absolute paths of newly downloaded files and skips already-present files (--skip-same). This addresses key behaviors, though it omits permissions, rate limits, or error handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: first states the core action and return value, second gives parameter usage hints. It is front-loaded, concise, and every sentence adds necessary information without waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 5 parameters, no output schema, and no annotations, the description covers the main purpose, return value, parameter behaviors, and skip-same behavior. It does not address prerequisites (e.g., authentication) or error scenarios, but it is largely complete for typical use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds value beyond schema: provides examples for extensions ('xlsx,pdf'), explains since_id as 'everything new after message X', and clarifies last_n as 'latest N media messages' with default 100. This enriches parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool downloads media files from a single chat to a local directory and returns paths of newly downloaded files. It specifies the resource (media files from one chat) and the action (download), distinguishing it from siblings like tg_download_url (URL downloads) and tg_chats (chat listing).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides usage guidance for parameters (extensions, since_id, last_n) and notes default behavior (last_n default 100) and skip-same behavior. However, it does not explicitly state when to choose this tool over siblings (e.g., tg_download_url for URL downloads, tg_messages for text), limiting differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tg_download_urlDownload Telegram media by t.me linkA
Download the media of specific Telegram messages given their t.me links (e.g. https://t.me/channel/123) and return the absolute paths of newly downloaded files. Use when you already have message links rather than a chat to scan. Already-present files are skipped (--skip-same).
| Name | Required | Description | Default |
|---|---|---|---|
| dest | No | Destination directory (default ~/Downloads/telegram) | |
| urls | Yes | Telegram message links; each must start with https://t.me/ | |
| extensions | No | Comma-separated file extensions to include, e.g. 'xlsx,pdf' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses a key behavior: 'Already-present files are skipped (--skip-same).' It also states it returns absolute paths of newly downloaded files. This is adequate for a download tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with purpose and usage. It is concise and informative, with no wasted words. The behavioral note about skipping existing files is well integrated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 3 parameters with full schema coverage and no output schema, the description sufficiently explains purpose, when to use, and a behavioral note. It is complete for this straightforward tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers all 3 parameters with descriptions (100% coverage). The description adds no additional parameter meaning beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Download the media of specific Telegram messages given their t.me links' with an example URL. It distinguishes itself from sibling tools like tg_download by specifying it uses direct links rather than scanning a chat.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use when you already have message links rather than a chat to scan,' providing clear context for when to use this tool. While it doesn't explicitly state when not to use it, the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tg_messagesRead recent Telegram messagesA
Export recent media messages from one chat (by id or @username) and return them as compact {id, date, file, text} objects β newest range exported via tdl. Use last_n for 'the last N media messages', or since_id to fetch only messages after a known message id (incremental reads). Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| chat | Yes | Chat id or @username/domain (as shown by tg_chats) | |
| last_n | No | How many recent media messages to export (default 50, max 500) | |
| since_id | No | Only messages with id > since_id (overrides last_n; for incremental reads) | |
| with_text | No | Include message text content (default true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavior. It states read-only and mentions the output format and parameter overrides (since_id overrides last_n). However, it does not disclose potential rate limits, auth requirements, or what happens if no media messages are found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise, consisting of two functional sentences plus a standalone 'Read-only.' It is front-loaded with the main action and every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately explains the return format and the two primary use cases. It does not define 'media messages' or mention error handling, but it is otherwise complete for a read-only tool with clear parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, baseline 3. The description adds valuable context beyond the schema: explains the difference between last_n and since_id, notes that since_id overrides last_n, and describes the output format compact objects. It also implies the chat parameter can be id or @username, matching the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool exports recent media messages from a single chat, using a specific verb ('Export') and resource ('recent media messages from one chat'). It distinguishes from siblings like tg_chats (which lists chats) and tg_download (which downloads files).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use last_n vs since_id (incremental reads). It says 'Read-only' but does not specify when not to use this tool or mention alternatives like tg_download or tg_status for other operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tg_statusTelegram session statusA
Check whether the local tdl Telegram session is logged in and usable. Call this first if another tg_* tool fails or before starting Telegram work. Never errors β returns {logged_in:false, hint} when the session is missing.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description carries full burden. It discloses that the tool never errors and returns {logged_in:false, hint} when missing, covering error handling and output format. However, it omits details about side effects or performance, but these are minimal for a status check.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. The first sentence states purpose, the second adds usage guidance and behavior. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, no output schema, and low complexity, the description covers purpose, usage, and behavior. It lacks explanation of what 'hint' contains or what 'usable' means, but these are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so schema coverage is 100% and the description need not add parameter info. Baseline 4 is appropriate as the description adds no parameter details but doesn't need to.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Check') and resource ('local tdl Telegram session'), clearly stating its function to verify login status. It distinguishes itself from siblings by being a diagnostic tool to call before other tg_* tools, though not explicitly mentioning what it doesn't do.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises calling this tool first if another tg_* tool fails or before starting Telegram work, providing clear context for when to use it. No alternatives are needed given its singular purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.0.0- First observed
tg_chats - First observed
tg_download - First observed
tg_download_url - First observed
tg_messages - First observed
tg_status
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose: listing chats, downloading media by chat, downloading media by URL, exporting message metadata, and checking session status. The two download tools are differentiated by source (chat vs. message links), and tg_messages returns metadata, not files, avoiding overlap.
All tools share the 'tg_' prefix, but the naming pattern is inconsistent: some use nouns (tg_chats, tg_messages, tg_status) and others use verbs (tg_download, tg_download_url). This mix could be confusing; a consistent verb_noun pattern would improve predictability.
With 5 tools, the server covers the core functionality of a Telegram media downloader (chat discovery, message inspection, two download methods, and status check) without unnecessary duplication or missing essentials.
The tool surface covers the main workflow: find chats, list messages, download media, and verify session. Minor gaps exist, such as the lack of date-range filtering or a direct login/logout tool, but these are not critical for common use cases.
Maintenance
Related MCP Connectors
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Search your AI chat history (ChatGPT, Claude, Codex) from any MCP client. Remote, private, read-only
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client β Claude, ChatGPT, Cursor, Cline, Windsurf.
Multi-tenant Telegram gateway for AI agents β HTTP+stdio, 8 tools, MTProto User API
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA read-only Telegram MCP server that retrieves messages from your DMs, groups, and channels, enabling Claude to generate executive briefings from Telegram conversations.MIT
- AlicenseNot gradedqualityBmaintenanceA Telegram integration for Claude, Cursor, and other MCP-compatible clients. It exposes Telegram account, chat, message, contact, media, folder, and admin operations through the Model Context Protocol using Telethon.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceA Telegram integration for Claude, Cursor, and other MCP-compatible clients. It exposes over 80 tools for account, chat, message, contact, media, folder, and admin operations through the Model Context Protocol.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants like Claude to read, search, and send messages through your personal Telegram account via MCP tools.MIT