Supafone Labs · Documentation

MCP Server#

Supafone Labs ships a local MCP server for Claude Desktop under:

text
supafone-labs/mcp/supafone_mcp.py

It is a dependency-light Python stdio JSON-RPC server. Claude can use it to create hosted agents, turn a plain-English job description into production call prompts, provision numbers, check usage, and poll Labs logs.

Use this when you want Claude Desktop to run agent-team experiments: one tool call can create an inbound receptionist, another can create an outbound sales agent, and a third can tail logs while the team evaluates different provider configurations.

The human benefit is that the conversation can begin with the outcome instead of infrastructure: “Build a warm lead caller for a roofing company.” The MCP generates an editable plan, explains the stages, and can create the hosted agent with the same key. It never asks Claude—or the user—to paste Supafone's Haiku, telephony, TTS, or SMTP credentials into the conversation.

Environment#

One-key setup (recommended, 0.4.4+): a single sl_ Labs key authenticates everything — the Labs Cloud tools and the campaign/calling tools on the main product API (via one-key auth). Set one env var:

bash
export SUPAFONE_TOKEN=sl_live_...   # one key: labs + campaigns + calls

The only requirement is that an app.supafone.ai account exists with the same email that owns the key.

The older, explicit per-surface variables still work and take precedence when set:

bash
export SUPAFONE_API_KEY=sl_live_...       # your one sl_ key (or a scoped sf_ hosted-agent key)
export SUPAFONE_LABS_API_KEY=sl_live_...  # Labs Cloud logs/usage
export SUPAFONE_API_BASE_URL=https://api.supafone.ai
export SUPAFONE_LABS_API_BASE_URL=https://api.labs.supafone.ai

For the campaign and calling tools, SUPAFONE_TOKEN may also hold an app.supafone.ai JWT, or the server can log in for you (and transparently re-login when the token expires):

bash
export SUPAFONE_TOKEN=eyJ...            # an app.supafone.ai JWT, or:
export SUPAFONE_EMAIL=you@company.com
export SUPAFONE_PASSWORD=...

Claude Desktop#

Add this server to claude_desktop_config.json:

json
{
  "mcpServers": {
    "supafone-labs": {
      "command": "python3.12",
      "args": [
        "/path/to/supafone-labs/mcp/supafone_mcp.py"
      ],
      "env": {
        "SUPAFONE_TOKEN": "sl_live_..."
      }
    }
  }
}

Restart Claude Desktop after saving the config.

Tools#

ToolPurpose
create_inbound_agentCreate an inbound hosted voice agent through the Python SDK.
create_outbound_agentCreate an outbound hosted voice agent through the Python SDK.
create_inbound_agent_with_numberCreate an inbound agent and provision or assign a number.
create_outbound_agent_with_numberCreate an outbound agent and provision or assign a number.
generate_call_stagesTurn one description into complete, validated prompts and a 3-8 stage runtime plan.
get_usageRead Labs Cloud usage and caps from /v1/usage.
list_logsRead recent Labs Cloud logs from /v1/logs.
tail_logsPoll Labs Cloud logs for a bounded live-looking stream.
poll_logsAlias for tail_logs.
get_call_modesExplain both call directions and check managed phone-grader readiness.
grade_existing_phone_agentSynthetic tester → existing agent. Provider-neutral across target runtime/carrier.
get_agent_gradeRead carrier state, transcript, and verdict for an agent-grading session.
wait_for_agent_gradePoll an agent-grading session to a bounded terminal result.
generate_qa_scenariosGenerate adversarial scenarios from an agent prompt.
list_qa_runsRead prior QA and Watcher benchmark results.
run_watcher_qaRun every scenario with and without Watcher supervision (Labs login required).

The four hosted creation tools also accept languageVoiceRouting, routingLanguages, and languageProfiles. These are public provisioning preferences only; the MCP server does not contain the private live-routing implementation. See Live Language and Voice Routing.

Test any voice stack#

