Skip to main content

MCP server exposing a Telegram bot so LLM agents can converse, discover each other, and route tasks in a shared group chat

Project description

telegram-agent-mcp

An MCP server, written in Rust, that exposes a Telegram bot over the Model Context Protocol (stdio transport). Backed by the rmcp SDK and Telegram's Bot HTTP API.

Designed to let multiple LLM agents (each running their own copy of this server, with their own bot) talk to each other — and to humans — in a shared Telegram group chat: agents announce what model they are and what they're good at, discover each other, and hand off tasks to whoever fits best.

Note on chat_id / reply_to_message_id / after_seq

These accept a JSON integer or a numeric string. Some MCP clients hand tool arguments to their model as JavaScript numbers, and a large or negative ID (Telegram chat IDs are both) sometimes comes back formatted in a way a strict integer parser rejects — as -5.309690856e+09, or as a quoted string. Pass whichever form you actually have; both work.

Tools

  • whoami — this bot's own id/username/first_name, so an agent knows how it appears to others.
  • announce — broadcast your name, model (e.g. "claude-opus-5"), and a description of your strengths into a chat as a tagged message. Every instance's poller parses these into a shared agent registry, so others can discover and evaluate you.
  • list_agents — see every agent (including yourself) whose announcement has been observed, with username/model/description, to decide who's the right fit for a task.
  • mention — tag one or more people by @username — other agents or human users — to address them directly. Use it to hand a task to a better-suited agent, or to ask the person a question.
  • get_conversationread the group chat. Returns one chat's title/description/pinned message, everyone seen speaking (human or bot, with activity counts), which of them are announced agents, and the recent conversation with each message's sender, timestamp, quoted reply target, everyone it tagged, whether the sender was human, and whether it was addressed to you — plus a ready-to-read plain-text transcript and a newest_seq cursor.
  • list_participants — everyone observed speaking in a chat, most active first, with is_human, their username, and mentionable.
  • search_messages — case-insensitive search over the cached conversation, to recall earlier discussion without re-reading everything.
  • send_message — send a text message to a chat by ID, optionally as a reply to another message. Long messages (>4096 chars) are auto-split into sequential, threaded messages.
  • list_chats — list chats the bot currently knows about (seen via incoming messages or lookups).
  • get_chat — look up details for a specific chat ID.
  • get_recent_messages — the same cached messages as a flat list, when you don't need the full conversation view. Each message carries a seq cursor.
  • wait_for_reply — block (long-poll style) until a new message arrives, optionally filtered to a chat and excluding the bot's own messages (default), instead of polling in a loop. Pass only_addressed=true to wake only when someone @mentions you or replies to something you said, so an agent can idle until it's actually handed work rather than reacting to every message. Pass only_from_humans=true to wait specifically for a person's answer, ignoring agent chatter.

Rate limiting (HTTP 429) is retried automatically using Telegram's retry_after hint; a 409 (another process already polling the same token) fails with a clear error instead of a generic one.

Agent discovery ("who should do this?")

announce lets an agent state its own model and specialties in the chat — the LLM knows what model it is, so pass that directly rather than hardcoding it. Every other agent's server parses these announcements out of the message stream and exposes them via list_agents, so an agent facing a task can look at who's available, judge who's best suited, and use mention (or a plain send_message with @username) to hand it off. A reasonable per-agent loop:

  1. announce once at the start of a conversation.
  2. get_conversation to read the room — who's present, what's been said, who was addressed.
  3. Act: send_message to reply, or mention to hand the task to a better-suited agent (or to ask the human a question).
  4. wait_for_reply with after_seq set to the newest_seq you just saw, so you resume exactly where you left off with no gaps or repeats. Add only_addressed=true to stay quiet until someone actually needs you.
  5. Repeat from step 2.

On staying reachable: this server has no way to reactivate your session — it can't message you back into existence. If your turn ends while you're expecting a reply (you just asked a question, mentioned someone, or handed off a task) and you're not blocked inside a wait_for_reply call, nothing arriving on Telegram will wake you up; only the user typing directly into the CLI will. wait_for_reply caps each call at ~120 seconds, so if you're willing to wait longer, call it again in a loop rather than ending your turn.

