mcp-server-telegram

mcp-server-telegram

Integrates Telegram bots as MCP tools for sending messages to staff groups or manager chats, listing buffered messages, and viewing group members.

Category
Visit Server

README

mcp-server-telegram

Model Context Protocol (MCP) server for Telegram integration. Exposes a Telegram bot as three MCP tools over the standard stdio transport.

Originally built for the YengTong 7-Scenario AI Agent demo as the second messaging channel alongside email, where:

  • Staff are modeled as a single Telegram group — reminders land as @mentions.
  • Escalations go to a separate manager-only chat, never visible to staff.
  • A background long-poller buffers incoming messages into a local JSON store so tool calls return synchronously with low, predictable latency.

Tools

Tool Description
telegram_send_message Send a text message to either the staff_group (for reminders) or manager_chat (for escalations).
telegram_list_messages List incoming messages buffered from the staff group. Optional since (ISO timestamp) filter.
telegram_list_group_members Setup/debug helper — list staff group members observed by the poller so far.

Setup

1. Create a Telegram bot

  1. Open Telegram and message @BotFather.
  2. Send /newbot, follow the prompts, and copy the bot token.
  3. Disable privacy mode for the bot (also via BotFather → /mybots → select your bot → Bot Settings → Group Privacy → Turn off). Without this, the bot only sees /command messages in groups, not regular text — the poller won't receive staff updates.

2. Create the chats

  1. Staff group: create a Telegram group, add the bot as a member, add the 5 staff personas (or real staff).
  2. Manager chat: a separate small group or a 1:1 DM with a manager test account that has sent /start to the bot. This is where telegram_send_message with target: "manager_chat" sends to.

To obtain the chat IDs, send a message in each chat and call the Telegram API manually:

curl "https://api.telegram.org/bot<TOKEN>/getUpdates"

Look for message.chat.id in the response. Group chat IDs are negative numbers (e.g. -1001234567890).

3. Configure environment

cp .env.template .env
# Edit .env with your bot token and the two chat IDs.

4. Install and build

npm install
npm run build

5. Run

npm start

The server boots, loads (or creates) the local store, starts the long-poller, and connects over stdio. Connect it from an MCP client.

6. Test

npm run build && node test_mcp.mjs

Runs an end-to-end MCP handshake (initialize → tools/list) and verifies all three tools are registered.

Environment variables

Variable Required Default Description
TELEGRAM_BOT_TOKEN yes — Bot token from @BotFather
TELEGRAM_STAFF_GROUP_CHAT_ID yes — Chat ID of the staff group (negative number for supergroups)
TELEGRAM_MANAGER_CHAT_ID yes — Chat ID of the manager-only chat
TELEGRAM_STORE_PATH no ./telegram_store.json Path to the local JSON message/member store
TELEGRAM_POLL_INTERVAL_MS no 1000 Delay between poll cycles (ms) — only relevant after errors
TELEGRAM_LONG_POLL_TIMEOUT no 30 Seconds to hold each getUpdates request open (Telegram long-polling)

Operational notes

  • The poller must be running before any workflow that reads messages fires. Messages sent to the group before the poller starts are lost unless the poller's offset was persisted from a previous run — on boot, the poller resumes from the last saved offset and Telegram redelivers any updates received while the server was down (within Telegram's 24-hour update retention window).
  • Attachments are flagged, not fetched. telegram_list_messages returns has_attachment: true for messages with photos/files. Photo/document captions are captured in the text field so the workflow still sees the sender's words. The workflow's edge-case guard routes media-bearing messages to human review; this server intentionally doesn't fetch or interpret attachment content.
  • Consumption contract: telegram_list_messages does not mark messages as consumed. The workflow is responsible for tracking its own last-run timestamp (e.g. in the tracker CSV or a workspace key) and passing it as the since parameter each run. For a daily 09:00 schedule, pass since=yesterday_09:00 to get the previous day's messages. Invalid since values throw rather than silently returning all messages.
  • Rate limits are handled automatically — on HTTP 429 from Telegram, the server sleeps for the Retry-After duration and retries up to 3 times before surfacing the error.
  • Graceful shutdown: SIGINT/SIGTERM aborts any in-flight long-poll immediately, stops the poller, and flushes the store to disk via an atomic temp-file-then-rename write.

Design decisions

  • No external Telegram library. Uses fetch directly against https://api.telegram.org/bot<TOKEN>/... — keeps dependencies minimal and avoids native bindings.
  • JSON file store, not SQLite. Demo-scale volume (under a few dozen messages) doesn't justify SQLite's native dependency cost. Swap in SQLite by replacing the loadStore/saveStore methods if needed for larger deployments.
  • Member list is observed, not enumerated. The Telegram Bot API has no "list all group members" endpoint. telegram_list_group_members returns the set of users the poller has seen send messages into the staff group, which for a demo with seeded personas is the full set.
  • target is an enum, not a freeform chat ID. Constrains sends to the two pre-configured chats, so workflows can't accidentally send escalations to the wrong audience by passing a wrong chat ID.

Security notes

  • Bot token is a secret. Keep it in .env, never commit it. .env is in .gitignore.
  • Sends are constrained to configured chats. The target enum means tool calls can only send to staff_group or manager_chat — the chat IDs are server-side, not caller-controlled.
  • No attachment content is fetched or written to disk. has_attachment is a flag only; no risk of malicious-file write-through.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured