MCP

View as Markdown

Dial speaks the Model Context Protocol two ways, so an agent can reach Dial’s capabilities as MCP tools without writing any HTTP code:

  • Local (Recommended)npx @getdial/cli mcp, a stdio server you run on your own machine. It reuses the API key already saved by dial onboard, and npx runs it without a global install. Use it when the agent runs on the same machine as your Dial setup — for example, Claude Code.
  • Remote — a hosted server at https://getdial.ai/mcp. Point any MCP client that supports remote servers at that URL and authorize in the browser — no install, no API key to copy. Use it when the agent runs off your machine, like a web or desktop client — for example, Claude Chat or Claude Cowork.

Both expose the same operational tools under the same names (send_message, place_call, wait_for_event, …), each mirroring a dial CLI command. The Local server is a strict superset: everything Remote has, plus enhanced inbound capabilities the hosted server can’t offer (a persistent listen daemon, local event fan-out, and onboarding).

Which one?

LocalRemote
Command / endpointnpx @getdial/cli mcphttps://getdial.ai/mcp
TransportstdioStreamable HTTP
AuthSaved CLI key (~/.local/share/dial/auth.v1.json)OAuth 2.1, browser consent
InstallNone — npx fetches the CLI on demandNone — hosted
Where it runsThe machine that owns the Dial setupAnywhere — agent can be off-machine
Tool surfaceOperational tools + enhanced inbound capabilitiesOperational tools

Pick Local when the agent runs on the same machine that owns the Dial setup and you want onboarding, the background listen daemon, or local event fan-out. Pick Remote when you want browser auth and the agent runs off-machine.

Connect

Add Dial as an MCP server in your client. The two transports take different config — both expose the same tools:

1{
2 "mcpServers": {
3 "dial": {
4 "command": "npx",
5 "args": ["-y", "@getdial/cli", "mcp"]
6 }
7 }
8}

Local runs the CLI’s stdio server through npx — no global install. It authenticates with the key already at ~/.local/share/dial/auth.v1.json (no OAuth, no config), so install the CLI and sign in once first (see Install & onboarding) — or let the sign_up and onboard tools bootstrap a fresh machine from inside the agent. The server speaks JSON-RPC on stdout and logs to stderr.

Remote points at the hosted server over Streamable HTTP at that single endpoint — there is no SSE or stdio variant. On first connect the client opens a browser to authorize:

1

The client requests access

It registers itself with Dial automatically (OAuth 2.1 dynamic client registration) and opens Dial’s consent page.

2

You sign in

If you’re signed out, Dial emails you a one-time code. If you don’t have a Dial account yet, a new one is created for you — with no phone number until you ask for one.

3

You grant access

Approve the request on the consent screen, and Dial issues the client an access token scoped to your account.

Tokens are scoped per account: a tool only ever sees your own numbers, messages, and calls.

Tools

The operational tools are identical on both servers; the enhanced inbound capabilities run only under the local server. See the CLI command reference for the underlying semantics.

ToolPurposeRemoteLocal
get_account_statusAccount and phone-number readiness
list_numbersList your phone numbers
purchase_numberProvision an additional number
set_number_propertiesUpdate a number’s properties (inbound instruction, language, voice, nickname)
send_messageSend an SMS
list_messagesList recent messages
place_callPlace an outbound AI voice call
list_callsList recent calls
get_callFetch one call (status, duration, transcript)
wait_for_eventBlock until a matching account event arrives
sign_upStart signup (email OTP)
onboardVerify the code and provision a number
listen_installInstall the background event daemon
listen_uninstallRemove the daemon
listen_statusDaemon health
add_url_targetFan events to a loopback URL
add_command_targetFan events to a spawned handler
remove_local_targetRemove a local target
list_local_targetsList local targets

When a tool that sends from a number omits fromNumberId, Dial uses your primary number.

A couple of tools behave slightly differently per server: wait_for_event reads the local listen service log when the daemon is running (and falls back to the REST API otherwise) on the Local server, while the Remote server always long-polls the REST API; get_account_status on the Local server reflects the local doctor view of the machine.

Enhanced inbound capabilities

Running on your machine, the local server can handle inbound events in ways the hosted server fundamentally can’t — it keeps a persistent listener alive and routes inbound calls and messages straight to your machine:

  • The listen service — an always-on background daemon that captures inbound calls and messages even while no agent is connected.
  • Local-target fan-out — deliver inbound events to a loopback URL or spawn a local handler as they arrive.
  • Sign-up and onboarding — bootstrap a fresh machine from inside the agent (the hosted server replaces these with its browser consent flow).

The hosted server can’t reach your machine, so these are exposed only by the local server. For any of them, run npx @getdial/cli mcp (or the CLI) on the machine that needs them.