grade_existing_phone_agent uses PSTN as the provider-neutral boundary. The target may run Vapi, Retell, Bland, OpenAI Realtime, Grok, LiveKit, a custom runtime, or another framework, and its carrier may be Twilio, Telnyx, SignalWire, SIP, or another provider. These names are recorded as metadata; Supafone does not need to host either side of the target stack.

The tool places a real call and spends tester credits. It rejects the request unless authorized is exactly true. Use get_agent_grade for one status read or wait_for_agent_grade for bounded polling to the final transcript and verdict.

run_watcher_qa is a different lane: it runs synthetic A/B conversations without dialing a phone. It requires the Labs account email/password because the saved Builder configuration is session-scoped.

Campaigns & calls (main-app account login)#

ToolPurpose
call_from_owned_agentOwned agent → human: places a real outbound call and requires confirmRealCall:true.
start_call_and_watchPreferred natural-language action: places the guarded owned-agent call and returns its authenticated live-dashboard link.
list_voice_agentsList the account's voice agents to pick an agentId for calls and campaigns.
list_campaignsList outbound campaigns with live stats.
create_campaignCreate a draft campaign (goal: book / qualify / follow_up / reengage).
get_campaignFetch one campaign's config, settings, cadence, and stats.
update_campaignUpdate name/goal/agent/email copy/cadence/settings (settings merge server-side).
add_campaign_recipientsAdd consented leads ({name, phone, email, outreach_consent:"yes"}).
list_campaign_recipientsList recipients with their cadence state.
launch_campaignStarts real calls/emails and requires confirmLaunch:true.
pause_campaignPause an active campaign.
list_campaign_presetsBuilt-in playbooks plus the account's saved custom presets.
apply_campaign_presetMaterialize a preset (goal, questions, scripts, signing doc) in one write.
create_sign_linkMint a recipient's tracked tap-to-sign page (inherits the campaign's signing PDF).
monitor_campaignWatch a campaign live: in-flight calls + recent calls, each with a portal listen link.
get_callOne call's record — poll it while in progress to follow the live transcript.

Owned-agent calls are carrier-neutral. Supafone resolves the provider already configured for the account—native, BYO Twilio, BYO Telnyx, BYO Plivo, or BYO SIP—inside the private runtime. Provider credentials never enter the MCP process or the returned dashboard URL.

Campaigns as code (YAML config)#

ToolPurpose
generate_campaign_configDraft a full campaign YAML from a plain-English description.
apply_campaign_configValidate, then apply a YAML/JSON campaign config. launch:true also requires confirmLaunch:true.
export_campaign_configRound-trip an existing campaign back out as YAML.

Campaign configs support branding: ({url} to scan on apply, and/or explicit colors/logo/favicon — explicit wins) and intake_form: ({description[, industry]} to LLM-generate on apply, or an explicit config: block) alongside goal, agent, cadence, recipients, and outbound script keys.

Branding & intake generation#

ToolPurpose
scan_brandScan a website for its branding: business name, colors, logo, favicon, OG metadata, images, key pages — the same detection that styles agents during onboarding, as plain data.
generate_intake_formLLM-generate an intake form from a description (optionally per industry), standalone or applied straight to an agent.

E-sign documents#

ToolPurpose
upload_signing_documentUpload a PDF (e.g. a retainer) as a campaign's signing document.
detect_signature_fieldsAuto-detect signature/date/initial coordinates on the uploaded PDF.
set_signature_fieldsSet or adjust the placed signature fields explicitly.

Together these make the whole signature-chase drivable from prose: upload the retainer, apply the detected coordinates, add leads, launch, then create_sign_link per recipient.

The coolest things to ask for#

These all work in plain English in Claude Desktop / Claude Code once the server is configured — Claude picks the tools, you get links back.

"Launch a campaign from this list"#

*"Create a win-back campaign using my Northline agent. Add these leads —

Jane Doe +1 555 123 4567, Marcus Reid +1 555 987 6543, both consented —

apply the win-back playbook, and launch it."*

