Four tools for the call.
Updated October 11, 2026
DialMCP exposes four MCP tools: place_call, get_call, end_call and list_calls. Calls are asynchronous. place_call returns a call ID as soon as the call is dialed, the call runs in the background for a few minutes, and your agent follows it with get_call until it reaches a final status. Your client sends these as tools/call requests after a tools/list; the JSON-RPC side is covered in MCP server commands and tool calls.
This page is the full contract: every argument, every response field, every status, and every rejection code, with what an agent should do about each. Your assistant reads the short tool descriptions on its own. This page is for you, and for anyone writing a client or prompt around DialMCP.
How results come back
Every tool returns a single text content block holding pretty-printed JSON. That includes refusals. A rejected call is a normal tool result with an error code and a human-readable message, not a protocol error, so the model sees the reason and can tell the user. Clients that only surface isError results should also check for an error key. Arguments outside the types or ranges below are different: the MCP SDK’s input validation rejects them before DialMCP sees them, as a standard isError result.
Every tool runs as the signed-in account. Call IDs belong to the account that created them. Looking up someone else’s ID, or one that does not exist, returns {"error": "not_found", "message": "Unknown call_id for this account."}. Sign-in is described on OAuth.
place_call
Starts an outbound call from your verified number to a US or Canadian number, with a stated objective. A real-time voice agent handles the conversation. It opens by saying it is an AI assistant calling on your behalf and that the call is recorded. It can press keys through phone menus, waits silently on hold, and does not leave voicemail messages.
Arguments
to(string, required): the destination in E.164 form, for example+14155551234. It must be+1followed by ten digits, with an area code that does not start with 0 or 1. Anything else returnsinvalid_number.objective(string, required, 10–2,000 characters): what the call should achieve, with every specific the agent needs and the fallbacks you would accept. The agent is instructed to state only facts given here or incontext, plus your first name and your verified number as a callback, and never to invent names, prices or phone numbers. Put everything it needs in the request.callee_name(string, optional, up to 200 characters): who is being called, such as “Zuni Café”. It helps the conversation and makes call history readable.context(string, optional, up to 2,000 characters): background the agent may share if asked but should not volunteer, such as a date of birth for an appointment lookup or a seating preference.max_duration_minutes(integer, optional, 1–10): a hard cap on call length. The default is 6. When the cap is hit, the carrier ends the call and it finishes ascompletedwith whatever was said.
A good objective reads like instructions to a capable assistant:
{
"to": "+14155551234",
"callee_name": "Zuni Café",
"objective": "Book a table for 2 tonight at 19:30 under 'Iddo'. Acceptable window 19:00–20:30. If nothing is free, ask about the bar and get the earliest time tomorrow.",
"context": "One guest is vegetarian. Do not give a credit card number.",
"max_duration_minutes": 6
}Response
{
"call_id": "c_4f1d…",
"status": "queued",
"listen_url": "https://mcp.dialmcp.com/listen/c_4f1d…?tok=…",
"note": "Call started. Poll get_call every ~20s (or pass wait_seconds). Typical call: 2–5 minutes. Offer the listen_url to the user — it lets them hear the call live, follow the transcript, and stop the call if needed."
}listen_url is an unguessable signed link meant for the person who placed the call. There is no separate login, so anyone holding the link can listen and stop the call. Share it only with the user. While the call runs, it streams the live audio and transcript and has a stop button. After the call it shows the recording and transcript. Each link works for four hours, and get_call returns a fresh one on every response. Agents should offer it to the user.
Before anything is dialed, the request goes through the safety checks listed under rejections. A rejected call is never dialed, and the response has no call_id. The one exception is dial_failed: the call record exists, but the carrier refused the call.
get_call
Returns the current state of a call and, once it has ended, its result.
Arguments
call_id(string, required): the ID fromplace_callorlist_calls.wait_seconds(integer, optional, 0–50): 0, the default, answers immediately. A higher value makes the server hold the request and return as soon as the status changes, or when the time runs out. If the call has already ended, the server uses the wait to hold for the recording instead.
Long-polling means fewer round trips and quicker updates. Check your client’s tool timeout first: a 50-second wait needs a timeout above 50 seconds. Per-client timeouts, such as Codex’s tool_timeout_sec, are on client setup. If the timeout is short, poll about every 20 seconds with no wait instead.
Response fields
status: one of the twelve statuses in the status lifecycle.toandcallee_name: as sent toplace_call.duration_seconds: time from answer to hang-up. It isnullfor unanswered calls, and can also benullfor calls that were canceled, failed or reached voicemail.amd_result: the carrier’s answering-machine guess:human,machine,not_sureorno_amd, ornullbefore pickup. It is a hint only. The voice agent makes the final call on voicemail from what it hears.listen_url: the private call page, minted fresh each time.transcript: turn-by-turn, as{"role": "agent" | "callee", "text": …}. It fills in while the call is live. Very long calls are trimmed to fit the response. The opening and the ending are kept, a marker replaces the middle, andtranscript_truncated: trueis set. The full conversation is in the recording.resolution: the structured result described below. It isnulluntil it has been extracted, which usually takes a few seconds after the call ends.recording_urlandrecording_status:available,processingornone. The carrier usually finishes the recording 15–90 seconds after hang-up. While it isprocessing, arecording_noteexplains that, and callingget_callagain withwait_secondswaits for it. A recording link expires after about an hour. An expired link returns HTTP 410 with “link expired — ask the agent for a fresh one”, and any newget_callmints a new link.ended_by: present only as"user", when you stopped the call from the listen page. It comes with anended_by_notetelling the agent not to retry unasked. The transcript shows how far the call got; see the resolution notes on canceled calls.error: set onfailedcalls with the technical cause, otherwisenull.
The resolution object
The resolution is the answer to “did it work?”. Agents should read it before the transcript. It has six fields:
{
"outcome": "achieved",
"summary": "Booked a table for 2 at 19:30 tonight under Iddo.",
"commitments": ["Table for 2 at 19:30 tonight, held 15 minutes"],
"follow_ups": ["Call back if plans change; no card was taken"],
"key_facts": ["Host: Marco", "Kitchen closes at 22:00"],
"callee_requested_no_further_calls": false
}outcome:achievedonly when the objective was done and the other side confirmed it. A tentative or unconfirmed arrangement ispartially_achieved.not_achievedmeans a conversation happened but did not get there.no_conversationmeans there was no real two-way exchange.summary: one or two sentences a person can read instead of the transcript.commitments: concrete promises made on the call, with specifics.follow_ups: things you still need to do, such as “bring ID” or “call back after 3pm”.key_facts: names, prices, hours and reference numbers learned on the call.callee_requested_no_further_calls: true only when the other person explicitly asked not to be called again. When it is true, the number goes on the permanent opt-out list.
The resolution is written by a model reading the transcript, and it is told to report only what the transcript supports. Speech recognition can still mishear names and numbers. For anything that matters, such as a confirmation code, check the transcript or the recording. Calls that end as no_answer, busy, voicemail or canceled, and any call with an empty transcript, get a fixed no_conversation resolution right away, such as “Nobody answered the call.” That includes a call you stopped from the listen page mid-conversation. For those, read the transcript rather than the resolution.
Status lifecycle
A call moves through up to four live statuses and ends in exactly one of eight final ones. Once a status is final, it never changes.
- Live:
queued→dialing→ringing→in_progress. Some carriers skipringingon a fast answer.in_progresscovers everything after pickup: phone menus, hold, the conversation, and the goodbye. completed: someone answered and the call ended normally. That includes the agent finishing, the other side hanging up, the duration cap, and a dead end such as an endless hold. Readresolution.outcometo see whether it worked.completeddoes not meanachieved.no_answer: nobody picked up.busy: the line was busy.voicemail: an answering machine picked up. The agent hangs up without leaving a message.failed: a carrier or system error. Checkerror. A call that loses contact with the carrier is failed by a watchdog about a minute past its duration cap, counted from dialing.canceled: stopped before a conversation throughend_call, or stopped from the listen page at any point before the goodbye (withended_by: "user"). Its resolution is alwaysno_conversation, so check the transcript.declined_recording: the other person objected to talking to an AI or being recorded. The agent apologizes and hangs up without arguing.opted_out: the other person asked not to be called again. The agent confirms, hangs up, and the number is permanently blocked for every DialMCP user.
end_call
Ends a call early. Its only argument is call_id. What happens depends on how far the call got:
- Once the voice agent is live on the line: the agent says a short goodbye (“Actually, I have everything I need — thanks so much for your time. Have a great day!”) and hangs up. If the goodbye takes more than about 10 seconds, the line is cut anyway. The tool returns
"status": "in_progress"while that happens. The call then finishes ascompleted, with its partial transcript and a resolution. - Before the voice agent is live (queued, dialing, ringing, or the first moments after pickup): the call is hung up at once and returns
canceled. - Already finished: nothing happens, and the tool returns the final status.
If the agent was already saying goodbye when you called it, end_call can report canceled while the call actually ends with another status. get_call is always the source of truth.
Use end_call when the user changes their mind or the task no longer needs the call. The stop button on the listen page is different. It is an emergency stop with no goodbye, for when a call is going wrong.
list_calls
Lists the account’s calls, newest first. Use it to recover a lost call ID, or to answer “what happened with the dentist yesterday?”. The optional limit is 1–100, default 20.
{
"user": { "name": "Iddo", "phone": "+1415…" },
"calls": [
{
"call_id": "c_4f1d…",
"to": "+14155551234",
"callee_name": "Zuni Café",
"status": "completed",
"objective": "Book a table for 2 tonight at 19:30…",
"created_at": "2026-10-11T02:14:07.312Z",
"duration_seconds": 143,
"outcome": "achieved"
}
]
}The list shows the outcome but not the full resolution, transcript or recording. Pass the call_id to get_call for those. Every client signed in with the same phone number sees the same history.
Rejections and what to do about them
Before dialing, place_call runs a fixed sequence of checks. Rejections that depend on time carry machine-readable fields, so an agent can tell the user exactly when to retry instead of retrying blindly.
invalid_number: not a US or Canadian E.164 number. Fix the format.service_paused: the operator has paused all outbound calling. Try later.blocked_destination: a premium-rate (1-900 or 976 exchange) or emergency/crisis code. These are never dialed, so do not retry.invalid_destination: a+1number in the Caribbean or a US territory, outside US and Canada calling.suppressed_destination: that number told a DialMCP agent not to call again. This is permanent.concurrent_call_active: one call at a time per account. Wait for the current one withget_call, or end it.rate_limited: 3 calls per rolling hour or 10 per rolling 24 hours per account, or a short burst limit. It includeswindow(burst,hourorday). The hour and day windows also includelimitandreset_at, the ISO time the oldest counted call drops out.destination_rate_limited: at most 2 calls from your account to the same number per rolling 24 hours, withreset_at. Repeated calls to one number look like harassment, so this limit exists for the person being called.excluded_stateandline_type_blocked: the destination’s region or line type is outside policy. Both lists are empty today, so these are reserved for future policy.outside_calling_hours: calls start only between 8:00 and 21:00 in the destination’s local time. The response includesdestination_local_houranddestination_tz. For an area code that spans zones or is not in DialMCP’s map,destination_tzis the string"conservative",destination_local_houris the Eastern hour, and the window must hold in both Eastern and Pacific time.objective_rejected: the objective failed a safety screen. Ordinary errands pass: reservations, appointments, order status, prices and availability, rescheduling and cancellations. The screen is built to stop harassment, threats, impersonating a real person or institution, debt collection, telemarketing, emergency lines, digging up private data about third parties, and anything illegal. Rephrase only if the task really is legitimate.dial_failed: the checks passed but the carrier rejected the call. The response carries thecall_id. Check the number.
Rate limits are per account, not per client, so Claude and Cursor signed in with the same number share one budget. The policy behind each check is on Safety.
A typical run
- The agent confirms the number and the details with the user, then calls
place_call. - It hands the user the
listen_url. - It calls
get_callwithwait_seconds(or every ~20 seconds) until the status is final. Most calls take 2–5 minutes. - It reads
resolutionfirst, then reports the outcome, commitments and follow-ups to the user, and quotes key facts from the transcript when exact wording matters. - If the user changes their mind mid-call, it calls
end_call.
FAQ
Why doesn’t place_call wait for the call to finish?
Calls take minutes, and most MCP clients time out tool calls well before that. Returning a call ID right away and following up with get_call works in every client.
Can the agent leave a voicemail?
No. When voicemail answers, the agent hangs up silently, and the call ends as voicemail with a no_conversation resolution.
Can I call the same number again if the first call failed?
Yes, up to twice from your account per number in a rolling 24 hours. Rejected attempts do not count toward the hourly, daily or per-number limits, though they do count toward the short burst limit. Every call that passed the checks counts, including dial_failed and unanswered calls.
Does a completed call mean the task worked?
No. completed only means someone answered and the call ended normally. Whether the task worked is in resolution.outcome.
Related docs
Need to connect first? Follow the installation guide or paste a client config from MCP server configuration examples. Building your own server instead of using these four tools? How to build an MCP server covers the same lifecycle. Need to understand sign-in? Read OAuth and phone verification. Want the end-to-end walkthrough? See how to make a phone call with an AI assistant. Want the capability map? See what an AI assistant can do on a call. Comparing a dedicated app to an agent in your existing client? See AI phone call app vs. agent. Picking among MCP phone agents? See best AI phone call agent. Checking launch pricing? See free during launch. Comparing voice stacks that can actually ring a cell phone? See which voice AI APIs can call a cell phone.