telegram-notify-mcp
Sends one-shot notifications to a Telegram chat through a bot, allowing agents to alert on task completion, failures, warnings, or requests for decisions.
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-notify-mcpsend a Telegram message that the deploy failed"
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-notify
One-shot Telegram notifications for coding agents. When a long task finishes, a deploy fails or an agent needs a decision, it sends one self-contained message to your phone through your own bot.
Three ways in, one message format:
For | Needs | |
| any agent or script with a shell |
|
| any MCP client: Claude Code, Cursor, Codex, Gemini CLI… |
|
Claude Code skill | Claude Code, so it knows when and how to notify | the CLI on PATH |
GUIDELINES.md says what a good message looks like; the skill and the MCP tool carry the same rules, so every agent writes the same kind of message:
✅ turtletrips 1.7.0 desplegado
📁 turtletrips · 🖥️ ginnugagap
Imagen ghcr.io/zurdi15/turtletrips:1.7.0 desplegada en el clúster.
Argo: turtletrips Synced/Healthy. Health: HTTP 200.
Novedades 1.7.0:
- Moneda secundaria por viaje (p. ej. VND), elegible junto a la base en el formulario del viaje.
- En el gasto, la moneda se elige con principal · secundaria · otra.1. Bot and chat (once)
Create a bot with @BotFather and copy its token.
Send it any message from the chat that should receive the notifications (your user, or a group the bot is in).
Find that chat's id:
telegram-notify-setup --token <token> --find-chat(or openhttps://api.telegram.org/bot<token>/getUpdatesand look for"chat":{"id":…}).
The same bot can serve as many machines and agents as you like.
Related MCP server: telegram-mcp-notify
2. Install on a machine
With uv (recommended)
uv tool install "telegram-notify[mcp] @ git+https://github.com/zurdi15/telegram-notify"
telegram-notify-setup --token <token> --chat-id <chat_id> --testsetup writes ~/.config/telegram-notify/notify.env (mode 600), installs the Claude Code skill
into ~/.claude/skills/telegram-notify/ and sends a test message. Drop [mcp] if you only want
the CLI. Upgrade later with uv tool upgrade telegram-notify.
Without uv
The CLI is a single stdlib file, so it can be dropped anywhere with a python3:
curl -fsSL https://raw.githubusercontent.com/zurdi15/telegram-notify/main/telegram_notify/cli.py -o ~/.local/bin/telegram-notify
chmod +x ~/.local/bin/telegram-notify
mkdir -p ~/.config/telegram-notify && printf 'TELEGRAM_BOT_TOKEN=%s\nTELEGRAM_CHAT_ID=%s\n' <token> <chat_id> > ~/.config/telegram-notify/notify.env && chmod 600 ~/.config/telegram-notify/notify.envpip install git+https://github.com/zurdi15/telegram-notify works too.
Credentials
Resolved in this order; the first complete pair wins. They are never written anywhere else, never logged and never printed.
TELEGRAM_BOT_TOKENandTELEGRAM_CHAT_IDin the environment.The file named by
TELEGRAM_NOTIFY_ENV.~/.config/telegram-notify/notify.env(whatsetupwrites).~/.config/claude-telegram/notify.env(legacy path, still read).
File format: KEY=VALUE, one per line. In CI, put the two variables in the job's secrets.
3. Use it
CLI
telegram-notify -s ok -t "immich 1.140 desplegado" -H ginnugagap "Imagen desplegada. Argo Synced/Healthy. Health: HTTP 200."
pytest -q 2>&1 | tail -20 | telegram-notify -s fail -t "Tests rotos en bifrost" # body from stdin
telegram-notify -s ask -t "Necesito confirmación" "¿Borro el PVC antiguo de immich (40 GB)?"
telegram-notify --dry-run -t "Prueba" "Imprime el mensaje sin enviarlo"Flag | Meaning |
|
|
| Headline, first line of the message. |
| Project shown in the context line (default: git repo or cwd name). |
| Host shown in the context line (default: this machine). Use the deploy target when that is what matters. |
| Drop the |
| Print the message instead of sending it. |
Exit code 0 means delivered; anything else prints the reason on stderr. Messages are plain text,
capped at Telegram's 4096 characters.
MCP server
One tool, notify(title, body, status="ok", project=None, host=None, dry_run=False), whose
description and the server instructions carry the message guidelines. Register it once per machine,
user-wide:
# Claude Code
claude mcp add --scope user telegram-notify -- telegram-notify-mcpAny other MCP client takes the same command in its own config (Cursor ~/.cursor/mcp.json, Codex
~/.codex/config.toml, Gemini CLI ~/.gemini/settings.json…). Without the tool install, uvx
runs it straight from this repository:
{
"mcpServers": {
"telegram-notify": {
"command": "uvx",
"args": ["--from", "telegram-notify[mcp] @ git+https://github.com/zurdi15/telegram-notify", "telegram-notify-mcp"]
}
}
}The server reads the credentials from the same places as the CLI. If your client cannot see your
shell environment, add "env": {"TELEGRAM_BOT_TOKEN": "…", "TELEGRAM_CHAT_ID": "…"} there, or
rely on the config file. Pin a revision with …/telegram-notify@v0.1.0 for reproducible installs.
Claude Code skill
telegram-notify-setup copies telegram_notify/SKILL.md to
~/.claude/skills/telegram-notify/SKILL.md. From then on any session, in any project, knows the
tool exists, when to use it and how to write the message. Check with:
claude -p "Lista los nombres de tus skills disponibles"Other agents that read skill files (or an AGENTS.md) can point at the same file: the rules are the
ones in GUIDELINES.md.
Always notify when a turn ends (optional)
A Claude Code Stop hook in ~/.claude/settings.json fires on every turn, trivial ones included;
the skill (the agent decides when it is worth it) is usually better:
{ "hooks": { "Stop": [ { "hooks": [ { "type": "command", "command": "telegram-notify -s ok -t 'Claude ha terminado' 'Turno completado'" } ] } ] } }Development
python3 -m unittest discover -s tests # stdlib only; pytest works too
uv run --extra mcp telegram-notify-mcp # run the server locallytelegram_notify/cli.py must stay dependency-free and importable on its own: that is what makes the
curl install and the copy-the-file fallback possible.
Available Tools
1 toolnotifyA
Envía un aviso por Telegram al usuario (una tarea terminada o bloqueada).
title: titular corto proyecto versión verbo (p. ej. "turtletrips 1.7.0 desplegado"), sin icono: lo pone status.
body: qué se hizo (con imagen/tag/commit), cómo se verificó y, en releases, "Novedades X.Y.Z:" con una línea "- " por cambio. Texto plano en español, sin Markdown ni secretos.
status: ok ✅ | fail ❌ | warn ⚠️ | info ℹ️ | ask ❓.
project: nombre del proyecto para la línea de contexto (por defecto, el repo git del cwd).
host: host de la línea de contexto (por defecto esta máquina; pasa el destino del despliegue si es lo relevante).
dry_run: devuelve el mensaje compuesto sin enviarlo.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| host | No | ||
| title | Yes | ||
| status | No | ok | |
| dry_run | No | ||
| project | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does so well: it explains dry_run returns the composed message without sending, documents default values for project and host, and specifies formatting constraints like plain Spanish, no Markdown, and no secrets.
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 efficiently organized as a field-by-field reference with the core purpose front-loaded. Each line earns its place and conveys concrete, non-redundant 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?
All six parameters are covered with defaults and content rules, an output schema exists so return-value documentation is not required, and the description gives enough context to compose a correct notification. No critical gaps remain for an agent to call 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?
Schema description coverage is 0%, so the description must fully compensate. It does: every parameter (title, body, status, project, host, dry_run) receives meaningful guidance on format, defaults, examples, and allowed values beyond the bare 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 opens with 'Envía un aviso por Telegram al usuario', identifying a specific verb, resource, and channel, and clarifies the use case: a finished or blocked task. Even without sibling tools, the purpose is unambiguous.
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 clear context for when to use it ('una tarea terminada o bloqueada') and describes the message format and status variants. There are no sibling tools or exclusions, so no alternative routing is needed.
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.
1 tool update
v0.1.0- First observed
notify
TDQS
Scored across 1 tool
Only one tool exists, so there is no possibility of confusion between tools. The single tool clearly defines its purpose of sending a Telegram notification.
With only one tool, naming is trivially consistent. The verb 'notify' clearly indicates the action, fitting the expected verb_noun pattern.
A single tool for a server is extremely thin, even if the purpose is narrow. This feels more like a helper function than a full MCP server; agents would expect additional tools for managing notifications or checking status.
The tool covers sending notifications, but there is no way to list, get, or delete sent notifications, nor any configuration management. The domain is so minimal that completeness is hard to assess, but it leaves obvious gaps for any non-trivial use.
Maintenance
Related MCP Connectors
Let your AI agent notify you by email, Slack, Discord, or webhook. One tool: send_notification.
Messaging tools for AI agents: send messages, manage chats, groups and channels.
Project memory, tasks and Telegram notifications for your coding agent. Chip account required.
Run a Telegram channel from your AI agent. Posts go out through your own bot, not your account.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI agents to send notifications and media (text, photos, documents, videos) via a Telegram bot.456 npm4Do What The F*ck You Want To Public
- AlicenseNot gradedqualityDmaintenanceEnables AI coding agents to send structured Telegram notifications for events like questions, plan_ready, final, attention_needed, and error.MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to send Telegram messages including text, images, links, and documents through MCP tools.MIT
- AlicenseNot gradedqualityDmaintenanceEnables sending Telegram notifications from an MCP client using a bot token and chat ID, with a single tool to send messages.126 npmMIT