Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Callmaibe

БесплатноНе проверен

MCP server for AI agent phone calls

GitHubEmbed

Описание

MCP server for AI agent phone calls

README

CI

Let your AI coding agent phone you. When it finishes a long task or gets stuck, it calls your phone over SIP, tells you what it did and what it weighed up, and has a spoken back-and-forth with you. Everything you say comes back to the agent as text, so it can act on it. Calls only happen while you have switched them on.

Example call (the agent speaks first):

Agent: Hi, it's Claude. I finished migrating the billing tests to pytest. Forty-one pass,
       two fail. I think both are real bugs, not test problems. Want me to fix them now?
You:   Yes, but don't touch the invoice module.
Agent: Understood, fix the two failing tests and leave the invoice module alone. Is that right?
You:   Yes.
Agent: Great. I'll start now and write the result in the terminal. Bye.

Status: early, but real calls work: tested over Wi-Fi and mobile data, see Project status.

How it works

 Agent (Claude Code or any MCP client)
     | stdio (MCP)
     v
 callmaibe mcp  --- HTTP 127.0.0.1 + token --->  callmaibe daemon
 (one per agent session)                          policy | conversation | TTS | STT+VAD | SIP
                                                      | SIP over TLS, SRTP media
                                                      v
                                              SIP provider (sip.linphone.org or any)
                                                      | push notification + SIP
                                                      v
                                              Linphone on your phone
  • The agent gets four MCP tools: call_start, call_say, call_end, call_status. None takes a phone number.
  • A separate daemon owns the SIP registration, the single phone line and the loaded speech models. The MCP server starts it automatically.
  • Speech is local by default: Kokoro for text-to-speech, faster-whisper for speech-to-text, a voice activity detector to find the end of your turn.
  • Whether calls are allowed is decided in the daemon, not by the agent. You switch calling on per chat session with /call on.
  • The agent runs on a computer; you answer on your phone. Linphone uses push notifications, so it rings even when the app is closed.
  • On Windows the SIP daemon runs inside WSL2 (the Windows SIP wheels lack TLS). Everything else stays on Windows.

Features

  • Spoken multi-turn conversation: silence-based end of turn, a short "yeah" in your pauses and "got it" when you stop talking, spoken fillers ("let me check", "still on it") and a soft sound while the agent works. It keeps listening while the agent works: what you say then reaches the agent before its next message, and "Can you hear me?" (as its own phrase) is answered at once.
  • Per-session on/off switch, a global kill switch, snooze, weekly quiet hours.
  • Declining a call on your phone snoozes calling for a while (default 30 minutes).
  • Claude Code plugin: /call command, a skill that teaches the agent when and how to phone.
  • Works with any MCP client through manual config.
  • Local transcripts, no audio stored.
  • Local mic/speaker mode to try the conversation without any SIP account.
  • SIP over TLS with SRTP, ICE/STUN, optional TURN.

Requirements

  • Two free SIP accounts: one for the agent, one for you (sip.linphone.org works).
  • The Linphone app on your phone, logged into your account, notifications allowed.
  • Python 3.12 (uv installs it for you).
  • For real calls on Windows: WSL2 with a Linux distro (Debian recommended).
  • About 150 to 500 MB of disk for the speech models, downloaded on first use.

Installation

Linux and macOS

git clone https://github.com/mnaomii/callmaibe && cd callmaibe
./scripts/install.sh

The script checks for uv (and asks before installing it), runs uv tool install --python 3.12 --force "callmaibe[sip,speech,local] @ <source>", runs uv tool update-shell, and finishes by running callmaibe setup (skipped with --yes). No sudo. The default source is the GitHub archive of main; override it with CALLMAIBE_SOURCE=/path/to/checkout ./scripts/install.sh or --source. Add --yes to skip the questions.

macOS note: the SIP wheel there is untested. Use --backend local or Docker until that is verified.

Windows

git clone https://github.com/mnaomii/callmaibe; cd callmaibe
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install.ps1

Why WSL: the pjsua2 Windows wheels are built without TLS and Opus, so they cannot register with linphone.org. The SIP daemon therefore runs in WSL2 while the CLI, MCP server and hooks stay native Windows. The script:

  1. installs uv if needed (asks first: winget or the official script),
  2. installs the Windows side, callmaibe[speech,local],
  3. checks WSL and a distro; if missing it tells you to run wsl --install -d Debian (admin PowerShell, reboot) and stops. The Windows side is installed, so local mode already works,
  4. inside WSL, without sudo: fetches the uv binary into ~/.local/bin, creates ~/.venvs/callmaibe and installs callmaibe[sip,speech],
  5. offers (asks first, makes a backup) to set networkingMode=mirrored in %USERPROFILE%\.wslconfig; then run wsl --shutdown,
  6. runs callmaibe setup (see Setup), so installing and configuring is one step. With -Yes or -DryRun it only records runner = "wsl" and tells you to run the wizard yourself.

Options: -Distro Debian, -Source <url-or-folder> (or env var CALLMAIBE_SOURCE), -Yes, and -DryRun to print every command without running it.

Manual install

uv tool install --python 3.12 "callmaibe[sip,speech,local] @ https://github.com/mnaomii/callmaibe/archive/refs/heads/main.zip"
uv tool update-shell

On Windows use callmaibe[speech,local] and set up the WSL side yourself: a Python 3.12 venv at ~/.venvs/callmaibe with callmaibe[sip,speech], then callmaibe setup --runner wsl. Extras: speech (Kokoro, faster-whisper, VAD, resampler), sip (pjsua2, Linux and Python 3.12 only), local (mic and speaker through sounddevice).

Claude Code plugin

Inside Claude Code:

/plugin marketplace add mnaomii/callmaibe
/plugin install callmaibe@callmaibe-marketplace

callmaibe setup does this for you (see Setup). The plugin adds the MCP server (callmaibe mcp), the /call command, the hook that handles it and the phone-call skill. It needs the callmaibe command on your PATH, so install the package first. Raise Claude Code's MCP tool timeout, since a call blocks while ringing and listening: set MCP_TOOL_TIMEOUT (milliseconds, for example 600000) in the environment that launches Claude Code. The wizard offers to set it under env in ~/.claude/settings.json.

Other MCP clients

callmaibe setup writes the config for Codex CLI, Claude Desktop, Cursor and Gemini CLI (see Setup). For any other client, add a stdio server to its MCP config, with the absolute path of callmaibe if it is not on the client's PATH, and a session name of your choice:

{ "mcpServers": { "callmaibe": { "command": "callmaibe", "args": ["mcp"],
                                 "env": { "CALLMAIBE_SESSION": "NAME" } } } }

Then paste instructions like these into its instructions file (AGENTS.md or similar):

You can phone the user with call_start, call_say and call_end, but only if call_status says
calling is available; the user switches that on. Call when a long task finishes, when you are
blocked on a decision, or when you need approval for a risky step. Speak in short plain sentences,
one question at a time, no code or URLs. Read back any destructive action and get a clear yes
before doing it. If calling is unavailable, write the summary in the terminal instead.

Other clients have no /call hook. Switch calling on from a terminal with callmaibe session on --session NAME, using the same name as CALLMAIBE_SESSION in the client's MCP config. callmaibe setup --clients other prints this snippet and the instructions for you.

Setup

  1. Create two accounts at https://subscribe.linphone.org: one for you (the one that rings) and one for the agent. Each needs its own email address. Creating yours inside the Linphone app also works, but the app asks for a phone number.

  2. Log your phone into your account. Install Linphone, choose the Linphone account login (not "third-party SIP account") and allow notifications. That login turns on push, so the phone rings even when the app is closed. Do not log the phone into the agent's account.

  3. Run the wizard. The installer starts it for you; to run it again at any time:

    callmaibe setup
    

    It asks, in order:

    1. Agent SIP address. my-agent, my-agent@host or sip:my-agent@host; a bare name gets @sip.linphone.org.

    2. Your SIP address (the phone that rings), same forms; it must differ from the agent's.

    3. Agent password, typed hidden, twice. It goes into the OS keyring (Windows Credential Manager, macOS Keychain, Linux Secret Service), never into a file and never onto the screen. If one is already stored you choose keep (default) or replace. With no keyring (headless, WSL) nothing is stored and it explains the CALLMAIBE_SIP_PASSWORD environment variable instead; that variable takes precedence over the keyring. Avoid setx on Windows: it stores the value in plaintext in the registry.

    4. Backend. pjsua2 for real phone calls, local for your laptop mic and speaker. On Windows with pjsua2 it sets the runner to wsl, checks that the WSL Python from scripts\install.ps1 exists, and prints how the daemon will run.

    5. Clients to install into. Numbers separated by commas; Enter keeps the ones it found on this machine.

      Client Found when What it does
      Claude Code claude is on PATH Installs the plugin (claude plugin marketplace add, then claude plugin install callmaibe@callmaibe-marketplace, user scope). If that fails it falls back to claude mcp add --scope user callmaibe, and /call then needs the plugin. Offers to set MCP_TOOL_TIMEOUT to 600000 under env in ~/.claude/settings.json.
      Codex CLI codex on PATH or ~/.codex codex mcp add callmaibe (or appends [mcp_servers.callmaibe] to ~/.codex/config.toml), and adds the agent instructions to ~/.codex/AGENTS.md between <!-- callmaibe:start --> and <!-- callmaibe:end -->.
      Claude Desktop its config folder exists mcpServers.callmaibe in claude_desktop_config.json.
      Cursor ~/.cursor exists mcpServers.callmaibe in ~/.cursor/mcp.json.
      Gemini CLI gemini on PATH or ~/.gemini mcpServers.callmaibe (with a 10 minute timeout) in ~/.gemini/settings.json.
      Other never preselected Prints the JSON snippet and the instructions.

      The MCP entries use the absolute path of callmaibe. Each file is backed up first as <file>.bak-YYYYmmdd-HHMMSS, only the callmaibe entry is changed, everything else is kept, running the wizard again changes nothing, and it prints exactly what it changed. Clients other than Claude Code have no /call; it prints the command to turn calling on for each, such as callmaibe session on --session codex.

    6. It writes config.toml (keeping any keys it does not manage), prints a summary, and, for pjsua2 with a password available, asks Place a test call now? Your phone will ring [y/N] (default no).

    On Windows the WSL daemon has no keyring, so callmaibe reads the password on the Windows side and hands it only to the daemon process (via WSLENV), not to your whole environment. callmaibe password set|status|delete still works for changing the password later.

  4. Test it (if the wizard did not already):

    callmaibe test-call
    

    Your phone rings, the agent speaks, you say something, it repeats it back.

Scripted use: every question has a flag, and --yes or --password-stdin turn off all prompts (clients are only touched when you pass --clients).

echo "$AGENT_PASSWORD" | callmaibe setup --agent-uri my-agent --callee-uri [email protected] \
    --backend pjsua2 --clients claude-code,codex --password-stdin
callmaibe setup --yes --agent-uri sip:[email protected] --callee-uri sip:[email protected] --runner wsl --wsl-distro Debian
callmaibe setup --dry-run --clients claude-code,cursor     # print every action, write nothing

Flags: --agent-uri --callee-uri --transport --backend --runner --wsl-distro --clients --password-stdin --dry-run --yes. --clients takes claude-code,codex,claude-desktop,cursor,gemini,other or none.

Usage

Calling is off until you switch it on, one chat session at a time. In Claude Code:

Command What it does
/call on This session's agent may phone you when it judges it useful.
/call off This session stops calling.
/call now One call right now about the current work, valid for 10 minutes, even if the session is off.
/call status Shows whether calling is allowed here and why not.

Global controls, from any terminal (they work with no agent and no daemon running):

callmaibe off          # kill switch: block every session
callmaibe on           # lift the kill switch (sessions still need /call on)
callmaibe snooze 2h    # block calls for a while (30m, 2h, 90s)
callmaibe unsnooze
callmaibe status       # policy, session key, how the daemon runs, daemon health

Quiet hours block calls even in a session where calling is on, including /call now:

[policy]
quiet_hours = [
  { days = "mon-fri", from = "09:00", to = "17:00" },   # work hours
  { days = "mon-sun", from = "23:00", to = "07:00" },   # overnight, ranges may wrap midnight
]

Decline to snooze: if you decline the call on your phone, calling is snoozed for decline_snooze_min (default 30) minutes. That is your remote off switch.

Local mode (no SIP, no accounts) uses your own mic and speaker:

callmaibe setup --backend local --yes
callmaibe test-call

More detail: docs/usage.md.

Session behaviour

Claude Code gives hooks a session id but gives MCP servers none. So callmaibe identifies a session by the Claude Code process: both the /call hook and the MCP server look for the nearest ancestor process named claude (falling back to node) and use claude-<pid> as the key. In a plain terminal the key is local. What follows from that:

  • After claude --resume or claude --continue there is a new process, so calling is off again. Type /call on again.
  • Two Claude Code windows are two sessions, each with its own switch.
  • Process ids can be reused after a reboot; "on" entries older than 7 days are pruned, and the global switch and quiet hours still apply.
  • Set CALLMAIBE_SESSION=name to override the key (for a client that is not Claude Code, or to share one switch across processes). callmaibe status prints the current session key.

Configuration reference

The file is config.toml in the callmaibe home directory (see Where things live). Every key is optional; this is the full set with defaults. Unknown keys are an error.

[account]                      # the account the agent calls FROM
uri = ""                       # "sip:[email protected]"
username = ""                  # auth user; empty = the user part of uri
password_env = "CALLMAIBE_SIP_PASSWORD"   # optional env var; overrides the keyring entry
transport = "tls"              # tls | tcp | udp
stun = ["stun.linphone.org"]
turn_server = ""               # "host:port"; empty = no TURN
turn_username = ""
turn_password_env = "CALLMAIBE_TURN_PASSWORD"

[callee]
uri = ""                       # YOU: "sip:[email protected]". The only address the agent can ever call.

[media]
backend = "pjsua2"             # pjsua2 (real SIP) | local (mic/speaker) | fake (tests)
encryption = "srtp"            # srtp | none ("none" only for debugging; Linphone rejects it with 488)
ice = true
codecs = ["G722/16000", "PCMU/8000", "PCMA/8000"]

[tts]
engine = "kokoro"
voice = "af_heart"
speed = 1.0
variant = "int8"               # kokoro model: int8 (88 MB) | fp32 (310 MB)

[stt]
engine = "faster-whisper"
model = "base.en"              # tiny.en | base.en | small.en ...; non-English needs a multilingual model: base | small
language = "en"
device = "auto"                # auto | cpu | cuda
compute_type = "int8"
prompt = ""                    # words to expect, e.g. project names (Whisper may echo them)

[conversation]
ring_timeout_s = 45            # give up if nobody answers
listen_timeout_s = 20          # no speech at all in a turn -> status no_reply
end_silence_ms = 900           # silence that ends your turn
max_turn_s = 60
idle_hangup_s = 120            # agent silent this long between turns -> hang up
max_call_min = 20
thinking_cue = true            # soft sound while the agent thinks
fillers = true                 # spoken "yeah", "got it", "let me check"; answers "can you hear me?" itself
keep_transcripts = true
barge_in = true                # you can interrupt the agent by talking over it
barge_in_min_ms = 700          # sustained speech needed to interrupt (short noises are ignored)
first_turn_grace_s = 2.5       # no interrupting the opening message ("hello?" at pickup)
vad_aggressiveness = 3         # 0-3; higher rejects more line noise
debug_audio = false            # save incoming audio to <home>/logs/audio/<call_id>-in.wav

[policy]
enabled = true                 # global kill switch default; sessions still need /call on
decline_snooze_min = 30
once_permit_min = 10           # how long /call now stays valid
quiet_hours = []               # none; e.g. [{ days = "mon-fri", from = "09:00", to = "17:00" }]

[daemon]
host = "127.0.0.1"
port = 47823
runner = "auto"                # auto | native | wsl (wsl only matters on Windows)
wsl_distro = ""                # empty = WSL default distro
wsl_python = "~/.venvs/callmaibe/bin/python"

Troubleshooting

The call rings but there is no audio (NAT). Signalling worked, media did not. The free Linphone accounts ship with STUN only. If your PC is behind a home router and the phone is on mobile data (often symmetric carrier NAT), STUN alone can fail. Options, cheapest first:

  • Put the phone on the same Wi-Fi to confirm that NAT is the cause.
  • Use a TURN relay on the PC side (one relayed side is enough): set turn_server, turn_username and the CALLMAIBE_TURN_PASSWORD env var in [account]. Cloudflare Realtime TURN has a free tier; coturn on a VPS also works.
  • Use Tailscale on both devices, or any VPN that gives them a direct path.
  • On Windows, enable WSL mirrored networking (networkingMode=mirrored in .wslconfig, then wsl --shutdown); the default NAT inside WSL is an extra hop.

488 Not Acceptable Here. Encryption mismatch. The Linphone apps require SRTP on sip.linphone.org accounts. Keep media.encryption = "srtp" and account.transport = "tls". "none" is for other providers.

The daemon does not start. Run it in the foreground to see the error: callmaibe daemon. Check callmaibe status (it shows how the daemon runs: native or WSL). On Windows with runner = "wsl", test the WSL side directly: wsl.exe --exec sh -c '$HOME/.venvs/callmaibe/bin/python -m callmaibe status'. Common causes: the WSL venv is missing (re-run scripts\install.ps1), wsl_distro names a distro that does not exist, or port 47823 is taken (change daemon.port). Also look at the logs directory below.

Where things live

All under one home directory: CALLMAIBE_HOME if set, otherwise %LOCALAPPDATA%\callmaibe (Windows), ~/.local/share/callmaibe (Linux), ~/Library/Application Support/callmaibe (macOS).

What Path
Config <home>/config.toml
Policy state (switches, snooze) <home>/policy.json
Logs <home>/logs/
Transcripts <home>/transcripts/
Speech models <home>/models/
Daemon token and lock <home>/daemon.token, <home>/daemon.lock

On Windows with the WSL daemon, both sides use the same Windows folder (the daemon sees it as /mnt/c/...).

Privacy and security

  • No MCP tool accepts a phone number or SIP address. The callee comes from config.toml only, so a prompt injection cannot make the agent call someone else.
  • Only you can enable calling. There is no tool that switches it on; /call is handled by a hook or a shell step that runs on your input, and the daemon enforces the result.
  • Speech is local by default (Kokoro and faster-whisper). Nothing is sent to a speech cloud unless you configure one.
  • Transcripts are stored locally in <home>/transcripts/; turn them off with keep_transcripts = false. Audio is not stored, unless you turn on debug_audio: that writes everything you say on a call to <home>/logs/audio/<call_id>-in.wav so thresholds can be tuned. It contains your voice and background sound, so leave it off normally and delete the files afterwards.
  • The daemon listens on 127.0.0.1 only and needs a random token from a user-only file. Inbound calls are rejected.
  • The SIP password lives in the OS keyring (callmaibe password set), or in an environment variable on headless machines. It is never written to the config.
  • Whoever answers your phone can steer the agent. A spoken yes can approve actions, including destructive ones. The skill makes the agent read the exact action back and hear a clear yes first; treat the phone like a keyboard.

Technologies used

Licenses are those the upstream projects state; check them before redistributing.

Component Used for License
PJSIP / pjsua2 SIP stack, calls, SRTP, ICE (via the community pjsua2-python wheel) GPL-2.0-or-later (or commercial)
Linphone app The phone side (push, CallKit) GPL-3.0
sip.linphone.org (Flexisip) Free SIP accounts, proxy and push gateway Flexisip: AGPL-3.0; service run by Belledonne
Kokoro via kokoro-onnx Text-to-speech model Apache-2.0, kokoro-onnx MIT
onnxruntime Runs Kokoro on CPU MIT
faster-whisper and CTranslate2 Speech-to-text MIT
webrtcvad (webrtcvad-wheels) Voice activity detection MIT (WebRTC code: BSD)
soxr Resampling between 8, 16 and 24 kHz LGPL-2.1-or-later
sounddevice / PortAudio Local mic/speaker mode MIT
MCP Python SDK MCP server for the agent MIT
uv Python and tool installs MIT or Apache-2.0
WSL2 Linux runtime for the SIP daemon on Windows part of Windows (Linux kernel: GPL-2.0)

Project status and roadmap

Where this stands:

  • Verified on real calls (Linphone app, daemon in WSL2): SIP over TLS with SRTP media, push wake-up with the app closed, Wi-Fi and mobile data with audio relayed by sip.linphone.org on free accounts, multi-turn conversation with barge-in.
  • Built and unit-tested with mocks, in CI on Linux, Windows and macOS: policy (switches, snooze, quiet hours), the daemon API, the conversation engine against a fake telephony backend, the local mic/speaker backend, the speech pipeline, the CLI, the /call hook, and the setup wizard. The pjsua2 backend is also tested with local loopback calls on Linux.
  • Not tested: the macOS SIP wheel, and the installers have only been dry-run (install.ps1 -DryRun, bash -n on install.sh).
  • Known limits: the Linux pjsua2 wheel bundles OpenSSL 1.0.2 (end of life) and has no Opus; SIP needs Python 3.12.

Roadmap: barge-in and sentence-streamed TTS polish, PyPI release, our own pjsua2 wheels (OpenSSL 3, Opus), inbound calls, PSTN through a SIP trunk, SIP MESSAGE commands, other agents. See docs/PLAN.md.

Contributing

uv sync --extra speech          # Linux: add --extra sip for the sip tests
uv run pytest                   # default run skips the markers below
uv run pytest -m slow           # downloads models, runs real speech engines
uv run pytest -m sip            # needs pjsua2 (Linux); local loopback calls only
uv run pytest -m network        # registers against sip.linphone.org
uv run ruff check

Telephony is mocked in the default tests. CI (.github/workflows/ci.yml) runs lint and the default tests on Linux, Windows and macOS, and the sip tests on Linux, for every push and pull request; the slow and network tests run every Monday and on demand. Do not put credentials in the repo. Architecture and decisions: docs/PLAN.md; daemon API: docs/API.md.

License

GPL-3.0-or-later, chosen to fit pjsua2 (GPLv2+) and liblinphone (AGPLv3). See LICENSE.

from github.com/mnaomii/callmaibe

Установка Callmaibe

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/mnaomii/callmaibe

FAQ

Callmaibe MCP бесплатный?

Да, Callmaibe MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Callmaibe?

Нет, Callmaibe работает без API-ключей и переменных окружения.

Callmaibe — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Callmaibe в Claude Desktop, Claude Code или Cursor?

Открой Callmaibe на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Opencode Omniroute Plugin

OpenCode plugin for the OmniRoute AI Gateway. Drives dynamic model discovery, /connect auth flow, and multi-instance OmniRoute providers via the official @openc

GitHub Actionsавтор: GitHub Actions
56

Roblox Studio

Enables AI coding tools to control Roblox Studio for workspace exploration, instance manipulation, and script management. It provides tools for playtesting, sce

paralovавтор: paralov

Antigravity Drawio

MCP server that enables AI assistants to create, parse, render, and validate Draw.io diagrams programmatically.

S-SUJAN-Sавтор: S-SUJAN-S

Fetch

Web content fetching and conversion for efficient LLM usage.

автор: Community

AWS KB Retrieval

Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.

modelcontextprotocolавтор: modelcontextprotocol

Spring AI MCP Server

Provides auto-configuration for setting up an MCP server in Spring Boot applications.

автор: Community

llm-analysis-assistant

A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also

xuzexin-hzавтор: xuzexin-hz

MCP-Agent

A simple, composable framework to build agents using Model Context Protocol by [LastMile AI](https://www.lastmileai.dev)

lastmile-aiавтор: lastmile-ai

Spring AI MCP Client

Provides auto-configuration for MCP client functionality in Spring Boot applications.

автор: Community

mcp.natoma.ai

A Hosted MCP Platform to discover, install, manage and deploy MCP servers by [Natoma Labs](https://www.natoma.ai)

автор: Community

Compare Callmaibe with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории ai