pyrogram-mcp
by SkrudjReal
README.md
<div align="center">
# β‘ pyrogram-mcp
**High-Performance Telegram Userbot & Model Context Protocol (MCP) Server**
*Built with [Kurigram], [dispyro], and [FastMCP] with an integrated, persistent OpenAI Codex App-Server Bridge.*
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
[](https://gofastmcp.com/)
[](https://python-poetry.org/)
[](https://pypi.org/project/dispyro/)
[](https://github.com/kurigram-org/kurigram)
---
</div>
`pyrogram-mcp` bridges native Telegram operations directly into LLM agent workflows (such as OpenAI Codex, Claude Code, and Cursor) via the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). It runs as both an interactive Telegram userbot and an MCP server over multiple Kurigram sessions in one asyncio loop, cleanly separating Telegram update dispatching, core business operations, and MCP tool adapters into isolated layers.
---
## π Key Highlights
- π **Unified Multi-Session Runtime**: Shares several active MTProto sessions and one `asyncio` event loop across userbot handlers, background workers, and MCP tool executions β without duplicate processes.
- π οΈ **Dual-Layer MCP Tooling**:
- **High-Level Tools**: Clean abstractions for managing chats, reading message history, sending media, search, contacts, and moderation.
- **Dynamic Reflection**: Runtime introspection into installed Kurigram MTProto methods (`raw_search`, `raw_describe`, `raw_call`) and high-level client methods (`client_search`, `client_describe`, `client_call`).
- π€ **Persistent Codex App-Server Bridge**: Issue commands directly inside Telegram using `Π°ΠΌ <Π·Π°ΠΏΡΠΎΡ>` to trigger a long-running, stateful OpenAI Codex session powered by `gpt-5.6-luna`.
- π **Flexible MCP Transports**: Supports **Streamable HTTP** (`http://127.0.0.1:8000/mcp`) for long-lived daemon connections and **stdio** for direct process execution.
- π‘οΈ **Owner-Only Security**: All Telegram commands enforce strict `filters.me` checks; MCP filesystem access is sandboxed via configurable `MEDIA_ROOTS`.
---
## ποΈ Architecture
```text
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MCP Clients / Codex β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β (HTTP / stdio)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β core/mcp/tools FastMCP Schemas & Adapters β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β core/service Telegram Operations & Policy β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β core/telegram Peer Resolution & Raw MTProto β
ββββββββββββββββ¬ββββββββββββββββββββββββββββββββ¬βββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββ
β Kurigram Client β β dispyro Dispatcher β
β (Shared MTProto Engine) β β (Telegram Update Handlers) β
βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββ
```
Detailed architectural diagrams and implementation notes are available in [`IMPLEMENTATION_PLAN.md`](IMPLEMENTATION_PLAN.md).
Userbot command behavior and conventions are specified in [`COMMANDS.md`](COMMANDS.md).
---
## π Requirements
| Requirement | Minimum Version | Notes |
| :--- | :--- | :--- |
| **Python** | `3.12+` | Modern `asyncio` runtime required |
| **Telegram API** | β | `API_ID` & `API_HASH` from [my.telegram.org](https://my.telegram.org) |
| **Poetry** | Latest | Dependency management & environment isolation |
| **Codex CLI** | `0.154+` | Required for Codex bridge (`gpt-5.6-luna`) |
| **MySQL / Redis** | Optional | Only needed if persistence / caching is enabled |
---
## π Quickstart
### 1. Clone & Install
```bash
git clone <repository-url>
cd pyrogram-mcp
poetry install --no-root
```
### 2. Configure Environment
```bash
cp settings.env.example settings.env
```
Open `settings.env` and supply your Telegram credentials:
```env
API_ID=1234567
API_HASH=your_telegram_api_hash
PHONE_NUMBER=+1234567890
# Minimal standalone configuration (disable optional databases)
MYSQL_ENABLED=false
REDIS_ENABLED=false
# MCP & Codex Bridge
MCP_TRANSPORT=streamable-http
MCP_HOST=127.0.0.1
MCP_PORT=8000
```
### 3. Launch
```bash
poetry run python3 run.py
```
> [!NOTE]
> Telegram authorization is performed from the TUI. Each session file is saved securely to `core/sessions/` (which is excluded by `.gitignore`).
The TUI offers:
1. **ΠΠ°ΠΏΡΡΡΠΈΡΡ** β starts every saved Telegram session in one asyncio loop;
this option is disabled until at least one session exists.
2. **Π‘ΠΎΠ·Π΄Π°ΡΡ ΡΠ΅ΡΡΠΈΡ Telegram** β asks for a session name, phone, Telegram code
and optional 2FA password.
The session list at the bottom shows five accounts at a time. Use `β/β` or
`j/k` to scroll; `PageUp/PageDown` moves by a page. Session files are stored in
`core/sessions/`, with non-secret names and phone numbers in the ignored
`core/data/sessions.json` metadata file.
---
## π MCP Transport & Configuration
### Streamable HTTP (Recommended)
When Codex or an external MCP client connects to an existing running instance of `pyrogram-mcp`, use Streamable HTTP:
```env
MCP_TRANSPORT=streamable-http
MCP_HOST=127.0.0.1
MCP_PORT=8000
```
- **MCP Endpoint**: `http://127.0.0.1:8000/mcp`
- Required for the interactive Telegram `Π°ΠΌ` bridge.
### stdio
When an MCP client manages the server lifecycle directly as a subprocess, configure:
```env
MCP_TRANSPORT=stdio
```
---
## π§ OpenAI Codex Bridge
The Codex bridge manages a single, persistent `codex app-server` process with durable conversational threads saved to `core/data/codex_thread.json`.
### Environment & Authentication Isolation
By default, native Codex state is isolated in its own workspace:
```env
CODEX_HOME=~/.local/share/pyrogram-mcp/codex
```
This prevents project rollouts and threads from polluting your main user or VS Code Codex environment.
- **Reusing existing auth**: If `~/.codex/auth.json` is present, the bridge automatically creates a symlink so credentials are not duplicated.
- **Manual login**: If no existing credentials exist:
```bash
CODEX_HOME=~/.local/share/pyrogram-mcp/codex codex login
```
### Bridge Tuning
```env
CODEX_BIN=codex
CODEX_MODEL=gpt-5.6-luna
CODEX_REASONING_EFFORT=xhigh
CODEX_SERVICE_TIER=default
CODEX_TIMEOUT=0
```
---
## π¬ Telegram Commands
`CODEX_TIMEOUT=0` lets long exports finish without a total turn deadline.
A positive value sets a total timeout in seconds. Requests remain serialized;
while a request runs, another `Π°ΠΌ` reports that the previous request is busy.
> [!IMPORTANT]
> All userbot commands are strictly **owner-only** (`filters.me`) and case-insensitive.
| Command | Description | Example |
| :--- | :--- | :--- |
| `ΠΏΠΈΠ½Π³` | Verifies userbot responsiveness | `ΠΏΠΈΠ½Π³` |
| `.ΠΌΠΎΠ΄Π΅Π»Ρ` | Lists available Codex models and reasoning levels | `.ΠΌΠΎΠ΄Π΅Π»Ρ` |
| `.ΠΌΠΎΠ΄Π΅Π»Ρ [model-slug]` | Switches active Codex model | `.ΠΌΠΎΠ΄Π΅Π»Ρ gpt-5.6-sol` |
| `.ΠΌΡΡΠ»Π΅Π½ΠΈΠ΅` / `/reasoning` | Shows current model and active reasoning effort | `.ΠΌΡΡΠ»Π΅Π½ΠΈΠ΅` |
| `.ΡΠΊΠΎΡΠΎΡΡΡ` | Displays current Codex service tier | `.ΡΠΊΠΎΡΠΎΡΡΡ` |
| `.ΡΠΊΠΎΡΠΎΡΡΡ [normal\|fast]` | Switches service tier (`ΠΎΠ±ΡΡΠ½ΠΎ`, `Π±ΡΡΡΡΠΎ`, `1.5x`) | `.ΡΠΊΠΎΡΠΎΡΡΡ fast` |
| `Π°ΠΌ [Π·Π°ΠΏΡΠΎΡ]` | Sends prompt to persistent Codex agent | `Π°ΠΌ ΠΠΎΠΊΠ°ΠΆΠΈ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ 20 ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΠΈΠ· ΡΠ°ΡΠ° [chat_id]` |
For complete usage guides and command behavior, see [`COMMANDS.md`](COMMANDS.md).
Codex response rules and Telegram HTML formatting live in
[`core/prompts/codex.md`](core/prompts/codex.md).
Codex replies are normalized from Markdown to Telegram HTML before delivery.
Message search supports server-side `from_user` filtering and exclusive
`min_id`/`max_id` pagination. History `offset_id` is an exclusive older-page
cursor. Batch known message IDs instead of fetching them individually.
For multi-account work, call `list_sessions` first and pass its `name` as the
`session` argument to the selected MCP tool. Omitting it uses the first/default
session. This applies to named message/entity/media tools, `client_call` and
`raw_call`.
---
## π Dynamic Kurigram Raw API
`pyrogram-mcp` introspects the installed Kurigram package dynamically at runtime rather than relying on static, hardcoded MTProto classes:
1. **`raw_search`**: Search for MTProto functions and types by pattern.
2. **`raw_describe`**: Inspect method signatures, parameter types, and docstrings.
3. **`raw_call`**: Execute any MTProto function dynamically with JSON arguments.
### Example: Calling Raw MTProto
```json
{
"peer": {
"_": "types.InputPeerSelf"
},
"limit": 50
}
```
### Peer Resolver Helper
To resolve usernames or channel IDs seamlessly without manual conversion, use the `__resolve_peer__` token:
```json
{
"_": "__resolve_peer__",
"value": "@channel_name"
}
```
---
## π Security & Repository Hygiene
- π« **Do Not Commit Secrets**: Never commit `settings.env`, `.session` files in `core/sessions/`, `auth.json`, or runtime logs.
- π **Sandboxed File Access**: Restrict `MEDIA_ROOTS` strictly to directories intended for MCP file access (e.g. `/tmp/pyrogram-mcp-media`).
- π **Restricted Command Scope**: Userbot commands are protected with `filters.me`; destructive write actions are clearly annotated in the tool schema.
---
## π§ͺ Development & Quality Checks
Run local checks prior to committing changes:
```bash
# Verify syntax and bytecode compilation
poetry run python3 -m compileall -q .
# Verify total registered MCP tools
poetry run python3 -c 'from core.mcp.server import mcp; print(f"Registered MCP tools: {len(mcp._tool_manager._tools)}")'
```
---
## π License
Distributed under the terms appropriate for your deployment. Refer to the repository license or contact the maintainers before redistribution.
[FastMCP]: https://gofastmcp.com/
[Kurigram]: https://github.com/kurigram-org/kurigram
[Poetry]: https://python-poetry.org/
[dispyro]: https://pypi.org/project/dispyro/
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues