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.
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
- Open Telegram and message @BotFather.
- Send
/newbot, follow the prompts, and copy the bot token. - 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/commandmessages in groups, not regular text — the poller won't receive staff updates.
2. Create the chats
- Staff group: create a Telegram group, add the bot as a member, add the 5 staff personas (or real staff).
- Manager chat: a separate small group or a 1:1 DM with a manager test account that has sent
/startto the bot. This is wheretelegram_send_messagewithtarget: "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
offsetwas persisted from a previous run — on boot, the poller resumes from the last savedoffsetand 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_messagesreturnshas_attachment: truefor messages with photos/files. Photo/document captions are captured in thetextfield 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_messagesdoes 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 thesinceparameter each run. For a daily 09:00 schedule, passsince=yesterday_09:00to get the previous day's messages. Invalidsincevalues throw rather than silently returning all messages. - Rate limits are handled automatically — on HTTP 429 from Telegram, the server sleeps for the
Retry-Afterduration 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
fetchdirectly againsthttps://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/saveStoremethods 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_membersreturns 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. targetis 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..envis in.gitignore. - Sends are constrained to configured chats. The
targetenum means tool calls can only send tostaff_groupormanager_chat— the chat IDs are server-side, not caller-controlled. - No attachment content is fetched or written to disk.
has_attachmentis a flag only; no risk of malicious-file write-through.
Recommended Servers
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.
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.
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.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
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.
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.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
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.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.