Telegram MCP Server
The Telegram MCP Server is a Model Context Protocol (MCP) gateway that connects AI agents to Telegram's MTProto API. It provides 8 context-efficient tools: search_messages_globally (cross-chat search with date/type filters), get_messages (unified message retrieval including browse, search, by-ID, and forum threads), send_message (text/files with formatting and reply support), edit_message (modify text), find_chats (discover users/groups/channels by name, username, phone, with folder/date filters), get_chat_info (profile/metadata details), send_message_to_phone (direct phone messaging with temporary contact), and invoke_mtproto (raw API access with safety guardrails). It supports multi-user with QR/phone/bot authentication, session isolation, optional S3 storage, and runs over stdio or HTTP, with production features like proxy support and telemetry.
Provides tools for interacting with Telegram's API, enabling AI agents to send messages, search chats, retrieve messages, and manage Telegram conversations via MTProto.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Telegram MCP Serversend hello to my saved messages in 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 MCP Server — Model Context Protocol (MCP) gateway for Telegram. 8 context-efficient tools, multi-tenant, MTProto bridge.
Canonical GitHub repository: alexeyleshchenko/fast-mcp-telegram. This is the same project previously published under
leshchenko1979/fast-mcp-telegram. The old GitHub URL is a public 404. Install remainspip install fast-mcp-telegramoruvx --from fast-mcp-telegram; PyPI is the stable pointer.
Try the Demo
Scan the QR code from Telegram mobile (Settings → Devices → Scan QR) — no phone typing, no OTP, no 2FA. Or enter your phone number as fallback.
Copy your Bearer token from the success page
Then choose your path:
MCP Client (AI assistants)
From the setup page, download the
mcp.jsonfileAdd the server to your AI client and ask: "send hello to my saved messages in telegram"
Direct API (curl)
Run the command below (replace TOKEN with yours):
curl -X POST "https://tg-mcp.l1979.ru/mtproto-api/messages.SendMessage" \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"params": {"peer": "me", "message": "Hello!"}}'
Related MCP server: MCP Telegram
How It Works
This server sits between your AI agent and Telegram's API:
Your agent → MCP/HTTP → this server → MTProto → TelegramWhat it does: Authenticates you with Telegram (QR or phone/bot token), exposes 8 AI-friendly tools instead of 80+ micro-APIs, and bridges raw MTProto for power users. Multi-tenant — one server, many users, isolated sessions.
Features
Feature | Description |
:building_construction: Dual Transport | Stdio for local MCP clients, HTTP for remote deploys ( |
:closed_lock_with_key: Multi-User Authentication | Shared |
:dart: AI-Optimized | 8 consolidated tools vs 80+ micro-tools — context-efficient design, LLM-friendly API, MCP ToolAnnotations |
:globe_with_meridians: HTTP-MTProto Bridge | Direct curl access to any Telegram API method with entity resolution and safety guardrails |
:shield: Session ACL | Opt-in per-principal limits on |
:tv: QR & Web Setup | Scan QR from Telegram mobile for instant auth (no phone/OTP/2FA) or use phone/code/2FA fallback — live at |
:label: One Agent, Multiple Accounts | Optional |
:rocket: MTProto Proxy Support | Connect via MTProto proxy with automatic Fake TLS (EE prefix) and standard proxy detection |
:card_file_box: Unified Session Management | Single configuration system for setup and server; per-token session files on shared multi-user hosts |
:cloud: S3 Session Storage | Store sessions in S3-compatible object storage for ephemeral hosted deployments (Smithery, Fly.io, Railway) |
:mag_right: Intelligent Search | Global & per-chat message search with multi-query support and intelligent deduplication |
:mag: Unified Message API | Single |
:speech_balloon: Universal Replies | Get replies from channel posts, forum topics, or any message with one parameter |
:busts_in_silhouette: Smart Contact Discovery | Search users, groups, channels with uniform entity schemas, forum detection, profile enrichment |
:file_folder: Folder Filtering | Filter chats by dialog folder (archived, custom folders) with integer ID or name matching |
:envelope: Advanced Messaging | Send, edit, reply, post to forum topics, formatting, file attachments, and phone number messaging |
:paperclip: Secure File Handling | Rich media sharing with SSRF protection, size limits, album support, optional HTTP attachment streaming |
:outbox_tray: Inline File Uploads | Data: URI (base64) file uploads in |
:microphone: Voice Transcription | Automatic speech-to-text for Premium accounts with parallel processing and polling |
:zap: High Performance | Async operations, parallel queries, and memory-conscious batching |
:shield: Production Reliability | Auto-reconnect, configurable logging, comprehensive error handling |
Quick Start
1. Install and authenticate
Quickest path (remote server): Open /setup → scan QR → copy token (see Try the Demo).
CLI path (local stdio): Run fast-mcp-telegram-setup once to create a Telegram session — then fast-mcp-telegram serves it:
uvx --from fast-mcp-telegram fast-mcp-telegram-setup \
--api-id="your_api_id" \
--api-hash="your_api_hash" \
--phone-number="+123456789"Bot token alternative (no phone, no OTP):
Set BOT_API_TOKEN instead of --phone-number. See Installation Guide.
2. Configure MCP Client
stdio mode (local): Add to your MCP client config (e.g. claude_desktop_config.json) — stdio (standard input/output) is the default transport for local MCP clients:
{
"mcpServers": {
"telegram": {
"command": "uvx",
"args": ["fast-mcp-telegram"],
"env": {
"API_ID": "your_api_id",
"API_HASH": "your_api_hash"
}
}
}
}http-auth mode (remote): Add to your MCP client config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"telegram": {
"url": "https://tg-mcp.l1979.ru/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}Get your token by scanning the QR code on the setup page or see Installation Guide for deploying your own server.
3. Start Using
{"tool": "search_messages_globally", "params": {"query": "hello", "limit": 5}}
{"tool": "get_messages", "params": {"chat_id": "me", "limit": 10}}
{"tool": "send_message", "params": {"chat_id": "me", "message": "Hello!"}}Deploy to Remote Server
Deploy your own MCP server on a VDS — see Installation Guide for step-by-step instructions.
Available Tools
Tool | Purpose | Key Features |
| Search across all chats | Multi-term queries, date filtering, chat type filtering |
| Unified message retrieval | Search/browse, read by IDs, get replies (posts/topics/messages), date filtering in all modes |
| Send new message | File attachments (URLs/local/data URIs), classic formatting (markdown/html), |
| Edit existing message | Classic or |
| Find users/groups/channels | Multi-term search, contact discovery, folder filtering, username/phone lookup |
| Get detailed profile info | Member counts, bio/about, online status, forum topics, common groups, enriched data |
| Message phone numbers | Auto-contact management, optional cleanup, file support (URLs/data URIs), |
| Direct Telegram API (power user) | Raw MTProto methods, entity resolution, safety guardrails — see MTProto Bridge |
See Tools Reference for detailed documentation with examples.
Documentation
Installation Guide - Local setup and remote server deployment
Tools Reference - Complete tools documentation
MTProto Bridge - Direct API access via curl
Contributing - Guidelines for contributors
Security - Security features and best practices
Telemetry
Anonymous tool telemetry since v0.30.1 — heartbeat every 6h, no credentials or message content collected. Opt out with DO_NOT_TRACK=1. See ADR 0005.
Auth flow telemetry since v0.38.0 — atomic events during setup (phone, QR, bot token, reauthorize). Buffered flush on flow completion. See ADR 0008.
License
MIT License - see LICENSE
mcp-name: io.github.alexeyleshchenko/fast-mcp-telegram
Available Tools
8 toolsedit_messageEdit messageADestructiveIdempotent
Replace the text of an existing message in a Telegram chat. Only works on messages sent by the authenticated account. Cannot edit media or other message attributes — text only. parse_mode: classic markdown/html/auto or rich (Rich Message; dialect auto-detected). Success: dict with message_id, date, chat, text, status='edited', and edit_date (rich messages also set rich=true and rich_format). Error: dict with ok=false and error string (e.g. message not found or not editable). Use edit_message to update a previously sent message; use send_message to create new ones. Full documentation: https://github.com/alexeyleshchenko/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Target chat: numeric id (e.g. -100…), username without @, 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'/'auto': classic entity formatting (auto detects). 'rich': Telegram Rich Message document; dialect auto-detected (known HTML tags outside code → rich HTML, else rich markdown). Default is 'auto'. parse_mode='rich' cannot be combined with files. | auto |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | No | |
| chat | No | |
| code | No | |
| date | No | |
| rich | No | |
| text | No | |
| error | No | |
| action | No | |
| params | No | |
| sender | No | |
| status | No | |
| topic_id | No | |
| edit_date | No | |
| exception | No | |
| operation | No | |
| error_code | No | |
| message_id | No | |
| rich_format | No | |
| reply_markup | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and openWorldHint=true, so mutation is known. The description adds valuable behavioral context: ownership limitation, no media editing, detailed success/error return dicts, and parse_mode behavior. No contradictions. Minor lack of rate-limit or auth details beyond 'authenticated account' keeps it from 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?
Compact and front-loaded—purpose, scope, and alternatives appear in the first two sentences. The rest covers return format and parse_mode in a structured way. Slightly verbose with the documentation URL and repetition of 'use edit_message', but every sentence adds value for a moderately complex tool.
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?
Covers constraints, usage, alternatives, return format, error format, parse_mode details, and provides a documentation link. Output schema exists for returns, but the description goes beyond that to explain error cases and rich message behavior—complete for the tool's 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 description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds context for parse_mode (rich dialect auto-detection) and success return fields, but these are largely redundant with schema and output schema. 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+resource: 'Replace the text of an existing message in a Telegram chat.' Immediately distinguishes from send_message with explicit guidance to use edit_message for updates and send_message for creations. Also clarifies scope (text-only, own messages only), eliminating ambiguity.
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 explicit when-to-use and alternatives: 'Use edit_message to update a previously sent message; use send_message to create new ones.' Also notes restrictions (only messages sent by the authenticated account, cannot edit media) which serve as exclusions. This is textbook guidance.
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. Comma-separated usernames are searched in parallel and results are merged round-robin. 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/alexeyleshchenko/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 usernames for batch lookup. Example: 'alice,bob,charlie'. 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 |
|---|---|---|
| ok | No | |
| code | No | |
| chats | No | |
| error | No | |
| action | No | |
| params | No | |
| exception | No | |
| operation | No | |
| error_code | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld/idempotent annotations, the description discloses rich behavioral details: parallel round-robin merging of username searches, global vs dialog list modes, the effect of include_peers on GetPeerDialogs, and flag-based filter timing. This is substantial added context that helps predict tool behavior.
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 somewhat dense and rambles through modes, but each sentence conveys useful behavior. It front-loads the core action and includes a docs reference. Slightly longer than strictly necessary, but every clause earns its place.
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 complex tool with 7 parameters, the description covers the main search modes, filter behaviors, and the success response shape. However, it introduces terms like 'flag-based filters' without elaboration and relies on external docs for full detail. Given the output schema exists, the return-value gap is mitigated, but some internal jargon remains unexplained.
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 each parameter already has a description. The description text adds cross-parameter semantics: it explains how comma-separated usernames are searched in parallel, how min_date/max_date toggle dialog-list search, and how include_peers interacts with last-activity data. This meaningfully enhances schema-only information.
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 opens with a clear, specific action: 'Find users/groups/channels by name, username, or phone.' This distinguishes it from sibling tools like search_messages_globally (which searches messages) and get_chat_info (which retrieves info about a specific chat). The resource and verbs are explicit.
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 explains when global search is used versus dialog-list/filter-based search, and how comma-separated usernames are handled. It doesn't explicitly name alternatives, but the sibling tools are clearly distinct, so the context is sufficient. It lacks explicit exclusion statements like 'use this for X, not for Y'.
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 infoARead-onlyIdempotent
Load profile and metadata for one user, bot, group, or channel. Success: info dict; forum chats may include topics up to topics_limit; user targets may include common_chats up to common_chats_limit. Full documentation: https://github.com/alexeyleshchenko/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Target chat: numeric id (e.g. -100…), username without @, or 'me' for Saved Messages. | |
| topics_limit | No | Max forum topics to list when the chat is a forum. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | |
| ok | No | |
| code | No | |
| error | No | |
| phone | No | |
| title | No | |
| action | No | |
| is_bot | No | |
| params | No | |
| topics | No | |
| is_user | No | |
| is_forum | No | |
| is_group | No | |
| username | No | |
| exception | No | |
| last_name | No | |
| operation | No | |
| error_code | No | |
| first_name | No | |
| is_channel | No | |
| common_chats | No | |
| topics_has_more | No | |
| participants_count | No | |
| common_chats_has_more | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the description adds value by disclosing the success return type (info dict) and conditional behaviors (topics_limit for forums, common_chats_limit for users). No contradiction with 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?
Three concise sentences: purpose, success/conditional details, and a documentation link. Front-loaded with the main verb and resource, no redundant phrases, every sentence earns its place.
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 two well-documented parameters, existing output schema, and rich annotations, the description covers the key nuances (forum topics, user common chats) and provides a full documentation link. It is complete for the tool's 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% for both parameters, so baseline is 3. The description goes beyond by explaining how topics_limit affects output for forum chats and mentioning common_chats_limit (a response field not in the schema), adding behavioral meaning to the parameters.
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 'Load' with a clear resource 'profile and metadata for one user, bot, group, or channel', distinguishing it from sibling tools like get_messages or send_message. It precisely scopes the tool to a single target entity.
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 clear context for when to use this tool (for fetching single-chat info) and mentions special cases (forum topics, user common chats). It does not explicitly name alternative tools or when-not-to-use conditions, but the context is unambiguous for the primary use case.
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 or search messages in one chat: browse latest, search text, fetch by ids, or load replies to a message (comments, forum topics, threads). Use from_user to filter by sender (server-side, per-chat only). Use context to include neighboring messages and reply chains around each result. Use include_replies to fetch up to 5 direct replies per result. 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/alexeyleshchenko/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…), username without @, or 'me' for Saved Messages. | |
| context | No | Number of surrounding messages to include as context for each search result. 0 = disabled (default). 1-10 = include N messages before and N after each result. Also fetches the message being replied to and top replies (if include_replies=true). Requires chat_id. Disabled when result count exceeds cost-based caps. | |
| 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. | |
| from_user | No | Only return messages from this sender. Not a display-name or contact-name search — bare strings resolve like chat_id via get_entity (usernames are case-insensitive and may match an unrelated channel). Prefer @username, phone (+…), or numeric user id. Also accepts 'me', 'self', t.me URL, -100 prefixed id. Uses Telegram's native from_id server-side filter (per-chat search only). | |
| 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 |
| include_replies | No | If true, fetch up to 5 direct replies per search result and attach as replies. Each result costs one API call (not batchable). Default: false. | |
| 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 |
|---|---|---|
| ok | No | |
| code | No | |
| error | No | |
| action | No | |
| params | No | |
| _warning | No | |
| has_more | No | |
| messages | No | |
| exception | No | |
| operation | No | |
| error_code | No | |
| total_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint/idempotentHint annotations, the description discloses return shape (messages, has_more, total_count, discussion), cost behavior ('Each result costs one API call (not batchable)'), mode incompatibilities, and dynamic context behavior ('Disabled when result count exceeds cost-based caps'). These are substantial behavioral details not present in 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 compact (~160 words), front-loaded with purpose, and each sentence carries distinct information about modes, parameters, constraints, or output. Long sentences add some density, but there is no filler or redundant repetition of schema content.
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 13-parameter tool with a rich schema and output schema, the description covers all operational modes (browse, search, ID fetch, replies, threads), states return fields, notes limitations, and links to full documentation. It provides enough operational detail for an agent to invoke correctly without additional lookups.
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 per-parameter descriptions, so baseline is 3. The description adds value by highlighting cross-parameter constraints (message_ids mutual exclusivity), server-side filtering scope ('per-chat only'), and cost implications of include_replies, which are not fully expressed in 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?
Description opens with 'Read or search messages in one chat' and enumerates distinct modes (browse latest, search text, fetch by ids, load replies), giving a specific verb and resource that distinguishes it from siblings like search_messages_globally and send_message.
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 usage context for each mode (from_user for sender filtering, context for neighbors/reply chains, include_replies for replies) and an explicit exclusion ('Do not combine message_ids with query or reply_to_id'). However, it does not explicitly name alternative tools like search_messages_globally, relying on the 'in one chat' scope and sibling names to imply alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
invoke_mtprotoInvoke MTProtoADestructive
Low-level Telegram API (MTProto) invoke for methods not wrapped by other tools. Dangerous methods require allow_dangerous=true. Success: API result dict or normalized error. Full documentation: https://github.com/alexeyleshchenko/fast-mcp-telegram/blob/main/docs/Tools-Reference.md
| Name | Required | Description | Default |
|---|---|---|---|
| resolve | No | If true, resolve string/int peer-like fields to TL Input* entities before invoke. | |
| params_json | Yes | JSON object string of TL parameters as in Telegram API docs; nested TL uses "_": "typeName" discriminator. | |
| allow_dangerous | No | If false, destructive methods (e.g. deletes) are blocked. Set true only when intended. | |
| method_full_name | Yes | Telegram API method, e.g. "messages.GetHistory" or "users.GetFullUser" (normalization applied). |
Output Schema
| Name | Required | Description |
|---|---|---|
| _ | No | |
| id | No | |
| ok | No | |
| code | No | |
| date | No | |
| chats | No | |
| error | No | |
| users | No | |
| action | No | |
| params | No | |
| result | No | |
| messages | No | |
| exception | No | |
| operation | No | |
| error_code | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare openWorldHint and destructiveHint, and the description adds meaningful behavioral context: dangerous methods are blocked without allow_dangerous=true, and successful responses are either an API result dict or a normalized error. This goes beyond the annotations by clarifying the guardrail and return behavior. The link to full documentation also supports transparency, though no rate limits or auth details are provided.
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 three sentences that front-load the core purpose, then add critical safety and result information. Every sentence earns its place, and the documentation link is a compact useful addition. No redundancy or fluff.
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 complex low-level tool, the description covers the essential aspects: what it does, when to use it, the dangerous-method guard, and the return type. The full schema and output schema handle parameter specifics, and the documentation link fills any remaining gaps. It does not mention authentication or rate limits, but those are shared across the MCP context and not uniquely critical here.
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 provides 100% coverage with detailed descriptions for all four parameters, so the baseline is 3. The description adds minimal parameter-related context beyond the schema, only implicitly referencing allow_dangerous and normalization. It does not explain parameter semantics in the description itself, but the schema is self-sufficient.
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 is a 'low-level Telegram API (MTProto) invoke' for 'methods not wrapped by other tools,' which is a specific verb+resource that distinguishes it from the high-level sibling tools. It also indicates the success output format, adding further specificity.
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 a clear usage rule: use this tool for methods not wrapped by other tools, implying that for wrapped methods one should use the appropriate sibling. It also warns that dangerous methods require allow_dangerous=true, setting expectations for when additional care is needed. However, it does not explicitly list alternative tool names.
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/alexeyleshchenko/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. | |
| 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 |
|---|---|---|
| ok | No | |
| code | No | |
| error | No | |
| action | No | |
| params | No | |
| _warning | No | |
| has_more | No | |
| messages | No | |
| exception | No | |
| operation | No | |
| error_code | No | |
| total_count | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses meaningful behavioral nuances: 'Global search ignores include_total_count' and 'Success: message list and metadata dict' describes return structure. These details inform the agent about parameter behavior and expected output, adding value over 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 compact and efficient, front-loading the core purpose and scope, then covering query format, filters, output, and a behavioral note in just four short sentences. Every sentence conveys useful information without redundant fluff, earning a 5.
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 tool with 8 parameters and a rich schema, the description effectively complements the structured data by clarifying global scope, output shape, and a key behavioral caveat. It doesn't need to explain every parameter because the schema does. The documentation link adds an escape hatch for deeper context.
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 already provides 100% coverage with detailed parameter descriptions, so the baseline is 3. The description adds no new parameter semantics beyond what the schema says, though it does restate query format ('Comma-separated query terms') and mentions include_total_count being ignored, which the schema also covers. This is sufficient but not additive.
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's core function: 'Search all Telegram chats at once' with explicit scope distinction ('not scoped to one chat'). This unambiguously differentiates it from per-chat search tools like get_messages, making the purpose immediately obvious.
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 clear context that this is for global cross-chat searching, contrasted with per-chat scope. It doesn't explicitly name sibling tools as alternatives, but the 'not scoped to one chat' phrasing strongly implies when to use it. The documentation link provides further guidance.
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 file attachments to a Telegram chat. Supports reply-to (including forum topics and channel discussion groups), parse_mode: classic markdown/html/auto (entities) or rich (Rich Message document; dialect auto-detected). parse_mode=rich cannot be combined with files. File attachments as http(s) URLs, local paths, or data: URIs. When files are provided, the message text becomes a caption. For channel posts with reply_to_id, automatically posts in the linked discussion group. Success: dict with message_id, date, chat, text, status='sent', and sender info (rich messages also set rich=true and rich_format). Error: dict with ok=false and error string. Use send_message to create new messages; use edit_message to modify existing ones. Use send_message_to_phone when targeting a phone number instead of a chat_id. Full documentation: https://github.com/alexeyleshchenko/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…), username without @, or 'me' for Saved Messages. | |
| message | Yes | Message text. When sending files, used as caption. | |
| parse_mode | No | 'markdown'/'html'/'auto': classic entity formatting (auto detects). 'rich': Telegram Rich Message document; dialect auto-detected (known HTML tags outside code → rich HTML, else rich markdown). Default is 'auto'. parse_mode='rich' cannot be combined with files. | 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 |
|---|---|---|
| ok | No | |
| chat | No | |
| code | No | |
| date | No | |
| rich | No | |
| text | No | |
| error | No | |
| action | No | |
| params | No | |
| sender | No | |
| status | No | |
| topic_id | No | |
| edit_date | No | |
| exception | No | |
| operation | No | |
| error_code | No | |
| message_id | No | |
| rich_format | No | |
| reply_markup | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare openWorldHint and destructiveHint, but the description adds substantial behavioral context: return format (success dict with message_id/status='sent', error dict with ok=false), channel post auto-reply behavior, parsing dialect auto-detection, and mode-specific file constraints (local paths stdio only, data URIs everywhere). No contradiction with 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 provides distinct information and it front-loads the core purpose. It could benefit from bullet points, but for the tool's complexity the length is justified.
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 purpose, alternatives, parameter interactions, return values, error handling, and links to full documentation. With a rich output schema and detailed parameter docs, nothing essential 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?
The input schema has 100% parameter description coverage, so baseline is 3. The description adds valuable cross-parameter semantics, such as files turning the message into a caption and reply_to_id triggering automatic posting in channel discussion groups, which goes beyond the schema's per-field descriptions.
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 opens with 'Send text and optional file attachments to a Telegram chat,' a specific verb+resource statement. It also distinguishes itself from sibling tools by explicitly pointing to edit_message for modifications and send_message_to_phone for phone targets.
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 provides explicit direction: 'Use send_message to create new messages; use edit_message to modify existing ones. Use send_message_to_phone when targeting a phone number instead of a chat_id.' It also details when to use reply_to and parse_mode options, including the limitation that rich mode cannot be combined with files.
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. Supports parse_mode: classic markdown/html/auto or rich (Rich Message; dialect auto-detected). parse_mode=rich cannot be combined with files. Success: send result plus contact_was_new / contact_removed when applicable. Full documentation: https://github.com/alexeyleshchenko/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'/'auto': classic entity formatting (auto detects). 'rich': Telegram Rich Message document; dialect auto-detected (known HTML tags outside code → rich HTML, else rich markdown). Default is 'auto'. parse_mode='rich' cannot be combined with files. | 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 |
|---|---|---|
| ok | No | |
| chat | No | |
| code | No | |
| date | No | |
| rich | No | |
| text | No | |
| error | No | |
| action | No | |
| params | No | |
| sender | No | |
| status | No | |
| topic_id | No | |
| edit_date | No | |
| exception | No | |
| operation | No | |
| error_code | No | |
| message_id | No | |
| rich_format | No | |
| phone_number | No | |
| reply_markup | No | |
| contact_removed | No | |
| contact_was_new | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that sending may create a temporary contact and reports contact_was_new/contact_removed flags in success results, which aligns with the destructiveHint annotation. It also adds a constraint that parse_mode=rich cannot be combined with files, providing context beyond the schema and annotations. No contradiction with 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 three sentences, front-loaded with the core purpose, followed by the parse_mode constraint, and rounded out with success result details and a documentation link. Every sentence earns its place, with no filler or repetition of schema fields.
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 essential behavioral aspects: temporary contact creation, text/files sending, parse_mode limitation, and return flags. Since an output schema exists and all parameters are fully described in the schema, the description provides sufficient context for an agent to invoke the tool correctly. It could have explicitly mentioned all 8 parameters, but those are already in the schema, so this is adequate.
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 all parameters with clear descriptions. The tool description adds some high-level context about parse_mode behavior (classic markdown/html/auto or rich) but largely repeats what the schema already states. It does not add meaningful detail about first_name, last_name, reply_to_msg_id, or remove_if_new 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?
The description opens with 'Send to a phone number,' which clearly states the action (send) and resource (phone number). It further specifies behavior: may create a temporary contact, then send text or files. This distinguishes it from the sibling tool send_message (which targets a chat), making the purpose 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 first sentence establishes when to use this tool: when the target is a phone number rather than a chat ID, and the temporary contact mechanism implies no pre-existing chat is needed. However, it does not explicitly name alternative tools like send_message or state conditions where this tool should not be used, so guidance is clear but not fully explicit.
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.
1 tool update
v0.44.1- Changed
get_chat_info2 fields changed- added
Output schema / properties / common_chatsAdded value: +{ + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" +} - added
Output schema / properties / common_chats_has_moreAdded value: +{ + "type": "boolean" +}
8 tool updates
v0.44.0- First observed
edit_message - First observed
find_chats - First observed
get_chat_info - First observed
get_messages - First observed
invoke_mtproto - First observed
search_messages_globally - First observed
send_message - First observed
send_message_to_phone
TDQS
Scored across 8 tools
Each tool targets a distinct action: finding chats, reading/searching messages in one chat, searching globally, sending, editing, and fetching chat info. The two send tools are clearly separated by target (chat_id vs phone), and global search vs per-chat search is explicitly scoped.
Tool names mostly follow a clean verb_noun pattern in snake_case (get_messages, send_message, edit_message, get_chat_info). Minor deviations like search_messages_globally and send_message_to_phone add modifiers, but the pattern remains predictable and readable.
Eight tools is a well-scoped size for a Telegram MCP server. Each tool covers a meaningful capability without unnecessary fragmentation, and the low-level invoke_mtproto tool rounds out the surface without bloating it.
Core workflows are covered: finding chats, reading/searching messages, sending, editing, and getting chat info. Obvious gaps like message deletion or marking messages read are not wrapped, but invoke_mtproto provides an escape hatch, so agents are not entirely blocked.
Maintenance
Related MCP Connectors
Multi-tenant Telegram gateway for AI agents — HTTP+stdio, 8 tools, MTProto User API
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
Unofficial Telegram MCP server — read, search, reply and react in your own Telegram account.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server that connects AI assistants to your real Telegram account via User API (MTProto). Features default-deny ACL with per-chat permissions, message search, file sending, forwarding, media downloads, and rate limiting.3MIT
- AlicenseNot gradedqualityBmaintenanceTelegram MTProto-based MCP server with 19 tools for reading, searching, sending, forwarding, and summarizing messagesMIT
- AlicenseBqualityDmaintenanceA Telegram MCP server that connects agents to a real Telegram user account via MTProto, enabling reading, searching, sending, moderating, and managing Telegram chats through natural language or automated tool calls.10090 npm29MIT
- FlicenseNot gradedqualityDmaintenanceModel Context Protocol server for Telegram. Let AI read, search, send, and forward your Telegram messages.35 npm-