telegram-bot-mcp/README.md
Mikkel Georgsen 1cb16e6e8f feat: MCP bridge - Telegram group logger + FastMCP HTTP server
Single-process Python app that:
- Runs a Telegram bot in a group chat, logging all messages/files to libsql
- Exposes send_message, pull_updates, queue_status MCP tools over HTTP
- Downloads and stores file attachments with Telegram file_id + local path
- Accessible via NetBird mesh at mgmt.mg:8321 (no auth needed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:56:05 +00:00

165 lines
5 KiB
Markdown

# Nexus MCP Bridge
MCP server that bridges claude.ai to a homelab Telegram group chat. Logs all messages and files to libsql, exposes three MCP tools over HTTP on the NetBird mesh.
## Architecture
```
claude.ai ──HTTP──► MCP Bridge (mgmt.mg:8321) ──Telegram API──► Group Chat
│ │
libsql (local) Mikkel + Homelab Bot + MCP Bot
media/ (files)
```
Single Python process running:
- **Telegram bot** — polls group chat, logs everything to libsql, sends outbound messages
- **FastMCP HTTP server** — exposes `send_message`, `pull_updates`, `queue_status` tools
## Setup Guide
### Step 1: Create a new Telegram bot
1. Open Telegram, message [@BotFather](https://t.me/BotFather)
2. Send `/newbot`
3. Name: `Nexus MCP Bridge` (or whatever you like)
4. Username: `nexus_mcp_bot` (must be unique, pick something available)
5. Copy the **bot token** BotFather gives you
### Step 2: Create the Telegram group
1. In Telegram, create a **new group**
2. Name: `Homelab Bridge` (or your preference)
3. Add members:
- Your existing homelab bot (`@georgsen_homelab_bot`)
- The new MCP bot (search by the username you chose)
4. **Important:** Make both bots **group admins** so they can read all messages
- Tap group name → Edit → Administrators → Add both bots
- Bots need at minimum: "Read messages" permission (enabled by default for admins)
### Step 3: Get the group chat ID
Option A — Send a message in the group, then check:
```bash
curl -s "https://api.telegram.org/bot<MCP_BOT_TOKEN>/getUpdates" | python3 -m json.tool
```
Look for `"chat": {"id": -100XXXXXXXXXX}` — the negative number is the group chat ID.
Option B — The bridge logs the chat ID on startup. You can start it once, send a message in the group, and check the logs.
### Step 4: Configure credentials
```bash
cd ~/repos/telegram-bot-mcp
cp credentials.example credentials
```
Edit `credentials`:
```
MCP_BOT_TOKEN=<token from BotFather>
GROUP_CHAT_ID=<negative number from step 3>
HOMELAB_BOT_ID=8521598773
```
### Step 5: Install and test
```bash
cd ~/repos/telegram-bot-mcp
# Create venv (if not already done)
python3 -m venv .venv
# Install dependencies
.venv/bin/pip install -r requirements.txt
# Test run (Ctrl+C to stop)
.venv/bin/python -m mcp_bridge
```
You should see:
```
Database initialized at /home/mikkel/repos/telegram-bot-mcp/data/bridge.db
MCP server starting on 0.0.0.0:8321
Telegram bot polling started
MCP Bridge bot started as @nexus_mcp_bot (ID: XXXXXXX)
Monitoring group chat: -100XXXXXXXXXX
```
Send a message in the group — you should see it logged.
### Step 6: Install systemd service
```bash
cp mcp-bridge.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now mcp-bridge
systemctl --user status mcp-bridge
```
View logs:
```bash
journalctl --user -u mcp-bridge -f
```
### Step 7: Configure claude.ai MCP connection
In claude.ai settings, add a new MCP server:
- **URL:** `http://mgmt.mg:8321/mcp`
- **Transport:** Streamable HTTP
This works because mgmt.mg resolves via NetBird mesh — no public exposure needed.
## MCP Tools
### send_message
Send a message to the group, attributed as `[claude.ai]`.
```json
{"message": "Fix the nexus.mg DNS record to 100.79.65.206"}
```
### pull_updates
Get conversation messages with cursor-based pagination.
```json
{"since_id": 0, "limit": 50}
```
Returns messages from all participants with attachment metadata. Use the `cursor` value from the response as `since_id` in the next call.
### queue_status
Quick summary: total messages, last activity, pending outbound count.
## File Structure
```
├── mcp_bridge/
│ ├── __main__.py # Entry point (bot + MCP server)
│ ├── config.py # Configuration loader
│ ├── db.py # libsql database layer
│ ├── telegram_bot.py # Telegram bot (logging + sending)
│ ├── mcp_server.py # FastMCP tool definitions
│ └── models.py # Data models
├── data/ # libsql database (auto-created)
├── media/ # Downloaded attachments (auto-created)
├── credentials # Bot token + chat ID (not in git)
├── credentials.example # Template
├── requirements.txt
└── mcp-bridge.service # systemd unit file
```
## Troubleshooting
**Bot doesn't see group messages:**
- Ensure bot is a group admin
- Check BotFather: `/mybots` → Bot Settings → Group Privacy → Turn OFF
(bots have "privacy mode" ON by default — they only see commands unless it's disabled)
**Can't get group chat ID:**
- Make sure you sent a message AFTER adding the bot
- For supergroups, the ID starts with `-100`
**MCP server unreachable from claude.ai:**
- Verify NetBird is connected: `netbird status`
- Test locally: `curl http://mgmt.mg:8321/mcp`
- Check firewall: port 8321 must be open