Voice MCP
Let an AI agent place real phone calls and talk for you. Two interchangeable voice pipelines behind two MCP servers, plus a browser test page so you can try both without a phone line.
What it does
You give the agent a phone number and a goal in plain language ("Confirm tomorrow's 14:30 appointment, or move it to any morning slot"). It dials, holds the conversation in the callee's language (Slovenian works well), hangs up when the goal is met, and returns a transcript plus a short summary and an outcome.
voice-mcp · Grok Voice
One speech-to-speech model does hearing, thinking and speaking. Lowest latency and the simplest setup. Audio goes from the SIP trunk straight to the model, with no transcoding.
Voices: ara (default), eve, rex, sal, leo.
livekit-mcp · Soniox + LLM
A classic pipeline: Soniox speech-to-text, a chat LLM for the reasoning, Soniox text-to-speech. Cheaper per minute, with hard language pinning and custom vocabulary for better recognition.
Voices: Soniox voices (default Maya).
Both servers speak the standard Model Context Protocol over streamable HTTP, so any MCP client (Claude, Cursor, Hermes, your own code) can use them.
Connect an MCP client
The MCP endpoints are private on purpose: a tool that can dial phone numbers costs money and must not be open to the internet. They listen on the server's loopback interface only and you reach them through an SSH tunnel (or run your client on the same host). Ask the owner for the tunnel command; it forwards a local port to each server.
Once the tunnel is up, point your MCP client at the local URL, path /mcp, transport streamable HTTP:
{
"mcpServers": {
"voice": { "url": "http://localhost:<voice-port>/mcp" },
"livekit": { "url": "http://localhost:<livekit-port>/mcp" }
}
}
Or test from a terminal with the MCP inspector: npx @modelcontextprotocol/inspector --transport http --server-url http://localhost:<port>/mcp
*_call_dial is blocking: it returns when the call ends, so set a generous tool timeout in your client (at least the call's max_seconds plus 30 s). One call at a time per server. Calls are capped at 600 s.voice-mcp tools (Grok Voice)
| Tool | Purpose |
|---|---|
voice_call_dial | Place an outbound call and run the whole conversation. Blocking. |
voice_call_status | Snapshot of the call in progress (or active: false). |
voice_call_hangup | Politely end the call in progress. |
voice_call_history | The last N finished calls, newest first. |
zadarma_balance | Remaining prepaid telephony balance. Check before long or costly calls. |
voice_call_dial parameters
| Name | Type | Description |
|---|---|---|
to * | string | E.164 number with country code, e.g. +38640123456. |
goal * | string | What the agent should achieve. Be specific; this goes into its system prompt. |
context | string | Facts the agent may use quietly (name, order id). No secrets. |
voice | string | ara (default), eve, rex, sal, leo. |
language | string | ISO code such as sl, en, or auto (default) to mirror the callee. |
max_seconds | integer | Hard cap on call length. Default and maximum 600. |
Example
voice_call_dial({
"to": "+38640123456",
"goal": "Ask if the table for 4 on Friday at 19:00 is still booked. If not, book it.",
"context": "Booking is under the name Novak.",
"language": "sl"
})
→ {
"ok": true,
"outcome": "success", // success | partial | failed | no_answer | timeout | error
"summary": "Table confirmed for Friday 19:00, 4 people.",
"transcript": [ {"role": "assistant", "text": "..."}, {"role": "user", "text": "..."} ],
"duration_s": 41.2,
"hung_up_by": "remote"
}
livekit-mcp tools (Soniox + LLM)
| Tool | Purpose |
|---|---|
livekit_call_dial | Place an outbound call through LiveKit with Soniox speech and an LLM. Blocking. |
livekit_call_status | Snapshot of the call in progress, with a growing partial transcript. |
livekit_call_hangup | End the call in progress. |
livekit_call_history | The last N finished calls, newest first. |
livekit_call_dial parameters
| Name | Type | Description |
|---|---|---|
to * | string | E.164 number with country code. |
goal * | string | What the agent should achieve. |
language * | string | ISO-639-1 code (sl, en, de, it, hr, ...) or auto. A concrete code pins recognition to that language and is noticeably more accurate. |
open_with_greeting * | boolean | true: agent speaks first once the callee picks up. false: it waits for the callee to say hello. |
context | string | Quiet background facts for the agent. |
voice | string | Soniox voice name. Default Maya. |
max_seconds | integer | Hard cap on call length. Default and maximum 600. |
vocabulary | string[] | Names and terms to bias recognition towards, e.g. ["Novak", "Kolodvorska"]. |
instructions_override | string | Replace the default persona prompt entirely. Advanced. |
Example
livekit_call_dial({
"to": "+38640123456",
"goal": "Order one large margherita for pickup at 19:30 under the name Jakob.",
"language": "sl",
"open_with_greeting": true,
"vocabulary": ["margherita"]
})
The result has the same shape as voice_call_dial: outcome, summary, transcript, duration_s, hung_up_by.
Call flow
(Claude, Cursor, code)"] -->|"voice_call_dial"| V["voice-mcp"] C -->|"livekit_call_dial"| L["livekit-mcp"] V -->|"SIP + RTP (G.711)"| T["SIP trunk"] V <-->|"realtime audio"| G["Grok Voice"] L -->|"room + agent"| LK["LiveKit Cloud"] LK -->|"SIP"| T LK <--> S["Soniox STT/TTS + LLM"] T --> P(("Callee's phone"))
- The client calls
*_call_dialwith a number and a goal. The server checks that no other call is running. - The server dials through the SIP trunk. On pick-up, audio is bridged to the AI.
- The agent talks until the goal is met, the callee hangs up, it decides to end the call, or
max_secondsexpires. - A summary and outcome are generated and the tool returns them, together with the full transcript. The call is saved to history.
Cost per minute
Rough list prices in USD at the time of writing; providers change them. Telephony is billed per second on the Standard plan.
| voice-mcp (Grok) | livekit-mcp (Soniox) | |
|---|---|---|
| AI | Grok Voice $0.08 / min | Soniox STT $0.12 / h (≈ $0.002 / min) + Soniox TTS $0.70 / h of generated speech (≈ $0.006 to $0.012 / min) + LLM (about a cent per minute or less) |
| Call routing | none | LiveKit Cloud free plan: 1,000 SIP minutes per month, then calls stop (hard cap, no surprise bill) |
| Phone line | Slovenian mobile $0.09 / min and fixed $0.15 / min when the caller ID is a number in the EU. From a non-EU caller ID the same mobile call costs $0.41 / min. | |
| Total, SI mobile, EU caller ID | ≈ $0.17 / min | ≈ $0.11 / min |
| Browser test page | $0.08 / min (AI only, no phone line) | ≈ $0.02 / min (AI only, no phone line, no SIP minutes) |
Try it in the browser
No phone number and no MCP client needed: talk to either agent through your microphone. The test page is password protected, runs at most 10 minutes per session, one session at a time, and a small hourly limit.
Open the test pagePrivacy: test sessions are not recorded. Phone calls made through the MCP servers keep a transcript in call history on the host.