MCP server for Telegram (MTProto/Telethon) — read chats, messages and media, send messages, via a user account
Server has 7 tools with complete input schemas and descriptions. Naming follows verb_noun convention (get_me, list_chats, send_message). Descriptions are detailed (100-250 chars) and explain WHAT, WHEN, and parameters. However, output schemas are not documented, LLMs cannot predict response structure. Parameters accept flexible identifiers (chat id/username/title) which matches chat data model, but this flexibility is not formally constrained. Error handling exists (TelegramMCPError) but recovery guidance is minimal. No tool annotations (readOnlyHint/destructiveHint) despite clear read/write distinction.
Download a message's media (photo/video/document) to disk. Args: chat: Chat id, @username, or exact/substring title. message_id: Message id (from get_messages). Returns the local file path.
Return the logged-in Telegram account (id, username, first_name, phone). Doubles as a session check — errors if no valid session exists.
Read recent messages from one chat. Args: chat: Chat id, @username, or exact/substring title. limit: Max messages (default 30, capped at 200). before_id: Only messages older than this message id (pagination). search: Optional full-text filter within the chat.
List chats (groups, channels, direct messages). Args: query: Optional case-insensitive substring filter on the chat title. When set, ALL dialogs are scanned so a match beyond the most-recent `limit` chats is still found (comparatively expensive, like title resolution); `limit` then caps the number of matches returned. limit: Max results (default 50, capped at 500). Without `query` this is also how many dialogs are fetched. Returns objects with id, title, type ('group'/'channel'/'user'), unread. Use this to find a chat's id/title before calling other tools.
Output schemas not documented. LLMs cannot predict response structure (fields, types, pagination). Responses from list_chats, get_messages, search_global lack documented pagination info (total_count, next_cursor).
No tool annotations (readOnlyHint/destructiveHint/idempotentHint). Agents cannot distinguish safe read-only tools from destructive ones without parsing descriptions. send_message and send_file are clearly WRITE but lack formal annotation.
Flexible 'chat' parameter (accepts id/username/title) is powerful but undocumented in schema. Parameter description explains the flexibility, but JSON Schema does not formally constrain it. LLMs may pass invalid formats.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
Search all chats for messages matching a query. Args: query: Search term (required). limit: Max results (default 50, capped at 200). Returns messages with their chat context (id, title, type).
Send a file to a chat. Args: chat: Chat id, @username, or exact/substring title. file_path: Local file path (required). caption: Optional caption text. Returns the sent message's id.
Send a text message to a chat. Args: chat: Chat id, @username, or exact/substring title. text: Message text (required). Returns the sent message's id.
Error messages are user-facing (TelegramMCPError) but lack recovery guidance. 'No valid session, run login.py first' is helpful, but most errors (e.g. chat not found, message not found) do not suggest next steps.
Limit parameters (list_chats, get_messages, search_global) are validated but lack explicit min/max in schema. Descriptions state caps (50/500, 30/200, 50/200) but JSON Schema does not enforce them, LLMs may pass invalid values.