MCP App Store
by KeenEthics

Overview

Speko is a voice AI platform: voice agents that make and take phone calls, with one API across 73 text-to-speech, 54 speech-to-text and 20 speech-to-speech models. Connect it and Claude can make phone calls, transcribe audio, and narrate text. Say “Call this number and ask if they are open on Sunday” and Claude calls from a number on your Speko account, then brings back the transcript and recording. Paste a link and say “Transcribe this Dropbox recording with word timestamps”. Paste a script, pick one of 100+ voices, and get the audio file back. Claude can also build and test voice agents in a simulated conversation (no phone rings), buy a phone number after a short business declaration so an agent takes inbound calls, and turn a Vapi, Retell, LiveKit or Pipecat config into a Speko draft. Sign in once with OAuth; Google or GitHub sign-up works in the flow. No API keys to paste. Start by typing: “Narrate this paragraph in a calm voice.” First prompts for the Use cases step: 1. Call this number and ask if they are open on Sunday. 2. Transcribe this Drive recording and give me word timestamps. 3. Narrate this paragraph in a calm voice and send me the audio file.

Tools

agents.calls.list

ChatGPT
List recent calls for an agent.

agents.create

ChatGPT
Create a Speko agent. The agent is pinned to the failover stack matching intent.optimizeFor (quality / latency / cost) and intent.region. Stack tiers and their components for a given description are reported by preview_stacks.

agents.get

ChatGPT
Get one agent and its complete editable configuration, including voice, turnHandling (profile, dtmfToolDescription, amdPrompt) and system prompt. Read this before diagnosing a silent call or a missing keypad response. Voice is not validated against what the TTS provider owns. The keypad tool only arms when turnHandling.profile is "ivr" or AMD detects a machine mid-call.

agents.list

ChatGPT
List agents in the current workspace without their full system prompts. Each item includes voice, turnHandling and runMode as currently stored. Use agents.get for one agent when the full system prompt is also needed.

agents.preview_stacks

ChatGPT
Preview the THREE voice-stack options before creating an agent — so the user picks. Returns the same recommendation the dashboard's agent-create shows, as three tiers. Present them to the user with these labels and each tier's STT / LLM / TTS: premium -> "Quality" balanced -> "Fastest" cost_optimized -> "Cheapest" Ask which one they want (and confirm the region — default USA). Then call create_agent with the chosen objective mapped to intent.optimizeFor: Quality -> 'quality', Fastest -> 'latency', Cheapest -> 'cost' plus intent.region. The server then pins that tier's failover stack automatically, so the created agent matches exactly what you previewed.

agents.test_call

ChatGPT
Start an agent-to-agent test call. Dispatches the agent under test plus a caller (a persona synthesized from objective, or another agent via caller_agent_id) into ONE LiveKit room with NO phone/SIP leg — so it CANNOT hairpin the way dialing the agent's own number does. Returns immediately with a RUN id and status 'queued' - NOT a session id. Review it in THREE separately bounded phases, polling about every 5 seconds. (1) Get the session id: poll agents.test_call.get(agent_id, runId) until run.result.testCall.agentSessionId appears - the worker publishes it once the call actually starts. RECORD that id the first time you see it and keep using it: the worker REPLACES run.result on timeout, retry and abort, so a later read can lose the id while the session itself lives on. If run.status reaches passed, failed or incomplete and you never saw an id, the call never started - report what run.result says. If it reaches aborted, the run hit its deadline or ran out of retries and its result was overwritten: a session may well exist, so recover it before reporting nothing. List candidates with agents.calls.list(agent_id, since=<dispatch time>), then IDENTIFY the right one by reading calls.get on each until metadata.evalRunId equals this runId and metadata.runKind is 'test_call'. Never just take the newest - another call on the same agent can start after your dispatch, and reviewing it would report the wrong transcript and recording as this test call's. Otherwise give up after ~24 checks. Never pass the run id to a call or session tool. (2) Wait for the call: poll calls.get(agentSessionId) until it reports the call ended, then read sessions.transcript.get(agentSessionId). Bound THIS phase by ttl_seconds PLUS ~60s of worker startup headroom - that sum is the run's own deadline - never by a check count. (3) Get the recording: it finalizes AFTER the call ends, so KEEP polling calls.get for a FURTHER ~24 checks, until recording_status reads 'ready', and only then call calls.recording.get(agentSessionId) - calling it earlier returns 404 by design. Stop at once if recording_status is failed, suppressed or discarded: that recording will never exist. Provide exactly one of objective / caller_agent_id / caller_system_prompt.

