telegram-commandcode
Provides tools for sending messages, photos, files, and reading updates from Telegram, allowing AI agents to communicate via Telegram chats.
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., "@telegram-commandcodeSend the test results to Telegram"
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.
telegram-commandcode
Telegram for your coding agent. An MCP server that lets Claude Code, Cursor, Codex CLI, Command Code or any other MCP client send you messages, files, photos and progress updates — and read your replies back.
your agent ──MCP stdio──▶ telegram-commandcode ──HTTPS──▶ Telegram ──▶ your phone
▲ │
└────────────────────── reply via getUpdates ◀───────────────────────┘The repository contains three independent pieces:
Piece | Direction | Language | What it does |
MCP server ( | agent → Telegram | Node | Seven tools: send message / photo / file, read updates, react, download, health check |
Bot daemon ( | Telegram → agent | Python | 48 commands, streaming output, persistent sessions; frozen at 2.2.0 (see status below) |
ACP bridge ( | Telegram → agent | Node | Drives any ACP agent: sessions, streaming, approvals, |
You can use any of them alone. The MCP server is the part that works with every
agent; the daemon is specific to the Command Code CLI — and not needed at all
if you already use Command Code's own /rc; the ACP bridge is the portable
chat driver for agents that speak ACP.
Command Code ships this itself now
If you use Command Code and just want it on your phone, the daemon below is
redundant: since Remote
Control (announced
2026-09-29)
an open session can be driven from Telegram or Discord with /rc.
Command Code | MCP server (this repo) | Bot daemon (this repo) | |
Direction | live session ↔ chat | any agent → chat, replies back | chat drives a CLI |
Works with | Command Code only | any MCP client | Command Code only |
Needs an open session | yes | no | no |
Status: the MCP server is the maintained part. The daemon is frozen at 2.2.0 — correct and tested, still useful for self-hosting a bot on a server or driving a CLI from a chat, but it gets no new features.
The MCP server is the part /rc does not replace: it works with every agent,
it can notify you from a CI job or a short-lived agent that has no session to
keep open, and it reads your replies back.
Quick start — MCP server
You need a bot token from @BotFather and your numeric
chat id (send the bot a message, then read chat.id from
https://api.telegram.org/bot<TOKEN>/getUpdates).
Command Code
cmd mcp add telegram \
-e TELEGRAM_BOT_TOKEN=<token> \
-e TELEGRAM_DEFAULT_CHAT_ID=<chat_id> \
-- npx -y github:qrak/telegram-commandcodeClaude Code
claude mcp add telegram \
-e TELEGRAM_BOT_TOKEN=<token> \
-e TELEGRAM_DEFAULT_CHAT_ID=<chat_id> \
-- npx -y github:qrak/telegram-commandcodeCursor / other MCP clients
Add a stdio server with the command npx and arguments
["-y", "github:qrak/telegram-commandcode"], plus the two environment
variables above (~/.cursor/mcp.json for Cursor).
Restart the agent, then ask it to call telegram_health. You should get your
bot's username back.
What the agent can do
Tool | Purpose |
| Text, plain or formatted; 4096-char limit enforced with a clear error |
| Local path or URL, up to 10 MB |
| Any document up to 50 MB — logs, diffs, PDFs, zips |
| Read replies; only unseen messages by default |
| 👀 / ✅ / ❌ on a message |
| Pull a file the user sent, up to 20 MB |
| Verify the token before doing anything else |
The server retries 429/5xx with backoff, retries once without parse_mode when
Telegram rejects the markup, redacts the token from every error it returns,
and refuses to start silently without a token — it exposes a single
telegram_status tool that explains the setup instead.
Related MCP server: mcp-telegram
Quick start — bot daemon (Command Code only)
git clone https://github.com/qrak/telegram-commandcode.git
cd telegram-commandcode
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .export TELEGRAM_BOT_TOKEN="123456:ABC..."
export TELEGRAM_ALLOWED_USERS="<your numeric user id>"
export COMMAND_CODE_WORKDIR="$HOME/projects/my-app"
telegram-commandcodeThen message the bot: a plain message becomes a prompt for cmd, and slash
commands map to the CLI — /model, /plan, /review, /status, /stop and
43 more. Type / in Telegram to see the menu.
Sessions, compaction and forks
The daemon keeps one Command Code session per chat and captures its id from
each run (--output-format json), so the session history is not guesswork:
You want | Command | What actually happens |
Continue where you left off |
|
|
Attach to a named/known session |
|
|
Name the current session |
| later runs pass |
Branch off |
| next prompt runs |
Shrink the context |
| one read-only summarisation run builds a handoff brief, then a new session is seeded with it |
Step back N turns |
| same brief, describing the state before the last N prompts; those prompts drop out of the history |
Wipe everything |
| new session, no brief |
/compact and /undo make one extra model call; if it fails, nothing is
changed and the bot says so. The handoff brief is injected exactly once, so it
does not keep costing tokens on every later turn.
Other settings are passed per run rather than written and forgotten:
/model → -m, /effort → --effort, /compact-mode → --config compact-mode=<default|fast> (also persisted as compactMode).
/usage and /context report the real token counts each run reports back.
Configuration
Variable | Default | Meaning |
| — | Required. From @BotFather |
| (empty = locked) | Comma-separated numeric ids, or |
|
| Path to the Command Code binary |
| current directory | Where the agent runs |
|
|
|
|
|
|
|
|
|
|
| Max turns per prompt |
| — | Optional, enables voice transcription |
An empty allow-list is fail-closed: the bot replies with your numeric id
and instructions instead of executing anything. TELEGRAM_ALLOWED_USERS=any
is an explicit opt-in, not the default.
Run it as a service
cp deploy/telegram-commandcode.service ~/.config/systemd/user/
# edit ExecStart / EnvironmentFile / WorkingDirectory first
systemctl --user daemon-reload
systemctl --user enable --now telegram-commandcode.serviceACP bridge — Telegram ↔ any ACP agent
acp-bridge/ is a single-file Node client for the
Agent Client Protocol. It spawns the agent
over stdio, keeps one ACP session per chat and turns protocol events into chat
UI: session/update streams into one edited message, session/request_permission
becomes inline buttons, /compact and /resume are implemented on top of
session/prompt, session/list and session/resume.
cd acp-bridge && npm install
cp agents.example.json agents.json # token, chatId, cwd, agents
npm startCommand | What it does |
| list agents, |
| new session, drops the context |
| list stored sessions, |
| agent writes a handoff brief, a new session continues from it |
| agent, session, busy state, capabilities |
|
|
Full details, config schema and limitations: acp-bridge/README.md.
Status
Tested end to end against DeepSeek Harness (dsh --profile acp, ACP v1):
sessions, streaming, cancel, session/list/session/resume, /compact,
permission buttons.
Missing and planned
Agent | Adapter | State | Next step |
DeepSeek Harness | native ( | ✅ working | command/mode discovery once upstream advertises it |
Claude Code |
| ⏳ wired, untested | install CLI + log in, then run the smoke test |
Codex |
| ⏳ wired, untested | same, with |
Gemini CLI |
| ⏳ wired, untested | confirm the flag per version, add to CI |
Not implemented yet:
Slash-command discovery. The bridge logs
available_commands_updatewhen an agent sends it, but DSH sends none, so the agents' own commands (/plan,/model,/goal) never reach the Telegram menu.Model and mode switching.
session/set_config_option/session/set_modeare unsupported by the current DSH build (modes: null, no config options); DSH's privateproviders/list+providers/setare a possible shortcut.Media. Text only; image/audio forwarding depends on
promptCapabilities, which DSH advertises as empty.Real compaction.
/compactis a summarise-then-restart with a handoff brief, not the agent's internal compaction plugin.Queueing. One turn per chat; a second message while busy is rejected.
Planned, roughly in order: per-adapter smoke test (so "supported" means
"checked"), command menu from available_commands_update, model/mode switching,
media, per-chat queue.
Security
This tool gives a chat app the ability to drive an agent that edits files and runs shell commands. Read SECURITY.md before exposing it:
set
TELEGRAM_ALLOWED_USERSto your own id,run it in a project directory, not your home directory,
treat the bot token like an SSH key,
on a shared host, run the bot in a container under a dedicated user.
COMMAND_CODE_YOLO=true is the intended mode — and it is remote code execution
by design. Do not put production credentials on the host.
Requirements
MCP server: Node.js ≥ 18, a Telegram bot token.
Bot daemon: Python ≥ 3.11,
python-telegram-bot20–21, the Command Code CLI onPATH. Command Code is closed-source and requires its own subscription; the bot daemon is only useful if you already use it.
Development
npm install
npm test # 6 MCP protocol tests (spawns the real server)
npm run deadcode # knip: unused JS files, exports, dependencies
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest # 163 unit tests, no network, no `cmd` needed
python -m vulture # dead Python code (clean; see docs/dead-code-audit.md)CI runs both test suites on Linux and Windows.
Repository layout
index.js MCP server (the agent-facing part)
package.json npm metadata, tests, bin
acp-bridge/ Telegram ↔ any ACP agent (standalone Node app)
acp-bridge.mjs the whole bridge: ACP client + Telegram UI
agents.example.json per-agent command lines (copy to agents.json)
telegram_commandcode/ Python bot daemon
gateway/ router, sender, processor, media
commands/ slash-command handlers (48)
executor.py async `cmd` subprocess runner
formatter.py, chunking.py MarkdownV2 escaping and 4096-char splitting
skill/ publishable SKILL.md + references for agent
marketplaces (Agensi, Claude Code skills)
tests/ pytest suite
test/ MCP protocol tests (node:test)
legacy/ original Node bot, archived and unsupported
deploy/ systemd unitPublishing as an agent skill
skill/ is a self-contained SKILL.md package: the playbook for when and how an
agent should use these tools, including MarkdownV2 pitfalls, limits, approval
loops and troubleshooting. Build the upload zip with:
node scripts/build-skill.mjs # writes dist/telegram-bridge-skill.zipThe skill depends on this repository (MIT) but is not a copy of it: it encodes the operating knowledge, while the MCP server stays free here.
Status and known limits
The MCP server is tested against
@modelcontextprotocol/sdk1.29 and Node 18/20/22.The ACP bridge is tested only against DeepSeek Harness. The Claude Code, Codex and Gemini adapters are configured in
agents.example.jsonbut have not been run against real installations — treat them as unverified.The ACP bridge implements
/compactitself (handoff brief + new session); it is not the agent's internal compaction.The bot daemon calls the
cmdCLI with-p <prompt>and Command Code flags; it is coupled to that CLI's argument surface by definition.Command Code is not open source, so the daemon cannot be tested end-to-end in CI. Everything that does not need the binary is unit-tested.
telegram_get_updatesacknowledges updates: do not run the bot daemon, the ACP bridge and the MCP server's read path against the same token at the same time, or they will steal each other's messages.
License
MIT — see LICENSE.
Available Tools
7 toolstelegram_download_fileA
Download a file from Telegram by file_id (max 20 MB via the Bot API) and return its local path.
| Name | Required | Description | Default |
|---|---|---|---|
| file_id | Yes | file_id from an incoming message. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations by disclosing the 20 MB Bot API ceiling and that the call produces a local file path. Annotations only mark it non-readOnly/openWorld; the description supplies the practical constraint that determines success or failure. It doesn't say where the file lands or how failures/oversized files surface.
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?
A single sentence with zero filler, leading with the action and ending with the return value. Every clause carries information an agent needs.
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 one parameter, no output schema, and a 20 MB limit disclosed, the description covers what an agent needs to invoke the tool and interpret the result. Only edge-case behavior (oversized file, missing file_id) is left implicit.
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 coverage is 100% and the sole parameter already says 'file_id from an incoming message'. The description repeats the parameter name and constraint but adds no format or sourcing detail beyond the schema, so baseline 3 applies.
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?
States a specific verb and resource ('Download a file from Telegram by file_id') and implies the returned artifact ('its local path'). It is clearly distinguishable from the send_* siblings, though it does not name them explicitly.
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 tool is single-purpose enough that when-to-use is obvious from the name and from the fact that all siblings are send/kill/health tools. There is no explicit statement about when not to use it or what alternative to pick for oversized files.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_get_updatesARead-only
Fetch recent incoming messages. By default only unseen updates are returned and acknowledged; pass offset: 0 to re-read the backlog.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max updates to return (default 5, max 20). | |
| offset | No | Update offset. Omit to continue from the last seen update. | |
| timeout | No | Long-polling timeout in seconds (default 0, max 50). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses the most important non-obvious trait: a default call acknowledges (consumes) unseen updates, so an agent knows repeat calls can lose messages, and offset: 0 is the escape hatch. This adds genuine value beyond the readOnlyHint/openWorldHint annotations. Minor tension: 'acknowledged' implies a cursor-advancing side effect that readOnlyHint=true does not advertise, but the description is the more accurate of the two and no return/blocking behavior is described.
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 tight sentences, zero filler. The default/consumption behavior leads, and the offset: 0 workaround follows immediately where it is needed.
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?
There is no output schema, and the description says nothing about what an 'update' contains or how results are shaped, which an agent needs in order to parse the response. For a 3-parameter, no-output-schema fetch tool with annotations present, the description is adequate but leaves that gap open.
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 coverage is 100%, so the baseline is 3, and the description earns an extra point by adding offset semantics the schema lacks (offset: 0 re-reads the backlog, vs. omitting it to continue). limit and timeout get no narrative treatment, but their schema descriptions are already sufficient.
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?
States a concrete verb+resource ("Fetch recent incoming messages") that an agent can immediately map to an operation, and it is implicitly the only read-side tool among send/download siblings. It stops short of naming a sibling or stating the inbox/polling role explicitly, so it is clear but not maximally differentiated.
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?
Gives usable operating context: default behavior returns only unseen updates, and offset: 0 forces a backlog re-read. That is a real when-to-use signal, though it never states when NOT to call it (e.g., rate limits, or that repeated default calls advance the cursor past messages).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_healthARead-only
Check that the bot token works: returns bot id, username and capabilities.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the description needn't re-explain the safety profile. It adds value by disclosing what the call returns (bot id, username, capabilities), which matters because there is no output schema; it does not mention auth prerequisites beyond the token itself or failure behavior on an invalid token.
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?
One short sentence, front-loaded with the action and then the return payload. Every clause earns its place with no filler.
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-parameter diagnostic tool with no output schema, the description covers purpose and return contents, which is enough for an agent to call it correctly. Adding a note about what happens on an invalid token would round it out but isn't essential.
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 takes zero parameters, so the baseline is 4 and the schema carries nothing to document. The description correctly adds no parameter discussion because none are needed.
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?
States a specific verb+resource (check bot token) and enumerates the result (bot id, username, capabilities), which clearly separates it from the send_* and get_updates siblings. It doesn't name those siblings, so differentiation is implied rather than explicit.
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?
"Check that the bot token works" implies a pre-flight/credential-validation use case, which is enough for an agent to infer when to call it. There is no explicit when-not guidance or named alternative, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_send_fileA
Send a document/file via an absolute local path or public URL (max 50 MB). Useful for build logs, diffs, screenshots and reports.
| Name | Required | Description | Default |
|---|---|---|---|
| caption | No | Optional caption (max 1024 chars). | |
| chat_id | No | Target chat ID (user, group, or channel). Omit to use TELEGRAM_DEFAULT_CHAT_ID. | |
| file_path | Yes | Absolute path to the file (e.g. /tmp/report.pdf) or a public URL. | |
| parse_mode | No | Caption parse mode. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=true, so the description's job is supplemental. It does add real value beyond them: the 50 MB cap and the fact that the source may be either a local path or a fetched public URL (which explains the openWorld hint). It stops short of saying what happens on oversized or unreachable files, but that is a minor gap given annotation coverage.
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 tight sentences: the core action and constraints come first, supported use cases second. No repetition of the name or schema fields, and every clause carries information.
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 four-parameter send tool with full schema coverage, annotations, and no output schema, the description covers action, input forms, and size limit. What is missing is failure behavior and the file-vs-photo boundary, both minor for a tool this simple.
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 100%, so the schema already documents all four parameters, including the TELEGRAM_DEFAULT_CHAT_ID fallback and the caption length limit. The description only reinforces file_path semantics (absolute path or public URL) and adds the size limit; it says nothing about parse_mode or caption behavior beyond what the schema states. Baseline 3 applies.
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?
States a specific verb and resource ('Send a document/file') plus the accepted input forms (absolute local path or public URL) and a size ceiling (max 50 MB). It implies the boundary with telegram_send_photo and telegram_send_message by naming documents/files rather than messages or images, but never explicitly routes the agent away from those siblings.
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 use-case list ('build logs, diffs, screenshots and reports') gives implied context for when this is the right tool, but there is no explicit when-not guidance and no mention of telegram_send_photo as the alternative for images — notable since 'screenshots' is listed as a use case here.
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 to a Telegram chat. Supports MarkdownV2 and HTML parse modes. Messages longer than 4096 characters are rejected by Telegram — split them first.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Message text to send. | |
| chat_id | No | Target chat ID (user, group, or channel). Omit to use TELEGRAM_DEFAULT_CHAT_ID. | |
| parse_mode | No | Formatting mode. MarkdownV2 requires escaping _ * [ ] ( ) ~ ` > # + - = | { } . ! |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description usefully adds the 4096-character rejection limit and the supported parse modes, but says nothing about rate limits, error behavior, or what the call returns.
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?
Three short sentences, front-loaded with purpose, then capabilities, then a hard constraint that prevents a failure mode. No filler.
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 simple three-parameter send tool with annotations and a full-coverage schema, the description plus structured fields give an agent everything needed to invoke it correctly. Only rate-limit/error and return-value expectations are absent, which is minor for a mutation with no output schema.
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 100%, so all three parameters are already documented, including the escape rules for MarkdownV2 and the default chat_id fallback. The description reinforces the length constraint on text but adds no new per-parameter semantics; baseline 3 applies.
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?
States a clear verb and resource ("Send a text message to a Telegram chat") and the word "text" implicitly distinguishes it from telegram_send_photo and telegram_send_file. It never names those siblings explicitly, so differentiation is inferential rather than stated.
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?
Sending a text message is the obvious implied use case, and the 4096-character note implies "split instead of calling this." But there is no explicit routing to alternatives (send_photo/send_file) or statement of prerequisites such as needing a valid chat_id or bot permissions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_send_photoA
Send a photo via a public URL or an absolute local file path (max 10 MB for photos).
| Name | Required | Description | Default |
|---|---|---|---|
| photo | Yes | Public https:// URL or absolute path to a local image file. | |
| caption | No | Optional caption (max 1024 chars). | |
| chat_id | No | Target chat ID (user, group, or channel). Omit to use TELEGRAM_DEFAULT_CHAT_ID. | |
| parse_mode | No | Caption parse mode. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=true, so the safety profile is clear. The description adds a useful behavioral constraint (max 10 MB) and allowed source types, but does not mention authentication, rate limits, or failure 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 definition is a single efficient sentence with the core constraint and accepted inputs front-loaded. There is no filler, though a brief distinction from send_file could have increased value without hurting conciseness.
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 straightforward send tool with full schema coverage and clear annotations, the description is largely complete. It covers accepted input sources and size limits; more detail on default chat behavior or failure modes is already handled by the schema.
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 100%, so parameter semantics are already well documented in structured form. The description reinforces the photo parameter by restating accepted sources and adding a size limit not present in the schema, which is useful but modest.
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 gives a clear verb and resource ('Send a photo') and states accepted input forms, making the purpose immediately understandable. It does not explicitly distinguish this tool from the sibling telegram_send_file, which likely handles generic files, so sibling differentiation is incomplete.
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?
Usage is implied by the description of accepted photo sources, but there is no explicit guidance on when to use this tool versus telegram_send_message or telegram_send_file. The agent must infer the boundary from the tool name and description alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_send_reactionA
Set an emoji reaction on a message (👀 working, ✅ done, ❌ failed). The bot must be a member of the chat.
| Name | Required | Description | Default |
|---|---|---|---|
| emoji | Yes | One of the allowed Telegram reaction emoji. | |
| chat_id | No | Target chat ID (user, group, or channel). Omit to use TELEGRAM_DEFAULT_CHAT_ID. | |
| message_id | Yes | ID of the message to react to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=true). The description adds a real operational prerequisite not present in structured fields — the bot must already be a member of the chat — which materially affects whether the call will succeed. It omits whether a reaction replaces a prior one or rate limits, keeping it from a 5.
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 zero filler; the core action leads and the precondition follows. Every clause earns its 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?
No output schema exists, but annotations plus the full-coverage schema plus the membership precondition give an agent enough to call correctly. Minor gaps remain around failure modes and whether reactions overwrite, which a single clause could close.
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 coverage is 100%, so all three parameters are already documented, which sets the baseline at 3. The emoji examples add flavor but don't constrain the allowed emoji set, and the description adds nothing for chat_id/message_id 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?
States a specific verb and resource: 'Set an emoji reaction on a message.' This clearly distinguishes it from the send_message/send_photo/send_file siblings, which create messages rather than react to existing ones. It stops short of naming siblings explicitly, but the distinction is obvious.
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 emoji examples (👀 working, ✅ done, ❌ failed) imply a progress-reporting use case and the membership precondition is stated, but there is no explicit when-to-use vs. when-not guidance nor a pointer to any alternative tool. Usage is implied rather than directed.
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.
7 tool updates
v2.2.0- First observed
telegram_download_file - First observed
telegram_get_updates - First observed
telegram_health - First observed
telegram_send_file - First observed
telegram_send_message - First observed
telegram_send_photo - First observed
telegram_send_reaction
TDQS
Scored across 7 tools
Each tool targets a distinct action: three send variants are cleanly separated by payload type (text, photo, document) with explicit size limits, and get_updates/download_file/reaction/health have no overlap. An agent can pick the right tool from the names alone.
All tools share a consistent `telegram_` prefix and snake_case, with verb_noun forms for the action tools (send_message, get_updates, download_file). The only deviation is `telegram_health`, a noun phrase rather than a verb, but it remains readable and predictable.
Seven tools is well-scoped for a Telegram bot bridge: send, receive, download, react, and health-check. Nothing feels redundant or missing from a count perspective.
Core lifecycle is covered: outbound text/media, inbound updates, file download, reactions, and auth verification. Gaps exist around message management (edit, delete, reply/thread targeting) and chat introspection (list chats, get chat info), which agents may need for richer interactions.
Maintenance
Related MCP Connectors
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Hosted Telegram MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
Unofficial Telegram MCP server — read, search, reply and react in your own Telegram account.
Related MCP Servers
- FlicenseAqualityDmaintenanceAn MCP server for interacting with Telegram bots and channels using the Telegraf library. It allows AI agents to send messages, manage channels, forward content, and intelligently respond to Telegram conversations.565 npm8-
- AlicenseBqualityDmaintenanceA Telegram MCP server that connects agents to a real Telegram user account via MTProto, enabling reading, searching, sending, moderating, and managing Telegram chats through natural language or automated tool calls.100168 npm33MIT
- FlicenseNot gradedqualityDmaintenanceMCP server that enables AI agents to send messages, photos, polls, and receive replies via Telegram with persistence and rate limiting.55 npm-
- AlicenseNot gradedqualityDmaintenanceAn MCP server enabling AI agents to interact with users via Telegram, supporting message and image sending, inline quick replies, and waiting for user responses.11 npmMIT