Skip to main content
Glama
ramich2077

tgreader-mcp

by ramich2077
README.md
# tgreader-mcp

Telegram channel reader MCP server — exposes Telegram channels as [MCP](https://modelcontextprotocol.io) tools via Telethon MTProto.

Designed for use with [Hermes Agent](https://hermes-agent.nousresearch.com), Claude Desktop, and any MCP-compatible client.

## Features

- **List channels** — discover channels the account is subscribed to, with optional RegExp search filter
- **Read messages** — fetch posts from any channel by `@username` or numeric ID, with date-based pagination and text search
- **Multi-account** — configure multiple Telegram accounts, switch between them per call
- **MCP stdio transport** — works out of the box with any MCP client
- **Security-hardened** — session files `0600`, config `0600`, sanitized error messages, ReDoS protection via `regex` library with per-match timeout

## Requirements

- Python ≥ 3.11 (developed on 3.13)
- [uv](https://docs.astral.sh/uv/) (recommended) or `pip`
- Telegram `api_id` / `api_hash` — get them at <https://my.telegram.org>

## Quick start

```bash
git clone <repo-url> tgreader && cd tgreader

# Create venv and install deps (runtime + dev, editable)
./setup.sh
# or: make setup

# Activate
source .venv/bin/activate

# Login with your Telegram account
tgreader login --account main --phone +79001234567

# Check status
tgreader status
```

### Register with Hermes Agent

Add to `~/.hermes/config.yaml`:

```yaml
mcp_servers:
  tgreader:
    command: /home/<user>/telegram_reader/.venv/bin/tgreader-mcp
    args: []
```

### Install the Hermes skill

The repo ships a ready-to-use Hermes Agent skill at `skills/tgreader/SKILL.md`.
Install it so the agent knows how to use the MCP tools:

```bash
# Copy (recommended)
cp -r skills/tgreader ~/.hermes/skills/tgreader

# Or symlink (tracks the repo, auto-updates on git pull)
ln -s ~/telegram_reader/skills/tgreader ~/.hermes/skills/tgreader
```

The skill teaches the agent when and how to call `list_channels` / `read_messages`,
including example workflows (find vacancies, read by date range, search across
channels) and pitfalls (FloodWait, session expiry, ReDoS-protected search).

### Register with Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "tgreader": {
      "command": "/home/<user>/telegram_reader/.venv/bin/tgreader-mcp"
    }
  }
}
```

## MCP tools

### `list_channels`

List Telegram channels the account is subscribed to.

| Parameter  | Type   | Default | Description                                      |
|------------|--------|---------|--------------------------------------------------|
| `account`  | str    | —       | Account name (default: configured default)       |
| `search`   | str    | —       | RegExp pattern to filter by title/username (max 200 chars) |
| `limit`    | int    | 100     | Max channels to return (max 500)                 |

Returns: `{"count": N, "channels": [{"id", "title", "username", "type", "participants_count"}]}`

### `read_messages`

Read messages from a Telegram channel.

| Parameter     | Type   | Default | Description                                              |
|---------------|--------|---------|----------------------------------------------------------|
| `channel`     | str    | —       | Channel `@username` or numeric ID (**required**)          |
| `account`     | str    | —       | Account name (default: configured default)               |
| `limit`       | int    | 20      | Max messages when `offset_date` is None (max 1000)       |
| `offset_date` | str    | —       | ISO 8601 datetime — read messages before this date       |
| `search`      | str    | —       | RegExp pattern to filter message text (max 200 chars)    |

Returns: `{"count": N, "channel": {"id", "title", "username"}, "messages": [{"id", "date", "text", "views", "reactions", "media_type", "link"}]}`

## CLI

```bash
# Login (creates session, saves to config)
tgreader login --account main --phone +79001234567

# Account management
tgreader accounts list
tgreader accounts add --name work --phone +790011122233 --label "Work account"
tgreader accounts remove main
tgreader accounts default main

# Check session status
tgreader status
tgreader status --account work

# Start MCP server (stdio)
tgreader run
# or: tgreader-mcp
```

## Configuration

Config lives at `~/.config/tgreader/config.json` (XDG-aware):

```json
{
  "api_id": 123456,
  "api_hash": "your_api_hash_here",
  "default_account": "main",
  "accounts": {
    "main": {
      "phone": "+79001234567",
      "label": ""
    }
  }
}
```

Session files (`.session`) are stored at `~/.config/tgreader/sessions/` with `0600` permissions.

## Development

```bash
# Setup
make setup           # create .venv, install deps

# Tests
make test            # full suite (113 tests)
make test-fast       # without isolation (debugging)

# Lint
make lint            # py_compile syntax check

# Run server
make run

# Clean
make clean           # remove .venv and caches
```

### Test suite

- **113 tests** — unit + integration + BDD (pytest-bdd with Gherkin `.feature` files)
- BDD features cover: login flow, channel listing, message reading
- Security tests: ReDoS, error sanitization, session permissions, config validation

### Project structure

```
tgreader-mcp/
├── src/tgreader_mcp/
│   ├── __init__.py      # version
│   ├── server.py        # FastMCP server — tool definitions
│   ├── client.py        # Telethon client — channel/message logic
│   ├── config.py        # Config load/save, account management
│   └── cli.py           # Click CLI — login, accounts, status
├── skills/tgreader/
│   └── SKILL.md         # Hermes Agent skill — tool usage guide
├── tests/
│   ├── test_server.py   # MCP tool tests
│   ├── test_client.py   # Telegram client tests
│   ├── test_config.py   # Config validation tests
│   ├── test_security.py # ReDoS, sanitization, permissions
│   ├── test_cli.py      # CLI command tests
│   ├── features/        # Gherkin .feature files
│   └── test_steps/      # pytest-bdd step implementations
├── pyproject.toml
├── Makefile
├── setup.sh
└── .python-version
```

## Security

- **Session files** — `0600` permissions, stored in `~/.config/tgreader/sessions/`
- **Config file** — `0600` permissions, atomic write (tmp → rename)
- **Error sanitization** — internal exceptions (Telethon, network) are caught; only safe, generalized messages reach the LLM
- **ReDoS protection** — `regex` library (not stdlib `re`) with 2s per-match timeout; `RegexTimeoutError` is caught and surfaced safely
- **Config validation** — full type checking on load; malformed config raises `ConfigError` with a clear message

## License

MIT © Andrey Romanchuk

TDQS

A4.5/5.0

Scored across 2 tools

Disambiguation5/5

The two tools are completely distinct: one lists channels, the other reads messages from a specific channel. There is no overlap or ambiguity.

Naming Consistency5/5

Both tool names follow the verb_noun pattern ('list_channels', 'read_messages'), making them predictable and easy to understand.

Tool Count4/5

With only 2 tools, the set is minimal but well-suited for a read-only Telegram client. It could benefit from additional tools like a channel info getter, but it is not overly sparse.

Completeness4/5

The tools cover the core read operations: listing channels and reading messages. Missing features like retrieving a single channel's details or searching across channels are minor gaps for a focused read-only tool.

Maintenance

ActivityInactive
ResponsivenessNo issues