Skip to main content
Glama
Telegram Bot MCP Server

Telegram Bot MCP Server

by aggeentik

Telegram Bot MCP Server

A Model Context Protocol (MCP) server that enables AI assistants to publish, edit, search, and manage messages in Telegram channels.

Features

  • Publish Text Messages: Post new text messages to Telegram channels with formatting support (Markdown/HTML)

  • Publish Photos: Post photos with optional captions to Telegram channels

  • Edit Text Messages: Modify existing text-only messages in channels

  • Edit Photo Captions: Update captions of existing photo messages

  • Delete Messages: Remove messages from channels

  • Search Messages: Search through cached messages (local cache)

  • Channel Info: Retrieve channel metadata and statistics

Related MCP server: Telegram Channel MCP Server

Quick Reference

Task

Message Type

Tool to Use

Publish a text message

Text

publish_message

Publish a photo

Photo

publish_photo

Edit a text-only message

Text

edit_message

Edit a photo's caption

Photo

edit_message_caption

Delete any message

Any

delete_message

Search cached messages

Any

search_messages

Get channel info

-

get_channel_info

Important: You cannot use edit_message on photo messages or edit_message_caption on text messages!

Installation

Prerequisites

  1. Python 3.10+ is required

  2. Create a Telegram Bot:

    • Open Telegram and search for @BotFather

    • Send /newbot and follow the instructions

    • Copy the bot token (format: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)

  3. Add Bot to Your Channel:

    • Create a Telegram channel or use an existing one

    • Add your bot as an administrator to the channel

    • Grant the bot permissions:

      • Post messages

      • Edit messages of others

      • Delete messages of others

  4. Get Channel ID:

    • For public channels, use the username format: @channelname

    • For private channels, you need the numeric chat ID (e.g., -1001234567890)

    • You can get this by:

      • Adding the bot to the channel

      • Sending a message to the channel

      • Checking the update using: https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates

Install from Source

# Clone the repository
git clone https://github.com/aggeentik/telegram-bot-mcp.git
cd telegram-bot-mcp

# Install with pip
pip install -e .

# Or install with uv (recommended)
uv pip install -e .

For Development

# Install with dev dependencies
pip install -e ".[dev]"

# Or with uv
uv pip install -e ".[dev]"

Configuration

Environment Variable

Set your Telegram bot token as an environment variable:

export TELEGRAM_BOT_TOKEN="your-bot-token-here"

Or add it to your .env file:

TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11

Claude Desktop Integration

Add this to your Claude Desktop configuration file:

MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "telegram-bot": {
      "command": "python",
      "args": ["-m", "telegram_bot"],
      "env": {
        "TELEGRAM_BOT_TOKEN": "your-bot-token-here"
      }
    }
  }
}

Or if installed via uv:

{
  "mcpServers": {
    "telegram-bot": {
      "command": "uvx",
      "args": ["telegram-bot-mcp"],
      "env": {
        "TELEGRAM_BOT_TOKEN": "your-bot-token-here"
      }
    }
  }
}

Usage

Once configured, the server will be available to your MCP client (like Claude Desktop). You can ask the AI assistant to:

  • "Post a message to @mychannel saying 'Hello from AI!'"

  • "Publish a photo from /path/to/image.jpg to @mychannel with caption 'Check this out!'"

  • "Edit message 12345 in @mychannel to say 'Updated message'"

  • "Search for messages containing 'important' in @mychannel"

  • "Delete message 12345 from @mychannel"

  • "Get information about @mychannel"

Available Tools

publish_message

Publish a new message to a Telegram channel.

Parameters:

  • channel_id (str, required): Channel username (@mychannel) or chat ID

  • text (str, required): Message text to publish

  • parse_mode (str, optional): Text formatting - "Markdown", "HTML", or "None". Default: "Markdown"

  • disable_web_page_preview (bool, optional): Disable link previews. Default: False

  • disable_notification (bool, optional): Send silently. Default: False

Returns:

{
  "message_id": 12345,
  "chat_id": -1001234567890,
  "date": "2024-01-15T10:30:00",
  "text": "Your message text",
  "link": "https://t.me/mychannel/12345"
}

publish_photo

Publish a photo to a Telegram channel with an optional caption.

Parameters:

  • channel_id (str, required): Channel username (@mychannel) or chat ID

  • photo (str, required): Photo to send (file path, URL, or file_id)

  • caption (str, optional): Caption text with Markdown/HTML formatting. Max 1024 characters

  • parse_mode (str, optional): Caption formatting - "Markdown", "HTML", or "None". Default: "Markdown"

  • disable_notification (bool, optional): Send silently. Default: False

Returns:

