← All Projects

Telegram MCP server in Rust

A Rust MCP server that gives an AI agent exact Telegram context and managed attachments without exporting the account. Replies are prepared for one recipient and sent only after a separate private approval; the result survives restart.

Demo + Source
What the agent receives

AI selects one dialog and message, then reads a bounded window around it instead of exporting the account.

What stays in the workspace

The original file is downloaded into a content-addressed workspace. The host can create a modified sibling without overwriting the source bytes.

What a reply requires

Before delivery, the server binds the account, recipient, reply target, text, payload hash, and expiry to one private approval card. The result is stored durably.

Public demo and source

v0.2.0 is the current public pre-1.0 build. The reproducible demo uses the real MCP binary without Telegram credentials or network delivery.

  1. 16 typed toolsEvery tool has an input schema, output schema, MCP annotations, and the same structured result envelope after argument parsing.
  2. Compiled server over stdioThe integration test launches the compiled server and connects an rmcp client through operating-system stdio.
  3. File identityThe demo finds a contract message, downloads its PDF, creates a changed sibling, replies with the bound SHA-256, and reads the result back.
  4. Restart statePrepared text, approval state, Telegram random_id, and the final send result remain available after restart.
01

The complete job

An AI agent using the server can locate a conversation, recover the exact message context, move an attachment into a controlled local workspace, and prepare a reply without receiving an unbounded account export.

The server is an interface, not an agent. Reasoning and file changes happen in the host; the Rust server owns exact account, chat, and message references, bounded reads, approval state, and the send result.

02

What the public demo actually runs

HOST AGENT
  find message | read context
          ↓
TELEGRAM MCP (Rust over stdio)
  download immutable PDF | return path + SHA-256
          ↓
MANAGED WORKSPACE
  host creates a modified sibling
          ↓
PREPARED REPLY
  exact target | reply ID | payload hash
          ↓
SEND + RESULT
  durable state | Telegram message ID
03

What the server exposes

16 typed operations
MCP tools
bounded search and context
Message access
immutable originals + SHA-256
Attachments
private Telegram button
Text approval
durable SQLite ledger
Send recovery
stable MCP 2025-11-25
Protocol
04

Why approval is durable state

Problem
A process can stop after Telegram accepts a message but before the caller records the result. A copied or stale callback must not become permission to send again.
Solution
Persist the prepared payload, stable Telegram random_id, exact approval card, approving user ID, expiry, and Telegram result with the sent message ID. Recovery reads the same operation instead of constructing a replacement send.
Why not that option
After a transport failure, a direct send tool cannot tell whether the message was never sent or the response was lost. Retrying can create a duplicate.
05

Why chat and file references are explicit

  • Round-trippable chats: Returned chat references can be used again as usernames or canonical numeric peer IDs; private peers are not guessed from interface labels.
  • Managed file roots: Uploads must resolve inside the selected account's cache root, so an arbitrary host path cannot be sent through Telegram.
  • Immutable originals: Downloaded source files are content-addressed. A changed file is a new sibling with its own hash, not a silent overwrite.
  • One session owner: Only one live process can own the Telegram session and approval worker at a time.
06

Implementation

Core
Rust 2024, Tokio, clap
MCP
rmcp 1.7.0, stdio, serde, schemars
Telegram
ferogram, MTProto, Bot API approval callback
State
SQLite ledger, content-addressed attachment cache