Claude chains list_voice_agentscreate_campaignapply_campaign_presetadd_campaign_recipientslaunch_campaign. Real calls start dialing on the cadence within seconds.

"Call me so I can hear my agent"#

*"Place a call from my sales agent to my cell, +1 555 000 1111 — I want to

hear how it sounds."*

call_from_owned_agent rings your phone and bridges the voice agent onto the line. The fastest possible demo of your own agent.

"Who's on the phone right now? Let me listen"#

"Which campaign calls are happening right now? Give me links to listen in."

monitor_campaign returns the live funnel and every in-flight call with a portal link — open one and watch the transcript grow as the conversation happens. The campaign-level link opens the developer portal (app.supafone.ai/app/developer) with all of it live on one page.

"Follow that call and tell me how it ends"#

"Keep an eye on the call with Jane and tell me whether she books."

Claude polls get_call — each poll returns the transcript so far — and narrates the conversation as it unfolds, then reports the outcome and classification when the call completes.

"Chase signatures on our retainer"#

*"Start a signature-chase for the Henderson matter: apply my

'Retainer signature chase' preset and send Jane her signing link."*

A custom preset carries your questions, scripts, email copy, AND the uploaded retainer PDF with placed signature fields. apply_campaign_preset + create_sign_link put a tracked tap-to-sign page in Jane's hands; when she signs, the stamped PDF lands on her lead row and in your inbox.

"Spin up an agent AND put it to work"#

*"Create an outbound agent for Northline Roofing with a 415 number, then

build a quote-follow-up campaign with it and add yesterday's quotes."*

Hosted-agent provisioning (create_outbound_agent_with_number) and the campaign tools compose — one conversation goes from nothing to a staffed, dialing campaign.

"Build the whole campaign from my website"#

*"Scan northline.example for our branding, draft a quote-follow-up campaign

config with an intake form for roofing leads, show me the YAML, then apply

it."*

scan_brandgenerate_campaign_configapply_campaign_config. The applied campaign carries your real colors and logo, an LLM-generated intake form, cadence, and scripts — and export_campaign_config round-trips it back to YAML for version control.

"Tune the script mid-flight"#

*"Pause the campaign, make the opening warmer — mention we spoke at the

home show — and relaunch."*

pause_campaignupdate_campaign (settings.outbound_prompts) → launch_campaign. The next dial uses the new script; the builder UI shows the same change instantly.

Example Agent#

json
{
  "agentKey": "northline-intake",
  "name": "Northline intake",
  "assistantName": "Maya",
  "websiteUrl": "https://northline.example",
  "number": { "search": { "areaCode": "415" } },
  "labs": {
    "enabled": true,
    "mode": "supafone_managed",
    "model": "gemma"
  },
  "voice": {
    "provider": "cartesia",
    "voiceId": "sonic-warm"
  }
}

For BYOK, keep the three credential lanes separate:

LaneMCP/config fields
Agent/provider stackbyok.agentProvider, providerKeys.ultravoxApiKey, providerKeys.retellApiKey, providerKeys.vapiApiKey
Telephonybyok.telephony, telephony.credentials, telephony.customSip
TTSbyok.tts, providerKeys.cartesiaApiKey, providerKeys.elevenlabsApiKey, providerKeys.inworldApiKey

For durable credentials, prefer the MCP env block or account credential store instead of prompt text.

MCP also exposes lifecycle and artifact tools:

Ask naturally#

Examples that map directly to generate_call_stages:

The response includes generated_by and fallback. An MCP client can explain whether the hosted planner or safe deterministic template produced the result, then present the ordinary JSON for human review.

Log Streaming Note#

MCP tool calls are request/response. The local MCP server therefore exposes tail_logs and poll_logs as bounded polling tools. The browser and SDKs can use the true SSE stream documented in Log Streaming.

Stripe card entry always stays on Stripe-hosted Checkout. MCP responses contain only the public checkout_url and session reference—never Stripe secrets or card data.

View raw Markdown