{
  "message_id": 12345,
  "chat_id": -1001234567890,
  "date": "2024-01-15T10:30:00",
  "caption": "Photo caption text",
  "photo": {
    "file_id": "AgACAgIAAxkBAAMCY...",
    "file_unique_id": "AQADAgATxxx",
    "width": 1280,
    "height": 720,
    "file_size": 102400
  },
  "link": "https://t.me/mychannel/12345"
}

edit_message

Edit an existing TEXT-ONLY message in a channel.

IMPORTANT: This only works for text messages. If the message contains a photo, use edit_message_caption instead.

Parameters:

  • channel_id (str, required): Channel username or chat ID

  • message_id (int, required): ID of the message to edit

  • new_text (str, required): New message text

  • parse_mode (str, optional): Text formatting. Default: "Markdown"

edit_message_caption

Edit the caption of an existing PHOTO message in a channel.

IMPORTANT: This only works for messages with media. For text-only messages, use edit_message instead.

Parameters:

  • channel_id (str, required): Channel username or chat ID

  • message_id (int, required): ID of the photo message to edit

  • new_caption (str, required): New caption text

  • parse_mode (str, optional): Caption formatting. Default: "Markdown"

delete_message

Delete a message from a channel.

Parameters:

  • channel_id (str, required): Channel username or chat ID

  • message_id (int, required): ID of the message to delete

search_messages

Search messages in local cache (messages published/edited in current session).

Note: Telegram Bot API doesn't support native message search. This searches locally cached messages.

Parameters:

  • channel_id (str, required): Channel username or chat ID

  • query (str, optional): Search query (case-insensitive). If None, returns all cached messages

  • limit (int, optional): Maximum results to return. Default: 10

get_channel_info

Get information about a Telegram channel.

Parameters:

  • channel_id (str, required): Channel username or chat ID

Returns:

{
  "id": -1001234567890,
  "title": "My Channel",
  "username": "mychannel",
  "type": "channel",
  "description": "Channel description",
  "invite_link": "https://t.me/mychannel",
  "member_count": 1234,
  "status": "success"
}

Development

Running Tests

# Install dev dependencies
pip install -e ".[dev]"

# Run all tests
pytest

# Run tests with verbose output
pytest -v

# Run tests with coverage
pytest --cov=telegram_bot --cov-report=html

# Run specific test
pytest tests/test_telegram.py::TestTelegramClient::test_publish_message

Code Quality

# Type checking
mypy telegram_bot

# Linting
ruff check .

# Formatting
ruff format .

Running the Server Locally

For testing purposes, you can run the server directly:

# Set your bot token
export TELEGRAM_BOT_TOKEN="your-token"

# Run the server
python -m telegram_bot

The server will start and communicate via stdio, following the MCP protocol.

Architecture

Component Structure

telegram-bot-mcp/
├── main.py                  # Entry point for the server
├── telegram_bot/
│   ├── __init__.py          # Package initialization
│   ├── server.py            # FastMCP server implementation with tool decorators
│   └── telegram_bot_client.py  # TelegramBotClient wrapper
└── tests/
    └── test_telegram.py     # Comprehensive tests

