Skip to main content
Glama
KolyaMetallist

telegram-search-mcp

README.md
# ๐Ÿ” telegram-search-mcp

[![MCP](https://badge.mcpx.dev?type=server)](https://modelcontextprotocol.io)
[![Version](https://img.shields.io/github/v/release/KolyaMetallist/telegram-search-mcp?style=flat-square&label=version)](https://github.com/KolyaMetallist/telegram-search-mcp/releases)
[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg?style=flat-square)](https://www.python.org/)
[![Tests](https://img.shields.io/github/actions/workflow/status/KolyaMetallist/telegram-search-mcp/tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/KolyaMetallist/telegram-search-mcp/actions)
[![License](https://img.shields.io/badge/license-Apache%202.0-green.svg?style=flat-square)](LICENSE)
[![Telethon](https://img.shields.io/pypi/v/telethon?label=telethon&style=flat-square&color=blue)](https://pypi.org/project/telethon/)
[![MCP](https://img.shields.io/pypi/v/mcp?label=mcp&style=flat-square&color=purple)](https://pypi.org/project/mcp/)
[![pytest](https://img.shields.io/pypi/v/pytest?label=pytest&style=flat-square&color=0a9edc)](https://pypi.org/project/pytest/)
[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json&style=flat-square)](https://github.com/astral-sh/uv)
[![Last commit](https://img.shields.io/github/last-commit/KolyaMetallist/telegram-search-mcp?style=flat-square)](https://github.com/KolyaMetallist/telegram-search-mcp/commits/main)
[![Stars](https://img.shields.io/github/stars/KolyaMetallist/telegram-search-mcp?style=social)](https://github.com/KolyaMetallist/telegram-search-mcp)

An **MCP server** that gives Claude (or any MCP-compatible client) the ability to search Telegram messages and read documents attached to those messages โ€” using your **personal Telegram account** via [Telethon](https://github.com/LonamiWebs/Telethon).

> [!NOTE]
> This server uses the Telegram **user API** (MTProto), not the Bot API. It reads your account's chats just like the official Telegram client does.

---

## โœจ Features

| Tool | Description |
|---|---|
| `search_messages` | Keyword search inside any chat or channel |
| `get_messages` | Fetch recent messages from a chat |
| `search_dialogs` | Find chats, channels, groups by name |
| `get_message_document` | Download and extract text from attached files (PDF, TXT, MD, CSV) |

All message results include a `has_document` field โ€” so Claude knows when to call `get_message_document` automatically.

---

## ๐Ÿ“‹ Requirements

- Python 3.10+
- Telegram API credentials from [my.telegram.org/apps](https://my.telegram.org/apps)

> [!IMPORTANT]
> You need to create an application on [my.telegram.org/apps](https://my.telegram.org/apps) to get your `api_id` and `api_hash`. This is free and takes ~1 minute.

---

## ๐Ÿš€ Installation

```bash
git clone https://github.com/KolyaMetallist/telegram-search-mcp.git
cd telegram-search-mcp
./install.sh
```

The script auto-detects **uv** and falls back to pip/venv. It creates `.venv`, installs all dependencies including `pdfplumber`, and prints the exact next steps.

### โšก With uv (recommended)

> [!TIP]
> [uv](https://docs.astral.sh/uv/) installs packages 10-100ร— faster than pip. One-time install: `curl -LsSf https://astral.sh/uv/install.sh | sh`

```bash
uv venv .venv
source .venv/bin/activate
uv pip install -e ".[pdf]"
```

Or run without activating the venv at all:

```bash
uv run --extra pdf python main.py --login
uv run --extra pdf python main.py
```

### ๐Ÿ With pip

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[pdf]"
```

---

## โš™๏ธ Configuration

Set environment variables before running. Add them to `~/.zshrc` or `~/.bashrc` so you don't have to repeat this:

| Variable | Required | Description |
|---|---|---|
| `TELEGRAM_API_ID` | โœ… | Integer API ID from my.telegram.org |
| `TELEGRAM_API_HASH` | โœ… | API Hash from my.telegram.org |
| `TELEGRAM_SESSION_PATH` | โž– | Custom session file path (default: `~/.local/state/telegram-search-mcp/session`) |

```bash
# Add to ~/.zshrc or ~/.bashrc
export TELEGRAM_API_ID=12345678
export TELEGRAM_API_HASH=abcdef1234567890abcdef1234567890
```

> [!WARNING]
> Never commit your `api_id` or `api_hash` to version control. The `.gitignore` already excludes `.env` files.

---

## ๐Ÿ” First Login

Run **once** to authenticate your account:

```bash
source .venv/bin/activate
python main.py --login
```

Telethon will prompt for your phone number, the SMS code, and your 2FA password if enabled. The session is saved locally at `~/.local/state/telegram-search-mcp/session.session` โ€” you won't need to log in again.

> [!CAUTION]
> The session file grants full access to your Telegram account. Keep it secure and never share it. It is excluded from git via `.gitignore`.

---

## โ–ถ๏ธ Running the Server

**stdio** โ€” for Claude Desktop, Claude Code, Codemie command mode:

```bash
python main.py
# or
python -m telegram_search_mcp
```

**SSE** โ€” HTTP server for Codemie URL mode or any web client:

```bash
python main.py --sse              # port 8000
python main.py --sse --port 9000  # custom port
```

Stop with **Ctrl+C** โ€” the server shuts down cleanly (SIGINT and SIGTERM both handled).

---

## ๐Ÿ”Œ MCP Client Configuration

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "telegram-search": {
      "command": "/path/to/telegram-search-mcp/.venv/bin/python",
      "args": ["/path/to/telegram-search-mcp/main.py"],
      "env": {
        "TELEGRAM_API_ID": "your_api_id",
        "TELEGRAM_API_HASH": "your_api_hash"
      }
    }
  }
}
```

### Codemie โ€” command mode

```json
{
  "command": "/path/to/.venv/bin/python",
  "args": ["/path/to/telegram-search-mcp/main.py"]
}
```

Add `TELEGRAM_API_ID` and `TELEGRAM_API_HASH` via the "Add Environment Variables" section.

### Codemie โ€” SSE / URL mode

Start the server first, then set MCP-Connect URL to `http://localhost:8000/sse`.

```bash
python main.py --sse --port 8000
```

---

## ๐Ÿ’ฌ Usage Examples

Once connected, ask Claude:

> *"Find messages about Python in @some_channel"*

> *"Search dialogs for 'Bulgaria Ukraine'"*

> *"Get the document attached to message 432583 in @Autochat_Bulgaria_Ukraine and summarize it"*

> *"Show me the last 20 messages in @my_group and extract any PDFs"*

---

## ๐Ÿ—๏ธ Architecture

The project follows **SOLID**, **DRY**, **KISS**, and **YAGNI** principles with these GoF patterns:

| Pattern | Where |
|---|---|
| Factory Method | `ClientFactory.create()`, `ExtractorRegistry.default()` |
| Strategy | `DocumentExtractor` ABC โ†’ `PDFExtractor`, `PlainTextExtractor` |
| Registry | `ExtractorRegistry.find(mime, filename)` |
| Template Method | `ToolSet.register(mcp)` โ€” each subclass adds its own tools |
| Facade | MCP tools hide Telethon complexity behind simple dicts |

### ๐Ÿ“ Package layout

```
src/telegram_search_mcp/
  config.py        Config dataclass (from env)
  client.py        ClientFactory
  auth.py          AuthManager โ€” login without mcp-telegram
  server.py        build_server() โ€” wires all ToolSets
  cli.py           main() entry point
  extractors/      DocumentExtractor ABC, PDFExtractor, PlainTextExtractor, ExtractorRegistry
  tools/           ToolSet ABC, DialogTools, MessageTools, DocumentTools
```

### โž• Adding a new extractor

Create `src/telegram_search_mcp/extractors/<name>.py` extending `DocumentExtractor`, register in `ExtractorRegistry.default()`. No other files change.

```python
class DocxExtractor(DocumentExtractor):
    @property
    def supported_mimes(self): return ("application/vnd.openxmlformats-officedocument.wordprocessingml.document",)
    @property
    def supported_extensions(self): return (".docx",)
    async def extract(self, data, filename): ...
```

### โž• Adding a new tool set

Create `src/telegram_search_mcp/tools/<name>.py` extending `ToolSet`, implement `register(mcp)`, add to list in `server.py`.

---

## ๐Ÿงช Tests

```bash
source .venv/bin/activate
python -m pytest tests/ -v
```

52 unit tests, zero network calls โ€” all Telegram interactions are mocked.

---

## ๐Ÿค Contributing

Contributions are welcome! Here's how to get started:

1. **Fork** the repository and clone your fork
2. **Create a branch** for your change: `git checkout -b feat/my-feature`
3. **Install dev dependencies:**
   ```bash
   uv pip install -e ".[pdf,dev]"
   ```
4. **Make your changes** โ€” add or update tests when behavior changes
5. **Run the test suite** before opening a PR:
   ```bash
   python -m pytest tests/ -v
   ```
6. **Open a pull request** with a concise description of what changed and why

> [!NOTE]
> For new file-type extractors or tool sets, see the [Architecture](#๏ธ-architecture) section โ€” the design is intentionally extension-friendly.

Please keep PRs focused: one feature or fix per PR. If you're unsure whether something is in scope, open an issue first.

---

## ๐Ÿ“„ License

This project is licensed under the **Apache License 2.0** โ€” see the [LICENSE](LICENSE) file for details.

Apache 2.0 was chosen over MIT because it includes an explicit **patent grant**, which is better for an open-source tool used in corporate environments.

TDQS

A4.2/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct resource/action: dialog lookup, message listing, message search, and document extraction. get_messages and search_messages overlap only superficially because one returns recent unfiltered messages and the other returns keyword-filtered results.

Naming Consistency5/5

All tools use lower_snake_case and follow a consistent verb_noun pattern such as search_dialogs, get_messages, search_messages, and get_message_document. The verbs match the operations clearly, and the nouns identify the resource being acted on.

Tool Count5/5

Four tools is a tight, well-scoped set for a read-only Telegram search/retrieval server. Each tool earns its place in the workflow of finding a dialog, reading or searching messages, and extracting document text.

Completeness4/5

The read-oriented workflow is well covered: discover dialogs, list recent messages, search messages by keyword, and extract document text. Minor gaps such as global message search and pagination/offset support mean some advanced retrieval tasks may require workarounds.

Maintenance

ActivityMaintained
ResponsivenessNo issues