built by the makers of Gamut
Tool reference

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

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

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

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
}

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.

end_call

Ends a call early. Its only argument is call_id. What happens depends on how far the call got:

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.

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

  1. The agent confirms the number and the details with the user, then calls place_call.
  2. It hands the user the listen_url.
  3. It calls get_call with wait_seconds (or every ~20 seconds) until the status is final. Most calls take 2–5 minutes.
  4. It reads resolution first, then reports the outcome, commitments and follow-ups to the user, and quotes key facts from the transcript when exact wording matters.
  5. If the user changes their mind mid-call, it calls end_call.
Guardrails apply to every call: calls disclose that they are AI-assisted and recorded, use your verified caller ID, respect destination-local hours and server-side rate limits, and cannot reach blocked ranges. Review Safety for the full model.

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.

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.