Skip to main content
Glama
GG-QandV

MCP-TG

by GG-QandV

MCP-TG — Telegram MCP Server with Reactive Daemon

Isolated fork of 45telega — rewritten as a standalone daemon + proxy architecture for multi-agent use. Independent repository: GG-QandV/MCP-TG.

License: MIT Python 3.9+ MCP

Telegram MCP server exposing 50+ tools over the Model Context Protocol. One persistent MTProto connection (tgmcpd daemon) serves N isolated agents via Unix-socket IPC proxies — each agent bound to its own Telegram topic.

Why this fork

Upstream 45telega is a single-process stdio MCP server (one connection per agent). MCP-TG splits it:

  • tgmcpd daemon — one Telethon client, persistent MTProto session, InboxEngine with per-topic buffers + disk persistence.

  • tg-mcp-proxy — thin stateless stdio↔IPC bridge per agent (env TG_TOPIC_ID isolates topics).

  • Reactive inbox v3asyncio.Event wake-up + JSONL store + priority envelope, no polling.

Other providers kept as-is; this repo is detached from the upstream fork (isFork: false).

Architecture

v2 — Daemon + Proxy (L2)

┌────────────────────────────────────────────┐
│                tg-mcpd daemon               │
│  ┌─────────────────────┐  ┌──────────────┐  │
│  │  TelegramClient     │  │  IPC Server  │  │
│  │  (MTProto)          │  │ /run/tgmcpd │  │
│  └────────┬────────────┘  └──────┬───────┘  │
│     ┌─────┴─────┐                │         │
│     │  Inbox    │                │         │
│     │ topic→buf │                │         │
│     └───────────┘                │         │
└──────────────────────────────────┼─────────┘
         ┌─────────┬───────────────┼──────────┐
    ┌────┴────┐ ┌──┴─────┐  ┌──────┴────┐ ┌───┴────┐
    │ proxy   │ │ proxy  │  │ proxy    │ │ proxy  │
    │ topic=205│ │topic=310│ │topic=415 │ │ ...    │
    │stdio↔IPC│ │stdio↔IPC│ │stdio↔IPC │ │        │
    └────┬────┘ └──┬─────┘  └──────┬───┘ └───┬────┘
         │         │               │         │
      Agent1    Agent2          Agent3    Agent4

v3 — Reactive Inbox

Telegram push → Telethon event → InboxEngine.handle()
  → InboxStore.append(JSONL) → buffer[(chat,topic)].append()
  → asyncio.Event[(chat,topic)].set()
  → proxy inbox_wait() wakes → IPC → MCP inbox_read → envelope + ack
  • InboxStore — per (chat_id, topic_id) JSONL in /home/gg/tgmcpd/inbox_store, ack via tmp→replace (atomic), survives restarts.

  • InboxEnginedefaultdict(deque) buffers + defaultdict(asyncio.Event) per topic, restore_from_store() on daemon start.

  • proxy inbox_read — blocking inbox_wait (25s) + inbox_ack after delivery, returns {priority_rules, messages}.

See docs/architecture-v2.md and docs/tg-mcpd Architecture v3 — Reactive Inbox.md.

Tools — 50 total (MCP stdio, Telethon/MTProto)

ChatsGetAllChats, GetChats, GetChatInfo, GetChatMembers, GetChatAdmins, GetChatOnlineCount, SearchChats, GetChatInviteLink, CheckChatInvite, JoinChatByInvite, LeaveChat, GetFolders, GetChatsFromFolder, GetForumTopics, AddChatMember, BanChatMember, UnbanChatMember, KickChatMember, PromoteToAdmin

MessagesSendMessage, ReplyToMessage, EditMessage, DeleteMessage, ForwardMessage, GetChatHistory, SearchMessages, MarkAsRead, PinMessage, UnpinMessage, SendFile, DownloadMedia

ContactsGetContacts, AddContact, DeleteContact, SearchContacts, BlockUser, UnblockUser, GetBlockedUsers, SearchGlobal

UsersGetMe, GetUserInfo, GetUserStatus, SearchUsers, ResolveUsername, UpdateProfile

Groups/ChannelsCreateGroup, CreateChannel, EditChatTitle

InboxInboxPeek, InboxRead (via proxy inbox_readinbox_peek/inbox_wait + inbox_ack)

Full table: TOOLS_RU.md.

Requirements

Quick Start

git clone https://github.com/GG-QandV/MCP-TG.git
cd MCP-TG
pip install -e .
cp .env.example .env  # fill TELEGRAM_API_ID, TELEGRAM_API_HASH
python -m mcp_telegram.qr_auth  # or: 45telega sign-in

Run daemon (systemd)

sudo cp scripts/tgmcpd.user.service ~/.config/systemd/user/tgmcpd.service
systemctl --user daemon-reload
systemctl --user enable --now tgmcpd
systemctl --user status tgmcpd

Daemon socket: /run/tgmcpd/tgmcpd.sock, store: ~/tgmcpd/inbox_store.

Run proxy per topic (opencode)

TG_CHAT_ID=-1003998609906 TG_TOPIC_ID=205 tg-mcp-proxy

opencode.json example:

{
  "mcpServers": {
    "tg-mcp-205": { "command": "tg-mcp-proxy", "env": { "TG_CHAT_ID": "-1003998609906", "TG_TOPIC_ID": "205" } }
  }
}

Add more proxies with different TG_TOPIC_ID for multi-agent isolation.

Docker (optional)

docker build -t mcp-tg .
docker-compose up -d

Configuration

Env / .env:

TELEGRAM_API_ID=
TELEGRAM_API_HASH=
TELEGRAM_SESSION_PATH=~/.config/mcp-tg/session.session
TGMCPD_SOCK=/run/tgmcpd/tgmcpd.sock
TGMCPD_STORE_DIR=~/tgmcpd/inbox_store
TG_CHAT_ID=-1003998609906
TG_TOPIC_ID=205

Entry points (setup.py): 45telega, telega-mcp, tgmcpd, tg-mcp-proxy.

Project Structure

src/mcp_telegram/
  daemon.py       # tgmcpd entry, Telethon + IPC
  inbox.py        # InboxEngine (buffers + Events)
  inbox_store.py  # JSONL persistence
  inbox_bridge.py # bridge (deprecated v2)
  ipc_server.py   # Unix socket JSON-line server
  ipc_client.py   # proxy side client
  proxy.py        # MCP stdio ↔ IPC
  telegram.py     # TelegramSettings, client helpers
  tools.py        # core 50 tools
  server.py       # legacy single-process server
docs/
  architecture-v2.md
  tg-mcpd Architecture v3 — Reactive Inbox.md
scripts/
  tgmcpd.user.service
  tgmcp-proxy-wrapper.py / tgmcp-proxy-watchdog.py

Development

pytest
pytest tests/unit/test_inbox_bridge.py
black src && ruff check src && mypy src

Inbox protocol for agents: see AGENTS.md — on ⚡ INBOX ALERT call inbox_read, then send_message with ack.

Relation to upstream

Forked from sergekostenchuk/45telega at 66e31ac, now standalone (GG-QandV/MCP-TG). Upstream origin removed; GG-QandV/tg-mcp remains as the preserved fork with upstream intact.

License

MIT — see LICENSE.