{"id":26937453,"url":"https://github.com/chigwell/telegram-mcp","last_synced_at":"2026-04-24T00:01:13.654Z","repository":{"id":283511788,"uuid":"951958279","full_name":"chigwell/telegram-mcp","owner":"chigwell","description":"Telegram MCP server powered by Telethon to let MCP clients read chats, manage groups, and send/modify messages, media, contacts, and settings.","archived":false,"fork":false,"pushed_at":"2026-04-22T15:26:35.000Z","size":1399,"stargazers_count":985,"open_issues_count":25,"forks_count":251,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-04-22T16:29:20.718Z","etag":null,"topics":["admin","api","chat-management","contacts","groups","mcp","media","messaging","search","telegram","telegram-api","telegram-client","telethon"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chigwell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-20T14:06:35.000Z","updated_at":"2026-04-22T15:26:22.000Z","dependencies_parsed_at":"2025-03-20T16:41:57.734Z","dependency_job_id":"a2ee6735-da74-4169-b481-eaa444439b42","html_url":"https://github.com/chigwell/telegram-mcp","commit_stats":null,"previous_names":["chigwell/telegram-mcp"],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/chigwell/telegram-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chigwell%2Ftelegram-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chigwell%2Ftelegram-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chigwell%2Ftelegram-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chigwell%2Ftelegram-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chigwell","download_url":"https://codeload.github.com/chigwell/telegram-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chigwell%2Ftelegram-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32203362,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T20:19:26.138Z","status":"ssl_error","status_checked_at":"2026-04-23T20:19:23.520Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["admin","api","chat-management","contacts","groups","mcp","media","messaging","search","telegram","telegram-api","telegram-client","telethon"],"created_at":"2025-04-02T13:15:15.022Z","updated_at":"2026-04-24T00:01:13.647Z","avatar_url":"https://github.com/chigwell.png","language":"Python","funding_links":[],"categories":["Communication \u0026 Messaging","Messaging Mcp Servers","📚 Projects (1974 total)","Community Servers","MCP 服务器精选列表","پیاده‌سازی‌های سرور","🤖 AI/ML","Python","Servers","Real-Time Collaboration","Communication","MCP Servers","Table of Contents"],"sub_categories":["Messengers","MCP Servers","💬 通讯与协作 (Slack, Email, Calendar, Social, etc.)","💬 \u003ca name=\"communication\"\u003e\u003c/a\u003eارتباطات","Communication","Social \u0026 Messaging"],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://capsule-render.vercel.app/api?type=waving\u0026color=gradient\u0026height=200\u0026section=header\u0026text=Telegram%20MCP%20Server\u0026fontSize=50\u0026fontAlignY=35\u0026animation=fadeIn\u0026fontColor=FFFFFF\u0026descAlignY=55\u0026descAlign=62\" alt=\"Telegram MCP Server\" width=\"100%\" /\u003e\n\u003c/div\u003e\n\n![MCP Badge](https://badge.mcpx.dev)\n[![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-green?style=flat-square)](https://opensource.org/licenses/Apache-2.0)\n[![Python Lint \u0026 Format Check](https://github.com/chigwell/telegram-mcp/actions/workflows/python-lint-format.yml/badge.svg)](https://github.com/chigwell/telegram-mcp/actions/workflows/python-lint-format.yml)\n[![Docker Build \u0026 Compose Validation](https://github.com/chigwell/telegram-mcp/actions/workflows/docker-build.yml/badge.svg)](https://github.com/chigwell/telegram-mcp/actions/workflows/docker-build.yml)\n\n---\n\n## 🤖 MCP in Action\n\nHere's a demonstration of the Telegram MCP capabilities in [Claude](https://docs.anthropic.com/en/docs/agents-and-tools/mcp):\n\n **Basic usage example:**\n\n![Telegram MCP in action](screenshots/1.png)\n\n1. **Example: Asking Claude to analyze chat history and send a response:**\n\n![Telegram MCP Request](screenshots/2.png)\n\n2. **Successfully sent message to the group:**\n\n![Telegram MCP Result](screenshots/3.png)\n\nAs you can see, the AI can seamlessly interact with your Telegram account, retrieving and displaying your chats, messages, and other data in a natural way.\n\n---\n\nA full-featured Telegram integration for Claude, Cursor, and any MCP-compatible client, powered by [Telethon](https://docs.telethon.dev/) and the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). This project lets you interact with your Telegram account programmatically, automating everything from messaging to group management.\n\n\n---\n\n## 🚀 Features \u0026 Tools\n\nThis MCP server exposes a huge suite of Telegram tools. **Every major Telegram/Telethon feature is available as a tool!**\n\n### Chat \u0026 Group Management\n- **get_chats(page, page_size)**: Paginated list of chats\n- **list_chats(chat_type, limit, unread_only, unmuted_only, with_about)**: List chats with metadata and filtering; `with_about=True` enriches output with each chat's description (slower).\n- **get_chat(chat_id)**: Detailed info about a chat\n- **create_group(title, user_ids)**: Create a new group\n- **invite_to_group(group_id, user_ids)**: Invite users to a group or channel\n- **create_channel(title, about, megagroup)**: Create a channel or supergroup\n- **edit_chat_title(chat_id, title)**: Change chat/group/channel title\n- **edit_chat_about(chat_id, about)**: Edit chat/group/channel description (About, max 255 chars)\n- **delete_chat_photo(chat_id)**: Remove chat/group/channel photo\n- **leave_chat(chat_id)**: Leave a group or channel\n- **get_participants(chat_id)**: List all participants\n- **get_admins(chat_id)**: List all admins\n- **get_banned_users(chat_id)**: List all banned users\n- **promote_admin(chat_id, user_id)**: Promote user to admin\n- **demote_admin(chat_id, user_id)**: Demote admin to user\n- **ban_user(chat_id, user_id)**: Ban user\n- **unban_user(chat_id, user_id)**: Unban user\n- **edit_admin_rights(chat_id, user_id, rank, ...rights)**: Set granular admin rights (extends promote_admin)\n- **set_default_chat_permissions(chat_id, ...perms, until_date)**: Set default member permissions (send, media, invite, pin, etc.)\n- **toggle_slow_mode(chat_id, seconds)**: Enable/disable slow mode in supergroups (0/10/30/60/300/900/3600s)\n- **get_invite_link(chat_id)**: Get invite link\n- **export_chat_invite(chat_id)**: Export invite link\n- **import_chat_invite(hash)**: Join chat by invite hash\n- **join_chat_by_link(link)**: Join chat by invite link\n- **subscribe_public_channel(channel)**: Subscribe to a public channel or supergroup by username or ID\n- **get_common_chats(user_id, limit=100, max_id=0)**: List chats shared with a specific user\n- **get_message_read_by(chat_id, message_id)**: List users who have read a message (small groups/supergroups with read receipts enabled)\n\n### Messaging\n- **get_messages(chat_id, page, page_size)**: Paginated messages\n- **list_messages(chat_id, limit, search_query, from_date, to_date)**: Filtered messages\n- **list_topics(chat_id, limit, offset_topic, search_query)**: List forum topics in supergroups\n- **send_message(chat_id, message)**: Send a message\n- **reply_to_message(chat_id, message_id, text)**: Reply to a message\n- **edit_message(chat_id, message_id, new_text)**: Edit your message\n- **delete_message(chat_id, message_id)**: Delete a message\n- **delete_messages_bulk(chat_id, message_ids, revoke=True)**: Delete multiple messages in one call\n- **delete_chat_history(chat_id, max_id=0, revoke=False)**: Clear the full message history of a chat\n- **forward_message(from_chat_id, message_id, to_chat_id)**: Forward a message\n- **pin_message(chat_id, message_id)**: Pin a message\n- **unpin_message(chat_id, message_id)**: Unpin a message\n- **unpin_all_messages(chat_id)**: Unpin all pinned messages in a chat\n- **mark_as_read(chat_id)**: Mark all as read\n- **get_message_context(chat_id, message_id, context_size)**: Context around a message\n- **get_history(chat_id, limit)**: Full chat history\n- **get_pinned_messages(chat_id)**: List pinned messages\n- **get_last_interaction(contact_id)**: Most recent message with a contact\n- **create_poll(chat_id, question, options, multiple_choice, quiz_mode, public_votes, close_date)**: Create a poll\n- **list_inline_buttons(chat_id, message_id, limit)**: Inspect inline keyboards to discover button text/index\n- **press_inline_button(chat_id, message_id, button_text, button_index)**: Trigger inline keyboard callbacks by label or index\n-  **send_reaction(chat_id, message_id, emoji, big=False)**: Add a reaction to a message\n-  **remove_reaction(chat_id, message_id)**: Remove a reaction from a message\n-  **get_message_reactions(chat_id, message_id, limit=50)**: Get all reactions on a message\n- **send_scheduled_message(chat_id, message, schedule_date)**: Schedule a message for future delivery (ISO-8601 or Unix timestamp)\n- **get_scheduled_messages(chat_id)**: List all pending scheduled messages in a chat\n- **delete_scheduled_message(chat_id, message_ids)**: Delete one or more scheduled messages\n- **get_message_link(chat_id, message_id, thread=False)**: Export a t.me/... link to a message (channels/supergroups only)\n\n### Contact Management\n- **list_contacts()**: List all contacts\n- **search_contacts(query)**: Search contacts\n- **add_contact(phone, first_name, last_name)**: Add a contact\n- **delete_contact(user_id)**: Delete a contact\n- **block_user(user_id)**: Block a user\n- **unblock_user(user_id)**: Unblock a user\n- **import_contacts(contacts)**: Bulk import contacts\n- **export_contacts()**: Export all contacts as JSON\n- **get_blocked_users()**: List blocked users\n- **get_contact_ids()**: List all contact IDs\n- **get_direct_chat_by_contact(contact_query)**: Find direct chat with a contact\n- **get_contact_chats(contact_id)**: List all chats with a contact\n\n### User \u0026 Profile\n- **get_me()**: Get your user info\n- **update_profile(first_name, last_name, about)**: Update your profile\n- **set_profile_photo(file_path)**: Set a profile photo from an allowed root path\n- **delete_profile_photo()**: Remove your profile photo\n- **get_user_photos(user_id, limit)**: Get a user's profile photos\n- **get_user_status(user_id)**: Get a user's online status\n\n### Media\n- **get_media_info(chat_id, message_id)**: Get info about media in a message\n- **send_file(chat_id, file_path, caption)**: Send a local file from allowed roots\n- **download_media(chat_id, message_id, file_path)**: Save message media under allowed roots\n- **upload_file(file_path)**: Upload a local file and return upload metadata\n- **send_voice(chat_id, file_path)**: Send `.ogg/.opus` voice note from allowed roots\n- **send_sticker(chat_id, file_path)**: Send `.webp` sticker from allowed roots\n- **edit_chat_photo(chat_id, file_path)**: Update chat photo from allowed roots\n\n### Search \u0026 Discovery\n- **search_public_chats(query, limit)**: Search public chats/channels/bots with a configurable result limit\n- **search_messages(chat_id, query, limit)**: Search messages in a chat\n- **search_global(query, page, page_size)**: Search messages globally with pagination\n- **resolve_username(username)**: Resolve a username to ID\n\n### Stickers, GIFs, Bots\n- **get_sticker_sets()**: List sticker sets\n- **get_bot_info(bot_username)**: Get info about a bot\n- **set_bot_commands(bot_username, commands)**: Set bot commands (bot accounts only)\n\n### Privacy, Settings, and Misc\n- **get_privacy_settings()**: Get privacy settings\n- **set_privacy_settings(key, allow_users, disallow_users)**: Set privacy settings\n- **mute_chat(chat_id)**: Mute notifications\n- **unmute_chat(chat_id)**: Unmute notifications\n- **archive_chat(chat_id)**: Archive a chat\n- **unarchive_chat(chat_id)**: Unarchive a chat\n- **get_recent_actions(chat_id)**: Get recent admin actions\n\n### Drafts\n- **save_draft(chat_id, message, reply_to_msg_id, no_webpage)**: Save a draft message to a chat/channel\n- **get_drafts()**: Get all draft messages across all chats\n- **clear_draft(chat_id)**: Clear/delete a draft from a specific chat\n\n### Multi-Account\n- **list_accounts()**: List all configured accounts with profile info\n\nAll tools accept an optional `account` parameter to target a specific account. In multi-account mode:\n- **Read-only tools** (e.g., `get_chats`, `list_messages`) query all accounts when `account` is omitted, returning results prefixed with `[label]`.\n- **Write tools** (e.g., `send_message`, `mark_as_read`) require an explicit `account` value.\n- **Single-account setups** work exactly as before — the `account` parameter is optional everywhere.\n\n### Input Validation\n\nTo improve robustness, all functions accepting `chat_id` or `user_id` parameters now include input validation. You can use any of the following formats for these IDs:\n\n-   **Integer ID**: The direct integer ID for a user, chat, or channel (e.g., `123456789` or `-1001234567890`).\n-   **String ID**: The integer ID provided as a string (e.g., `\"123456789\"`).\n-   **Username**: The public username for a user or channel (e.g., `\"@username\"` or `\"username\"`).\n\nThe server will automatically validate the input and convert it to the correct format before making a request to Telegram. If the input is invalid, a clear error message will be returned.\n\n## File-path Tools Security Model\n\nFile-path tools are available, but **disabled by default** until allowed roots are configured.\n\nSupported file-path tools:\n- `send_file`, `download_media`, `set_profile_photo`, `edit_chat_photo`, `send_voice`, `send_sticker`, `upload_file`\n\nSecurity semantics (aligned with MCP filesystem server):\n- Server-side allowlist via CLI positional arguments (fallback when Roots API is unsupported).\n- Client-provided MCP Roots replace the server allowlist when available.\n- If the client returns an empty Roots list, file-path tools are disabled (deny-all).\n- All paths are resolved via realpath and must stay inside an allowed root.\n- Traversal/glob-like patterns are rejected (`..`, `*`, `?`, `~`, etc.).\n- Relative paths resolve against the first allowed root.\n- Write tools default to `\u003cfirst_root\u003e/downloads/` when `file_path` is omitted.\n\nExample server launch with allowlisted roots:\n```bash\nuv --directory /full/path/to/telegram-mcp run main.py /data/telegram /tmp/telegram-mcp\n```\n\nGIF tools are currently limited: `get_gif_search` and `send_gif` are available, while `get_saved_gifs` is not implemented due to reliability limits in Telethon/Telegram API interactions.\n\n---\n\n## 📋 Requirements\n- Python 3.10+\n- [Telethon](https://docs.telethon.dev/)\n- [MCP Python SDK](https://modelcontextprotocol.io/docs/)\n- [Claude Desktop](https://claude.ai/desktop) or [Cursor](https://cursor.so/) (or any MCP client)\n\n---\n\n## 🔧 Installation \u0026 Setup\n\n### 1. Fork \u0026 Clone\n\n```bash\ngit clone https://github.com/chigwell/telegram-mcp.git\ncd telegram-mcp\n```\n\n### 2. Install Dependencies with uv\n\n```bash\nuv sync\n```\n\n### 3. Generate a Session String\n\n```bash\nuv run session_string_generator.py\n```\nFollow the prompts to authenticate. You'll be asked for an optional account label (e.g., `work`, `personal`) — leave empty for a single-account setup.\n\n### 4. Configure .env\n\nCopy `.env.example` to `.env` and fill in your values.\n\n**Single account:**\n```\nTELEGRAM_API_ID=your_api_id_here\nTELEGRAM_API_HASH=your_api_hash_here\nTELEGRAM_SESSION_STRING=your_session_string_here\n```\n\n**Multiple accounts:**\n```\nTELEGRAM_API_ID=your_api_id_here\nTELEGRAM_API_HASH=your_api_hash_here\nTELEGRAM_SESSION_STRING_WORK=session_string_for_work_account\nTELEGRAM_SESSION_STRING_PERSONAL=session_string_for_personal_account\n```\n\nAdd `_\u003cLABEL\u003e` suffix to `TELEGRAM_SESSION_STRING` for each account. Labels become account identifiers used in tool calls. A shared `TELEGRAM_API_ID` and `TELEGRAM_API_HASH` are used for all accounts.\n\nGet your API credentials at [my.telegram.org/apps](https://my.telegram.org/apps).\n\n---\n\n## 🐳 Running with Docker\n\nIf you have Docker and Docker Compose installed, you can build and run the server in a container, simplifying dependency management.\n\n### 1. Build the Image\n\nFrom the project root directory, build the Docker image:\n\n```bash\ndocker build -t telegram-mcp:latest .\n```\n\n### 2. Running the Container\n\nYou have two options:\n\n**Option A: Using Docker Compose (Recommended for Local Use)**\n\nThis method uses the `docker-compose.yml` file and automatically reads your credentials from a `.env` file.\n\n1.  **Create `.env` File:** Ensure you have a `.env` file in the project root containing your `TELEGRAM_API_ID`, `TELEGRAM_API_HASH`, and `TELEGRAM_SESSION_STRING` (or `TELEGRAM_SESSION_NAME`). Use `.env.example` as a template.\n2.  **Run Compose:**\n    ```bash\n    docker compose up --build\n    ```\n    *   Use `docker compose up -d` to run in detached mode (background).\n    *   Press `Ctrl+C` to stop the server.\n\n**Option B: Using `docker run`**\n\nYou can run the container directly, passing credentials as environment variables.\n\n```bash\ndocker run -it --rm \\\n  -e TELEGRAM_API_ID=\"YOUR_API_ID\" \\\n  -e TELEGRAM_API_HASH=\"YOUR_API_HASH\" \\\n  -e TELEGRAM_SESSION_STRING=\"YOUR_SESSION_STRING\" \\\n  telegram-mcp:latest\n```\n*   Replace placeholders with your actual credentials.\n*   For multiple accounts, use `-e TELEGRAM_SESSION_STRING_WORK=\"...\"` `-e TELEGRAM_SESSION_STRING_PERSONAL=\"...\"` instead.\n*   Use `-e TELEGRAM_SESSION_NAME=your_session_file_name` instead of `TELEGRAM_SESSION_STRING` if you prefer file-based sessions (requires volume mounting, see `docker-compose.yml` for an example).\n*   The `-it` flags are crucial for interacting with the server.\n\n---\n\n## ⚙️ Configuration for Claude \u0026 Cursor\n\n### MCP Configuration\nEdit your Claude desktop config (e.g. `~/Library/Application Support/Claude/claude_desktop_config.json`) or Cursor config (`~/.cursor/mcp.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"telegram-mcp\": {\n      \"command\": \"uv\",\n      \"args\": [\n        \"--directory\",\n        \"/full/path/to/telegram-mcp\",\n        \"run\",\n        \"main.py\"\n      ]\n    }\n  }\n}\n```\n\n## 📝 Tool Examples with Code \u0026 Output\n\nBelow are examples of the most commonly used tools with their implementation and sample output.\n\n### Getting Your Chats\n\n```python\n@mcp.tool()\n@with_account(readonly=True)\nasync def get_chats(account: str = None, page: int = 1, page_size: int = 20) -\u003e str:\n    \"\"\"\n    Get a paginated list of chats.\n    Args:\n        account: Account label (optional in single-account mode).\n        page: Page number (1-indexed).\n        page_size: Number of chats per page.\n    \"\"\"\n    try:\n        cl = get_client(account)\n        dialogs = await cl.get_dialogs()\n        ...\n```\n\nExample output (multi-account, no `account` specified):\n```\n[work]\nChat ID: -100987654321, Title: My Project Group\nChat ID: 111223344, Title: Jane Smith\n\n[personal]\nChat ID: 123456789, Title: John Doe\nChat ID: -200123456789, Title: News Channel\n```\n\n### Sending Messages\n\n```python\n@mcp.tool()\n@with_account(readonly=False)\nasync def send_message(chat_id: Union[int, str], message: str, account: str = None) -\u003e str:\n    \"\"\"\n    Send a message to a specific chat.\n    Args:\n        chat_id: The ID of the chat.\n        message: The message content to send.\n        account: Account label (required in multi-account mode).\n    \"\"\"\n    try:\n        cl = get_client(account)\n        entity = await resolve_entity(chat_id, cl)\n        await cl.send_message(entity, message)\n        return \"Message sent successfully.\"\n    ...\n```\n\nExample output:\n```\nMessage sent successfully.\n```\n\n### Listing Inline Buttons\n\n```python\n@mcp.tool()\n@with_account(readonly=True)\nasync def list_inline_buttons(\n    chat_id: Union[int, str],\n    message_id: Optional[int] = None,\n    limit: int = 20,\n    account: str = None,\n) -\u003e str:\n    \"\"\"\n    Discover inline keyboard layout, including button indices, callback availability, and URLs.\n    \"\"\"\n```\n\nExample usage:\n```\nlist_inline_buttons(chat_id=\"@sample_tasks_bot\")\n```\n\nThis returns something like:\n```\nButtons for message 42 (date 2025-01-01 12:00:00+00:00):\n[0] text='📋 View tasks', callback=yes\n[1] text='ℹ️ Help', callback=yes\n[2] text='🌐 Visit site', callback=no, url=https://example.org\n```\n\n### Pressing Inline Buttons\n\n```python\n@mcp.tool()\n@with_account(readonly=False)\nasync def press_inline_button(\n    chat_id: Union[int, str],\n    message_id: Optional[int] = None,\n    button_text: Optional[str] = None,\n    button_index: Optional[int] = None,\n    account: str = None,\n) -\u003e str:\n    \"\"\"\n    Press an inline keyboard button by label or zero-based index.\n    If message_id is omitted, the server searches recent messages for the latest inline keyboard.\n    \"\"\"\n```\n\nExample usage:\n```\npress_inline_button(chat_id=\"@sample_tasks_bot\", button_text=\"📋 View tasks\")\n```\n\nUse `list_inline_buttons` first if you need to inspect available buttons—pass a bogus `button_text`\nto quickly list options or call `list_inline_buttons` directly. Once you know the text or index,\n`press_inline_button` sends the callback, just like tapping the button in a native Telegram client.\n\n### Subscribing to Public Channels\n\n```python\n@mcp.tool()\n@with_account(readonly=False)\nasync def subscribe_public_channel(channel: Union[int, str], account: str = None) -\u003e str:\n    \"\"\"\n    Join a public channel or supergroup by username (e.g., \"@examplechannel\") or ID.\n    \"\"\"\n```\n\nExample usage:\n```\nsubscribe_public_channel(channel=\"@daily_updates_feed\")\n```\n\nIf the account is already a participant, the tool reports that instead of failing, making it safe to\nrun repeatedly in workflows that need idempotent joins.\n\n### Getting Chat Invite Links\n\nThe `get_invite_link` function is particularly robust with multiple fallback methods:\n\n```python\n@mcp.tool()\n@with_account(readonly=True)\nasync def get_invite_link(chat_id: int, account: str = None) -\u003e str:\n    \"\"\"\n    Get the invite link for a group or channel.\n    \"\"\"\n    try:\n        cl = get_client(account)\n        entity = await resolve_entity(chat_id, cl)\n        # Tries ExportChatInviteRequest, then export_chat_invite_link,\n        # then GetFullChatRequest as fallbacks\n        ...\n```\n\nExample output:\n```\nhttps://t.me/+AbCdEfGhIjKlMnOp\n```\n\n### Joining Chats via Invite Links\n\n```python\n@mcp.tool()\n@with_account(readonly=False)\nasync def join_chat_by_link(link: str, account: str = None) -\u003e str:\n    \"\"\"\n    Join a chat by invite link.\n    \"\"\"\n    try:\n        cl = get_client(account)\n        # Extracts hash, checks membership, and joins via ImportChatInviteRequest\n        ...\n```\n\nExample output:\n```\nSuccessfully joined chat: Developer Community\n```\n\n### Searching Public Chats\n\n```python\n@mcp.tool()\n@with_account(readonly=True)\nasync def search_public_chats(query: str, limit: int = 20, account: str = None) -\u003e str:\n    \"\"\"\n    Search for public chats, channels, or bots by username or title.\n    \"\"\"\n    try:\n        cl = get_client(account)\n        result = await cl(functions.contacts.SearchRequest(q=query, limit=limit))\n        entities = [format_entity(e) for e in result.chats + result.users]\n        return json.dumps(entities, indent=2)\n    ...\n```\n\nExample output:\n```json\n[\n  {\n    \"id\": 123456789,\n    \"name\": \"TelegramBot\",\n    \"type\": \"user\",\n    \"username\": \"telegram_bot\"\n  },\n  {\n    \"id\": 987654321,\n    \"name\": \"Telegram News\",\n    \"type\": \"user\",\n    \"username\": \"telegram_news\"\n  }\n]\n```\n\n### Getting Direct Chats with Contacts\n\n```python\n@mcp.tool()\n@with_account(readonly=True)\nasync def get_direct_chat_by_contact(contact_query: str, account: str = None) -\u003e str:\n    \"\"\"\n    Find a direct chat with a specific contact by name, username, or phone.\n\n    Args:\n        contact_query: Name, username, or phone number to search for.\n    \"\"\"\n    try:\n        cl = get_client(account)\n        result = await cl(functions.contacts.GetContactsRequest(hash=0))\n        # Searches contacts, then matches against dialogs\n        ...\n```\n\nExample output:\n```\nChat ID: 123456789, Contact: John Smith, Username: @johnsmith, Unread: 3\n```\n\n---\n\n## 🎮 Usage Examples\n\n- \"Show my recent chats\"\n- \"Send 'Hello world' to chat 123456789\"\n- \"Add contact with phone +1234567890, name John Doe\"\n- \"Create a group 'Project Team' with users 111, 222, 333\"\n- \"Download the media from message 42 in chat 123456789\"\n- \"Mute notifications for chat 123456789\"\n- \"Promote user 111 to admin in group 123456789\"\n- \"Search for public channels about 'news'\"\n- \"Join the Telegram group with invite link https://t.me/+AbCdEfGhIjK\"\n- \"Send a sticker to my Saved Messages\"\n- \"Get all my sticker sets\"\n\n**Multi-account examples:**\n- \"Show unread messages from all accounts\"\n- \"Reply to John from my work account: see you at 3pm\"\n- \"List my accounts\"\n\nYou can use these tools via natural language in Claude, Cursor, or any MCP-compatible client.\n\n---\n\n## 🧠 Error Handling \u0026 Robustness\n\nThis implementation includes comprehensive error handling:\n\n- **Multi-account support**: Run multiple Telegram accounts simultaneously with label-based configuration\n- **Session management**: Works with both file-based and string-based sessions\n- **Error reporting**: Detailed errors logged to `mcp_errors.log`\n- **Graceful degradation**: Multiple fallback approaches for critical functions\n- **User-friendly messages**: Clear, actionable error messages instead of technical errors\n- **Account type detection**: Functions that require bot accounts detect and notify when used with user accounts\n- **Invite link processing**: Handles various link formats and already-member cases\n\nThe code is designed to be robust against common Telegram API issues and limitations.\n\n---\n\n## 🛠️ Contribution Guide\n\n1. **Fork this repo:** [chigwell/telegram-mcp](https://github.com/chigwell/telegram-mcp)\n2. **Clone your fork:**\n   ```bash\n   git clone https://github.com/\u003cyour-github-username\u003e/telegram-mcp.git\n   ```\n3. **Create a new branch:**\n   ```bash\n   git checkout -b my-feature\n   ```\n4. **Make your changes, add tests/docs if needed.**\n5. **Push and open a Pull Request** to [chigwell/telegram-mcp](https://github.com/chigwell/telegram-mcp) with a clear description.\n6. **Tag @chigwell or @l1v0n1** in your PR for review.\n\n---\n\n## 🔒 Security Considerations\n- **Never commit your `.env` or session string.**\n- The session string gives full access to your Telegram account—keep it safe!\n- All processing is local; no data is sent anywhere except Telegram's API.\n- Use `.env.example` as a template and keep your actual `.env` file private.\n- Test files are automatically excluded in `.gitignore`.\n\n---\n\n## 🛠️ Troubleshooting\n- **Check logs** in your MCP client (Claude/Cursor) and the terminal for errors.\n- **Detailed error logs** can be found in `mcp_errors.log`.\n- **Interpreter errors?** Make sure your `.venv` is created and selected.\n- **Database lock?** Use session string authentication, not file-based sessions.\n- **iCloud/Dropbox issues?** Move your project to a local path without spaces if you see odd errors.\n- **Regenerate session string** if you change your Telegram password or see auth errors.\n- **Bot-only functions** will show clear messages when used with regular user accounts.\n- **Test script failures?** Check test configuration in `.env` for valid test accounts/groups.\n\n---\n\n## 📄 License\n\nThis project is licensed under the [Apache 2.0 License](LICENSE).\n\n---\n\n## 🙏 Acknowledgements\n- [Telethon](https://github.com/LonamiWebs/Telethon)\n- [Model Context Protocol](https://modelcontextprotocol.io/)\n- [Claude](https://www.anthropic.com/) and [Cursor](https://cursor.so/)\n- [chigwell/telegram-mcp](https://github.com/chigwell/telegram-mcp) (upstream)\n\n---\n\n**Maintained by [@chigwell](https://github.com/chigwell) and [@l1v0n1](https://github.com/l1v0n1). PRs welcome!**\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=chigwell/telegram-mcp\u0026type=Date)](https://www.star-history.com/#chigwell/telegram-mcp\u0026Date)\n\n## Contributors\n\n\u003ca href=\"https://github.com/chigwell/telegram-mcp/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=chigwell/telegram-mcp\" /\u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchigwell%2Ftelegram-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchigwell%2Ftelegram-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchigwell%2Ftelegram-mcp/lists"}