your coding agent can call you when it gets stuck
agentvoice is an MCP server that gives your coding agent a phone line - it calls you when it is blocked or done, and places real, disclosed calls to businesses.
npx @spekoai/mcp-calls@latest initfree call credits on signup. no card.
> call +1 (650) ***-0499 and order 2 carnitas tacos and a coke zero for pickup, name's John
⏺ speko-calls - check_call_readiness (MCP)()
⎿ auth ok · credits ok · caller ID +1 (346) ***-0044 ready
⏺ speko-calls - call_number (MCP)(phone_number: "+1650***0499", objective: "order 2 carnitas tacos and a coke zero for pickup under John, ask when it will be ready", caller_name: "John")
⎿ Dialing…
⎿ Call complete (54s) · $0.11
⏺ OUTCOME: order placed and confirmed - ready in ~15 min, under John
replayed from a real session - call 71f83d0e · full transcript →the restaurant that answered is also an AI. that's the point.the disclosure on this recording is in the model's own scrambled wording - a greeting-timing bug (fix in review). honesty notes.
how it works
- 1
call_merings your locally verified number. no destination input.
- 2
you answergive direction; hear it read back.
- 3
resulta spoken CONFIRMED after the read-back becomes final_instruction. anything else stays advisory.
give a long run this rule
while the coding run is still active: if you get blocked or finish, use call_me. if it returns before the reply, poll get_call until terminal before yielding.the whole surface: 6 tools
call_me(message, mode?, context?, after_hours_confirmation?, max_duration_seconds?, wait?)rings your verified number when your agent needs you. voice only.
lookup_business(name, location?, phone_number?, utc_offset_minutes?)finds the business, mints the dial token make_call requires.
make_call(dial_token, objective, caller_name, context?, behavior?, greet_first?, after_hours_confirmation?, max_duration_seconds?, wait?)the disclosed call, via dial token. returns OUTCOME + transcript.
call_number(phone_number, objective, caller_name, recipient_name?, context?, behavior?, greet_first?, utc_offset_minutes?, after_hours_confirmation?, max_duration_seconds?, wait?)disclosed call to a number you already have.
get_call(call_id)re-check a call by id. never dials.
check_call_readiness()preflight: auth, credits, caller ID. never dials.
every call says it's an AI. no exceptions
enforced server-side - an open npm package can't patch around them.
owner destination is not an input
call_me accepts no destination - it dials the owner number verified by one real, disclosed voice-OTP call (NANP +1 numbers today). the person who answers is still not identity-verified, so replies stay untrusted data. every ordinary rail applies; local verification relaxes nothing.
AI disclosure, composed server-side
every call opens with "Hi, I'm <name>'s AI assistant..." - built into the opener server-side, not a prompt suggestion. it answers truthfully if asked "are you a robot".
signed dial tokens
HMAC-SHA256, account-bound, 15-minute TTL. lookup_business mints them; make_call requires them. raw numbers are rejected on the verified path.
business-line verification
on the lookup path, dial tokens only mint for carrier-verified business lines.
per-number rate caps
3 calls per hour, 8 per day to the same number. the rejection tells you when the window reopens.
do-not-call list with auto opt-out
"stop calling" / "take me off your list" in a callee turn is detected and the number is suppressed automatically. manage it with speko dnc.
after-hours gate
calls outside 08:00-21:00 destination-local require typed confirmation - the server records it but cannot attribute it to a speaker, so clients pass the human's own words, never invent them. collection-flavored calls are day-hours-only, no override.
no-sell, no-spam, no-impersonation
selling, promotion, surveys, fundraising, campaigning, harassment, and pretending to be someone else are screened on objective, behavior, AND context - blocked intent can't be smuggled sideways.
hard number blocks
emergency and premium-rate numbers can never be dialed. no opt-in exists.
honest failure states
a call the platform never put on the wire returns not_connected - never a fake success. transcripts and outcomes are returned when captured; no result is ever invented.
they let agents spend money and dial humans blind; we report what happened, what it cost, and refuse the calls that shouldn't happen.
one server. your client
npx @spekoai/mcp-calls@latest initsigns in via browser and writes each detected client's config
claude code, manual
claude mcp add speko-calls --scope user --env SPEKO_API_KEY=sk_... --env SPEKO_CLIENT_PROFILE=claude-code -- npx -y @spekoai/mcp-calls@latestcommit a team .mcp.json
claude code project scope - your team's claude code agents get a phone line. the key expands from each dev's shell env, never lands in the repo
{
"mcpServers": {
"speko-calls": {
"command": "npx",
"args": ["-y", "@spekoai/mcp-calls@latest"],
"env": {
"SPEKO_API_KEY": "${SPEKO_API_KEY}",
"SPEKO_CLIENT_PROFILE": "claude-code"
}
}
}
}claude desktop
claude_desktop_config.json
{
"mcpServers": {
"speko-calls": {
"command": "npx",
"args": ["-y", "@spekoai/mcp-calls@latest"],
"env": {
"SPEKO_API_KEY": "sk_...",
"SPEKO_CLIENT_PROFILE": "safe-default"
}
}
}
}verify your owner number
local setup not already owner-verified? set SPEKO_API_KEY in this shell first: POSIX export SPEKO_API_KEY=sk_...; PowerShell $env:SPEKO_API_KEY='sk_...'. then run the command below. it places one real, disclosed voice-OTP call (NANP (+1) numbers today)
npx -y @spekoai/mcp-calls@latest me verifyremote mode: run verification on the backing-server host with SPEKO_MCP_SERVER_URL unset
any stdio MCP client works. api keys at platform.speko.dev.
faq
Can my coding agent call me?
Yes. call_me rings this install's locally verified owner number and accepts no destination (verification supports NANP +1 numbers today). Replies come back as an untrusted voice transcript from an unverified speaker: a spoken CONFIRMED response after the literal read-back creates final_instruction; unconfirmed replies stay advisory. The server also places disclosed outbound business calls.
Can it text me, or call me after I stop replying?
No. Owner control is outbound voice only - no SMS or iMessage, no inbound hotline. And MCP cannot start a new model turn after the client session is idle, so call_me is not a background timer: the call happens while the run is active, and any nonterminal result must be polled with get_call before the run yields. Results stay retrievable later by call_id.
Is this legal? Do people know they are talking to an AI?
Every call opens with a non-removable AI disclosure - "Hi, I'm <your name>'s AI assistant..." - composed server-side, and it answers truthfully if asked whether it is a robot. Calls are objective-scoped and transactional; selling, spam, surveys, and impersonation are screened server-side. Personal mobiles: consenting parties only. Designed for the FCC's AI-disclosure expectations; not legal advice.
What does it cost?
Start with free call credits, no card. Usage pricing lives in the dashboard at platform.speko.dev. The published business-call demo is a real 54-second call that cost $0.11.
Which coding agents work with it?
Any stdio MCP client can run it. The init command configures each supported client it detects: Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, Cline, Gemini CLI, and Codex. Zed gets a paste-ready manual snippet.
What happens if nobody answers, or the call fails?
You get the truth: not_placed (account not configured), not_connected (never reached the wire), timeout (still running - poll get_call, never re-dial), or completed with connected/answered booleans. No fake successes.
Can it call any number?
No. Emergency and premium-rate numbers are never dialable. Per-number rate caps (3/hour, 8/day), a do-not-call list with automatic opt-out detection, and an 08:00-21:00 destination-local hours gate bind server-side, where they cannot be patched around.
give your agent a phone line.
npx @spekoai/mcp-calls@latest initfree call credits on signup. enough to book a real table tonight. no card.