agents.test_call.get

ChatGPT
Read one agents.test_call run, to get its agentSessionId. agents.test_call answers with a run id and nothing else: the room and session are created by the worker afterwards, so run.result.testCall.agentSessionId - the id every review step needs - only appears here once the call has actually started. Poll this until it does. run.status is queued / running / passed / failed / aborted / incomplete, so this is also how you learn the call ended. run.result is NOT append-only. The worker overwrites it wholesale when a run times out, is requeued, or is abandoned after its retries, leaving only an error - so an agentSessionId that was published earlier DISAPPEARS from later reads even though the session, its transcript and its recording all still exist. Record the id the first time you see it; never treat its absence from a settled or requeued run as proof that no call ever ran.

audio.synthesize

ChatGPT
Synthesize speech from text, returning base64 audio. Routed across TTS providers by the intent. The audio is returned as base64 with its content type and sample rate so a client can save or play it. Served by the Speko Router when the request is one the Router's speech body can express, and by the Platform endpoint otherwise — a request naming speed, instructions, spokenForm, a bare model or more than one allowed provider keeps the knob it asked for rather than losing it.

audio.transcribe

ChatGPT
Transcribe audio to text. Speech to text only: no audio is generated and none is returned. Google Drive's "can't scan for viruses" confirmation pages are refused as web pages; use a link that downloads the audio without a confirmation form.

calls.get

ChatGPT
Get call detail including transcript.

calls.recording.get

ChatGPT
Get a signed recording URL for one call.

models.list

ChatGPT
List the STT/LLM/TTS/S2S provider and model catalog. Each entry's id ('vendor' or 'vendor:model') is the literal string accepted by allowedProviders pins in agent and session configs; benchmarked marks entries with live Speko benchmark scores. STT and TTS entries carry priced: on audio.synthesize and audio.transcribe, a priced: false model is skipped on Speko-managed keys (the request fails if no priced model is left) and works only with the caller's own provider key, so pin a priced: true model for managed usage.

phone_numbers.kyb.get

ChatGPT
Read this workspace's phone compliance status. OAuth connector workspaces submit automatically from the phone authorization accepted during sign-in; do not collect or submit declaration fields in chat. submissionMode identifies automatic OAuth, manual dashboard/API, or grandfathered migration handling.

phone_numbers.list

ChatGPT
List phone and SIP numbers owned by the current workspace. For OAuth connectors, the first outbound call automatically provisions a dedicated number from workspace credits when none exists. Manual dashboard/API users keep the explicit declaration and purchase flow.

sessions.end

ChatGPT
Immediately request hang-up of a live voice or outbound phone session in this workspace. Use this when a call is stuck, no longer useful, or the user asks to stop it. Safe to repeat. Status ending means hang-up was requested; check sessions.get to confirm the session ended. Already ended sessions return already_ended.

sessions.get

ChatGPT
Get one session.

sessions.list

ChatGPT
List sessions for the authenticated organization.

sessions.phone.create

