Sautikit runs a hosted Model Context Protocol server that gives Claude 42 tools over your voice workspace. Add it to claude.ai as a custom connector, sign in with OAuth — no API key — and your call center becomes a conversation: check the wallet, place a call, launch or pause a broadcast, pull a recording, inspect call stats, validate a voice-actions document before you wire it to a number. Anything that spends money stops and asks you first. This post walks each workflow end to end, then covers scoped API keys for editor clients like Claude Code and Cursor.
A call-center lead's morning is a dashboard tour. Wallet page to check the balance. Campaign page to see how Friday's broadcast finished. Call log to find the complaint call a customer mentioned. Recording player to hear it. Each screen is fine on its own; the tax is the switching, and the translating — turning a CSV report and a ledger into the one sentence your boss asked for.
With the Sautikit connector in claude.ai, that whole loop is one chat. Claude holds the context between steps, so "pull Friday's broadcast report and tell me who to retry" is a single instruction, not four tabs and a spreadsheet.
Two things make this safe enough to hand to an operator rather than a developer. First, every tool wraps the public REST API — same auth, same scopes, same rate limits, same billing, no backdoor. Second, the client keeps a human in the loop: tools that spend money or destroy things are annotated so Claude asks before running them. More on both below.
As of this writing (July 2026), Sautikit is the only voice-first CPaaS we could find with a hosted, OAuth-protected MCP server and live call-event tools. Twilio's hosted MCP server is docs-only — search and retrieval over its API reference, no account actions (per Twilio's MCP docs, July 2026). Telnyx ships a full-featured server, but it installs locally and runs on a raw API key. Infobip hosts remote MCP servers in beta, led by its messaging channels. The pattern itself is well proven outside telephony: Stripe, PayPal, and Square all run hosted MCP servers where consequential actions sit behind confirmation. Voice was the missing column.
In claude.ai, open Settings → Connectors and choose Add custom connector.
Paste the server URL: https://mcp.sautikit.com/mcp (the trailing /mcp is required).
Click Connect. A browser popup opens Sautikit's sign-in — the OAuth 2.1 flow the MCP spec mandates, so no API key ever touches the chat client.
Sign in, pick the workspace to connect, and approve the scope groups you want to grant: Read-only, Calls + numbers, Agents + broadcasts, Account.
Done. Ask Claude for your wallet balance to confirm the handshake.
Grants are yours to inspect and kill: revoke the connection any time under app.sautikit.com → Settings → Connected apps, and access ends on the next request. Custom connectors are available on every claude.ai plan — Free accounts get one connector; paid plans get more (per Anthropic's support docs, July 2026). On Team and Enterprise plans, an org owner adds the connector under Organization settings first, then each member connects and signs in individually — the connector acts as you, with your workspace permissions, not as a shared robot account.
Full setup details, including editor clients, live in the connect guide.
The first time Claude wants to use a tool, it asks. You can allow it once, or choose Always allow for that tool going forward. Anthropic's guidance is to reserve Always allow for tools you would let run unsupervised — and the Sautikit tool set is designed so that split is obvious:
The money-spending tools carry MCP annotations that tell the client to confirm before running, so even a fully-trusted chat stops at "Place this call?" On Enterprise plans, admins can go further and set org-wide per-tool policy — Always allow, Needs approval, or Blocked — so an operator cannot approve an action the organization has ruled out.
Below the client sit harder floors. The wallet is prepaid, so the worst-case blast radius of any conversation is the balance you have loaded — a confirmation slip cannot overdraw KES that is not there. And some things are simply not tools: there is no top-up tool, no API-key-minting tool, no secret-rotation tool. Money-in and identity stay in the dashboard, on purpose.
"What's our balance, what did we spend yesterday, and how much of it was AI minutes?"
Claude calls get_wallet_balance, list_wallet_statements, and get_ai_spend, then does the arithmetic for you. The API returns minor units — a balance of 184530 is KES 1,845.30 — and Claude converts without being asked. If the balance sits below your low-balance threshold, you will hear about it before your callers do.
place_call wraps POST /v1/calls: the from number must be one your workspace owns, and the tool is money-annotated, so Claude shows you the numbers and waits for a yes. Cost stays legible because billing is per second after connect — a 42-second confirmation call at KES 0.05/sec is KES 2.10. Sautikit pricing (as of 2026-06-30): KES 3/min outbound billed per second, inbound free, KES 100/month ex. VAT (KES 116 incl. VAT) per local Nairobi number — see /pricing for current rates.
"Set up a reminder campaign with the payments agent for this contact list, weekdays 9 to 5 Nairobi time, retry no-answers twice."
Claude drafts it with create_broadcast (the agent must be published — drafts are rejected with a clear error, which Claude reads and fixes), loads the list with add_broadcast_contacts (row-level validation, so one malformed number doesn't sink the batch), and then stops at start_broadcast for your confirmation. Later, "pause the reminder campaign" takes effect immediately — pausing costs nothing and needs no approval, while resume_broadcast is money-annotated and asks again. When it finishes, get_broadcast_report pulls the funnel and Claude turns it into the sentence you need: reached, voicemail, retry-worthy.
"Find yesterday's completed calls from +254733000210 and get me the recording of the longest one."
Claude filters with list_calls (status, direction, time range, or a number substring), then get_call_recording returns a download link with the duration and size. The link is presigned and expires in 15 minutes — audio never streams through the API — so click through promptly. If the recording has aged past your storage plan's retention window, the tool reports it as expired rather than handing you a dead link; retention windows per plan are on /pricing. For the summary itself, drop the transcript into the same chat — if your flow records with transcription enabled, this step is copy-paste — and ask for a summary, the customer's actual request, and the follow-up owner. That last mile is where the chat model earns its seat: the recording player was never going to write your QA note.
"How did this week compare to last week on answer rates?"
get_call_stats pulls the aggregates; list_calls sliced by status=no_answer,busy,failed gives Claude the raw material for the "why". Because it is a conversation, the follow-ups are free: "same numbers, outbound only", "which hours had the worst pickup", "draft the note to the team". The tools return data; Claude turns it into decisions.
Before you point a number at a new IVR handler, paste the actions document into the chat:
{ "actions": [ { "say": { "text": "Habari! Press 1 to confirm your appointment.", "language": "en-KE" } }, { "getDigits": { "timeout": 8, "numDigits": 1, "nested": [{ "say": { "text": "Press 1 to confirm, 2 to reschedule." } }] } }, { "say": { "text": "We did not get a selection. Goodbye." } }, { "hangup": {} } ]}
validate_voice_actions checks it against the exact schema the runtime enforces — locally, with no API call, no charge, and no scope required. Language models and humans alike love inventing plausible fields (a follow-up URL on getDigits is the classic — digits actually come back to your voice_callback_url as a Digits field), and the validator rejects those at authoring time instead of on a live call. Once it passes, update_number_routing points the number at your handler in the same conversation. The full DSL is in the voice actions reference.
Mint that key at app.sautikit.com → Settings → API keys, and scope it to the job. A reporting assistant gets wallet.read, calls.read, and recordings.read. A campaign desk gets broadcasts.read, broadcasts.manage, and agents.read — and nothing that dials ad hoc. The server only advertises the tools your key's scopes cover, so a read-only key produces a genuinely read-only Claude. Agent and broadcast scopes are enforced server-side today — a key without broadcasts.manage cannot start a campaign through MCP or the REST API — with enforcement rolling out across the remaining groups. Keys are revocable at any time, and revocation is checked on every request.
That split — OAuth for people in chat, narrow keys for tools in editors — is the same least-privilege posture the broader agent-security guidance keeps converging on: scope the credential, gate the spend below the prompt, keep confirmation on anything consequential.
In claude.ai, add https://mcp.sautikit.com/mcp under Settings → Connectors, sign in, and ask Claude for your wallet balance — then ask it to do something real. Full walkthrough on the MCP page and in the connect guide.