list_accounts
List all configured Telegram accounts with profile info.
Run your own Telegram account from an agent — read and search chats, send and schedule messages, manage groups and contacts, and wait for a reply to arrive.
LABSCO SUMMARY
Aliases let you name a person the way you actually say it while only an exact saved wording ever sends, so a near-miss asks instead of messaging the wrong contact. The wait tools then let the agent stop, receive the reply, and continue rather than polling or giving up.
A Telegram integration built on Telethon that exposes account, chat, message, contact, media, folder and admin operations over MCP. It signs in as your user account, not as a bot.
send_message, reply_to_message and edit_message also take server-side rich formatting with tables, headings and collapsible sections, which requires Telegram Premium and returns a structured telegram_premium_required result rather than sending anything when the account lacks itset_contact_alias teaches it what you call someone, and every tool taking a chat_id understands that name afterwards. Only an exact saved wording ever sends — similar wording is matched only to suggest, and confirming saves it as its own aliaslist_contact_aliases, delete_contact_alias and a save path that refuses any target it would have to guess atwait_for_new_message and wait_for_settled_message, optionally scoped to one chat, or an opt-in event feed via enable_incoming_feed / incoming_feed_status / disable_incoming_feed for clients that can wake an agent on external outputPython 3.10+, Telegram API credentials from my.telegram.org/apps, and a session string. Do not install it from PyPI: the telegram-mcp name there belongs to a different project, and passing your API credentials to that package exposes your Telegram account to unrelated third-party code. Clone the repository, run uv sync, then uv run session_string_generator.py — with --qr when you can scan from another device or --phone for code login — and set TELEGRAM_API_ID, TELEGRAM_API_HASH and TELEGRAM_SESSION_STRING. TELEGRAM_EXPOSED_TOOLS=read-only registers only read-only tools, and read-only+send_message,reply_to_message adds named write tools back; an unknown name aborts startup rather than silently narrowing the surface. MCP_TRANSPORT selects stdio, http or sse, with HTTP binding 127.0.0.1:8765 and serving /mcp. File-path tools stay disabled until allowed roots are configured, either from the client's MCP Roots or as arguments after main.py. A session string grants access to the account it belongs to.
Build from source — git clone https://github.com/chigwell/telegram-mcp.git
USE CASES
Teach it the alias once; from then on the name you actually say resolves. Unfamiliar wording returns an instruction to confirm rather than a message to the wrong person.
Block on a settled incoming message, scoped to one chat so an unrelated conversation does not wake the agent early.
Set the exposed-tools variable to read-only; write tools are never registered, and a typo in the allowlist stops startup instead of quietly producing a narrower surface that looks like it worked.
Use the HTTP transport so a single long-lived process holds one Telegram connection — Telegram throttles and may flag accounts that open many parallel sessions.
Suffixed session variables give each account a label; read-only tools fan out over all of them, and write tools make you name the one you meant.
Turn on the incoming feed and arm a watch on the file it appends to; every settled burst re-invokes the agent without holding a blocking call open.
Listed in project code.
list_accountsList all configured Telegram accounts with profile info.
list_contactsList all contacts in your Telegram account.
search_contactsSearch for contacts by name, username, or phone number using Telethon's SearchRequest. Saved favorite aliases matching the query are checked first and returned at the top.
get_contact_idsGet all contact IDs in your Telegram account.
get_direct_chat_by_contactFind a direct chat with a specific contact by name, username, or phone.
get_contact_chatsList all chats involving a specific contact.
get_last_interactionGet the most recent message with a contact.
add_contactAdd a new contact to your Telegram account.
delete_contactDelete a contact by user ID.
block_userBlock a user by user ID.
unblock_userUnblock a user by user ID.
import_contactsImport a list of contacts. Each contact should be a dict with phone, first_name, last_name.
export_contactsExport all contacts as a JSON string.
get_blocked_usersGet a list of blocked users.
send_contactSend a contact to a chat.
set_contact_aliasRemember what the user calls someone, so any tool taking a chat_id understands it.
list_contact_aliasesList remembered contacts, one row per person with all of their aliases.
delete_contact_aliasForget one remembered alias. Exact match only — deleting the wrong memory is silent, so fuzzy matching is deliberately not used here. Use list_contact_aliases first if unsure of the exact wording.
get_chatsGet a paginated list of chats.
subscribe_public_channelSubscribe (join) to a public channel or supergroup by username or ID.
list_topicsRetrieve forum topics from a supergroup with the forum feature enabled.
enable_forum_topicsEnable Telegram forum topics for a supergroup.
create_forum_topicCreate a Telegram forum topic in a forum-enabled supergroup.
list_chatsList available chats with metadata.
get_chatGet detailed information about a specific chat.
search_public_chatsSearch for public chats, channels, or bots by username or title.
resolve_usernameResolve a username to a user or chat ID.
get_full_chatGet full info of a channel or group including description/about text.
mute_chatMute notifications for a chat.
unmute_chatUnmute notifications for a chat.
archive_chatArchive a chat.
unarchive_chatUnarchive a chat.
get_common_chatsList chats shared with a specific user.
get_message_read_byList user IDs who have read a specific message.
get_message_linkExport a t.me/... link for a specific message.
get_messagesGet paginated messages from a specific chat. Lines include custom_emojis when present: unique {emoji, id} pairs, with IDs as strings. Reuse them with send_message/reply_to_message and parse_mode='html'.
send_messageSend a message to a specific chat. Reuse custom_emojis from message-reading tools with parse_mode='html' and <tg-emoji emoji-id="ID">EMOJI</tg-emoji>, using the returned id and emoji. HTML-escape the emoji and other literal text. Custom emoji availability is subject to Telegram's account restrictions. format_date renders a tappable chip (copy / add-to-calendar / reminder) over the date text given verbatim: '13/09', '13/09/2026', or '13/09 17:00'.
send_scheduled_messageSchedule a message to be sent at a future time.
get_scheduled_messagesList all scheduled (pending) messages in a chat. Lines include custom_emojis when present: unique {emoji, id} pairs for reuse with parse_mode='html' and <tg-emoji emoji-id="ID">EMOJI</tg-emoji>.
delete_scheduled_messageDelete one or more scheduled (pending) messages from a chat.
list_inline_buttonsInspect inline buttons on a recent message to discover their indices/text/URLs.
press_inline_buttonPress an inline button (callback) in a chat message.
list_messagesRetrieve messages with optional filters.
transcribe_voiceTranscribe a voice message or video note (video circle) to text.
get_message_contextRetrieve context around a specific message.
get_send_asList Telegram's allowed send-as peers for this destination where supported.
forward_messageForward a message (or several) from a source chat to a destination chat.
forward_messagesForward a BATCH of messages from a source chat to a destination chat in a single atomic call.
edit_messageEdit a message you sent. Reuse custom_emojis from message-reading tools with parse_mode='html' and <tg-emoji emoji-id="ID">EMOJI</tg-emoji>, using the returned id and emoji. HTML-escape the emoji and other literal text. format_date renders a tappable chip (copy / add-to-calendar / reminder) over the date text given verbatim: '13/09', '13/09/2026', or '13/09 17:00'.
delete_messageDelete a message by ID.
delete_chat_historyClear the full message history of a chat.
delete_messages_bulkDelete multiple messages in a single call.
pin_messagePin a message in a chat.
unpin_messageUnpin a message in a chat.
unpin_all_messagesUnpin all pinned messages in a chat.
mark_as_readMark all messages as read in a chat.
reply_to_messageReply to a specific message in a chat. Reuse custom_emojis from message-reading tools with parse_mode='html' and <tg-emoji emoji-id="ID">EMOJI</tg-emoji>, using the returned id and emoji. HTML-escape the emoji and other literal text. format_date renders a tappable chip (copy / add-to-calendar / reminder) over the date text given verbatim: '13/09', '13/09/2026', or '13/09 17:00'.
search_messagesSearch for messages in a chat by text.
search_globalSearch for messages across all public chats and channels by text content.
get_historyGet full chat history (up to limit).
get_pinned_messagesGet all pinned messages in a chat.
create_pollCreate a poll in a chat using Telegram's native poll feature.
send_reactionSend a reaction to a message.
remove_reactionRemove your reaction from a message.
get_message_reactionsGet the list of reactions on a message.
save_draftSave a draft message to a chat or channel. The draft will appear in the Telegram app's input field when you open that chat, allowing you to review and send it manually.
get_draftsGet all draft messages across all chats. Returns a list of drafts with their chat info and message content. Drafts include custom_emojis when present: unique {emoji, id} pairs for reuse with parse_mode='html' and <tg-emoji emoji-id="ID">EMOJI</tg-emoji>.
clear_draftClear/delete a draft from a specific chat.
create_groupCreate a new group or supergroup and add users.
invite_to_groupInvite users to a group or channel.
leave_chatLeave a group or channel by chat ID.
get_participantsList participants in a group or channel with pagination.
create_channelCreate a new channel or supergroup.
edit_chat_titleEdit the title of a chat, group, or channel.
edit_chat_photoEdit the photo of a chat, group, or channel. Requires a file path to an image.
edit_chat_aboutEdit the description ("About") of a chat, group, or channel.
delete_chat_photoDelete the photo of a chat, group, or channel.
promote_adminPromote a user to admin in a group/channel.
demote_adminDemote a user from admin in a group/channel.
ban_userBan a user from a group or channel.
unban_userUnban a user from a group or channel.
remove_userRemove a user from a group or channel WITHOUT banning them.
set_default_chat_permissionsSet default member permissions for a group, supergroup, or channel.
toggle_slow_modeEnable or disable slow mode for a supergroup.
edit_admin_rightsSet granular admin rights for a user in a supergroup or channel.
get_adminsGet all admins in a group or channel.
get_banned_usersGet all banned users in a group or channel.
get_invite_linkGet the invite link for a group or channel.
join_chat_by_linkJoin a chat by invite link.
export_chat_inviteExport a chat invite link.
import_chat_inviteImport a chat invite by hash.
get_recent_actionsGet recent admin actions (admin log) in a group or channel.
send_fileSend a file to a chat.
send_albumSend multiple photos/videos as one Telegram media group (album).
download_mediaDownload media from a message in a chat.
send_voiceSend a voice message to a chat. File must be an OGG/OPUS voice note.
upload_fileUpload a local file to Telegram and return upload metadata.
get_media_infoGet info about media in a message.
get_sticker_setsGet all sticker sets.
send_stickerSend a sticker to a chat. File must be a valid .webp sticker file.
get_gif_searchSearch for GIFs by query. Returns a list of Telegram document IDs (not file paths).
send_gifSend a GIF to a chat by Telegram GIF document ID (not a file path).
list_photosIndex the photos of any peer as text, without transferring any image.
open_photoView one photo of any peer at full resolution.
get_photo_sheetView many photos of a peer as one labelled collage, for a single image cost.
get_meGet your own user information.
update_profileUpdate your profile information (name, bio).
set_profile_photoSet a new profile photo.
delete_profile_photoDelete your current profile photo.
get_privacy_settingsGet your privacy settings for last seen status.
set_privacy_settingsSet privacy settings (e.g., last seen, phone, etc.).
get_full_userGet full profile info of a Telegram user including bio/about text, personal channel link, and other profile details.
get_bot_infoGet information about a bot by username.
set_bot_commandsSet bot commands for a bot you own. Note: This function can only be used if the Telegram client is a bot account. Regular user accounts cannot set bot commands.
get_user_photosGet profile photos of a user.
get_user_statusGet the online status of a user.
list_foldersGet all dialog folders (filters) with their IDs, names, and emoji. Returns a list of folders that can be used with other folder tools.
get_folderGet detailed information about a specific folder including all included chats.
create_folderCreate a new dialog folder.
add_chat_to_folderAdd a chat to an existing folder.
remove_chat_from_folderRemove a chat from a folder.
delete_folderDelete a folder. Chats in the folder are preserved, only the folder is removed.
reorder_foldersChange the order of folders in the folder list.
wait_for_new_messageBlock until a new incoming private message from a non-bot user arrives, then return immediately with the list of chats that currently have pending (unprocessed) incoming messages. If nothing arrives within timeout seconds, returns {"event": false, "reason": "timeout"}. Lets the agent react to events instead of polling. Does NOT consume the pending set — use wait_for_settled_message to consume a debounced burst.
wait_for_settled_messageEvent-driven, DEBOUNCED wait. Blocks until some private user chat has received one or more incoming messages AND then gone quiet for settle_ms — so a client who types several messages (or sends file + text) in a row is delivered as ONE settled burst instead of waking the agent on every message. Returns that chat's burst summary and removes it from the pending set, so the next call returns the next settled chat. If no chat settles within max_wait_ms, returns {"event": false, "reason": "timeout"} (caller should simply call again).
enable_incoming_feedCLAUDE CODE ONLY. Enable callback mode: a background task appends every settled incoming burst as one JSON line to the feed file, so an external watcher can wake the agent per event instead of the agent blocking in wait_for_settled_message.
disable_incoming_feedDisable the incoming event feed (stops writing to the feed file).
incoming_feed_statusReport whether the incoming event feed is enabled, its file path, and the watch command for waking an agent per event.
BEFORE YOU INSTALL
128 tools registered in the project's code.
INSTALLATION
You clone this one yourself.
git clone https://github.com/chigwell/telegram-mcp.git
cd telegram-mcp
uv syncGet your API ID and API hash from https://my.telegram.org/apps, then generate a session string and save it securely (--qr logs in by scanning a QR code; --phone uses a verification code):
uv run session_string_generator.py --qrFor the shared HTTP server, also copy the example environment file and put the three values in it:
cp .env.example .env{
"mcpServers": {
"telegram-mcp": {
"command": "uv",
"args": [
"--directory",
"<YOUR_PATH_TO_TELEGRAM_MCP>",
"run",
"main.py"
],
"env": {
"TELEGRAM_API_ID": "<YOUR_TELEGRAM_API_ID>",
"TELEGRAM_API_HASH": "<YOUR_TELEGRAM_API_HASH>",
"TELEGRAM_SESSION_STRING": "<YOUR_TELEGRAM_SESSION_STRING>"
}
}
}
}Install a pinned release into a virtualenv
Not from PyPI: the telegram-mcp name there belongs to a different project. <YOUR_TAG_COMMIT> is a release tag or commit.
python -m venv .venv
. .venv/bin/activate
pip install "git+https://github.com/chigwell/telegram-mcp.git@<YOUR_TAG_COMMIT>"
telegram-mcp-generate-sessionPoint your client at the installed console script
Use the absolute path of .venv/bin/telegram-mcp, and the session string telegram-mcp-generate-session printed.
{
"mcpServers": {
"telegram-mcp": {
"command": "<YOUR_PATH_TO_VENV>/bin/telegram-mcp",
"env": {
"TELEGRAM_API_ID": "<YOUR_TELEGRAM_API_ID>",
"TELEGRAM_API_HASH": "<YOUR_TELEGRAM_API_HASH>",
"TELEGRAM_SESSION_STRING": "<YOUR_TELEGRAM_SESSION_STRING>"
}
}
}
}From your clone, with TELEGRAM_API_ID, TELEGRAM_API_HASH and TELEGRAM_SESSION_STRING in .env. It listens on 127.0.0.1:8765 and serves /mcp; leave it running.
Start one shared server over streamable HTTP
cd telegram-mcp
MCP_TRANSPORT=http uv run main.pyRegister it with Claude Code
claude mcp add --transport http telegram http://127.0.0.1:8765/mcpFrom your clone, with TELEGRAM_API_ID, TELEGRAM_API_HASH and TELEGRAM_SESSION_STRING in .env. It listens on 127.0.0.1:8765 and serves /mcp; leave it running.
Start one shared server over streamable HTTP
cd telegram-mcp
MCP_TRANSPORT=http uv run main.pyRegister it with Codex
codex mcp add telegram --url http://127.0.0.1:8765/mcpFrom your clone, with TELEGRAM_API_ID, TELEGRAM_API_HASH and TELEGRAM_SESSION_STRING in .env. It listens on 127.0.0.1:8765 and serves /mcp; leave it running.
Start one shared server over streamable HTTP
cd telegram-mcp
MCP_TRANSPORT=http uv run main.pyBridge a stdio-only client to it with mcp-remote
{
"mcpServers": {
"telegram-mcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://127.0.0.1:8765/mcp"
]
}
}
}