Telegram MCP
This server provides an MCP interface to a Telegram user account, enabling read/search of messages and chats, media retrieval, and (when enabled) sending/editing messages.
Search messages globally across all chats, with filters by date, chat type, and public username.
Read chat history (DMs, groups, channels, Saved Messages) with text search, fetching by message IDs, and loading reply threads/forum topics.
Fetch photos/images inline as base64 from messages; non-image files get download links, and voice/round video points to transcription.
Open public Yandex.Disk links and return images inline, recursing into subfolders.
Find chats/users by name, username, phone, folder, or activity dates.
Get chat profile/metadata, including forum topics.
Send messages with optional attachments (URLs, local paths, or data URIs), parse modes, and reply-to.
Edit existing messages.
Send messages to phone numbers (may create a temporary contact).
Send rich messages (markdown tables/headings) via a configured bot.
Note: sending and editing require explicit opt-in via ACL; defaults are read-only.
Provides controlled access to a Telegram user account, allowing MCP clients to search and read messages, inspect chats, fetch media, and optionally send or edit messages after explicit opt-in.
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 MCPsearch Saved Messages for the flight confirmation email"
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 AI Deploy
Self-hosted Telegram MCP that an AI coding agent can deploy for you.
What it does
The server gives MCP clients controlled access to a Telegram user account through FastMCP and Telethon. It can search and read messages, inspect chats, fetch media and, only after explicit opt-in, send or edit messages. It supports remote deployment through Docker Compose, OAuth/bearer authentication and an outbound-only Cloudflare Tunnel.
This MCP can expose Telegram content to an AI client. Defaults are deliberately strict:read-only, Saved Messages only, destructive tools blocked by ACL, and raw MTProto disabled. Expand permissions only after reviewing the threat model.
Related MCP server: my-tg-mcp
Architecture
Claude / ChatGPT -- OAuth -----┐
├─ Cloudflare Tunnel ─ private Docker network ─ FastMCP ─ Telegram
Codex / Claude Code -- Bearer -┘No application port is published on the VPS. Runtime secrets and Telegram sessions stay in ignored files or Docker volumes and never belong in the repository.
Deploy with AI
git clone https://github.com/salto-agancy/telegram-mcp-ai-deploy
cd telegram-mcp-ai-deployOpen the directory in Codex, Claude Code or another capable coding agent and paste the prompt from INSTALL_WITH_AI.md. The agent performs preflight, prepares the VPS, opens a temporary SSH-forwarded QR login page in the local browser, provisions Cloudflare, deploys the stack and verifies the MCP protocol. The operator never needs to open a terminal manually.
Manual operator path: QUICKSTART.md.
Supported clients
Client | Connection | Guide |
Claude | Remote MCP with OAuth | |
Claude Code | Streamable HTTP, OAuth or bearer | |
ChatGPT | Remote MCP with OAuth where supported | |
Codex | Streamable HTTP with bearer environment variable |
Security
Secrets, sessions, ACLs, backups and runtime state are Git-ignored.
Cloudflare uses a temporary scoped API token, never a Global API Key.
ACL is fail-closed; raw MTProto requires two explicit opt-ins.
Every push and pull request runs tests and full-history secret scanning.
Never paste unredacted logs or credentials into an Issue or Pull Request.
Read SECURITY.md before enabling Telegram write access. Report vulnerabilities privately through GitHub Security Advisories.
Update
Ask your coding agent: Update my Telegram MCP to the latest stable version.
The reproducible path is make update: it scans the checkout, creates an encrypted
backup, fetches the latest stable tag, deploys it, runs health checks and restores the
previous commit if deployment fails. See docs/UPDATE.md.
Something doesn't work?
Attach only sanitized logs—remove tokens, hostnames, IPs, phone numbers, chat names, message content and session paths.
Ask Codex or Claude Code to investigate using PROMPTS/CONTRIBUTE_WITH_AI.md.
If it finds a fix, let it create a tested Pull Request.
If an installation agent already found local fixes, use the Russian retrospective prompt in PROMPTS/REPORT_INSTALLATION_WITH_AI_RU.md to extract only sanitized, still-missing changes into a fork and Pull Request.
Contribute
Contributions are welcome through forks and Pull Requests. Run make check before opening
a PR and follow CONTRIBUTING.md. Architecture and deployment details
live under docs/.
Licensed under MIT. The application began as a fork of
leshchenko1979/fast-mcp-telegram;
see NOTICE.md for attribution.
Available Tools
11 toolsedit_messageEdit messageBDestructiveIdempotent
Replace text of an existing message you can edit in this chat. Success: edit result dict. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Target chat: numeric id (e.g. -100…), a username with or without the leading @ (resolved server-side, no lookup call needed), or 'me' for Saved Messages. | |
| message | Yes | Message text. When sending files, used as caption. | |
| message_id | Yes | Message id in this chat to edit (from get_messages or Telegram). | |
| parse_mode | No | 'markdown', 'html', or 'auto' (detect from content). Default is 'auto'. | auto |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, covering the mutation/safety profile. The description adds 'you can edit' as an eligibility constraint and notes the success return is 'edit result dict', but doesn't explain what gets replaced or permission requirements beyond annotations.
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 purpose. However, the second sentence mixes a return value note with a documentation URL, which is slightly disjointed. No wasted words, but structure could be cleaner.
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?
With annotations covering behavioral traits and a full schema plus output schema, the description needn't explain return values or parameters. However, it lacks guidance on permission requirements for editing and doesn't differentiate from siblings like send_message, leaving a gap for an edit-specific 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?
Schema description coverage is 100%, so all parameters including chat_id, message_id, message, and parse_mode are fully documented in the schema. The description adds no parameter-level detail beyond what the schema already 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?
States a specific verb (Replace text) and resource (existing message) with a scope constraint ('you can edit in this chat'). Distinguishes from send_message by making clear it targets an existing message, though it doesn't name siblings explicitly.
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 phrase 'you can edit' implies a permission/ownership constraint but doesn't explain when to use this versus alternatives like send_message. No explicit when-to-use or when-not-to-use guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_chatsFind chatsARead-onlyIdempotent
Find users/groups/channels by name, username, or phone. Global search (query required) searches all Telegram; with min_date, max_date, or filter, search uses dialog list or a named filter; include_peers filters use last-activity from GetPeerDialogs; flag-based filters use dialog list dates. Success: dict with key chats (list of chat objects). Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum chats to return (recommended 50 or less). | |
| query | No | Name, username (no @), phone (+country…), or comma-separated multi-queries. Required for global search unless you use min_date/max_date or folder alone. | |
| folder | No | Telegram folder name (case-insensitive exact match after normalization). In Telegram's UI these are called folders; internally they are "dialog filters" — saved filter presets that group chats by custom criteria (pinned, unread, business, etc.). See Filters-vs-Folders.md for the technical distinction. | |
| public | No | If true, prefer chats with a public username; if false, without. Does not apply to private DMs. Omit to skip this filter. | |
| max_date | No | Inclusive maximum date filter (ISO 8601 date or datetime). Omit for no upper bound. | |
| min_date | No | Inclusive minimum date filter (ISO 8601 date or datetime). Omit for no lower bound. | |
| chat_type | No | Comma-separated chat kinds: private, bot, group, channel. Case-insensitive; extra spaces allowed. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=true. The description adds context on how search behavior changes based on parameters (global vs local) and mentions the success output shape, which is consistent with the annotations.
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 a single dense paragraph but every sentence adds value. It could be more structured (e.g., bullet points), but it is reasonably concise for the complexity.
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?
With 7 parameters, 0 required, and an output schema, the description covers the main search modes and return value. It references external documentation for full details, which is acceptable given the complexity.
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%, so baseline is 3. The description adds meaningful explanations for parameters like query (required for global search), folder (technical distinction), and date filters, providing context beyond 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 that the tool finds users/groups/channels by name, username, or phone, and distinguishes between global search and dialog-based search, which is specific and unambiguous.
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 guidance on when to use global search vs dialog/folder search, noting that query is required for global search and that min_date, max_date, or folder can be used otherwise. However, it does not explicitly compare with sibling tools like search_messages_globally or get_chats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_chat_infoGet chat infoBRead-onlyIdempotent
Load profile and metadata for one user, bot, group, or channel. Success: info dict; forum chats may include topics up to topics_limit. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Target chat: numeric id (e.g. -100…), a username with or without the leading @ (resolved server-side, no lookup call needed), or 'me' for Saved Messages. | |
| topics_limit | No | Max forum topics to list when the chat is a forum. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description adds useful behavioral context about successful returns ('info dict') and forum topic inclusion up to topics_limit, but it does not go much beyond the basic contract.
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 compact and front-loaded with the core purpose, followed by return behavior and a documentation link. It wastes little space, though the 'Success: info dict' fragment is slightly terse.
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?
With annotations covering safety and an output schema covering return structure, the description is largely complete for a simple read tool. The main gap is the absence of usage guidance versus sibling tools.
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 both parameters are fully documented in the schema. The description repeats that topics_limit affects forum chats but adds no syntax, format, or edge-case detail beyond 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 gives a clear verb ('Load') and resource ('profile and metadata for one user, bot, group, or channel'), making the scope of one specific chat understandable. It does not explicitly name or differentiate from siblings like find_chats, but the singular focus distinguishes it implicitly.
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?
There is no guidance on when to use this tool versus alternatives such as find_chats or get_messages. The description states what it loads but offers no conditions, exclusions, or alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_media_contentGet media content inlineARead-onlyIdempotent
Fetch photos/images from specific messages and return them INLINE as native image content (base64), so web clients can read screenshots without fetching a URL. Non-image files return a short text note plus their download URL; voice / round video return a note pointing at get_messages field transcription. Limits: max 6 images per call; originals over 5 MB are skipped with a note. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Target chat: numeric id (e.g. -100…), a username with or without the leading @ (resolved server-side, no lookup call needed), or 'me' for Saved Messages. | |
| message_ids | Yes | Exact message ids to fetch. Mutually exclusive with query and reply_to_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations already declaring readOnlyHint, idempotentHint, and openWorldHint, the description adds critical operational limits (max 6 images per call, originals over 5 MB skipped) and specifies exact return behavior for each media type. This goes well beyond the safety and idempotency hints provided by annotations.
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 front-loaded with the primary purpose and return format, then efficiently covers edge cases and limits in two dense sentences. No extraneous information; every clause earns its place, and the documentation link is appropriately placed at the end.
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's complexity (media handling, size limits, multiple return formats), the description covers all necessary behavioral details: inline base64 return, fallback for non-images, voice/video routing, and per-call limits. No output schema is needed because the description fully explains what to expect in the response.
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 the schema already documents both parameters thoroughly (chat_id formats, message_ids mutual exclusivity with query/reply_to_id). The description adds no additional parameter syntax or format details, making the baseline score of 3 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 states a specific verb and resource ('Fetch photos/images from specific messages'), specifies the return format ('INLINE as native image content (base64)'), and enumerates fallback behavior for non-image, voice, and round video. This distinguishes it from siblings like get_messages and get_yandex_disk_content.
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?
It explains the core use case ('so web clients can read screenshots without fetching a URL') and routes non-image requests appropriately, directing to get_messages field `transcription` for voice/round video. It does not explicitly name get_messages or get_yandex_disk_content as alternatives for other file types, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messagesGet messages in chatARead-onlyIdempotent
Read chat history: the conversation, dialog, or DM with one person, group, or channel. Browse the latest messages, search text inside the chat, fetch by ids, or load replies to a message (comments, forum topics, threads). Accepts a @username directly as chat_id, so a known handle needs no lookup step. Filter a time window with min_date and max_date (e.g. what was written this morning). Do not combine message_ids with query or reply_to_id. Success: messages, has_more, optional total_count and discussion fields. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum messages to return (recommended 50 or less). | |
| query | No | Search within this chat only; comma-separated terms. Omit to browse latest or use message_ids / reply_to_id modes. | |
| chat_id | Yes | Target chat: numeric id (e.g. -100…), a username with or without the leading @ (resolved server-side, no lookup call needed), or 'me' for Saved Messages. | |
| max_date | No | Inclusive maximum date filter (ISO 8601 date or datetime). Omit for no upper bound. | |
| min_date | No | Inclusive minimum date filter (ISO 8601 date or datetime). Omit for no lower bound. | |
| message_ids | No | Exact message ids to fetch. Mutually exclusive with query and reply_to_id. | |
| reply_to_id | No | Anchor message id: channel post id, forum topic_id from get_chat_info, or a message id for direct replies. Use with thread_scope. | |
| thread_scope | No | Only with reply_to_id. auto: full forum topic (topic_id) or channel comment thread via getReplies; else direct replies. full: nested branch under a message id (forum in-topic uses search window, not whole topic); supergroup threads use search top_msg_id. direct: immediate replies only. | auto |
| auto_expand_batches | No | Extra search batches to run when filters narrow results. Higher values may return more matches at the cost of latency. | |
| include_total_count | No | If true, response may include total_count where supported (per-chat search; ignored for global search). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint, lowering the burden, but the description still adds real behavioral content: the mutual-exclusion constraint on input modes, the @username shortcut that avoids a lookup call, and the success shape (messages, has_more, total_count, discussion). Pagination semantics beyond the has_more flag are not elaborated.
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?
Front-loaded with the core action and organized as scope, modes, shortcuts, constraints, and return shape. The synonym list ('conversation, dialog, or DM') and the trailing doc link add bulk, but nearly every sentence carries operational information.
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?
For a 10-parameter tool with an output schema, the description covers purpose, mode selection, the exclusivity constraint, the username shortcut, and the return shape, so an agent has everything needed to call it correctly. Return-value detail is a bonus rather than a necessity given the output schema.
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 the baseline is 3, and the description genuinely adds over it: it explains the @username-as-chat_id shortcut, illustrates the date window with a use case ('what was written this morning'), and restates the message_ids/query/reply_to_id exclusivity that the schema only states per-parameter.
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?
States a specific verb and resource ('Read chat history') and immediately enumerates the four distinct modes (browse latest, search text, fetch by ids, load replies), which separates it from the sibling search_messages_globally ('within this chat only'). An agent can identify the tool and its scope without opening the schema.
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?
Gives concrete mode-selection guidance ('Browse the latest messages, search text inside the chat, fetch by ids, or load replies') and an explicit exclusion rule ('Do not combine message_ids with query or reply_to_id'). It does not explicitly name search_messages_globally as the alternative for cross-chat search, so routing for the global case is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_yandex_disk_contentGet Yandex.Disk content inlineARead-onlyIdempotent
Open a public Yandex.Disk link (folder or file) sent in Telegram and return its images INLINE as native image content (base64), recursing into subfolders. Non-image files return a short note plus a preview/download URL. Use when a chat message contains a disk.yandex / yadi.sk link and the user wants to see what is in it. Max 12 images per call. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| public_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, openWorld and idempotent, but the description adds genuinely new behavior: recursion into subfolders, inline base64 image return, the note+preview-URL fallback for non-images, and a hard 'max 12 images per call' limit. Those operational constraints are exactly the kind of detail agents cannot infer from structured fields.
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?
Front-loaded with the action and resource, then return behavior, then the trigger condition, then the one hard limit, then a docs link. Every clause adds information; nothing is padding.
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?
No output schema exists, and the description steps in to describe return values (inline images, fallback note + URL) and the per-call image cap. What is missing is any treatment of the `path` parameter and error behavior for invalid/private links, so it falls just short of fully self-contained.
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 0%, so the description carries the full burden for the two parameters. It never explains the required public_url format beyond the implied host names, and the `path` parameter is completely unaddressed (subfolder recursion is mentioned, but not how to target one via path). Minimal compensation for a real coverage gap.
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?
Specific verb ('Open') plus resource ('public Yandex.Disk link, folder or file') and an explicit statement of what comes back (images inline as base64, non-images as note + URL). This cleanly separates it from siblings like get_media_content, which handle Telegram-hosted media rather than public Yandex.Disk links.
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?
Gives a concrete trigger: a chat message containing a disk.yandex / yadi.sk link that the user wants to inspect. That is clear when-to-use guidance, but it never names an alternative tool or states when NOT to use it (e.g., for Telegram-native attachments the agent should pick a sibling).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recent_activityRecent activity snapshotARead-onlyIdempotent
One prepared snapshot of recent activity across chats, instead of discovering chats and then opening each one. Returns, per chat: Telegram's own unread state (unread_count, read_inbox_max_id, read_outbox_max_id), the messages in the window with direction and reply links, attachment metadata, voice transcripts that are already available, and last incoming / last outgoing. Voice without a ready transcript is marked pending, never omitted. Whether a message needs a reply is not decided here. Success: dict with keys chats and coverage. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | Start of the window: a relative span ('24h', '7d', '90m', '2w') or an ISO 8601 timestamp. Relative spans resolve against the current UTC instant, so 'the last 24 hours' does not shift with local calendar days. | 24h |
| until | No | End of the window as an ISO 8601 timestamp. Omit for 'up to now'. Relative values are rejected here because they read ambiguously. | |
| accounts | No | Account labels to include. One authenticated session covers exactly one Telegram account, so a second account needs its own call with its own token; anything unavailable is reported in coverage rather than dropped. | |
| chat_type | No | Comma-separated chat kinds: private, bot, group, channel. Case-insensitive; extra spaces allowed. | |
| limit_chats | No | Maximum chats to return (recommended 50 or less). | |
| unread_only | No | If true, return only chats Telegram currently marks unread (unread_count above zero or an explicit unread mark). | |
| include_channels | No | If true, include broadcast channels. Off by default: channels out-post conversations by an order of magnitude and bury working chats. | |
| include_telemetry | No | If true, attach per-run counters (durations, call counts, archive coverage). Counts and statuses only — never message content. | |
| limit_messages_per_chat | No | Maximum messages returned per chat (recommended 20 or less). | |
| include_archived_dialogs | No | If true, also scan dialogs the owner moved to the archive folder. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, openWorldHint, and idempotentHint, but the description adds valuable behavioral detail: voice transcripts without ready transcripts are marked pending and never omitted, reply decisions are explicitly not made here, and the success output is a dict with keys chats and coverage. It also mentions that unavailable accounts are reported in coverage rather than dropped (in parameter description). This goes beyond annotations with concrete guarantees.
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 a single paragraph but is well-structured: it opens with the core purpose, then lists return fields, notes special cases, and concludes with success format and a documentation link. It is not overly verbose, though it could be tightened without losing content. Front-loading is effective.
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's complexity (10 optional parameters) and rich schema coverage, the description covers the key behavioral aspects: what is returned, the treatment of pending transcripts, the exclusion of reply decisions, and the success format. The output schema exists, so return values are documented. The link to full documentation also supplements completeness. Nothing critical is missing for correct invocation.
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 the parameters are fully documented in the schema. The description does not add additional meaning to the parameters themselves; it focuses on output structure and behavioral notes. Baseline 3 is appropriate since the schema carries the parameter documentation.
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 a specific verb and resource: 'One prepared snapshot of recent activity across chats'. It explains what it returns (unread state, messages, attachments, transcripts, last incoming/outgoing) and explicitly contrasts with the alternative of 'discovering chats and then opening each one', distinguishing it from sibling tools like find_chats and get_messages.
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 implies when to use this tool ('instead of discovering chats and then opening each one') and indicates it is a batch overview. However, it does not explicitly name sibling alternatives or specify conditions when one would prefer get_messages or find_chats. The usage guidance is present but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_messages_globallySearch messages globallyARead-onlyIdempotent
Search all Telegram chats at once (not scoped to one chat). Comma-separated query terms; optional filters by date, chat kind, and public username. Success: message list and metadata dict. Global search ignores include_total_count. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum messages to return (recommended 50 or less). | |
| query | Yes | Search terms, comma-separated for multiple terms (OR-style global search). Required. | |
| public | No | If true, prefer chats with a public username; if false, without. Does not apply to private DMs. Omit to skip this filter. | |
| source | No | Where global search looks: 'auto' (default) also searches the local archive when one is configured, which makes voice transcripts, recognised screenshot text and attachment names findable; 'live' searches Telegram only; 'archive' searches the local projection only. With no archive configured, all three behave identically. | auto |
| max_date | No | Inclusive maximum date filter (ISO 8601 date or datetime). Omit for no upper bound. | |
| min_date | No | Inclusive minimum date filter (ISO 8601 date or datetime). Omit for no lower bound. | |
| chat_type | No | Comma-separated chat kinds: private, bot, group, channel. Case-insensitive; extra spaces allowed. | |
| auto_expand_batches | No | Extra search batches to run when filters narrow results. Higher values may return more matches at the cost of latency. | |
| include_total_count | No | If true, response may include total_count where supported (per-chat search; ignored for global search). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering the safety profile. The description adds the global-scope constraint and notes that include_total_count is ignored, but these details also appear in the input schema; no new behavioral risks or side effects are disclosed. Moderate value beyond annotations.
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?
Five short sentences with the main purpose front-loaded and a documentation link at the end. All sentences are purposeful, though mentioning 'Success: message list and metadata dict' is somewhat redundant given the output schema.
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 rich input schema, output schema, and annotations, the description is complete enough for correct invocation. It adds global-scope context, a key parameter caveat, and a documentation link; no critical operational detail is missing.
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?
Input schema has 100% description coverage, so the baseline is 3. The description's mention of comma-separated terms and optional filters by date, chat kind, and public username only mirrors schema content without adding new parameter semantics.
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?
States a specific action and resource: 'Search all Telegram chats at once', explicitly contrasting with chat-scoped searches. It also summarizes the query format and optional filters, making the tool's purpose immediately distinguishable from siblings like get_messages or find_chats.
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?
Provides clear context that this tool performs cross-chat global search and is 'not scoped to one chat', which implies it is the right choice for broad message search. However, it does not explicitly name alternatives or state when not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageSend messageADestructive
Send text and optional attachments to a chat. Success: send result dict. Each item in files may be a public URL, a server-local path, OR a base64 data URI (data:;base64,) — use the data URI form to send a file the caller has in memory or attached locally, without needing a public link (supported up to ~30 MB). Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| files | No | List of attachment URLs, local paths, or data URIs (one or more strings). data: URIs (data:<mime>;base64,<payload>) work in all server modes; local paths work in stdio mode only. | |
| chat_id | Yes | Target chat: numeric id (e.g. -100…), a username with or without the leading @ (resolved server-side, no lookup call needed), or 'me' for Saved Messages. | |
| message | Yes | Message text. When sending files, used as caption. | |
| parse_mode | No | 'markdown', 'html', or 'auto' (detect from content). Default is 'auto'. | auto |
| reply_to_id | No | Telegram message id to reply to. For forums, topic root id; for channel posts, post id (may create a comment). Omit for a new top-level message. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare openWorldHint and destructiveHint, so the safety profile is partially covered. The description adds a real behavioral constraint the schema lacks (~30 MB attachment cap) and states the success shape ('send result dict'), but says nothing about Telegram rate limits, auth/permission requirements, or the reversibility of a sent message.
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?
Front-loads the core action and outcome in the first sentence, then one focused sentence on attachment sourcing, then a doc link. It is efficiently sized, though the data-URI explanation partially duplicates the schema's own files description.
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?
With an output schema present, return-value explanation is unnecessary, and the description still adds the success shape and attachment constraints. It is largely complete for a send tool, with minor gaps around message-size limits and the absence of any routing cue versus the other send_* siblings.
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%, so every parameter is already documented in the schema, which sets the baseline at 3. The description restates the files data-URI form and adds the size ceiling, but contributes little beyond what the schema entries already say for chat_id, message, parse_mode, and reply_to_id.
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?
Names a specific verb+resource ('Send text and optional attachments to a chat') and covers the scope of the operation. It does not, however, differentiate itself from nearby siblings like send_rich_message, send_message_to_phone, or edit_message, so the agent must infer which send variant applies.
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 gives useful in-context guidance for one parameter ('use the data URI form to send a file the caller has in memory... without needing a public link'), which implies when that path is appropriate. It never says when to prefer this tool over send_rich_message or send_message_to_phone, and offers no prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_message_to_phoneSend message to phoneADestructive
Send to a phone number: may create a temporary contact, then send text or files. Success: send result plus contact_was_new / contact_removed when applicable. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| files | No | List of attachment URLs, local paths, or data URIs (one or more strings). data: URIs (data:<mime>;base64,<payload>) work in all server modes; local paths work in stdio mode only. | |
| message | Yes | Message text. When sending files, used as caption. | |
| last_name | No | Last name when creating a temporary contact. | Name |
| first_name | No | First name when creating a temporary contact. | Contact |
| parse_mode | No | 'markdown', 'html', or 'auto' (detect from content). Default is 'auto'. | auto |
| phone_number | Yes | E.164 phone number with country code, e.g. +1234567890 (must be on Telegram). | |
| remove_if_new | No | If true, delete the contact after send when it was created only for this send. | |
| reply_to_msg_id | No | Reply to this message id in the target chat after resolve. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint and openWorldHint. The description adds context that creation and removal of temporary contacts may occur, and explains the return fields (contact_was_new, contact_was_removed). This goes beyond the annotations, providing useful behavioral insight.
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-loading the core action and side effects, then explaining the return value. No unnecessary words, and it includes a link to full documentation, making it efficient and well-structured.
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?
The description covers the main behavior, side effects, and return structure. Given the output schema exists, it adequately informs the agent. Missing are error scenarios or prerequisites (e.g., phone must be on Telegram, already in schema). Overall, mostly complete with a doc link.
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% with detailed parameter descriptions. The description adds some contextual meaning (e.g., 'may create a temporary contact' relates to first_name, last_name, remove_if_new) but does not significantly improve understanding beyond 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 sends to a phone number, may create a temporary contact, and sends text or files. The name and description distinguish it from sibling 'send_message' which likely sends to a chat, not a phone number.
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 implies usage via the name and actions, but lacks explicit guidance on when to use this tool versus alternatives like 'send_message' or 'search_messages_globally'. No when-not or context exclusions are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_rich_messageSend rich messageADestructive
Send markdown as a Telegram Rich Message with REAL tables and headings (Bot API 10.1 sendRichMessage). Use this instead of send_message when the content has markdown tables (| ... |), headings (#), or structured report layout that should render natively in Telegram. Sent by the separately configured bot, so chat_id must identify a chat shared with that bot, NOT 'me'/Saved Messages. Success: {sent, id, chat_id, type}. Full documentation: https://github.com/leshchenko1979/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Target chat: numeric id (e.g. -100…), a username with or without the leading @ (resolved server-side, no lookup call needed), or 'me' for Saved Messages. | |
| markdown | Yes | Message text. When sending files, used as caption. | |
| reply_to_id | No | Telegram message id to reply to. For forums, topic root id; for channel posts, post id (may create a comment). Omit for a new top-level message. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare openWorldHint and destructiveHint, so the description carries most of the burden. It contributes the non-obvious fact that sending is done by a separately configured bot, that chat_id must be shared with that bot, and the success response shape ({sent, id, chat_id, type}). It does not explain failure modes or rate limits, so it falls short of a 5.
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?
Front-loads the core purpose and the send_message alternative, then tacks on the bot constraint, success shape, and docs link. Dense but every clause earns its place; only the trailing documentation URL is dispensable.
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?
An output schema exists, so the explicit success shape is a bonus rather than a necessity, and the description still covers the key operational constraint (bot-shared chat). The only gap is a mild conflict with the schema, which lists 'me' for Saved Messages while the description warns against it.
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%, so the baseline is 3, but the description adds a real constraint not present in the schema: the bot-shared-chat requirement for chat_id. This meaningfully narrows how the parameter may be used, going beyond the schema's own description.
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?
Names a specific verb+resource (send markdown as a Telegram Rich Message) and explicitly differentiates from the sibling send_message, even naming the API (Bot API 10.1 sendRichMessage). An agent can tell it apart from send_message without opening either schema.
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 states when to prefer this over send_message (content containing markdown tables, headings, or structured report layout) and adds a routing constraint that chat_id must be a chat shared with the separately configured bot. This is precisely the when/when-not/alternative guidance the dimension asks for.
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.
2 tool updates
v0.35.0- Added
recent_activity - Changed
search_messages_globally1 field changed- added
Input schema / properties / sourceAdded value: +{ + "default": "auto", + "description": "Where global search looks: 'auto' (default) also searches the local archive when one is configured, which makes voice transcripts, recognised screenshot text and attachment names findable; 'live' searches Telegram only; 'archive' searches the local projection only. With no archive configured, all three behave identically.", + "type": "string" +}
10 tool updates
v0.34.0- First observed
edit_message - First observed
find_chats - First observed
get_chat_info - First observed
get_media_content - First observed
get_messages - First observed
get_yandex_disk_content - First observed
search_messages_globally - First observed
send_message - First observed
send_message_to_phone - First observed
send_rich_message
TDQS
Scored across 11 tools
The tool set is clearly separated by resource and action, with distinct tools for reading messages, searching, editing, sending, and fetching media. The three send tools are differentiated by destination (phone, rich content vs plain) and the two media-fetch tools by source (message vs Yandex.Disk link), though send_message and send_rich_message could cause minor selection confusion for plain text.
Almost all tools follow a consistent verb_noun pattern (get_, edit_, search_, send_, find_), with send_message_to_phone and get_yandex_disk_content being verbose but still predictable. Only recent_activity breaks the pattern by using a noun phrase instead of a verb, making it the single deviation.
At 11 tools, the server covers a typical Telegram integration scope without bloat. Each tool addresses a distinct operation—sending, reading, searching, editing, chat discovery, and media retrieval—so no tool feels redundant or missing.
Core message lifecycle is mostly covered: send, read, search, edit, but delete_message is absent, which is a notable gap for a messaging client. Also lacks explicit mark-read or forward operations, though recent_activity provides unread state. Overall the surface is functional but not complete.
Maintenance
Related MCP Connectors
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Unofficial Telegram MCP server — read, search, reply and react in your own Telegram account.
Related MCP Servers
- FlicenseAqualityDmaintenanceRead-only MCP server for self-hosted Telegram access via Telethon. Enables reading messages, chats, and media but disallows any write operations.10-
- FlicenseNot gradedqualityBmaintenanceRead-only MCP access to a personal Telegram account. Allows querying chats, reading and searching messages via Streamable HTTP.-
- AlicenseNot gradedqualityAmaintenanceA safe-by-default MCP server for real Telegram accounts powered by TDLib, enabling AI agents to read and act on your account with read-only mode and human approval for destructive actions.8Apache 2.0
- AlicenseNot gradedqualityCmaintenanceA read-only Telegram MCP server that only exposes a user-defined allowlist of chats, providing tools to list chats, fetch messages, search, and get context while stripping untrusted text and with no write capabilities.MIT