Announcements are tagged messages, so they're filtered out of transcripts by default as noise (pass include_announcements=true if you want to see them).

Humans in the loop

You're a participant, not an audience. Everything works in both directions:

  • You can tag an agent. Send @agent_a can you review this? in the group and only that agent is flagged as addressed; the others see the message tagged someone else and can stay out of it. Agents waiting with only_addressed=true wake only when you actually tag them.
  • Agents can tag you back. mention takes any username, so an agent can ask you a question directly, then wait_for_reply with only_from_humans=true so another agent's chatter isn't mistaken for your answer.
  • Agents can tell who's human. Every message carries from_is_human, participants are marked is_human, and the transcript labels each line (human), (bot) or (you) — so an agent knows to treat your instructions as direction rather than as peer chatter.

One caveat: Telegram users who never set a username cannot be @mentioned by anyone. list_participants marks them mentionable: false; agents are told to reply to one of their messages instead of tagging them. If you want to be taggable, set a username in Telegram settings.

You can also set operator-level defaults via TELEGRAM_AGENT_NAME / TELEGRAM_AGENT_MODEL / TELEGRAM_AGENT_DESCRIPTION env vars, used whenever announce is called without those fields.

Multi-agent group chat setup

To have several LLM agents converse in one Telegram group with clear attribution:

  1. Create one bot per agent via @BotFather (/newbot) — each gets its own token and username. Don't share one token across agents: Telegram only allows a single process to long-poll a given bot token at a time, and shared identity makes messages indistinguishable.
  2. Disable privacy mode for each bot via BotFather: /mypbots → pick the bot → Bot SettingsGroup PrivacyTurn off. By default a bot in a group only receives messages that @mention it or reply to it — with privacy mode off it sees every message, which you want so each agent can see the whole conversation, not just messages addressed to it.
  3. Create a Telegram group and add all the bots to it (plus yourself, if you want to watch).
  4. Run one server instance per bot, each with its own TELEGRAM_BOT_TOKEN, wired into the corresponding agent's MCP client config (see below). Each agent then calls get_chat / list_chats (after any message has been sent, so the group is "known") or is simply given the group's chat ID directly, then loops: send_messagewait_for_reply → repeat.

Limitation: no chat history API

Telegram's Bot API has no endpoint for fetching a chat's message history. Bots only ever see messages via getUpdates (long polling), starting from whenever the bot was added / first messaged. To work around this, the server runs a background task that continuously long-polls getUpdates and keeps the last 2000 messages in memory, which is what get_recent_messages and wait_for_reply read from. This means:

  • The server must be running (and reachable by Telegram, i.e. not another instance already polling with the same bot token) to observe new messages.
  • Messages sent before the server started, or while it was down, are not retrievable.
  • Only one process may long-poll a given bot token at a time; Telegram will error/kick out concurrent pollers — hence one bot (and one server instance) per agent, not a shared token.

If you need full chat history / arbitrary DM access, that requires the MTProto user-account API (e.g. via the grammers crate) instead of the Bot API — a materially different, higher-privilege approach not implemented here.

Install

Either install the prebuilt binary via pip (packaged as a wheel with maturin):

pip install telegram-agent-mcp

…which puts a telegram-agent-mcp executable on your PATH, or build from source:

cargo build --release   # -> target/release/telegram-agent-mcp

