io.github.antonio-castellon/mcp-telegram-bridge
Allows sending and managing Telegram messages through a bot, including sending messages with inline buttons, editing reply markup, answering callback queries, and fetching updates and chat metadata, with outbound text scrubbing and optional chat allowlist enforcement.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@io.github.antonio-castellon/mcp-telegram-bridgeSend 'Build #42 passed' to the DevOps Telegram group"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-telegram-bridge
Controlled Telegram channel bridge for any MCP host.
A small stdio Model Context Protocol server that sits between your local agent (Cursor, Claude Desktop, Windsurf, Grok/Cursor agents, and others) and the Telegram Bot API. The agent owns conversation logic; this process handles I/O, always-on outbound scrubbing, and chat allowlist enforcement. Optional strict inbound classification is disabled by default.
Built for client-owned deployments: the bridge runs on your machine, not on a hosted Grok VM. Games and game-master flows are one demo use case, not the product.
Owner context: Antonio Castellon / Castellon.CH - Swiss freelance architect. The same bridge shape is useful for SME lab patterns (notify channels, specialist handoff, moderated drafts) alongside email or ERP connectors.
What / why
Agents are good at reasoning and poor at holding a raw Bot API session by themselves. Telegram is a convenient human surface (groups, buttons, mobile). This project gives you a narrow, reviewable bridge:
Client-owned - stdio MCP on the workstation or CI runner that already hosts your agent.
Host-agnostic - any MCP client that can launch a local command.
Controlled - outbound scrubbing and optional
ALLOWED_CHAT_IDS; optional strict inbound classification for untrusted groups.Minimal tools - send, edit markup, answer callbacks, get updates, getMe / getChat. No game engine, no inbox file, no wake-RPC.
Pitch pattern for SMEs: start with a Telegram notify or triage channel using the same architecture you would later apply to email or ERP.
Related MCP server: Telegram MCP
Architecture
+---------------------------+
| MCP host / agents | Cursor / Claude Desktop / Windsurf / ...
| (conversation logic) |
+-------------+-------------+
|
| MCP (stdio)
v
+---------------------------+
| mcp-telegram-bridge | tools + safety scrub/classify
| (this process) |
+-------------+-------------+
|
| HTTPS Bot API
v
+---------------------------+
| api.telegram.org |
+-------------+-------------+
v
Telegram chats / groupsThe agent owns polling offsets, handoffs between specialists, and product policy. This server enforces destination controls and sends scrubbed text; inbound classification is opt-in.
Install
Requirements: Python 3.11+, a Telegram bot token from @BotFather.
git clone https://github.com/antonio-castellon/mcp-telegram-bridge.git
cd mcp-telegram-bridge
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
cp .env.example .env # set TELEGRAM_BOT_TOKEN (never commit .env)Or without cloning, once published:
uvx --from mcp-telegram-bridge mcp-telegram-bridge
# or: pipx run mcp-telegram-bridgeCursor / Claude Desktop (mcp.json)
Example for Cursor (User MCP settings) or Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"telegram-bridge": {
"command": "uvx",
"args": ["--from", "mcp-telegram-bridge", "mcp-telegram-bridge"],
"env": {
"TELEGRAM_BOT_TOKEN": "YOUR_BOT_TOKEN_HERE",
"ALLOWED_CHAT_IDS": "-1001234567890"
}
}
}
}On Windows, point command at your venv Python if needed, for example:
C:\DEV.Personal\mcp-telegram-bridge\.venv\Scripts\python.exe
Leave ALLOWED_CHAT_IDS empty only if you intentionally accept traffic from every chat the bot can see - document that risk for your deployment.
Smoke without a host:
python -m mcp_telegram_bridge
# process waits on stdio for MCP JSON-RPC (Ctrl+C to stop)MCP tools
Tool | Purpose |
| Bot identity / connectivity check |
|
|
| Strip or replace inline buttons |
| Ack a |
|
|
| Chat metadata |
Outbound text is always scrubbed. ALLOWED_CHAT_IDS restricts destinations when configured. telegram_get_updates runs the heuristic secret/NSFW classifier only when SAFETY_STRICT=1 (or true/yes/on); strict mode is optional and recommended for public or untrusted groups.
Usage guide
Collaborative agents in a Telegram group
Run one bridge process per bot (or one bot with clear agent roles). Use the group for standup notes, triage queues, and handoff between specialist agents ("ops acknowledges; billing drafts the reply"). Keep humans in the loop for irreversible actions.
Game master / tabletop facilitator (demo)
Send scene text with buttons=[{id,label}, ...] for player choices; on callback_query, answer the callback, optionally claim-style first-tap handling in the agent, then edit markup to clear spent choices. This is a demo of buttons + agent loop - not a bundled RPG engine.
Support / ops notify channel
Push alerts with ack buttons (ack, snooze, escalate). The agent records who tapped what; Telegram is the pager surface, not the source of truth.
Community moderation assistant
Draft replies and suggest actions. Humans still own ban / restrict / delete in Telegram Admin - say so in your agent prompt. The bridge must not be treated as a moderation authority.
Lab / SME pattern
Same shape as an email or ERP connector: narrow tools, allow-listed destinations, scrubbed egress, explicit inbound warnings. Telegram is the demo channel; swap the transport later without rewriting agent policy.
What this is NOT
Not a hosted bot SaaS or multi-tenant cloud bridge
Not Grok-only (works with any stdio MCP host)
Not a full RPG / game engine (no dice ruleset, no campaign DB in this repo)
Not an unattended admin bot (no ban tools shipped here)
Relation to sibling demos
Optional context only - this project does not require them:
grokgame - tabletop / game demo surface
grok2telegram - earlier bridge experiment whose safety doctrine informed
SAFETY.mdandsafety.py
mcp-telegram-bridge is the reusable, host-agnostic extraction: I/O + safety, no game loop and no Grok VM wake logic.
Safety
See SAFETY.md for the threat model, always-on scrubbing and allowlist controls, token handling, and optional strict mode. Do not put secrets in the repository; prefer ALLOWED_CHAT_IDS in production-like setups.
Development
pip install -e ".[dev]"
pytestTests mock Telegram HTTP with respx / httpx; no live token required.
MCP Registry
Canonical name: io.github.antonio-castellon/mcp-telegram-bridge
License
MIT (c) Antonio Castellon / Castellon.CH
Available Tools
6 toolstelegram_answer_callbackC
Acknowledge a callback_query (optional toast text / alert).
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | ||
| show_alert | No | ||
| callback_query_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states the action and optional text/alert, but does not mention that this is a required acknowledgment to avoid the Telegram loading indicator, or any constraints (e.g., invalid callback_query_id behavior). It is too terse to convey the operational context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no waste. It is front-loaded with the core action and includes the optional parameters in parentheses. However, it is so brief that it borders on under-specification, though it earns a 4 for efficiency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool is a mutation with no annotations and an output schema (which likely describes the result), the description should still cover prerequisites and typical usage context. It fails to mention that this should be called after receiving a callback_query, or that it is necessary to prevent UI spinning. The description is incomplete for an agent to understand when and why to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It adds meaning by explaining 'toast text / alert', which maps to the 'text' and 'show_alert' parameters, giving agents a hint about their purpose. However, it does not clarify the distinction between toast and alert (i.e., show_alert=true forces a popup), nor does it explain the required callback_query_id beyond its obvious name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: acknowledging a callback_query, which is a specific verb and resource. It also hints at optional parameters (toast text/alert). However, it does not explicitly differentiate from sibling tools like telegram_send_message or telegram_edit_reply_markup, though the resource is distinct enough to infer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. It does not mention that this is typically called in response to a callback_query from the user, nor does it state any conditions or exclusions. The description provides no context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_edit_reply_markupA
Edit or clear inline buttons on an existing message. Pass buttons=null/omit to strip markup; or a new [{id,label}] list.
| Name | Required | Description | Default |
|---|---|---|---|
| clear | No | ||
| buttons | No | ||
| chat_id | Yes | ||
| row_width | No | ||
| message_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the responsibility for behavioral disclosure. It does explicitly disclose that null/omitted buttons strip markup, which is a destructive action, and that the target must be an existing message. However, it does not mention side effects on message content, permission requirements, or the separate clear parameter's behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences with no fluff. The core action is front-loaded, and the parameter guidance follows naturally without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the primary use case well and benefits from an output schema, but it leaves material gaps: the clear flag and row_width are undocumented, and there are no notes about constraints or failure modes. For a mutation tool with zero annotations, a bit more context would be needed for fully confident invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description compensates partially by explaining the buttons parameter's two modes: null/omit to clear and a [{id,label}] list to set. However, it does not explain the clear boolean or row_width parameter, which are both non-obvious and absent from the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Edit or clear') and resource ('inline buttons on an existing message'), making the tool's purpose immediately clear. It also distinguishes this tool from sibling tools like telegram_send_message and telegram_get_updates by focusing on modifying an existing message's markup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear operational guidance: pass buttons=null/omit to strip markup, or provide a new list to set buttons. It does not name sibling alternatives or explicitly state when not to use the tool, but the context of editing an existing message is sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_get_chatC
Fetch chat metadata (getChat) for a chat_id.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It only says the operation fetches metadata and offers no context about read-only behavior, authentication requirements, failure modes, or what happens if the chat_id is invalid or inaccessible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no filler and no redundant information. Every word contributes to the meaning, which is ideal for a simple one-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a simple one-parameter schema and an output schema present, the description covers the core mechanics. However, the absence of annotations and usage guidance leaves gaps around when to call it and what behavioral expectations exist, making it only minimally adequate overall.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, but it merely repeats the chat_id parameter name without explaining accepted formats, constraints, or meaning. It adds little beyond the input schema itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Fetch'), a clear resource ('chat metadata'), and names the underlying API ('getChat'). It clearly conveys the tool's purpose, though it does not explicitly differentiate it from siblings like telegram_get_me or telegram_get_updates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, nor does it mention any exclusions or preferred contexts. An agent must infer the intended use solely from the tool name and the word 'metadata'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_get_meA
Return the bot identity (getMe). Useful as a connectivity check.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden, and it does convey the read-only behavior by saying 'Return' and framing the call as a check. It adds the useful operational context of connectivity verification, though it does not discuss auth or error behavior, which is acceptable for this simple tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with no filler. The core action and resource are stated first, and the diagnostic use case is added in a single appended clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-argument, read-only endpoint with an output schema available, the description is complete. It tells the agent what the tool returns and when to use it, and nothing else is needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema confirms this, so there are no parameter semantics to clarify. The baseline score of 4 applies because the description has nothing meaningful to add beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the specific verb 'Return' and the resource 'bot identity', and explicitly references the getMe API. This clearly distinguishes it from sibling tools like telegram_get_chat or telegram_send_message, which act on different resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly frames the tool as useful for a connectivity check, which is clear usage context. It does not name exclusions or alternatives, but for a zero-argument diagnostic method this is sufficient guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_get_updatesA
Long-poll getUpdates. The agent owns the offset loop. When SAFETY_STRICT is enabled, each update is annotated with safety.{kind,blocked,warning}; otherwise inbound text is returned unchanged and is not classified.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| timeout | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description takes on the disclosure burden and does it well: it reveals long-polling, agent-managed offsets, and the conditional safety classification output. It stops short of a 5 by omitting things like rate limits, webhook conflicts, or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences front-load the core operation and then add the two most important behavioral details: offset-loop ownership and the SAFETY_STRICT behavior. No filler, no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema covers the return shape and the description covers key behavior, so the agent is not entirely lost. But for a tool with three parameters and 0% schema coverage, the lack of limit/timeout semantics and any prerequisites makes it incomplete for fully correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description only meaningfully explains the offset concept via 'agent owns the offset loop.' Limit and timeout are left completely unexplained, so it only partially compensates for the schema's lack of parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Long-poll getUpdates') and conveys the core nature of the operation. This clearly separates it from siblings like get_me, get_chat, and send_message, which serve obviously different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides operational context by telling the agent it owns the offset loop and by explaining the SAFETY_STRICT conditional behavior. However, it does not explicitly state when to choose this tool over alternatives or when not to use it, leaving selection guidance mostly implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_send_messageA
Send a text message. Outbound text is scrubbed for token-shaped secrets. Optional buttons=[{id,label}] become an inline keyboard.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| buttons | No | ||
| chat_id | Yes | ||
| row_width | No | ||
| parse_mode | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations to carry safety or side-effect information, the description discloses two meaningful behaviors: outbound text is scrubbed for token-shaped secrets, and optional buttons become an inline keyboard. It does not cover all possible behaviors (e.g., parse_mode side effects), but it adds real value beyond a bare 'send message' statement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the main action front-loaded and no filler. The token-scrubbing warning and button behavior each earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has five parameters, no annotations, and no schema description coverage, so the description carries a heavy load. It covers the core action and a critical gotcha (secret scrubbing), but omits semantics for parse_mode and row_width, which an agent would need to format messages or arrange buttons correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must explain parameters. It only clarifies that optional buttons=[{id,label}] produce an inline keyboard, leaving chat_id, text, row_width, and parse_mode unexplained beyond their schema names and types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Send a text message.' This clearly distinguishes it from sibling tools like telegram_get_me and telegram_get_updates, which are read/polling operations, and from telegram_edit_reply_markup, which modifies existing messages rather than creating a new one.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the core use case clear—sending a message—and implies it should be used whenever the agent needs to post text to a chat. However, it provides no explicit guidance on when not to use it or how it differs from siblings such as telegram_answer_callback or telegram_edit_reply_markup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
telegram_answer_callback - First observed
telegram_edit_reply_markup - First observed
telegram_get_chat - First observed
telegram_get_me - First observed
telegram_get_updates - First observed
telegram_send_message
TDQS
Scored across 6 tools
Each tool targets a distinct Telegram API endpoint: identity, chat info, sending messages, editing buttons, answering callbacks, and fetching updates. The only minor ambiguity is between send_message and edit_reply_markup since both handle buttons, but their purposes (new vs. existing message) are clearly different.
All tools follow a consistent 'telegram_' prefix followed by a verb_noun pattern (e.g., get_me, get_chat, send_message). The naming is predictable and consistent across the entire set.
With 6 tools, the server covers the essential operations for a Telegram bridge without unnecessary bloat. Each tool serves a clear purpose in the core workflow of a bot, making the count well-scoped.
The server covers identity, chat info, sending, editing, callback answers, and updates. However, it lacks common operations like deleting messages or sending media/files. Also, the update loop relies heavily on the agent, and there is no method to manage webhooks, but the core messaging loop is covered.
Related MCP Connectors
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Unofficial Telegram MCP server — read, search, reply and react in your own Telegram account.
Hosted MCP messaging across owners, tools, and machines, with readable transcripts.
Manage Telegram drafts, media, schedules and publications from AI clients.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with Telegram accounts through MCP, supporting messaging, contacts, groups, media, and admin functions.4Apache 2.0
- FlicenseBqualityCmaintenanceEnables MCP clients to interact with Telegram user accounts, providing tools for messaging, contacts, groups, channels, and media management through the Telegram API.853-
- AlicenseAqualityAmaintenanceEnables MCP-compatible clients to securely access and manage Telegram accounts, chats, messages, media, and contacts, with tiered permissions, write controls, and local caching.22Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients like Codex or ChatGPT to securely receive, acknowledge, and send Telegram messages with durable delivery guarantees and idempotency.MIT