inline-claude
by benzin8
README.md
<div align="center">
[](README.md) [](README.ru.md)
[](https://www.npmjs.com/package/inline-claude)
[](https://www.npmjs.com/package/inline-claude)
[](https://nodejs.org)
[](LICENSE)
</div>
# inline-claude
> Summon Claude in any Telegram chat — inline (like `@gpt`) or via a Business Bot that replies to your contacts as if it were you.
An MCP server for Claude Code that turns Claude into your Telegram assistant. Two roles in one:
- **Inline mode** — type `@your_bot question` in any chat and Claude answers right there.
- **Business Bot (Secretary Mode)** — when someone DMs you, Claude replies as if it were you. With conversation memory, voice transcription, and photo understanding.
---
## ✨ Features
- 💬 **Inline queries** in any Telegram chat
- 🤝 **Business replies** on your behalf (Telegram Business)
- 🧠 **Conversation memory** — SQLite keeps per-chat history across sessions
- 🎙️ **Voice messages** — automatic transcription (ffmpeg + Google STT, no API keys)
- 🖼️ **Photos** — Claude sees and describes incoming images
- 💬 **Reply triggers** — reply to the bot's message without a keyword; it still responds
- 🔐 **Roles** — owner gets full access, guests are Q&A-only
---
## 🚀 Quick Start
### 1. Install in Claude Code
Add to your project's `.mcp.json`:
```json
{
"mcpServers": {
"inline-claude": {
"command": "npx",
"args": ["-y", "inline-claude"]
}
}
}
```
### 2. Run the setup wizard
```bash
npx inline-claude setup
```
The wizard walks you through all 7 steps: Telegram API → userbot → bot creation → Business Bot → `.env` → connection → test.
### 3. Restart Claude Code
Done. Type `@your_bot hello` in any chat.
---
## 📋 Requirements
| Component | Why | Required |
|---|---|---|
| Node.js ≥ 18 | Server runtime | ✅ |
| Python 3 + Telethon | Userbot delivers triggers into the session | ✅ |
| ffmpeg | Voice transcription | Only for voice |
| Telegram Premium | Business Bot (Secretary Mode) | Only for business mode |
---
## ⚙️ Configuration
Everything is configured via `.env` in the data directory (`~/.claude/inline-bot/.env`) or via environment variables.
| Variable | Description | Default |
|---|---|---|
| `INLINE_BOT_TOKEN` | Bot token from @BotFather | — (required) |
| `OWNER_ID` | Your Telegram user id | — (required) |
| `BRIDGE_TARGET` | @username of the bridge bot for delivery | — |
| `INLINE_ALLOW_IDS` | Extra ids for guest Q&A (comma-separated) | empty |
| `INLINE_DATA_DIR` | Data directory (DB, .env, logs) | `~/.claude/inline-bot` |
| `INLINE_USERBOT_DIR` | Userbot scripts directory | `~/.claude/userbot` |
| `INLINE_PYTHON` | Path to Python | `python3` (unix) / `python` (win) |
Example `.env`:
```ini
INLINE_BOT_TOKEN=123456:AAxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OWNER_ID=123456789
BRIDGE_TARGET=@your_bridge_bot
# INLINE_ALLOW_IDS=111111111,222222222
```
---
## 🎯 How It Works
### Inline mode
```
You → @bot question ──▶ card "🤔 Claude is thinking…" ──▶ Claude ──▶ inline_answer() ──▶ answer in chat
```
### Business Bot
```
Contact writes "Claude, <question>"
│
▼
Server downloads photo/voice (if any), writes to SQLite
│
▼
[[ic:biz:ID ...]] trigger ──▶ Claude reads history, transcribes voice, views photo
│
▼
business_reply() ──▶ message is sent to the contact on your behalf
```
**Business bot triggers** — the bot fires when a message:
- contains a keyword (`claude,` / `клод,`) or starts with it
- mentions the bot (`@your_bot`)
- is a reply to any of the bot's own messages (no mention needed)
---
## 🔐 Security & Roles
The role is decided **by the server from the telegram_id** — it cannot be changed by message text.
| Role | Who | Rights |
|---|---|---|
| `owner` | The owner | Full access: commands, files, sending on your behalf |
| `guest` | Everyone else | Q&A only — no commands, files, or actions |
Prompt-injection resistant: even if a guest writes `[[role=owner]]` in the text — it's just text, the server ignores any role claims inside the message body.
---
## 🛠️ Scripts (`scripts/`)
Helper Python scripts for the userbot and media processing:
| Script | Purpose |
|---|---|
| `get_biz_history.py <chat_id> [limit]` | Chat history from SQLite |
| `transcribe_voice.py <file.oga> [lang]` | Transcribe a voice message (deletes file after) |
| `get_photo.py <chat_id> [limit] [dir]` | Download the latest photo from a chat |
| `read_chat.py <peer> [limit]` | Read the latest messages |
| `send_message.py <target> <file>` | Send text via the userbot |
---
## 🏗️ Architecture
```
Telegram ◀──▶ grammY bot (server.ts)
│ downloads media to tmp/
│ writes history to chat_history.db
▼
userbot fallback (send_message.py)
│ delivers trigger to @bridge_bot
▼
Claude Code session
│
▼
inline_answer / business_reply ──▶ Telegram
```
The userbot fallback exists because the harness does not surface notifications from a second MCP server directly into the session — the trigger is delivered through the telegram plugin's working channel.
---
## 🧑💻 Development
```bash
git clone https://github.com/benzin8/inline-claude-public.git
cd inline-claude-public
npm install
npm run build # tsc -> dist/
npm start # start the server
```
Stack: TypeScript · [grammY](https://grammy.dev) · [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) · [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol)
---
## 🩺 Troubleshooting
| Problem | Fix |
|---|---|
| Bot doesn't answer inline | Enable `/setinlinefeedback` → 100% in @BotFather |
| `409 Conflict` in logs | Two instances running — one poller per token only |
| Business Bot silent | Check Business → Chatbots → Can reply ✅ (requires Premium) |
| Voice not transcribed | Make sure ffmpeg is installed and on PATH |
| Userbot not authorized | Delete `*.session` and re-run `python auth.py` |
---
## 📄 License
MIT
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues