Writing

Let Claude message you on Telegram, and only you

A scheduled task finishes at night. A long build fails while you're in another room. A reminder comes due. The agent knows, and you don't, because you aren't looking at the screen.

This post covers what tends to go wrong when an agent gets a Telegram bot, and telegram-notify: a small open-source MCP server that lets Claude send you Telegram messages and files, and does nothing else.


Why a tool and not a hook

Claude Code can already run a command when a session ends, through a hook. That works, and for "ping me when you stop" it may be all you need. A hook fires on an event, though, and the text is whatever the script writes.

An MCP tool is something the model calls, so the message can say what actually happened: which test failed, what the report found, what needs your decision. It also works wherever MCP works: Claude Desktop, Claude Code, a scheduled task, another MCP client.


What goes wrong with a Telegram bot in an agent's hands

I read the source code of eight Telegram servers for MCP on 7 and 8 November 2026, plus the official Claude Telegram channel plugin. Three problems keep coming back.

The model can choose the recipient

In four of them, every send tool takes a chat_id. There is a default chat, but the model can pass another one on any call: aahl/mcp-notify, mcp-telegram-bridge, kstonekuan/telegram-notification-mcp and adeshatole/telegram-notifier-mcp. A model that misreads an instruction, or reads an instruction planted in an email or a web page, can then message someone who isn't you.

The server reads the bot

A Telegram bot hands out its incoming messages through one method, getUpdates, and only to one reader at a time. A second reader gets 409 Conflict. Several of these servers call it anyway:

  • ParthJadhav/telegram-notify-mcp finds your chat id in getUpdates every time it starts. Telegram keeps pending updates for 24 hours, so a day after you last wrote to the bot, it can't find you.
  • adeshatole/telegram-notifier-mcp and mcp-telegram-bridge have a tool that reads incoming messages, so they are two-way servers rather than notifiers.
  • anthony-potts/claude-telegram-alerts calls it in its get_chat_id tool.
  • The channel plugin polls the bot continuously, because receiving messages is its job.

Any of these fights every other tool that uses the same bot.

Files from anywhere on the disk

ParthJadhav/telegram-notify-mcp and adeshatole/telegram-notifier-mcp send any local path the model names. A file-sending tool is a tool that can send your SSH keys.

Some get the basics right

Two of them have a fixed recipient and never read the bot from the server: zurdi15/telegram-notify and telegram-notification-mcp on npm. Each has one tool that sends text, with no file sending.

telegram-notify keeps those two properties and adds files limited to one folder, Markdown, long-message splitting, silent delivery, a token that never reaches the model, and a one-click install for Claude Desktop.


What telegram-notify does

It has two tools.

  • notify sends text to your chat. Plain text by default, or format: "markdown" for bold, italic, code, links and headings, converted to Telegram's HTML with everything else escaped. A message over 4096 characters, Telegram's limit, is split into several. silent: true delivers it without a sound.
  • notify_file sends a file of up to 50 MB, with an optional caption, from one folder you allow and from nowhere else.

One recipient, fixed in configuration

The chat id is set when you configure the server. No tool takes a chat id, so there is nothing for the model to change. A test checks that a chat_id slipped into a tool call is ignored.

That is also what makes it safe to skip the permission prompt. You can allow notify in ~/.claude/settings.json, and the worst a confused model can do is send you a message.

It never polls the bot

telegram-notify calls three Bot API methods: sendMessage, sendDocument and getMe. It never calls getUpdates, the method a bot uses to receive messages. A test checks that too.

Two things follow from that. The same bot can keep serving another tool that does poll it, such as the Claude Code Telegram channel plugin, without either one hitting a 409 Conflict. And nothing depends on Telegram's 24-hour window for pending updates, so nothing stops working a day after you last wrote to the bot.

Files from one folder only

notify_file is off until you name a folder in TELEGRAM_NOTIFY_FILES_DIR. Every path is resolved to its real location before the check, so .. and symbolic links can't reach outside that folder. Without the variable, every call is refused.

The token stays out of sight

The bot token is never logged, and it is removed from every error message before the message reaches the model or your terminal. setup writes it to ~/.telegram-notify/config.json with 600 permissions, so it doesn't have to sit in your MCP client's config.


What it looks like in use

These are requests you type into Claude as you would say them.

"Run the full test suite, and message me on Telegram when it's done, with the failures if there are any."
You leave the room. The message tells you whether to come back.

"Every morning at seven, go through the overnight mail and send me a short summary on Telegram."
A scheduled task with nobody watching the screen, and a mail server such as multi-mail beside it. The summary arrives on your phone before you open the laptop.

"When the export finishes, send me the PDF."
If the file is in the folder you allowed, it arrives in Telegram as a document, with a caption.

"If the deploy fails, tell me. If it succeeds, send it silently."
A failure makes a sound. A success waits quietly in the chat until you look.

The messages come from your own bot, to your own chat, from whichever client ran the task.


Setup

You need Node.js 20 or newer. Create a bot with @BotFather and press Start in a chat with it, because a bot can only message people who started it. Get your numeric chat id from a bot such as @userinfobot. An existing bot works too, even one another tool already polls.

Then save the token and the chat id once:

npx -y @yybd/telegram-notify-mcp setup

It asks for the token without showing it, checks it, writes the config file and sends a test message. Add --files-dir <folder> to allow notify_file. Then add the server to Claude Code, with no secret on the command line:

claude mcp add telegram-notify -s user -- npx -y @yybd/telegram-notify-mcp

For Claude Desktop there is a one-click extension: download the .mcpb file from the latest GitHub release and double-click it. Desktop asks for the token, which it stores as a secret, the chat id and, optionally, the folder for files.


What it deliberately doesn't do

  • Receive messages. What you type back in Telegram never reaches the model.
  • Ask you a question and wait for the answer. That needs a tool that reads the bot, which is the thing this one avoids.
  • Send to anyone else. There is one recipient, and it isn't a tool parameter.

If you want a two-way conversation with Claude over Telegram, use a channel plugin or a bridge. telegram-notify is for the other direction, and it can share the same bot with them.


telegram-notify is open source (MIT) and published on npm as @yybd/telegram-notify-mcp: github.com/yybd/telegram-notify-mcp. The README has its own comparison table, with the date it was checked.