mcp-telegram
by Prgebish
README.md
# mcp-telegram
[](https://modelcontextprotocol.io)
[](https://go.dev)
[](LICENSE)
An [MCP](https://modelcontextprotocol.io) server that connects AI assistants like Claude to your **real Telegram account** via the User API (MTProto). Not a bot — Claude reads and sends messages as you.
Built with [gotd/td](https://github.com/gotd/td) and the official [MCP Go SDK](https://github.com/modelcontextprotocol/go-sdk).
> **Telegram API Terms of Service**: This project uses the Telegram User API. You must obtain your own `api_id` and `api_hash` from [my.telegram.org](https://my.telegram.org) and comply with the [Telegram API Terms of Service](https://core.telegram.org/api/terms). Misuse of the User API (spam, bulk messaging, scraping) may result in your account being banned. You are solely responsible for how you use this tool.
## Contents
- [Features](#features)
- [What you can do with it](#what-you-can-do-with-it)
- [How it compares to chaindead/telegram-mcp](#how-it-compares-to-chaindeadtelegram-mcp)
- [Quick start](#quick-start)
- [Client configuration](#client-configuration)
- [Configuration reference](#configuration)
- [Security](#security)
---
## Features
| Tool | What it does | Required permission |
|------|-------------|---------------------|
| `tg_me` | Returns current account info | — |
| `tg_dialogs` | Lists dialogs visible to the ACL whitelist | — |
| `tg_history` | Fetches message history with pagination, date filtering, and media download | `read` |
| `tg_search` | Searches messages in a chat by text query, with optional sender filter | `read` |
| `tg_send` | Sends a text message or file, with optional reply-to | `send` |
| `tg_forward` | Forwards messages from one chat to another | `read` + `send` |
| `tg_draft` | Saves a draft message (does not send) | `draft` |
| `tg_mark_read` | Marks a chat as read | `mark_read` |
**Additional capabilities:**
- File and photo sending
- Forward messages between chats
- Reply to specific messages
- Download photos and documents from message history
- Filter history by date range (`since` / `until`)
- Typed peer references (`user:ID`, `chat:ID`, `channel:ID`) to prevent ID collisions
- Lazy peer resolution — avoids `FLOOD_WAIT` errors at startup
- Global rate limiting at the RPC level
## What you can do with it
Once connected, you can ask your AI assistant things like:
**Catch up on messages**
- "Check my unread Telegram messages and give me a summary"
- "What did @alice write in the last 24 hours?"
- "Show me messages from the Dev Team chat since Monday"
**Reply and communicate**
- "Draft a response to the last message from @bob — don't send it yet"
- "Send 'sounds good, let's meet at 3pm' to @alice"
- "Reply to message 1234 in the project chat with my feedback"
**Manage your inbox**
- "Mark all read in the news channel"
- "Which of my whitelisted chats have unread messages?"
- "Download the photos from today's messages in the design chat"
**Research and analyze**
- "Find all messages mentioning the deployment in the last week"
- "Summarize the discussion in the team chat from yesterday"
- "What files were shared in the project channel this month?"
---
## How it compares to chaindead/telegram-mcp
| | mcp-telegram | chaindead/telegram-mcp |
|---|---|---|
| Access control | Default-deny ACL whitelist with granular per-chat permissions | Full access to all chats |
| Peer addressing | Typed references (`user:ID`, `chat:ID`, `channel:ID`) | Numeric IDs only (collision-prone) |
| Configuration | YAML config with environment variable expansion | CLI flags |
| Startup safety | Lazy peer resolution (no bulk API calls) | Eager resolution (FLOOD_WAIT risk) |
| Rate limiting | Built-in token bucket middleware | None |
| File support | Send files, photos; download media from history | Text only |
| Reply support | Yes | No |
| Date filtering | Yes | No |
---
## Quick start
### Prerequisites
- Go 1.26+
- A Telegram account
- API credentials from [my.telegram.org](https://my.telegram.org) (`api_id` and `api_hash`)
### Install
**Homebrew (macOS / Linux):**
```bash
brew install Prgebish/tap/mcp-telegram
```
**NPX (no install needed):**
```bash
npx @prgebish/mcp-telegram serve --config config.yaml
```
**Pre-built binaries (macOS / Linux / Windows):**
Download from [GitHub Releases](https://github.com/Prgebish/mcp-telegram/releases).
**Go install:**
```bash
go install github.com/Prgebish/mcp-telegram/cmd/mcp-telegram@latest
```
**From source:**
```bash
git clone https://github.com/Prgebish/mcp-telegram.git
cd mcp-telegram
go build ./cmd/mcp-telegram
```
This produces `mcp-telegram` (or `mcp-telegram.exe` on Windows) in the current directory.
### Authenticate
Run the auth command once to create a session file. You will be prompted for your phone number, the login code, and (if enabled) your 2FA password.
**macOS / Linux:**
```bash
export TG_APP_ID=12345
export TG_API_HASH="your_api_hash"
mcp-telegram auth --config config.yaml
```
**Windows (PowerShell):**
```powershell
$env:TG_APP_ID = "12345"
$env:TG_API_HASH = "your_api_hash"
mcp-telegram.exe auth --config config.yaml
```
**Windows (cmd):**
```cmd
set TG_APP_ID=12345
set TG_API_HASH=your_api_hash
mcp-telegram.exe auth --config config.yaml
```
### Configure
Create a `config.yaml`:
```yaml
telegram:
app_id: ${TG_APP_ID}
api_hash: ${TG_API_HASH}
session_path: ~/.config/mcp-telegram/session.json
acl:
chats:
- match: "@username"
permissions: [read, draft, mark_read]
- match: "user:123456789"
permissions: [read, send]
- match: "channel:2225853048"
permissions: [read, mark_read]
limits:
max_messages_per_request: 50
max_dialogs_per_request: 100
rate:
requests_per_second: 2.0
burst: 3
logging:
level: info
```
Environment variables in `${...}` syntax are expanded at load time.
### Client configuration
The server communicates over stdio — your MCP client starts and manages the process.
**Claude Code** (CLI — add via command):
```bash
claude mcp add telegram -- /path/to/mcp-telegram serve --config /path/to/config.yaml
```
**Claude Desktop / Claude Code** (`~/.claude.json` or `claude_desktop_config.json`):
```json
{
"mcpServers": {
"telegram": {
"command": "/path/to/mcp-telegram",
"args": ["serve", "--config", "/path/to/config.yaml"],
"env": {
"TG_APP_ID": "12345",
"TG_API_HASH": "your_api_hash"
}
}
}
}
```
**Cursor** (Settings > MCP Servers > Add):
```json
{
"telegram": {
"command": "/path/to/mcp-telegram",
"args": ["serve", "--config", "/path/to/config.yaml"],
"env": {
"TG_APP_ID": "12345",
"TG_API_HASH": "your_api_hash"
}
}
}
```
---
## Configuration
### ACL
The ACL is **default-deny**. Only chats explicitly listed in `acl.chats` are accessible, and only with the permissions you specify.
Supported match patterns:
| Pattern | Example | Description |
|---------|---------|-------------|
| `@username` | `@johndoe` | Match by Telegram username (case-insensitive) |
| `+phone` | `+79001234567` | Match by phone number |
| `user:ID` | `user:123456789` | Match a user by numeric ID |
| `chat:ID` | `chat:987654321` | Match a group chat by numeric ID |
| `channel:ID` | `channel:2225853048` | Match a channel or supergroup by numeric ID |
Permission types: `read`, `send`, `draft`, `mark_read`.
If the same peer matches multiple rules (e.g. via `@username` and `user:ID`), permissions are merged — they never shadow each other.
### Rate limiting
The `limits.rate` section configures a global token bucket that wraps all Telegram RPC calls:
- `requests_per_second` — sustained rate (default: 2.0)
- `burst` — maximum burst size (default: 3)
### Media download
```yaml
media:
download: [photo, document, video, voice, audio]
directory: ~/telegram-media
allowed_upload_dirs:
- ~/Documents
- ~/Downloads
```
When configured, `tg_history` will automatically download media files to the specified directory. The `download_to` parameter can override the path, but only to `media.directory` or its subdirectories.
`allowed_upload_dirs` restricts which directories `tg_send` can read files from. File sending is disabled unless this is configured.
---
## Security
- **Default-deny ACL** — no chat is accessible unless explicitly whitelisted
- **Filesystem boundary** — `tg_send` can only read files from `allowed_upload_dirs`; `download_to` is restricted to subdirectories of `media.directory`
- **Session file permissions** — enforced to `0600` (owner-only read/write)
- **No secret logging** — API hashes, session tokens, and auth keys are never written to logs
- **No access hash exposure** — internal Telegram access hashes are stripped from all tool output
- **Rate limiting** — prevents accidental API abuse
- **Local timezone** — date filters use your system timezone, not UTC
---
## License
[MIT](LICENSE)
---
If you find this project useful, please give it a star — it helps others discover it.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessUnresponsive