Skip to content
Conduit

skill

telegram-mcp-cli

Telegram MCP server and CLI for Claude Code, Codex and AI agents. 74 tools for chats, history, search, sending, media, contacts, groups, admin, topics, reactions, polls, folders and privacy, on your r

thenavidm/telegram-mcp-clicommunitylistedunreviewednot running here yet

Set up

Skills are installed by placing their folder where your agent loads skills.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below; one-click install arrives with accounts.

README

synced Oct 14, 2026

Telegram MCP Server & CLI

npm License YouTube X LinkedIn

Telegram MCP server and CLI for Claude Code, Codex and AI agents. 74 tools for chats, history, search, sending, media, contacts, groups, admin, topics, reactions, polls, folders and privacy, on your real account.

One install gives you both surfaces, the same tools under the same names, covering what the app does rather than what a bot is allowed to see.

Most Telegram integrations are bots, and a bot only ever receives messages sent to that bot. Your own conversations are invisible to it. This signs in as you over MTProto, so an agent can read the group you were actually talking in and answer in it.

Built and maintained by Navid Moazzez.

Two ways to use it

Command line

telegram-cli in your terminal, for scripting, cron, pipes, or just asking a quick question without opening anything:

telegram-cli                                       # every command, one line each
telegram-cli list-chats --unread-only --limit 10   # what needs an answer
telegram-cli history --peer @sarah --limit 20      # one conversation
telegram-cli search --query invoice                # across every chat
telegram-cli send --peer me --text "note to self"  # Saved Messages
telegram-cli list-chats --json | jq -r '.items[].name'
telegram-cli which search my messages             # find the command for a task
telegram-cli <command> --help                      # what any command takes

--confirm is the shell spelling of the confirmation that deleting requires. --json gives JSON, --compact puts it on one line, --agent turns on both with no prompts and no color, and errors are JSON on stderr whichever you pick. Built on Slipway, which turns one definition of each tool into the MCP server and the CLI.

Reads return real objects rather than rendered text, so --json hands you fields you can filter, and --fields id,text cuts the response before it is ever printed.

MCP server, for AI agents

telegram-mcp is what Claude Code, Claude Desktop, Cursor and the rest launch. You never run it by hand:

claude mcp add telegram \
  -e TELEGRAM_API_ID=1234567 \
  -e TELEGRAM_API_HASH=your_hash \
  -e TELEGRAM_SESSION=your_session_string \
  -- npx -y @thenavidm/telegram-mcp-cli

Then just ask: "what did I miss in the group chats while I was asleep?"

Every other client is in section 4.

Which one

Where you areWhat you can reach
An agent that can run shell commands, like Claude Code or CursorBoth. The CLI is the cheaper one: nothing until it runs
claude.ai, the Claude Desktop chat tab, or a phoneThe server only. There is no shell to run a command in
A terminal, a script, cron or CIThe CLI only. There is no MCP client in a shell

They are the same program reading the same tool definitions, so anything one can do, the other can.

Features

74 tools. Every one is both a shell command and an MCP tool, under the same name; the command is the tool name with dashes.

These 13 are what the server loads by default, because they cover daily use:

CapabilityCLI commandMCP tool
Who am Itelegram-cli whoamiwhoami
Resolve a handle or idtelegram-cli resolveresolve
List chatstelegram-cli list-chatslist_chats
One chat's detailstelegram-cli get-chatget_chat
Read historytelegram-cli historyhistory
Search messagestelegram-cli searchsearch
Send a messagetelegram-cli sendsend
Edit a messagetelegram-cli editedit
Delete messagestelegram-cli deletedelete
Forward messagestelegram-cli forwardforward
Mark a chat readtelegram-cli mark-readmark_read
Download mediatelegram-cli download-mediadownload_media
Send a filetelegram-cli send-filesend_file
Check your setuptelegram-cli doctornot a tool
Sign in oncetelegram-mcp loginnot a tool

The other 61 cover contacts and blocking, groups and admin, reactions, pins, polls and scheduling, archiving, muting and drafts, chat folders, stickers, albums and voice notes, forum topics, inline buttons, your own profile and your privacy settings. They are always there in the CLI. TELEGRAM_TOOLS=full loads them into the server as well, and section 6 says what that costs.

All 74 are in section 7.

Contents

Section
1What you can ask itReal prompts, not features
2Quick installNode 20 and one command
3Set up your accountapi_id, api_hash, session string
4Connect your clientEvery client, copy and paste
5Output and exit codesWhat scripts branch on
6Which surface, and what each costsMeasured in Claude Code, and how to spend less
7ToolsAll 74, grouped, with the default 13 in full
8Writing safelyWhy deleting asks twice
9Reading messagesThe output format, and why
10How it worksArchitecture
11Your dataWhat is stored and where
12RisksRead this before you install
13TroubleshootingWhen something breaks
14FAQIncluding what an MCP server is

1. What you can ask it

Real prompts, not a feature list. Each of these is one or two tool calls.

What did I miss in the group chats while I was asleep?

Find the last thing Sarah sent me about the invoice and reply that I will look at it tonight.

Search every chat for the wifi password someone sent me last year.

Which conversations have unread messages, and which actually need an answer rather than an emoji?

Save the PDF that Tom sent me this morning to my desktop.

Send myself a note in Saved Messages with these three links.

The reading tools are the ones worth having on. Searching a decade of chat for a thing you half remember is what this is genuinely better at than scrolling.

2. Quick install ⚡

Node 20 or newer. Nothing else.

npx -y @thenavidm/telegram-mcp-cli@latest --version

That is the whole install. npx fetches it on demand, so there is nothing to update later. Prefer it on your $PATH?

npm install -g @thenavidm/telegram-mcp-cli

Installing needs no account. Only signing in does, which is the next section.

Before you start

You needCheck withIf missing
Node 20 or newernode -vnodejs.org
A Telegram accountOpen the appAny account works, no Premium needed
A phone you can receive a code onThe code arrives in the Telegram app, not by SMS

[!IMPORTANT] You need an api_id from my.telegram.org, not a bot token from BotFather. A bot cannot read your chats, which is the entire point of this. Section 3 walks through it.

3. Set up your account 🔑

Three values. The first two identify the application, the third is you.

The api_id and api_hash

Go to my.telegram.org, sign in with your phone number, open API development tools, and fill in the short form. Any app name and a short description are fine. You get an api_id and an api_hash.

These identify the software, not you, and they are not especially secret. They cannot read anything on their own.

The session string

export TELEGRAM_API_ID=1234567
export TELEGRAM_API_HASH=your_hash_here
npx -y @thenavidm/telegram-mcp-cli login

It asks for your phone number, the code Telegram sends you, and your two-step password if you have one. It prints the session string on stdout and everything else on stderr, so telegram-mcp login > session.txt captures only the string.

export TELEGRAM_SESSION='the string it printed'

What that string is

Full access to your account, and it does not expire. It is not a token scoped to some permissions, it is your login. Anyone holding it can read every message you have and send as you.

Keep it out of repos. Put it in your MCP client's config, which is a file only you can read, rather than in a shell profile that gets committed by accident.

Revoking

Telegram, Settings → Devices. The session shows up as a logged-in device and terminating it invalidates the string immediately. Do that if it leaks, or whenever you stop using this, then run login again if you come back.

4. Connect your client 🔌

npm install -g @thenavidm/telegram-mcp-cli

Or run it without installing anything:

npx -y @thenavidm/telegram-mcp-cli

Node 20 or newer.

Claude Code

claude mcp add telegram \
  -e TELEGRAM_API_ID=1234567 \
  -e TELEGRAM_API_HASH=your_hash \
  -e TELEGRAM_SESSION=your_session_string \
  -- npx -y @thenavidm/telegram-mcp-cli

Claude Desktop

The short way: download the .mcpb extension from the latest release and double-click it. It carries its own dependencies, so there is no config file to edit and nothing to install first. It asks for your API ID, API hash and session string in a form, and stores them as sensitive fields rather than plain text in a config file.

The long way, if you would rather edit the config yourself:

Settings → Developer → Edit Config, then add:

{
  "mcpServers": {
    "telegram": {
      "command": "npx",
      "args": ["-y", "@thenavidm/telegram-mcp-cli"],
      "env": {
        "TELEGRAM_API_ID": "1234567",
        "TELEGRAM_API_HASH": "your_hash",
        "TELEGRAM_SESSION": "your_session_string"
      }
    }
  }
}

Restart Claude Desktop afterwards.

Cursor

Settings → MCP → Add new global MCP server, using the same JSON as Claude Desktop.

Windsurf

Settings → Cascade → Model Context Protocol, same JSON shape.

VS Code

code --add-mcp '{"name":"telegram","command":"npx","args":["-y","@thenavidm/telegram-mcp-cli"]}'

Then set the three environment variables in your shell profile, or add an env block to the entry.

Anything else

Any client that speaks MCP over stdio. The command is npx -y @thenavidm/telegram-mcp-cli with the three variables in the environment.

Docker

docker build -t telegram-mcp .
docker run --rm -i \
  -e TELEGRAM_API_ID -e TELEGRAM_API_HASH -e TELEGRAM_SESSION \
  telegram-mcp

Check it worked

telegram-cli doctor

It names any missing variable, says where to get it, and signs in to confirm the session actually works rather than only that it is present.

5. Output and exit codes

What gets printed

Reads return objects. A list comes back as {count, next_cursor, items}, so paging is a field rather than something you infer.

telegram-cli list-chats --limit 3 --fields name,unread
{
  "count": 3,
  "items": [
    { "name": "Sarah", "unread": 2 },
    { "name": "Design", "unread": 14 },
    { "name": "Mum", "unread": 1 }
  ]
}

Errors are JSON on stderr, with the code and often a hint:

{
  "error": "Telegram rate limited this account. Wait 42s.",
  "code": "RATE_LIMIT",
  "retryAfter": 42,
  "hint": "Flood waits are per method and get longer if you keep calling. Wait it out."
}

Exit codes

A script branches on the number.

CodeMeans
0Fine
1Something unexpected went wrong
2Bad usage, or a write refused for want of --confirm
3No such chat, user or message
4The session is invalid or expired
5Telegram rejected the call, or forbade it
7Rate limited, retry_after_seconds says how long
10Nothing configured yet

6. Which surface, and what each costs

Both surfaces are the same program with the same 13 tools. The difference is when the model pays for them. Measured in Claude Code:

MCP serverCLI
Every message, with every tool loaded2,400 tokensnothing
Every message, Claude Code's default130 tokensnothing
When Telegram comes upnothing more, or the tools it picks2,300 tokens for SKILL.md, once
20 messages with Telegram in 1, every tool loaded48,000 tokens2,300 tokens

Claude Code's tool search is on by default: it sends only the tool names and the server instructions, and loads a tool's full definition when the model reaches for it. An app that loads every tool up front pays the first line on every message, whether Telegram comes up or not. With the skill added, Claude Code also lists its one-line description, about 130 tokens.

To spend less, turn the server off when you are not using it, which in Claude Code is the /mcp panel. TELEGRAM_READ_ONLY=1 takes the six write tools off the list, leaving seven. These numbers are the default profile's 13 tools; TELEGRAM_TOOLS=full lists all 74 and costs more. Or install the CLI and add the server on the days it earns its place.