Design Patterns

  • Singleton Client: Global TelegramBotClient instance reused across tool calls

  • Async-First: All I/O operations are async for better performance

  • Error Handling: Graceful error responses with status information

  • Local Cache: Message caching for search functionality (since Telegram API doesn't support search)

Limitations

  1. Message Types and Editing:

    • Text messages: Use edit_message (won't work on photo messages)

    • Photo messages: Use edit_message_caption (won't work on text-only messages)

    • You cannot change a text message to a photo or vice versa

    • The bot can only edit messages it sent itself

  2. Message Search: Only searches locally cached messages from current session (Telegram Bot API limitation)

    • Messages are cached in-memory during the current session

    • Cache is cleared when the server restarts

    • You can still edit messages from previous sessions if you know the message_id

  3. Message Retrieval: Telegram Bot API doesn't provide a way to fetch arbitrary messages by ID

  4. Bot Permissions: Bot must be channel admin with appropriate permissions:

    • Post messages

    • Edit messages

    • Delete messages

  5. Edit Time Limit: Telegram has a 48-hour limit for editing messages

  6. Rate Limits: Telegram enforces rate limits on bot API calls

Troubleshooting

"Telegram bot token is required" Error

Make sure you've set the TELEGRAM_BOT_TOKEN environment variable or configured it in your MCP client.

"Chat not found" Error

  • For public channels, ensure you use @channelname format

  • For private channels, use numeric chat ID (e.g., -1001234567890)

  • Verify the bot is added to the channel as an admin

"Not enough rights to send messages" Error

The bot needs admin permissions in the channel with:

  • Post messages

  • Edit messages

  • Delete messages

"Message can't be edited" Error

This usually means:

  1. Wrong edit method for message type: Use edit_message_caption for photos, edit_message for text

  2. Bot didn't send the message: Bots can only edit messages they sent themselves

  3. Message is too old: Telegram has a 48-hour limit for editing messages

License

MIT License - See LICENSE file for details

Contributing

Contributions are welcome! Please:

  1. Fork the repository

  2. Create a feature branch

  3. Add tests for new functionality

  4. Ensure all tests pass

  5. Submit a pull request

Resources

Support

For issues and questions:

Available Tools

8 tools
telegram_delete_messageA
DestructiveIdempotent

Delete a message from a Telegram channel.

Use this tool to permanently remove a message from a channel. The bot must have delete message permissions in the channel.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID. message_id: The unique identifier of the message to delete. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing success status, message_id, and operation status. If response_format='markdown', returns formatted text content.

Inputs: channel_id (required), message_id (required), response_format. Returns: object

telegram_edit_messageA
Idempotent

Edit an existing TEXT message in a Telegram channel.

Use this tool to modify the content of a previously published TEXT message. IMPORTANT: This only works for text messages. If the message contains a photo, use edit_message_caption instead.

The bot must be the original sender of the message and have edit permissions.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID. Must be the same channel where the original message was sent. message_id: The unique identifier of the message to edit. This is returned when you publish a message. new_text: The new text to replace the existing message content. Supports formatting based on parse_mode. parse_mode: Text formatting mode. Options: 'Markdown', 'HTML', or 'None'. Default is 'Markdown'. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing message_id, chat_id, date, edit_date, text, and link. If response_format='markdown', returns formatted text content.

Inputs: new_text (required), channel_id (required), message_id (required), parse_mode, +1 more. Returns: object

telegram_edit_message_captionA
Idempotent

Edit the caption of an existing photo message in a Telegram channel.

Use this tool to modify the caption text of a previously published photo message. This only works for messages that contain media (photos, videos, etc.). You cannot change the photo itself, only the caption text. The bot must be the original sender of the message and have edit permissions.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID. Must be the same channel where the original message was sent. message_id: The unique identifier of the photo message to edit. This is returned when you publish a photo. new_caption: The new caption text to replace the existing caption. Supports formatting based on parse_mode. Maximum 1024 characters. parse_mode: Caption formatting mode. Options: 'Markdown', 'HTML', or 'None'. Default is 'Markdown'. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing message_id, chat_id, date, edit_date, caption, photo info, and link. If response_format='markdown', returns formatted text content.

Inputs: channel_id (required), message_id (required), new_caption (required), parse_mode, +1 more. Returns: object

telegram_get_channel_infoA
Read-onlyIdempotent

Get detailed information about a Telegram channel.

Use this tool to retrieve metadata and statistics about a channel where the bot is a member or admin.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing id, title, username, type, description, invite_link, and member_count. If response_format='markdown', returns formatted text content.

Inputs: channel_id (required), response_format. Returns: object

telegram_publish_messageA

Publish a message to a Telegram channel.

Use this tool to post new messages to a Telegram channel where the bot is an admin. The bot must have permission to post messages in the channel.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID (e.g., '-1001234567890'). Use '@' prefix for public channels with username. text: The message text to publish. Supports Markdown or HTML formatting based on parse_mode. parse_mode: Text formatting mode. Options: 'Markdown', 'HTML', or 'None' for plain text. Default is 'Markdown'. disable_web_page_preview: If True, disables link preview for URLs in the message. Default is False. disable_notification: If True, sends the message silently (no notification to users). Default is False. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing message_id, chat_id, date, text, and link. If response_format='markdown', returns formatted text content.

Inputs: text (required), channel_id (required), parse_mode, response_format, +2 more. Returns: object

telegram_publish_photoA

Publish a photo to a Telegram channel with an optional caption.

Use this tool to post photos to a Telegram channel where the bot is an admin. The photo can include a text caption with formatting. The bot must have permission to post messages in the channel.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID. photo: Photo to send. Can be: - File path to a local image file (e.g., '/path/to/image.jpg') - URL to a remote image (e.g., 'https://example.com/image.png') - Telegram file_id of a photo that exists on Telegram servers caption: Optional text caption for the photo. Supports Markdown or HTML formatting based on parse_mode. Maximum 1024 characters. parse_mode: Caption formatting mode. Options: 'Markdown', 'HTML', or 'None' for plain text. Default is 'Markdown'. disable_notification: If True, sends the photo silently (no notification to users). Default is False. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing message_id, chat_id, date, caption, photo info, and link. If response_format='markdown', returns formatted text content.

Inputs: photo (required), channel_id (required), caption, parse_mode, +2 more. Returns: object

telegram_publish_photo_albumA

Publish multiple photos as an album (media group) to a Telegram channel.

Use this tool to post 2-10 photos in a single message as an album/gallery. Users can swipe through the photos. Each photo can have its own caption. The bot must have permission to post messages in the channel.

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID. photos: List of photo objects (2-10 items). Each photo object must contain: - photo (required): Photo to send. Can be: - File path to a local image file (e.g., '/path/to/image.jpg') - URL to a remote image (e.g., 'https://example.com/image.png') - Telegram file_id of a photo that exists on Telegram servers - caption (optional): Text caption for this specific photo. Maximum 1024 characters. - parse_mode (optional): Caption formatting mode ('Markdown', 'HTML', or 'None'). Default is 'Markdown' if not specified. disable_notification: If True, sends the album silently (no notification to users). Default is False. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing: - album_id: Unique identifier for the media group - message_count: Number of photos in the album - messages: List of message details for each photo (message_id, caption, photo info, link) - first_message_id: ID of the first message in the album - chat_id: Channel chat ID If response_format='markdown', returns formatted text content.

Example: photos = [ { "photo": "https://example.com/photo1.jpg", "caption": "First photo caption", "parse_mode": "Markdown" }, { "photo": "/path/to/photo2.jpg", "caption": "Second photo caption" }, { "photo": "AgACAgIAAxkBAAIC...", # Telegram file_id "caption": "Third photo" } ]

Inputs: photos (required), channel_id (required), response_format, disable_notification. Returns: object

telegram_search_messagesA
Read-onlyIdempotent

Search for messages in a Telegram channel (from local cache ONLY).

⚠️ CRITICAL LIMITATIONS - READ CAREFULLY:

  1. Session-Only Cache: This tool ONLY searches messages cached in the CURRENT SERVER SESSION.

    • Messages published/edited BEFORE the server started are NOT available

    • Cache is CLEARED when the server restarts

    • This is a Telegram Bot API limitation, not a bug

  2. Cannot Retrieve Historical Messages: The Telegram Bot API does not provide methods to fetch arbitrary messages or search message history.

  3. What IS Cached: ✅ Messages published via publish_message in current session ✅ Messages edited via edit_message in current session ✅ Photos published via publish_photo in current session ✅ Photo captions edited via edit_message_caption in current session

  4. What is NOT Cached: ❌ Messages sent before server started ❌ Messages sent by other bots or users ❌ Messages sent when server was offline

  5. You CAN Still: ✅ Edit messages from previous sessions if you have the message_id ✅ Delete messages from previous sessions if you have the message_id ✅ The message_id is returned when publishing messages - store it if needed later!

Args: channel_id: Channel username (e.g., '@mychannel') or numeric chat ID to search in. query: Search query string. Performs case-insensitive search in message text/caption. If None or empty, returns all cached messages for the channel. limit: Maximum number of results to return. Default is 10. Results are sorted by date (newest first). offset: Number of results to skip. Use for pagination. Default is 0. response_format: Response format. Options: 'json' for structured data, 'markdown' for human-readable text. Default is 'markdown'.

Returns: A dictionary containing: - messages: List of matching messages (may be empty if nothing cached) - count: Number of messages returned in this page - total: Total number of matching messages in cache - offset: Current offset value - limit: Current limit value - has_more: Boolean indicating if more results are available - next_offset: Offset value for the next page (if has_more is True) - query: The search query used - channel_id: The channel searched - status: Operation status If response_format='markdown', returns formatted text content.

Note: If you need to work with older messages, you must keep track of message_id values returned when publishing. There is no way to retrieve message_id for historical messages through the Telegram Bot API.

Inputs: channel_id (required), limit, query, offset, +1 more. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.7/5.0

    Scored across 8 tools

    Disambiguation5/5

    Each tool targets a distinct operation: publishing text, photos, albums; editing text vs captions; deleting; searching; and retrieving channel info. The overlap between edit_message and edit_message_caption is clearly resolved by their descriptions (text vs media). No two tools appear to do the same thing.

    Naming Consistency5/5

    All tool names follow the consistent telegram_verb_noun pattern (publish_photo, edit_message_caption, get_channel_info). The use of snake_case is uniform, and the verb accurately reflects the action, making the set predictable and easy to navigate.

    Tool Count5/5

    With 8 tools, the server is well-scoped for channel management: create (publish), read (get info, search), update (edit), and delete. The count is neither too thin nor too heavy, and each tool serves a clear purpose within the domain.

    Completeness4/5

    The server covers the core lifecycle for messages (publish, edit, delete, search) and channel info. However, it lacks support for other media types like video or documents, and search is limited to session-cached messages, which might be a notable gap for some use cases. Overall, the most essential operations are present.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to interact with Telegram accounts through MCP, supporting messaging, contacts, groups, media, and admin functions.
      4
      Apache 2.0
    • A
      license
      B
      quality
      D
      maintenance
      Enables users to read, search, and manage Telegram messages in channels, groups, and private chats through MCP tools.
      8
      MIT