Ringback
ringback
Your AI agent can call your phone — and actually talk to you.
ringback gives an LLM (Claude, or any MCP client) tools to reach you on your phone — from a one-way "fierce" alert all the way to a live, interruptible voice conversation — using only free, self-hosted pieces. No paid telephony. No extra API key for the conversation: the model already driving the MCP is the voice on the line.
Highlights
📞 Two-way voice calls — the agent rings your phone, you talk, it transcribes you and replies in speech. Barge-in: talk over it and it stops.
🔔 Tiered alerts — a loud push (ntfy / Pushover) or a real SIP ring + chat message, fired only when the LLM judges it urgent.
🆓 Free & self-hosted — pjsua2 + whisper.cpp + macOS
say+ a free Linphone SIP account. No Twilio, no per-minute fees.🧠 No conversation API key — the calling model is the brain; these tools are just its ears and mouth.
It ships two MCP servers, ringback-alert and ringback-voice:
Platform: macOS only. The voice feature uses Apple's
say(TTS) and CoreAudio via pjsua2.
Server | Tools | What it does |
ringback-alert |
| Fire-and-forget notification: a loud push (ntfy / Pushover) and/or a SIP ring + chat message. |
ringback-voice |
| A real two-way phone conversation. Rings your phone; you talk, it transcribes you, the LLM replies in speech. Supports barge-in (talk over it and it stops). |
The criteria for when to contact you live in the tool descriptions — the calling LLM decides. These servers are just the mechanism.
What a call looks like
agent → call_start("Your nightly deploy failed — want me to walk you through it?")
📞 your phone rings; you pick up and hear the line
you → "yeah, which step broke?"
agent → "The database migration. I can roll it back and retry — want that?"
you → "yes, do it" ← you can also just talk over the agent to interrupt
agent → call_end()The LLM calls call_start once, then converse(...) for each turn. Plain alerts are even simpler: one alert_me(...) call.
Quick start
git clone https://github.com/mohitbadwal/ringback && cd ringback
./setup.sh # installs EVERYTHING (toolchain, pjsua2, whisper model, deps) + creates voice.env
# edit voice.env → add your 3 SIP vars (free account: https://subscribe.linphone.org), then:
claude mcp add ringback-voice --scope user -- "$PWD/run_voice_mcp.sh"Full walkthrough + env-var reference: Set up ringback-voice below.
Honest caveats (read first)
macOS only.
say+ CoreAudio. No Linux/Windows path today.Not ChatGPT-realtime. The voice loop is record → whisper STT → LLM →
sayTTS, so expect ~1–2 s per turn. It's a reliable walkie-talkie with barge-in, not a streaming realtime voice.The voice feature depends on GPL software (pjproject/pjsua2). This repo is Apache-2.0, but redistributing a bundle that links pjsua2 carries GPL obligations — see
NOTICE. The ringback-alert server is unaffected.Your Mac must be awake and online, and for a voice call a Claude session must be live (it's the brain) for the duration.
Barge-in assumes low acoustic echo (handset or headset). On speakerphone, the TTS can echo into the mic and false-trigger "interruption." There's no echo cancellation in this path.
iOS push reality: a self-hosted/free push can't truly pierce Focus/Silent on iPhone except via Pushover's Critical Alerts (paid) — see ringback-alert notes below.
Architecture
LLM (Claude) ──MCP tools──▶ ringback-voice server (Python)
│ call_start / converse / listen / speak
▼
pjsua2 (SIP+SRTP, built from source) ──▶ Linphone SIP server
│ say → ffmpeg → WAV (speak) │ APNs VoIP push
│ record → whisper.cpp (listen) ▼
└───────────────────────────────────▶ your iPhone ringsringback-alert is simpler: it shells out to ntfy/Pushover HTTP and/or baresip for a SIP ring + chat message.
Prerequisites
macOS (Apple Silicon or Intel) with Homebrew
A free Linphone SIP account (
sip.linphone.org) and the Linphone iOS app (for the ring/voice features)Python 3.10+ (the pjsua2 bindings are built against whichever
python3you point at)
Set up ringback-voice — 4 steps
1. Clone + install everything:
git clone https://github.com/mohitbadwal/ringback && cd ringback
./setup.shsetup.sh installs the toolchain, compiles pjsua2 from source (~20–30 min — no Homebrew formula exists for the bindings), downloads the whisper model, installs deps, and creates voice.env for you. Safe to re-run. (Override PYTHON_BIN / PJPROJECT_DIR / WHISPER_MODEL_NAME if your layout differs.)
2. Get a free SIP account (this is the phone that rings):
Sign up at https://subscribe.linphone.org (or tap Create account in the Linphone app). You get a username and password; your address is
sip:<username>@sip.linphone.org.Install the Linphone app on your iPhone, sign in, and confirm it shows Connected.
3. Fill in voice.env (already created by setup.sh — just edit it). Only three vars are required:
export VOICE_SIP_ID="sip:yourname@sip.linphone.org"
export VOICE_SIP_USER="yourname"
export VOICE_SIP_PASS="your-password"Full variable reference:
Variable | Required | Default | What it is |
| ✅ | — | Your SIP address, e.g. |
| ✅ | — | SIP username (the part before |
| ✅ | — | Your SIP password |
| — | = | Address to call (normally yourself) |
| — |
| SIP registrar/proxy |
| — |
| STT model: |
| — |
| pjsua2 build dir (auto-detected) |
| — |
| Python that has pjsua2 (auto-detected) |
| — |
| OpenSSL libs (auto-detected) |
4. Register + test:
claude mcp add ringback-voice --scope user -- "$PWD/run_voice_mcp.sh"Then in a fresh Claude session say: "Use ringback-voice to call me and say hello." Your phone should ring.
Claude Desktop instead of Code? Add this to
~/Library/Application Support/Claude/claude_desktop_config.json(absolute path required; restart the app):{ "mcpServers": { "ringback-voice": { "command": "/absolute/path/to/ringback/run_voice_mcp.sh" } } }
Set up ringback-alert (optional)
ringback-alert reads its config from the MCP client's env block (no file to source). Register it with the channels you want:
# Claude Code
claude mcp add ringback-alert --scope user \
--env ALERT_CHANNEL=ntfy \
--env NTFY_URL=https://ntfy.sh/your-long-random-topic \
-- /opt/homebrew/bin/uv --directory "$PWD" run server.pySee alert.env.example for all variables (ntfy / Pushover / SIP ring). Use a long random ntfy topic — anyone who knows it can read/publish.
Using ringback-voice (the conversation)
The LLM drives a simple loop:
reply = call_start("Hi, it's your assistant — your deploy failed. Want details?")
# rings the phone, speaks the line, returns the user's first words
reply = converse("It failed on the database migration step. Want me to retry it?")
# speaks AND listens in one interruptible turn
... repeat converse() each turn ...
call_end() # when the user says "bye" / hangs upconverse(text)speaks while listening. If you talk over it, it stops immediately and tells the LLM how far it got and what you said (barge-in).get_conversation()returns the full transcript so far — both sides, plus where it got interrupted.TTS reads text literally, so the tool descriptions instruct the model to speak plain-language summaries, never raw logs/codes — those go via
alert_meas text instead.
Whisper model accuracy/speed trade-off (set WHISPER_MODEL): base.en (fast/rough) → small.en (balanced, default) → medium.en (most accurate/slow).
Using ringback-alert (notifications)
alert_me(message, severity, title) with severity = info | warn | critical. Channels via ALERT_CHANNEL (comma list of ntfy, pushover, call):
ntfy — free push; loud but does not pierce iOS Focus/Silent unless whitelisted per-Focus.
Pushover — $5 one-time; true iOS Critical Alerts (pierces Focus/Silent, repeats until acknowledged) at
critical.call — free SIP ring + Linphone chat message via baresip; rings full-screen, only at
criticalby default.
A built-in rate-limit guard (default 5/60s, per-process) stops a misfiring caller from spamming you.
Bundled skill: watchdog
skills/watchdog/ is a ready-to-use Claude skill built on these servers. It watches a condition you give it (a CI run, a deploy, a pod, a file) and escalates only when you're actually away from the laptop — chat status → chat warning → ringback-alert push → ringback-voice call — judged by macOS HID idle time. It never interrupts you while you're typing, and de-escalates the moment you touch the keyboard.
cp -r skills/watchdog ~/.claude/skills/watchdog # install for Claude CodeThen: /watchdog <what to watch> | priority=<low|medium|critical> — low = chat only, medium = may send a phone alert, critical = may place a call. Full design in skills/watchdog/SKILL.md.
Security
SIP credentials live only in your local, gitignored
voice.env(and the baresipaccountsfile for ringback-alert) — never in the repo or the MCP client config when you can avoid it.The voice server only ever calls the single SIP URI you configure — it cannot dial arbitrary numbers.
Treat ntfy topics as secrets (use a long random topic); don't put sensitive detail in alert bodies on public ntfy.sh.
See
NOTICEfor the GPL/pjproject licensing caveat before redistributing.
License
Apache-2.0 (see LICENSE), with an important GPL caveat for the voice
component's pjproject dependency — see NOTICE.
Credits
Built on pjproject/pjsua2, whisper.cpp, baresip, ntfy, and Linphone.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mohitbadwal/ringback'
If you have feedback or need assistance with the MCP directory API, please join our Discord server