ChatGPT
Create an outbound phone session, dialing body.to from an owned or auto-provisioned number. Use maxDurationSeconds to set a hard call limit. ChatGPT and connector calls default to five minutes. Use sessions.end to hang up immediately when the call is stuck or the user wants to stop; sessions.get confirms that it ended. This tool has the highest error rate on this surface. Read the failure modes below before retrying. A rejected call returns one of these codes in the error body: AGENT_NOT_FOUND (agentId not in this workspace), PHONE_NUMBER_CONSENT_REQUIRED (the connector's phone-use authorization needs reacceptance), PHONE_NUMBER_KYB_ACCESS_SUSPENDED (compliance review pending, retrying will not help; check phone_numbers.kyb.get for status), PHONE_NUMBER_PROVISIONING_CREDITS_REQUIRED, _PENDING, and _FAILED (auto-provisioning a number failed or needs credit; see the returned balance and price fields), and INSUFFICIENT_CREDITS. A 2xx response does not mean the call was answered. No-answer, voicemail, and carrier rejection all settle normally and appear afterward in get_call or sessions.transcript.get, not as a tool error here. A 403 with code PHONE_NUMBER_SCOPE_REQUIRED means this connection predates phone calling and needs a full reconnect (a token refresh cannot add the permission). A 403 with code PHONE_NUMBER_CONSENT_REQUIRED means the workspace needs to accept the phone-use consent screen instead - no reconnect needed. body.voice, if set, is not validated against what the selected TTS provider owns before dialing. An unrecognized or foreign voice id can produce a dead-air leg with no error. Omit voice unless it came from this agent's own configuration; there is no voice-lookup tool on this profile.

sessions.recording.get

ChatGPT
Get a signed recording URL for one session.

sessions.transcript.get

ChatGPT
Get the ordered transcript and per-turn latency for a workspace session, including any tool calls made mid-call (toolCalls, by name and args) and a latencyStatus per turn ("partial"|"complete"|"interrupted"|"error"). Use this to confirm whether a keypad press (send_dtmf) was invoked, or whether a turn with no agent text and an "error" latency status points to a synthesis failure rather than the callee hanging up.

support.ticket.create

ChatGPT
Open a support ticket with the Speko team on behalf of the signed-in user. summary is one line (3-200 characters); details is the full description (up to 4,000 characters). category is billing, calls, setup or other (default other). related optionally carries ids the team should look at: sessionId, callId, agentId, phoneNumber. Ids only: recordings and transcripts are never attached. Returns ticketId and expectedResponse; the user also receives a confirmation email and the team replies to that email address. Returns 429 SUPPORT_TICKET_RATE_LIMITED after too many tickets in a short time; the error says when to retry. A ticket is stored even when the team notification is delayed, so a success never needs a resend.

support.ticket.list

ChatGPT
List the organization's support tickets, most recent activity first. status filters to open (waiting on Speko), answered (Speko replied last), closed, or all (default). limit is 1-100 (default 50). stage is where the ticket stands for the user: sent, in_review (the team opened it), replied or resolved. Each ticket carries unreadReplies, the number of Speko replies the user has not read yet, and ticketUrl, the dashboard page for it. Read a conversation with support.ticket.get. An organization with no tickets returns an empty list.

support.ticket.reply

ChatGPT
Add a message from the user to a support ticket (1-4,000 characters). The Speko team sees it in the same thread, and the ticket moves to open (waiting on Speko); a closed ticket is reopened. Use it to answer a question the team asked or to add details, instead of opening a new ticket. Ids only: never paste recordings, transcripts or secrets. Returns 404 SUPPORT_TICKET_NOT_FOUND for an id outside this organization and 429 SUPPORT_TICKET_RATE_LIMITED after too many messages in a short time.

voices.list

ChatGPT
List the Speko TTS voice catalog: voices (vendor, id, name) plus TTS providers with their models. Use a returned voice id as the voice field on agents.create or POST /v1/sessions bodies.

agent_access.oauth_grant.revoke

Claude

agent_access.overview

Claude

agents.apply_prompt_fix

Claude

agents.apply_stack_fix

Claude

agents.calls.list

Claude

agents.config_structure.get

Claude

agents.create

Claude

agents.delete

Claude

agents.deploy

Claude

agents.duplicate

Claude

agents.evals.character.set

Claude

agents.evals.create

Claude

agents.evals.delete

Claude

agents.evals.generate

Claude

agents.evals.list

Claude

agents.evals.run

Claude

agents.evals.runs.list

Claude

agents.evals.runs.suggest_fix

Claude

agents.evals.suggest_prompt_fix

Claude

agents.evals.update

Claude

agents.get

Claude

agents.graph.get

Claude

agents.graph.replace

Claude

agents.graph.seed

Claude

agents.list

Claude

agents.monitoring.results.list

Claude

agents.monitors.create

Claude

agents.monitors.delete

Claude

agents.monitors.events.list

Claude

agents.monitors.list

Claude

agents.monitors.update

Claude

agents.preview_stacks

Claude

agents.rollback

Claude

agents.test_call

Claude

agents.tools.create

Claude

agents.tools.delete

Claude

agents.tools.get

Claude

agents.tools.list

Claude

agents.tools.update

Claude

agents.update

Claude

agents.versions.list

Claude

api_keys.create

Claude

api_keys.list

Claude

api_keys.revoke

Claude

audio.synthesize

Claude

audio.transcribe

Claude

billing.auto_topup.get

Claude

billing.auto_topup.resume

Claude

billing.auto_topup.setup

Claude

billing.auto_topup.update

Claude

billing.checkout.create

Claude

billing.invoices.list

Claude

billing.portal.create

Claude

calls.get

Claude

calls.recording.get

Claude

capabilities.describe

Claude

code_snippets.get

Claude

credits.balance.get

Claude

credits.ledger.list

Claude

evals.get

Claude

gateway.activity.list

Claude

gateway.instances.list

Claude

gateway.legacy_keys.list

Claude

gateway.legacy_keys.revoke

Claude

gateway.models.list

Claude

gateway.overview.get

Claude

gateway.profiler.conversations.get

Claude

gateway.profiler.conversations.list

Claude

gateway.profiler.turn_trace.get

Claude

gateway.provider_credentials.delete

Claude

gateway.provider_credentials.list

Claude

gateway.provider_credentials.replace

Claude

gateway.relay.activity.list

Claude

gateway.relay.credit.get

Claude

gateway.relay.tts_preview.create

Claude

gateway.relay.usage.get

Claude

gateway.usage.get

Claude

gateway.workloads.list

Claude

knowledge_bases.create

Claude

knowledge_bases.delete

Claude

knowledge_bases.documents.create

Claude

knowledge_bases.documents.delete

Claude

knowledge_bases.documents.finalize

Claude

knowledge_bases.documents.get

Claude

knowledge_bases.documents.list

Claude

knowledge_bases.get

Claude

knowledge_bases.list

Claude

migration.briefing.render

Claude

migration.external_config.parse

Claude

migration.session_config.build

Claude

migration.workspace.inspect

Claude

models.list

Claude

operations.cancel

Claude

operations.get

Claude

operations.list

Claude

operations.wait

Claude

organization.get

Claude

phone_numbers.create

Claude

phone_numbers.delete

Claude

phone_numbers.get

Claude

phone_numbers.kyb.get

Claude

phone_numbers.kyb.submit

Claude

phone_numbers.list

Claude

phone_numbers.update

Claude

scenarios.archive

Claude

scenarios.attach

Claude

scenarios.create

Claude

scenarios.detach

Claude

scenarios.list

Claude

scenarios.runs.list

Claude

sessions.create

Claude

sessions.get

Claude

sessions.list

Claude

sessions.phone.create

Claude

sessions.recording.get

Claude

sessions.transcript.get

Claude

share_cards.create

Claude

usage.summary.get

Claude

voices.list

Claude

App Stats

148

Tools

3

Prompts

ChatGPT, Claude

Platforms

Works with

ChatGPT
Claude

Data refreshed daily