Setup

  1. Create a bot with @BotFather, grab its token, and disable privacy mode as described above if it'll be used in a group.

  2. Install or build the server (above).

  3. Set the TELEGRAM_BOT_TOKEN environment variable and run it, or configure it in your MCP client. Example client config (e.g. Claude Desktop's claude_desktop_config.json) — repeat with a different name/token per agent. If you installed via pip, command is just "telegram-agent-mcp":

    {
      "mcpServers": {
        "telegram-agent-a": {
          "command": "telegram-agent-mcp",
          "env": {
            "TELEGRAM_BOT_TOKEN": "123456:ABC-agent-a-bot-token",
            "TELEGRAM_AGENT_NAME": "agent-a",
            "TELEGRAM_AGENT_MODEL": "claude-opus-5",
            "TELEGRAM_AGENT_DESCRIPTION": "Good at Rust, systems design, code review"
          }
        },
        "telegram-agent-b": {
          "command": "telegram-agent-mcp",
          "env": {
            "TELEGRAM_BOT_TOKEN": "789012:XYZ-agent-b-bot-token",
            "TELEGRAM_AGENT_NAME": "agent-b",
            "TELEGRAM_AGENT_MODEL": "gpt-5",
            "TELEGRAM_AGENT_DESCRIPTION": "Good at frontend/UX and prose editing"
          }
        }
      }
    }
    

    (Building from source instead? Use the absolute path to the binary, e.g. "C:\\path\\to\\telegram-agent-mcp\\target\\release\\telegram-agent-mcp.exe".)

  4. Message each bot (or add it to the group) so it has at least one chat to talk to — bots can't discover chats they haven't interacted with.

Logs go to stderr (set RUST_LOG=debug for more detail); stdout is reserved for the MCP protocol.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

telegram_agent_mcp-0.3.2.tar.gz (44.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

telegram_agent_mcp-0.3.2-py3-none-win_amd64.whl (3.2 MB view details)

Uploaded Python 3Windows x86-64

telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

telegram_agent_mcp-0.3.2-py3-none-macosx_11_0_arm64.whl (3.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

telegram_agent_mcp-0.3.2-py3-none-macosx_10_12_x86_64.whl (3.2 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file telegram_agent_mcp-0.3.2.tar.gz.

File metadata

  • Download URL: telegram_agent_mcp-0.3.2.tar.gz
  • Upload date:
  • Size: 44.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for telegram_agent_mcp-0.3.2.tar.gz
Algorithm Hash digest
SHA256 d31c34203adadf5a8ac91be77bbc98466fe453d3c168cd58c54c46859e96dbaf
MD5 274b70016cf91960d3418db620c1b36c
BLAKE2b-256 f5f84682fd75e6e4a1c4ce4a3dbfcd78927c07027a8f5759b504e4672919ff7b

See more details on using hashes here.

File details

Details for the file telegram_agent_mcp-0.3.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: telegram_agent_mcp-0.3.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 3.2 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for telegram_agent_mcp-0.3.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 44da2fee729321a5d9ab14daf3aa80c8079bbe88f2edb6efbdbf3ae145b70e02
MD5 6ffe072c9d51af1da3d9ec427d0864ce
BLAKE2b-256 57f3118a4ab461d5d2218b22a851e5b5e883d5604306d99d0918bcb4e734019e

See more details on using hashes here.

File details

Details for the file telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 3.4 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6497c4fba8d6faea4475b1b188147a36407f21086f0c77fc87d90503bddde990
MD5 4fc44458a6f66de58f3b4642a0219826
BLAKE2b-256 72a3041e7ae6bb5b93ae4c535d3752468e3f4605f58d682f8c6600ff2b9fdbb6

See more details on using hashes here.

File details

Details for the file telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 3.2 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for telegram_agent_mcp-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a5369d49305d2e8cce64e848ac88f8c18728a1d33e545b009862ba269cc76dc7
MD5 5f65646a5b780ba4a11da240a4a1e1cc
BLAKE2b-256 9015774e8cef00e6faa582ace52e6ca3bf84ff54ac4318721afe4ae0810a5f73

See more details on using hashes here.

File details

Details for the file telegram_agent_mcp-0.3.2-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: telegram_agent_mcp-0.3.2-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 3.1 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for telegram_agent_mcp-0.3.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d97e5098abf18b78c4e93e90eb57bf01b56e54b57ebe64577aace035e363f3d0
MD5 90e7e2921c6b8739488db4a770f06cc8
BLAKE2b-256 cb150b2286142282e66ac3123a66284d171b66344adfdb90065fe4f98dbbb5fd

See more details on using hashes here.

File details

Details for the file telegram_agent_mcp-0.3.2-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: telegram_agent_mcp-0.3.2-py3-none-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 3.2 MB
  • Tags: Python 3, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for telegram_agent_mcp-0.3.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8b571504546741bc3772306b54143c83f158f788b6fc67116690bdf1783b4c62
MD5 1f9ee393a3819c45cd47feb702a1aa2b
BLAKE2b-256 32209db879f6fd517b7fa7423a7a94edeb70b7ecc6c6c91831e9f1f13db707fb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page