mcp-telegram
by Moreti2002
README.md
# mcp-telegram
An [MCP](https://modelcontextprotocol.io) server that lets an LLM send messages,
photos and documents to Telegram through a bot, as well as retrieve incoming updates.
Point any MCP-capable client (Claude Desktop, Claude Code, Antigravity, or your own agent) at
this server and the model gains tools: `get_me`, `get_updates`, `get_file`, `send_message`,
`send_photo` and `send_document`. The model decides *what* to say or process; the server
handles *how* it communicates with Telegram.
## Why the Bot API
This server talks to the [Telegram Bot API](https://core.telegram.org/bots/api).
That means you create a bot, the bot sends messages, and users receive them.
- No phone-number login, no `api_id`/`api_hash`, no session files.
- The bot can only message chats it already shares with a user (the user must
start the bot first) or channels/groups it belongs to.
If you instead need to send messages *as your own user account* to arbitrary
people, that requires the MTProto client API (Telethon/Pyrogram) and account
authentication — a deliberately different, heavier tool that is out of scope
here.
## Architecture
Three small layers, each with one responsibility:
```
src/mcp_telegram/
├── config.py # load & validate settings from the environment (fail-fast)
├── telegram.py # thin async client over the Bot API (httpx, no heavy SDK)
├── server.py # FastMCP server: tool definitions + shared client lifespan
└── __main__.py # entry point (stdio transport)
```
The MCP layer never builds HTTP requests and the HTTP layer never knows about
MCP, so each can be tested and changed on its own. A single `httpx.AsyncClient`
is created once per server run via the FastMCP lifespan and reused across calls.
## Requirements
- Python 3.10+
- A Telegram bot token from [@BotFather](https://t.me/BotFather)
## Setup
### 1. Create the bot and get a token
1. Open [@BotFather](https://t.me/BotFather) in Telegram and send `/newbot`.
2. Follow the prompts and copy the token it gives you
(looks like `123456789:AA...`).
### 2. Find your chat id
The bot can only message a chat it knows. The simplest path:
1. Send any message to your new bot in Telegram.
2. Ask [@userinfobot](https://t.me/userinfobot) for your numeric id, **or** call:
```bash
curl "https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates"
```
and read `result[].message.chat.id` from the JSON.
Set that value as `TELEGRAM_DEFAULT_CHAT_ID` so the model can send without
specifying a chat every time.
### 3. Install
```bash
# with uv (recommended)
uv venv
uv pip install -e .
# or with pip
python -m venv .venv && source .venv/bin/activate
pip install -e .
```
### 4. Configure
Copy the example env file and fill it in:
```bash
cp .env.example .env
# edit .env: set TELEGRAM_BOT_TOKEN (and ideally TELEGRAM_DEFAULT_CHAT_ID)
```
| Variable | Required | Default | Description |
| -------------------------- | :------: | ---------------------------- | -------------------------------------------------- |
| `TELEGRAM_BOT_TOKEN` | yes | — | Token from @BotFather. |
| `TELEGRAM_DEFAULT_CHAT_ID` | no | — | Chat used when a tool call omits `chat_id`. |
| `TELEGRAM_API_BASE` | no | `https://api.telegram.org` | Override the API host (e.g. a local Bot API server). |
| `TELEGRAM_TIMEOUT` | no | `30` | Per-request timeout in seconds. |
## Running
The server speaks MCP over stdio, so you normally don't launch it by hand — your
MCP client does. To sanity-check that it starts:
```bash
TELEGRAM_BOT_TOKEN=... mcp-telegram
```
It will wait for an MCP client on stdin. Press `Ctrl+C` to stop.
## Connecting a client
### Claude Desktop
Add this to your `claude_desktop_config.json`
(`~/Library/Application Support/Claude/` on macOS,
`%APPDATA%\Claude\` on Windows):
```json
{
"mcpServers": {
"telegram": {
"command": "mcp-telegram",
"env": {
"TELEGRAM_BOT_TOKEN": "123456789:AA...",
"TELEGRAM_DEFAULT_CHAT_ID": "123456789"
}
}
}
}
```
If `mcp-telegram` is not on your PATH, use the venv's absolute path or run it
through `uv`:
```json
{
"mcpServers": {
"telegram": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/mcp-telegram", "mcp-telegram"],
"env": { "TELEGRAM_BOT_TOKEN": "123456789:AA..." }
}
}
}
```
### Claude Code
```bash
claude mcp add telegram \
--env TELEGRAM_BOT_TOKEN=123456789:AA... \
--env TELEGRAM_DEFAULT_CHAT_ID=123456789 \
-- mcp-telegram
```
Restart the client after editing its config, then ask the model something like
*"send me a Telegram message saying the build passed"*.
## Tools
| Tool | What it does |
| --------------- | -------------------------------------------------------- |
| `get_me` | Return the bot's identity — use it to verify the token. |
| `get_updates` | Fetch incoming messages and updates (supports offset & polling). |
| `get_file` | Get file info and download URL for voice/photos/docs. |
| `send_message` | Send a text message (optional Markdown/HTML formatting). |
| `send_photo` | Send a photo by URL, local path, or Telegram `file_id`. |
| `send_document` | Send a file by URL, local path, or Telegram `file_id`. |
Every send tool accepts an optional `chat_id`; when omitted it falls back to
`TELEGRAM_DEFAULT_CHAT_ID`. `parse_mode` is optional and defaults to plain text —
only set `"MarkdownV2"`, `"HTML"` or `"Markdown"` when you need formatting, and
make sure the payload is escaped for that mode.
## Development
```bash
uv pip install -e ".[dev]"
pytest
```
Tests mock the Telegram HTTP API with `respx`, so they run offline and never
touch a real bot.
## License
MIT — see [LICENSE](LICENSE).
TDQS
A4/5.0
Scored across 4 tools
Disambiguation5/5
Each tool has a distinct purpose: get_me verifies bot identity, send_message sends text, send_photo sends images, send_document sends files. No ambiguity.
Naming Consistency5/5
All tools follow a consistent verb_noun pattern: get_me, send_document, send_message, send_photo, using snake_case throughout.
Tool Count4/5
Four tools is a small but reasonable set for a basic Telegram bot, covering identity and three message types. Could be expanded but not inappropriate.
Completeness2/5
The tool surface lacks many common Telegram operations like send_audio, send_video, forward_message, delete_message, limiting the bot's capabilities for a full-featured server.
Maintenance
ActivityMaintained
ResponsivenessNo issues