Ringback
Let your AI agent call your phone and talk to you — MCP servers for live, interruptible voice calls + tiered alerts, using free self-hosted pieces (pjsua2 + whisper.cpp + Linphone). No paid telephony, no extra API key.
README
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 | alert_me, alert_test, alert_status |
Fire-and-forget notification: a loud push (ntfy / Pushover) and/or a SIP ring + chat message. |
| ringback-voice | call_start, converse, get_conversation, call_end, … |
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 rings
ringback-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.sh
setup.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 |
|---|---|---|---|
VOICE_SIP_ID |
✅ | — | Your SIP address, e.g. sip:you@sip.linphone.org |
VOICE_SIP_USER |
✅ | — | SIP username (the part before @) |
VOICE_SIP_PASS |
✅ | — | Your SIP password |
VOICE_SIP_CALLEE |
— | = VOICE_SIP_ID |
Address to call (normally yourself) |
VOICE_SIP_PROXY |
— | sip:sip.linphone.org;transport=tls |
SIP registrar/proxy |
WHISPER_MODEL |
— | ~/.whisper-models/ggml-small.en.bin |
STT model: base.en (fast) · small.en (default) · medium.en (accurate) |
PJPROJECT_DIR |
— | ~/build/pjproject-2.17 |
pjsua2 build dir (auto-detected) |
PYTHON_BIN |
— | $(command -v python3) |
Python that has pjsua2 (auto-detected) |
OPENSSL_PREFIX |
— | $(brew --prefix openssl@3) |
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.py
See 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 up
converse(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 Code
Then: /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.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.