Measured on 2026-10-05 against 0.4.4, with Claude Code 2.1.286 on Claude Opus 5.5 (one short prompt with and without the server connected, once with ENABLE_TOOL_SEARCH=false and once with the default, the difference read from the API's own usage figures; SKILL.md the same way) and Codex 0.159.3 on gpt-6.1-sol, with a placeholder session that cannot connect:

Cost0.4.40.5.0
Claude Code, the 13 daily tools loaded, every message2,8202,380
Claude Code, all 74 loaded (TELEGRAM_TOOLS=full), every message14,43811,868
Claude Code's default, tool search, every message (median of nine runs)123124
SKILL.md, read once2,5812,293
Codex over the CLI, one task, median of five72,80053,221
Codex over MCP, the same task, median of five35,38035,372

The task was "find the command that searches message text across every chat, and the flags it requires". Other apps and models count tokens a little differently, and tool-list characters divided by four are not API usage.

7. Tools

74 tools. Each is also a shell command under the same name with dashes, so list_chats runs as telegram-cli list-chats.

The 13 in the default set are documented here with their arguments, because they are what the server loads unless you tell it otherwise. The other 61 are listed by name only. Arguments move, and a hand-typed list of 74 signatures goes stale the day a tool is added, so ask the binary instead:

telegram-cli                    # all 74, one line each, writes marked
telegram-cli <command> --help   # its arguments, derived from the schema
telegram-cli schema <command>   # the JSON Schema an MCP client receives

Two things hold across all of them. Every list tool takes fields for projection and a limit that is clamped rather than trusted. Writes are marked *, and the irreversible ones are marked ! and refuse to run without confirmation. Those are the same marks the bare command prints.

peer is the same everywhere: a @username, a numeric id, or me for Saved Messages.

The default 13

What TELEGRAM_TOOLS=core advertises, which is the default: about 2,400 tokens a message in an app that loads every tool, measured in Claude Code.

Account

ToolArgumentsWhat it does
whoaminoneWhich account this session is signed in as
resolvepeerA @username, phone or id to something you can act on

Chats

ToolArgumentsWhat it does
list_chatslimit, unread_only, kind, fieldsRecent conversations, newest first
get_chatpeerOne chat: name, kind, username, member count

Reading

ToolArgumentsWhat it does
historypeer, limit, before_id, full, fieldsMessages from one chat, newest first
searchquery, peer, limit, fieldsSearch text in one chat or everywhere
download_mediapeer, message_id, dirSave a photo, video, document or voice note

Writing

ToolArgumentsWhat it does
send *peer, text, reply_to, silentSend a message. Posts as you
send_file *peer, path, captionSend a local file
edit *peer, message_id, textChange a message you sent
forward *from, to, message_idsForward between chats
mark_read *peerClear a chat's unread count
delete !peer, message_ids, revoke, confirmDelete messages. Cannot be undone

The other 61

Always reachable from the CLI, where an unused command costs nothing. TELEGRAM_TOOLS=full loads them into the server too, at about 11,900 tokens a message in an app that loads every tool. See section 6 before you do.

Contacts and people

ToolWhat it does
list_contactsList contacts
search_contactsSearch contacts and users
get_userGet a user's profile
list_blockedList blocked users
add_contact *Add a contact
block *Block someone
unblock *Unblock someone
delete_contact !Remove a contact

Groups, channels and admin

ToolWhat it does
get_participantsList members of a chat
get_full_chatFull details of a chat
create_group *Create a group or channel
join_chat *Join a chat
invite_to_chat *Add people to a chat
invite_link *Get or create an invite link
set_admin *Promote or demote an admin
edit_chat *Change a chat's title or description
leave_chat !Leave a chat
set_banned !Ban or unban someone

Reactions, pins, polls and scheduling

ToolWhat it does
get_pinnedList pinned messages
get_reactionsWho reacted to a message
get_scheduledList scheduled messages
message_linkGet a link to a message
pin *Pin or unpin a message
react *React to a message
create_poll *Send a poll
delete_scheduled !Cancel scheduled messages

Organizing your chat list

ToolWhat it does
common_chatsChats you share with someone
search_publicSearch public chats
list_draftsList unsent drafts
archive *Archive or unarchive a chat
mute *Mute or unmute a chat
save_draft *Save or clear a draft
delete_history !Delete a chat's history

Chat folders

ToolWhat it does
list_foldersList chat folders
get_folderOne folder's contents
create_folder *Create a chat folder
update_folder *Rename a folder or change what is in it
reorder_folders *Reorder chat folders
delete_folder !Delete a chat folder

More media

ToolWhat it does
list_sticker_setsList your sticker sets
search_gifsSearch GIFs
media_infoDescribe a message's media
transcribe_voiceTranscribe a voice message
send_sticker *Send a sticker or GIF
send_album *Send several photos as one album
send_contact *Share a contact card
send_voice *Send a voice note

Forum topics and inline buttons

ToolWhat it does
list_topicsList forum topics
list_buttonsList a message's inline buttons
create_topic *Create a forum topic
edit_topic *Rename, close or reopen a topic
enable_topics *Turn forum topics on or off
press_button *Press an inline button

Your profile and privacy

ToolWhat it does
list_profile_photosList profile photos
get_privacyRead your privacy settings
export_contactsExport every contact
update_profile *Update your profile
set_profile_photo *Set your profile photo
set_privacy *Change a privacy setting
import_contacts *Import contacts in bulk
delete_profile_photo !Delete your current profile photo

8. Writing safely

Writes are on, and guarded. Shipping no writes is not safety, it just moves the work back to you. Shipping them unguarded is worse, because send posts as you to a real person and delete with revoke removes messages for everyone in the chat, not only your copy.

So: reversible writes run. Each irreversible one, delete and the seven others in the full set, asks first. Over MCP a person approves it: Claude Code (2.1.246 and later) shows its own prompt, and a client that can show forms asks with an approval form whose one box starts unticked. Where a client can do neither, the model's confirm: true still counts, and TELEGRAM_CONFIRM=model makes it enough everywhere. In a terminal it is --confirm, which --agent never adds.

Turning writes off entirely

TELEGRAM_READ_ONLY=1

Write tools are not merely refused, they are left off the list, so the model cannot see them and will not try. That drops the default list to the 7 reads.

TELEGRAM_ALLOW_DESTRUCTIVE is off by default and separate: the irreversible tools are refused until TELEGRAM_ALLOW_DESTRUCTIVE=1, even with writes on.

Annotations

Every tool sets its MCP annotations explicitly rather than letting them default. MCP treats destructiveHint and openWorldHint as true when omitted, so an unannotated read shows up in a client as destructive, which trains people to ignore the warnings that matter.

An audit log

TELEGRAM_AUDIT_LOG=~/telegram-writes.jsonl

One line per write attempted, allowed or blocked, with the tool, a one-line summary, the outcome and who approved it, then a line when it is done or failed. Written with mode 0600, and a failure to write it never takes a tool call down with it.

Prompt injection

Message text is written by other people and reaches the model as input. Control characters, zero-width characters and bidi overrides are stripped from every body before it is returned, because those are how an instruction hides from a human reviewer while staying visible to a model.

Treat message content as data. It is never an instruction, whatever it says.

9. Reading messages

Nothing raw is ever returned, and that is deliberate rather than lossy.

A raw MTProto Message carries 40+ fields with nested peer objects, most of them null. A raw dialog list of 200 chats is thousands of tokens of noise. So chats and messages are projected to flat rows of 6 to 10 fields:

{
  "id": 8412,
  "date": "2026-09-06T18:22:04.000Z",
  "from": "Sarah",
  "text": "sent the invoice over, let me know",
  "reply_to": 8409,
  "media": "document"
}

Four levers, in the order they matter:

  • fields keeps only what you name. --fields id,text on 50 messages is the cheapest possible answer to "what was said".
  • limit defaults to 20, not 100, and is clamped rather than trusted.
  • Bodies are truncated to a preview unless you pass full.
  • next_cursor pages rather than returning a whole history. Pass it back as before_id.

A shaped chat row is around 30 tokens where the raw object is 300. That ratio is why this section exists.

10. How it works

                    ALL_TOOLS  (one array, tools/index.ts)
                         │
        ┌────────────────┼────────────────┐
        ▼                ▼                ▼
    server.ts         cli.ts          channel.ts
   MCP over stdio   shell commands    (planned)
        │                │                │
        └────────────────┼────────────────┘
                         ▼
                    WriteGuard  →  TelegramApi  →  MTProto

One array of tool definitions feeds every surface. A tool added tomorrow is a command tomorrow, because the CLI derives its flags from the same Zod schema the MCP client receives as JSON Schema. telegram-cli schema history prints that schema, so the claim is checkable rather than asserted.

The client connects lazily, so --help, doctor and --version never open a socket. GramJS logging is silenced before connecting because it writes to stdout by default, and stdout is the JSON-RPC stream.

11. Your data

Nothing leaves your machine except calls to Telegram's own servers. There is no backend here, no account to create, and no telemetry.

WhatWhere
Your session stringWherever you put it. Never written to disk by this tool
The audit logOnly if you set TELEGRAM_AUDIT_LOG, at that path, mode 0600
Downloaded mediaWhere you asked for it, default the working directory
Message contentHeld in memory for the length of one call

telegram-mcp login prints the session on stdout and nothing else, precisely so that you decide where it lands rather than the tool choosing for you.

12. Risks

Worth reading before you install, not after.

The session string is your account. Not a scoped token. If it leaks, whoever has it can read everything and send as you, until you revoke it under Settings → Devices.

An agent with this connected can message real people. That is the point, and it is also the risk. TELEGRAM_READ_ONLY=1 exists for when you are pointing something you do not fully trust at it.

Message text is untrusted input. Sanitising helps and is not a guarantee. Anything you would not want a model to act on unquestioned should not be in a chat it can read.

Telegram rate limits hard. FLOOD_WAIT on a new session is normal, the waits get longer if you keep calling, and an automated retry loop can get an account limited for hours. The error carries retryAfter so a caller can wait the right amount instead of guessing.

Automating a user account is not what a bot account is. Telegram's terms allow user clients, but bulk or spammy behaviour through one is what gets accounts limited. This is built for reading your own chats and answering them.

13. Troubleshooting

SymptomCause and fix
not_configured, exit 10One of the three variables is missing. telegram-cli doctor names it
auth, exit 4Session revoked or expired. Run login again
rate_limited, exit 7Flood wait. retry_after_seconds says how long. Wait, do not retry
not_found on a peerUse resolve or list_chats to get a valid id first
The server starts then exitsUsually a bad session string. doctor connects and will say so
Garbled JSON-RPC in a clientSomething is writing to stdout. Open an issue with the client name
delete refusesBy design. TELEGRAM_ALLOW_DESTRUCTIVE=1, then a person's approval or --confirm

Environment variables

Credentials

VariableWhat it is
TELEGRAM_API_IDFrom my.telegram.org, API development tools
TELEGRAM_API_HASHIssued with the api_id, same page
TELEGRAM_SESSIONFrom telegram-mcp login. Full account access

Safety

VariableWhat it does
TELEGRAM_READ_ONLY=1Leaves every write off the list, so the model cannot see one
TELEGRAM_ALLOW_DESTRUCTIVE=1Permits the irreversible tools at all. Off by default
TELEGRAM_CONFIRM=modelLets confirm: true alone approve an irreversible call over MCP, for an agent with no person to ask
TELEGRAM_AUDIT_LOGAppend-only record of every write attempted, allowed or blocked

Tuning

VariableWhat it does
TELEGRAM_TOOLScore (default), full, or read. Decides context cost
TELEGRAM_TOOLSETSThe same choice by module, comma separated: core, account, chats, messages, media, contacts, groups, engage, organize, profile, topics, stickers, folders, or all. Unlike TELEGRAM_TOOLS, it narrows the CLI too
TELEGRAM_SURFACEsearch lists three tools that find, describe and run the rest
TELEGRAM_TIMEOUTPer-call deadline in seconds, default 30
TELEGRAM_TOOL_TIMEOUT_MSGive up on any tool after this long
TELEGRAM_DEBUG1 prints debug lines on stderr

Several accounts

VariableWhat it does
TELEGRAM_SESSION_<LABEL>A second account, for example TELEGRAM_SESSION_WORK. Read and kept as a secret, but no tool chooses between accounts yet

0.4's docs said every account-scoped tool took an optional account; none did. Run one server per account until one does.

Pushing messages into a session

VariableWhat it does
TELEGRAM_CHANNEL_ALLOWAllowlist path for --channel, default ~/.telegram-mcp/channel-allow.json
telegram-mcp --channel

Runs as a Claude Code channel, pushing real Telegram messages into a session that is already open. It declares claude/channel under the experimental capabilities, where Claude Code looks for it, and tells the model to reply with the reply tool and the chat_id from the event. A channel you build yourself is not on Claude Code's allowlist, so start Claude Code with --dangerously-load-development-channels server:<the name in your MCP config>. The official Telegram channel is a bot, so it only sees messages sent to that bot. This one is backed by your account, so an event can come from any chat you are actually in.

Nothing is forwarded until you allow a chat, which the allow_chat tool does. That default matters: without it every message in every group you are in becomes model input, which is both expensive and a prompt-injection surface.

Each allowed chat can carry a persona name, and it arrives on the event as persona, so one session can answer as a different assistant depending on which chat the message came from.

Running it always on

VariableWhat it does
TELEGRAM_HTTP_PORTPort for --http, default 8787
TELEGRAM_HTTP_HOSTInterface for --http, default 127.0.0.1
TELEGRAM_HTTP_TOKENBearer token required on every HTTP request
TELEGRAM_HTTP_ALLOWED_ORIGINSComma-separated browser origins allowed to call --http; a page from any other site is refused
telegram-mcp --http --port=8787

Binds to loopback, because a process holding a session string should not be reachable from the network, and refuses to bind anywhere else without TELEGRAM_HTTP_TOKEN, which would hand your account to anyone who can route to the port.

Running it 24/7

For claude.ai, your phone, or the channel, the server has to be reachable when the call happens. deploy/install.sh sets that up on a Linux box:

sudo bash deploy/install.sh
sudo nano /etc/telegram-mcp.env
sudo systemctl start telegram-mcp

Own user, own directory, port 8788 bound to loopback only, systemd unit that restarts on failure and starts on boot. Put your reverse proxy in front of 127.0.0.1:8788.

telegram-mcp login runs on your laptop, not the server: it asks for a phone code interactively. Paste the session string into the env file.

Worth knowing: a Telegram session does not expire and needs no live connection. The process can be down for a month and reconnect with the same string. A server buys reachability, not session survival, so if you only use the CLI you do not need one at all.

Versions

See CHANGELOG.md.

14. FAQ ❓

An MCP server is a standard way to give an AI assistant real access to a tool, so it can act rather than guess. You install it once, your assistant gains the tools, and it works in Claude, Cursor and anything else that speaks the protocol. You never call the tools yourself, you just ask in plain language.

telegram-cli is the same program as the MCP server, run as commands. AI agents that run commands, like Claude Code, Codex and OpenCode, use it on their own, and you can type the same commands in a terminal, a script or a cron job. Every tool is a command with dashes, so list_chats runs as telegram-cli list-chats.

Use the MCP server in an app with no terminal, like Claude Desktop's chat. Use the CLI anywhere commands run: an agent like Claude Code, Codex or OpenCode, a script or a cron job. The MCP server's tools take up context on every message, and the CLI costs nothing until it runs.

A bot is a separate account, and it only receives messages that people send to that bot. It cannot read your conversations, your groups, or anything that happened before it existed.

This signs in as you, over the same protocol the official apps use. Every chat you are in, all of the history, and search across it.

Telegram publishes the client API at my.telegram.org specifically so people can build clients, and third-party clients are common and long-standing.

What gets accounts limited is behaviour, not the API: bulk messaging, spam, mass adding people. Reading your own chats and answering them is what this is for. Rate limits are real and the tool surfaces them rather than retrying into them.

Telegram authenticates a user by sending a code to an existing session, so there is a one-time interactive login. What comes out is a session string, which is how the tool signs in afterwards without asking again.

It is full access to the account and does not expire. Treat it exactly as you would your password, and revoke it under Settings → Devices when you are done.

No. BotFather issues bot tokens, and a bot is the thing this deliberately is not. You need an api_id and api_hash from my.telegram.org, which is a different page and a different kind of credential.

Nothing leaves your machine except calls to Telegram. There is no backend here, no account to create and no telemetry. Your session sits in your client's config file and the audit log, if you enable one, sits where you pointed it.

It only acts when a model calls a tool, and a model only calls one in response to something you said. The risk is not spontaneity, it is misreading: a request to "reply to everyone" doing more than you meant.

That is what the guard is for. delete refuses without explicit confirmation, TELEGRAM_ALLOW_DESTRUCTIVE keeps it off entirely by default, and TELEGRAM_READ_ONLY=1 removes every write tool from the list.

Because an app that loads every tool up front sends every definition with every message, whether you use it or not. All 74 here measure about 14,400 tokens in Claude Code, against 2,800 for the 13, and more tools make tool selection worse: a model picks correctly from 13 far more reliably than from 80.

The 13 cover what actually gets used. The long tail belongs in the CLI, where it costs nothing until you type it.

Not yet. One session per server instance today. You can run a second instance with a different session string under a different name in your client config, which works but is clumsier than it should be.

Reading and sending work the same either way. Premium-only features like longer messages and larger uploads follow whatever your account already has, because this is your account rather than a bot with its own limits.

Questions

Run into a problem or have a question? Open an issue and I will help.

About the author

Navid Moazzez is a leading AI business strategist, and the host of the AI Creator Summit, watched by 100,000+ creators. He helps creators and founders master AI and build their own AI Operating System (AI OS) to automate their business and life. He creates useful free tools, MCP servers and CLIs that creators and founders can use in their own workflows.

Links

If this is useful, star the repo and come say hi on X.

Dependencies

LibraryLicenseWhat it does
SlipwayApache-2.0The MCP server and the CLI from one definition of each tool
MCP TypeScript SDKApache-2.0The MCP protocol and its transports, through Slipway
GramJSMITThe MTProto client, published as telegram

License

MIT. Free to use, modify, and share.

Not affiliated with, endorsed by, or connected to Telegram Messenger Inc.


© 2026 Navid Media. Made with ❤️ by Navid Moazzez.

↑↓ navigate openesc close