telegram-call-mcp
The server lets AI agents send urgent alerts to a specific Telegram user via real voice calls with TTS, and also send plain text messages.
Voice calls (
make_call): Synthesizes a message using OpenRouter TTS, calls the target user, plays the message on answer (repeatable 1–10 times with pauses), and returns a structured outcome (answered, no_answer, busy, declined, error) to let the agent know if it was heard.Pre-call text: Automatically sends a detailed text message before ringing to include context (links, error output, etc.) that would be unclear or too long for voice.
Text-only messages (
send_message): Deliver non-urgent updates without initiating a call.Message sanitization: Spoken messages are cleaned (markdown, URLs, emojis, long identifiers stripped) and length-limited to keep TTS clear.
TTS customization: Supports any OpenRouter TTS model and voice, configurable via environment variables.
Diagnostics: A
check/doctorcommand validates configuration, ffmpeg, Telegram session, target reachability, and TTS key—without making a call.Security: Restricted to a fixed target user, uses a dedicated Telegram account, session file protection, and supports proxy/MTProto/TUN mode for voice calls.
Deployment: Works as an MCP server, compatible with Claude Code, Claude Desktop, and other MCP clients.
Places real Telegram voice calls to a configured user, synthesizes the provided message via TTS, plays it aloud (optionally repeated), and returns the call status (answered, no_answer, busy, declined, error).
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-call-mcpcall me and say the deploy finished"
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-call-mcp
An MCP server that lets AI agents place
real Telegram voice calls and speak a message aloud. The agent calls one
tool — make_call — with the text and a repeat count; the server synthesizes
speech (any TTS model on OpenRouter, default
x-ai/grok-voice-tts-1.0
with the rex voice), texts the fuller details version to the owner's chat,
rings their Telegram, waits for them to pick up, plays the message, and hangs
up. A second tool — send_message — texts the owner without ringing, for
updates that can wait.
Built for "wake me up if production is on fire" scenarios: text notifications are easy to sleep through, a ringing phone is not.
Agent ──make_call("DB is down", details="…")──▶ telegram-call-mcp
│ 1. TTS via OpenRouter (mp3)
│ 2. ffmpeg → WAV 48kHz mono
│ 3. 💬 text message with the details
│ 4. 📞 Telegram P2P call (py-tgcalls)
▼
owner's phone rings,
message plays twiceThe tools
make_call
Argument | Type | Required | Description |
| string | yes | Text to speak. Markdown, URLs, emojis and long IDs are stripped; if the result still exceeds |
| int 1–10 | no (default 2) | How many times to play the message, with a 2s pause between repeats. |
| string ≤4000 | no | Fuller version of the alert, sent as a plain Telegram text message right before the call rings — links, IDs, error output and next steps belong here, not in the voice. When omitted, the spoken text is sent instead, so every call is preceded by a text. |
Returns a structured result:
{ "status": "answered", "detail": "message played in full", "message_spoken": "DB is down", "text_sent": true }status is one of answered, no_answer, busy, declined, error;
text_sent reports whether the pre-call text message reached the chat. An
unanswered call means the spoken message was not heard — the text usually
still lands, but for anything critical the agent should retry the call later.
send_message
Argument | Type | Required | Description |
| string ≤4000 | yes | Text delivered verbatim to the owner's Telegram chat. |
Returns { "status": "sent", "detail": "text message sent (57 chars)" }.
No ringing — for "deploy finished, all green" class updates that the owner
reads whenever they next pick up the phone. The tool descriptions steer the
agent to reserve make_call for things that cannot wait.
Related MCP server: telegram-commandcode
Requirements
Python 3.10+
ffmpeg (with ffprobe) in
PATH—brew install ffmpeg/apt install ffmpegA dedicated Telegram account for the server (bots can't make calls, so it signs in as a real user account; see Security notes)
An OpenRouter API key for TTS
Setup
1. Install
pip install telegram-call-mcp # or: pipx install / uv tool installOr from source:
git clone https://github.com/maloleg/telegram-call-mcp
cd telegram-call-mcp
pip install .2. Get Telegram API credentials
Sign in at my.telegram.org with the account that will be making the calls (a spare/dedicated account, not your own).
Open API development tools, create an application (any name, URL can be left empty).
Note the
api_idandapi_hash.
3. Sign in once
export TELEGRAM_API_ID=123456
export TELEGRAM_API_HASH=abcdef...
export CALL_TARGET_USER_ID=111111111 # your own numeric Telegram user id
telegram-call-mcp login(The OpenRouter key is not needed here — login only talks to Telegram.)
The login prompts for the phone number, the code Telegram sends, and the 2FA
password if enabled, then saves a session file to
~/.telegram-call-mcp/telegram.session.
Not sure about your numeric user id? Ask @userinfobot on Telegram.
The caller and the callee must be different accounts. Telegram cannot call itself. Sign the server in with a dedicated account and point
CALL_TARGET_USER_IDat your personal one.
On the receiving account, allow calls from non-contacts (Settings → Privacy → Calls → Everybody) or add the server's account to your contacts — otherwise Telegram rejects the call before it ever rings.
4. Verify the setup
export OPENROUTER_API_KEY=sk-or-... # the remaining variable, for TTS
telegram-call-mcp checkcheck (alias: doctor) verifies everything a real call needs — config,
ffmpeg, the Telegram session, that the target user is reachable, and the TTS
key — without ringing anyone:
OK config all required variables set
OK ffmpeg ffmpeg and ffprobe found in PATH
OK session signed in as Alert Bot (id=8012345678)
OK target can call Oleg (id=111111111)
OK tts x-ai/grok-voice-tts-1.0 synthesized 38400 bytes of audio
All checks passed - ready to place calls.Run it after any config change: the server connects lazily, so a broken setup would otherwise surface only on the first real call — usually at the worst possible moment.
5. Add to your MCP client
Claude Code — a personal alert tool belongs in user scope (-s user,
available in all your projects); the default scope registers the server only
in the current project. Reference the variables exported above instead of
pasting literal values, so the secrets don't end up in your shell history:
claude mcp add -s user telegram-call \
--env TELEGRAM_API_ID="$TELEGRAM_API_ID" \
--env TELEGRAM_API_HASH="$TELEGRAM_API_HASH" \
--env CALL_TARGET_USER_ID="$CALL_TARGET_USER_ID" \
--env OPENROUTER_API_KEY="$OPENROUTER_API_KEY" \
-- telegram-call-mcp(If you keep the variables in a .env file, load them first with
set -a; source .env; set +a.)
Claude Desktop / any JSON-config client (claude_desktop_config.json):
{
"mcpServers": {
"telegram-call": {
"command": "telegram-call-mcp",
"env": {
"TELEGRAM_API_ID": "123456",
"TELEGRAM_API_HASH": "abcdef...",
"CALL_TARGET_USER_ID": "111111111",
"OPENROUTER_API_KEY": "sk-or-..."
}
}
}
}That's it. Ask the agent to "call me and say the deploy finished" to test.
Configuration reference
Variable | Required | Default | Description |
| ✅ | — | From my.telegram.org |
| ✅ | — | From my.telegram.org |
| ✅ | — | Numeric Telegram user id to call |
| ✅ | — | OpenRouter API key for TTS (not needed for |
|
| Any TTS model on OpenRouter's | |
|
| Voice name. The default applies only with the default model (voice names are model-specific); set it explicitly for other models, or set it empty to send no voice | |
|
| Any OpenAI-compatible audio API works | |
| — |
| |
|
| Session file location (without | |
|
| Seconds to wait for the callee to answer | |
|
| Pause between repeats, seconds | |
|
| Max message length after sanitization; longer messages are rejected, not truncated | |
|
| stderr logging verbosity |
Security notes
The session file is full access to the Telegram account. It is created with your user permissions in
~/.telegram-call-mcp/; treat it like a private key. Use a dedicated account so a leak never exposes your personal chats.The tool can only reach the one user id fixed in the server config — the agent cannot choose an arbitrary callee or text recipient, dial numbers, or message anyone else. The pre-call text goes to that same user.
The message text passes through OpenRouter for synthesis; don't have agents speak secrets aloud.
Automating a user account is subject to Telegram's terms; a dedicated account keeps any risk away from your personal one.
Troubleshooting
Start with telegram-call-mcp check — it validates the config, ffmpeg, the
session, target reachability and the TTS key in one pass, without placing a
call.
Symptom | Cause / fix |
Tool error: session not authorized | Run |
| Direct MTProto is blocked in your network. Set |
Call connects but there is silence / | The voice media stream (UDP to Telegram relays) is blocked. A SOCKS proxy is not enough — voice traffic bypasses it. Run your VPN in TUN / system-tunnel mode so UDP is routed too. |
| The callee's privacy settings reject calls from non-contacts, or the two accounts are the same. |
ffmpeg not found | Install ffmpeg and make sure |
TTS HTTP 401/402 | Bad or out-of-credit |
Development
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/mypy src
LOG_LEVEL=DEBUG .venv/bin/telegram-call-mcp # run on stdioThe call machinery lives in caller.py (Telethon + py-tgcalls, pinned to
2.3.3 — private-call APIs are version-sensitive), TTS and audio prep in
tts.py, tool definition in server.py.
License
MIT
Available Tools
1 toolmake_callA
Place a real Telegram voice call to the owner and speak the message aloud.
Use this when something is urgent enough to interrupt the owner with a
ringing phone call — a critical incident, a failed deployment, anything
they asked to be actively alerted about. The call rings like a normal
Telegram call; once answered, the synthesized message plays repeat
times and the call hangs up. The whole attempt can take up to ~2 minutes
(ring timeout + playback). The result reports whether the owner answered
("answered"), didn't pick up ("no_answer"), was on another call ("busy"),
or declined ("declined") — an unanswered call means the message was NOT
delivered, so consider retrying later or falling back to a text message.
| Name | Required | Description | Default |
|---|---|---|---|
| repeat | No | How many times to repeat the message during the call, with a short pause between repeats. | |
| message | Yes | The text to speak during the call. Keep it short and clear — the listener may have just been woken up. Plain language only: markdown, URLs, emojis and long identifiers are stripped before synthesis. Longer texts are truncated (default limit 500 chars). |
Output Schema
| Name | Required | Description |
|---|---|---|
| detail | Yes | |
| status | Yes | |
| message_spoken | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so impressively. It discloses the call ringing behavior, repetition of the message, approximate duration of ~2 minutes, possible outcomes ('answered', 'no_answer', 'busy', 'declined'), and the critical implication that an unanswered call means the message was not delivered. This goes well beyond the schema.
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 front-loaded with the primary action, then gives usage context, behavioral details, and outcome interpretation in a logical flow. Three sentences cover all essential aspects without redundancy or filler; every sentence contributes meaningful 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?
The description is complete for a tool of this complexity. It covers purpose, when to use, how the call behaves, duration, possible results, and failure implications. Even though an output schema exists, the description also summarizes return statuses, making it self-contained and highly usable for an agent.
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 baseline is 3. The description's mention that 'the synthesized message plays `repeat` times' adds only marginal reinforcement to what the schema already states about the repeat parameter. It does not provide additional semantic meaning 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?
The description opens with a specific verb and resource: 'Place a real Telegram voice call to the owner and speak the message aloud.' This clearly identifies the tool's function, and although no siblings are listed, the phrasing distinguishes it from messaging or notification tools by emphasizing a ringing voice call.
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 explicitly says when to use: 'when something is urgent enough to interrupt the owner... a critical incident, a failed deployment, anything they asked to be actively alerted about.' It also provides a fallback instruction: if the call is not answered, 'consider retrying later or falling back to a text message.' This is strong, actionable guidance.
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
make_call
TDQS
Scored across 1 tool
There is only one tool in this server, so there is no possibility of overlap or confusion between tools. The tool's purpose is clearly distinct because it is the sole capability provided.
The single tool uses a clear verb_noun convention (`make_call`), which is consistent and intuitive. With only one tool, there are no naming conflicts or style inconsistencies to evaluate.
The server has only one tool, which is at the lower boundary of the typical range. While the narrow purpose of making Telegram calls could justify a single tool, the count feels thin compared to more comprehensive servers, making it borderline.
The tool fully covers the stated domain: it places a call, delivers a spoken message, and reports the call outcome. There are no obvious missing operations for this specific use case, as calls are ephemeral and require no update or delete actions.
Maintenance
Related MCP Connectors
Telegram bridge for your MCP-compatible agent. Bidirectional, no LLM in our stack.
Give AI agents real phone numbers, messages, and voice calls via MCP.
Official MCP server for OmniDimension. Drive voice agents, dispatch calls, and run bulk campaigns.
MCP server for AI dialogue using various LLM models via AceDataCloud
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceMCP server with persistent memory, voice understanding, multi-thread orchestration, and remote control via Telegram for AI assistants.2,299 npm5MIT
- AlicenseNot gradedqualityBmaintenanceMCP server for Telegram integration with Command Code, enabling AI agents to send messages, photos, files, and read updates via Telegram.2MIT
- FlicenseNot gradedqualityCmaintenanceMCP server that enables AI agents to send messages, photos, polls, and receive replies via Telegram with persistence and rate limiting.29 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.5 npmMIT