Skip to main content
Glama
Dmitrii-ive

telegram-mcp-server

by Dmitrii-ive
README.md
# telegram-mcp-server

A local, **read-only**, **folder-scoped** MCP server that lets an AI agent
(Claude Code, etc.) read your **personal** Telegram chats — but only the chats
inside an allowlist of Telegram folders. No send/edit/delete capability exists.

Built for a common use case: let an agent read your client/lead conversations
and pull out tasks, without giving it the keys to your whole Telegram.

> ⚠️ This logs in as your **personal Telegram account** via the official MTProto
> API (GramJS). Automating a user account is a grey area under Telegram's ToS;
> the risk is low for read-only use but not zero. Use on your own account.

## How it stays safe

- **Read-only.** The server registers four tools, all read-only. There is no
  tool that can send, edit, or delete anything.
- **Folder-scoped.** Only chats inside the folders listed in `config.json`
  (`allowedFolders`) are reachable. Every tool resolves the requested chat
  against that allowlist and refuses anything outside it. Chats in your other
  folders (family, personal, etc.) are physically unreachable.
- **Secrets stay local.** `api_id`/`api_hash` live in `config.json` (gitignored).
  The session string — which grants full account access — is stored in the
  **macOS Keychain**, never on disk, never in git.

## Requirements

- [Bun](https://bun.sh) (runs the TypeScript directly)
- macOS (uses the Keychain via the `security` CLI for session storage)
- A Telegram account, and an `api_id` / `api_hash` from <https://my.telegram.org>

## Setup

```bash
# 1. install
bun install

# 2. configure
cp config.example.json config.json
#   edit config.json: apiId, apiHash, allowedFolders (exact Telegram folder names)

# 3. log in (QR — the reliable method; see note below)
bun run qr
#   On your phone: Telegram -> Settings -> Devices -> Link Desktop Device -> scan the QR

# 4. verify which folders/chats resolved
bun run folders

# 5. register with your MCP client (Claude Code example, user scope):
claude mcp add telegram -s user -- bun run "$(pwd)/src/server.ts"
```

### Why QR login, not the SMS/app code

`bun run login` (phone + code) often fails: Telegram frequently accepts the
`SendCode` request and reports "code sent to app", but never actually delivers
the code (and offers no SMS fallback) for third-party API logins — especially
with a freshly created `api_id`. **`bun run qr` sidesteps this entirely**: the
login is approved from your already-authorized phone, so no code delivery is
needed. Use QR first.

## Tools

| Tool | What it does |
|------|--------------|
| `tg_list_folders` | List allowed folders + resolved chat counts |
| `tg_list_chats` | List chats in allowed folders (optionally one folder) |
| `tg_read_chat` | Recent messages from one allowed chat |
| `tg_search` | Search messages across allowed chats / one folder / one chat |

## Troubleshooting

- **A folder shows 0 chats** → its name in `config.json` doesn't match Telegram
  exactly. Run `bun run folders`; if needed, temporarily inspect all folder
  titles (the diagnose output lists matched ones). Names are case-insensitive
  but must otherwise match (watch for typos / emoji / extra words).
- **`FLOOD_WAIT_N`** → too many login attempts; wait N seconds. Don't spam
  retries — each one extends the window.
- **`CHANNEL_PRIVATE` skipped** → a private channel you've left/been removed
  from can't be resolved; it's skipped, harmless.
- **Login code never arrives** → use `bun run qr` (see above).

## Files

```
src/
  server.ts      MCP server (4 read-only tools)
  client.ts      GramJS client + folder allowlist (the privacy boundary)
  qr-login.ts    QR-code login (recommended)
  login.ts       phone+code login (fallback, with 'sms' resend)
  config.ts      loads config.json
  keychain.ts    session string <-> macOS Keychain
  diagnose.ts    'bun run folders' — show allowed folders + counts
  probe.ts       'bun run probe +NUMBER' — dump raw SendCode response
```

## License

MIT