Crixin Call Assistant is the phone primitive for developers shipping voice AI to clients. The MCP server gives your AI agent make_call, send_sms, transcribe_call. Every call lands in local SQLite — auditable, searchable, Wrapped-ready. You build the application; Crixin is the dial tone underneath.
One npm install. Wires the MCP into Claude Code, Cursor, Codex CLI, Claude Desktop. Your AI agent can now place calls.
crixin voice install
Your client's app calls make_call with a TwiML prompt or persona. CRM trigger, cron, webhook — your choice.
await makeCall(client, { to, prompt })
Every call mirrored to local SQLite + (optional) Deepgram transcripts. Voice Wrapped + Caller Archetype + Ducked rebuilt for any time window.
crixin voice wrapped
The pain. 40% of inbound calls miss the host stand between 6–9pm. Each missed call is a probable reservation lost. Hiring a hostess just for the phone costs $14/hr + benefits. The fix. Twilio routes inbound to your endpoint. Crixin's MCP server speaks for you — Polly-Hala-Neural in Spanish or English, knows the menu (RAG over a Notion doc), books a reservation in the POS, hangs up. Average call: 38 seconds.
// app/api/twilio/inbound.ts — Vercel function on your client's project import { speakOnly, wrap, say } from "crixin/voice"; import { getMenu, reserveTable } from "./pos"; export default async function handler(req, res) { const caller = req.body.From; const menu = await getMenu(); // Inbound call lands here as a Twilio webhook. Return TwiML. const twiml = `<Response> <Gather input="speech" action="/api/twilio/handle" language="es-MX,en-US"> <Say voice="Polly.Hala-Neural" language="es-MX"> ${menu.greeting} </Say> </Gather> </Response>`; res.setHeader("Content-Type", "text/xml"); res.send(twiml); } // Your AI agent picks up via the crixin-voice MCP server, // classifies intent (reservation / hours / menu / human), // and either books via reserveTable() or speaks back.
The pain. 28% of scheduled appointments no-show, costing the clinic ~$8K/month in lost chair time. The front desk is supposed to confirm 24h prior — they don't, because they're already drowning in walk-ins and insurance calls. The fix. A cron job at 9am pulls tomorrow's appointments from the EHR, fires make_call for each. AI confirms, reschedules, or cancels. Writes back to the EHR. Done by 9:08am.
// scripts/morning-confirms.ts — runs daily at 9am via cron import { TwilioClient, makeCall, loadEnv } from "crixin/voice"; import { tomorrowsAppointments, recordOutcome } from "./ehr"; const client = new TwilioClient(loadEnv()); const appts = await tomorrowsAppointments(); for (const a of appts) { const call = await makeCall(client, { to: a.phone, prompt: `Hi ${a.firstName}, this is Apex Dental confirming your ${a.procedure} appointment tomorrow at ${a.time}. Press 1 to confirm, 2 to reschedule, 3 to cancel.`, voice: "Polly.Joanna-Neural", record: true, maxRecordingSeconds: 20, consented: true, // existing patient relationship }); recordOutcome(a.id, call.sid); }
The pain. Trial users sign up, send 3 messages, then ghost. The activation team is one person, and they're busy. Email nudges convert at 4%. The fix. 3 days into the trial, if the user hasn't hit the activation event, your app fires make_call. AI walks them through the missing step, answers questions, books a Calendly with a human if they want one. Tracked back to Mixpanel.
// services/activation-checker.ts — runs hourly import { TwilioClient, makeCall, loadEnv } from "crixin/voice"; import { stalledTrials, trackEvent } from "./analytics"; const client = new TwilioClient(loadEnv()); for (const user of await stalledTrials({ daysSinceSignup: 3, activatedEvent: false })) { await makeCall(client, { to: user.phone, prompt: `Hi ${user.firstName}, I'm calling from Acme. I saw you signed up Tuesday but haven't connected your first data source yet. It's a 90-second step. Can I walk you through it, or would you rather book 15 minutes with someone on our team?`, voice: "Polly.Joanna-Neural", consented: true, // signup ToS captures consent }); trackEvent(user.id, "activation_call_placed"); }
The pain. Founder/AE needs to qualify 100 leads/week. Hiring SDRs costs $4–6K/mo loaded. Outreach platforms send email — but the lead in question already gets 200 emails/week. The fix. AI agent calls businesses on the lead list (B2B = looser TCPA), asks 4–5 discovery questions, books the qualified ones into the founder's Calendly. Disqualifies the rest. Founder gets meetings, not a list.
// scripts/b2b-discovery.ts — fed leads from Clay / Apollo / Google Places import { TwilioClient, makeCall, loadEnv } from "crixin/voice"; import { qualifyLead, bookMeeting } from "./crm"; const client = new TwilioClient(loadEnv()); for (const lead of leads) { // Geo-gate auto-enforces: this is a US business landline. // crixin voice doctor confirmed our setup. const call = await makeCall(client, { to: lead.businessPhone, prompt: `Hi, this is James from Apex. I'm calling because I noticed ${lead.companyName} just expanded to a second location — nice. Quick question — who handles your POS integration these days? Looking to chat about a 15% margin lift if you're open to it.`, voice: "Polly.Joanna-Neural", record: true, maxRecordingSeconds: 120, machineDetection: "DetectMessageEnd", // B2B landline + no DNC: no --consented needed under TCPA carve-out }); const outcome = await qualifyLead(call.sid); // transcribe + classify if (outcome === "qualified") await bookMeeting(lead); }
The pain. The on-call tech can't take every after-hours call — most are not emergencies (it's a thermostat reset, or "what time do you open"). But the few that ARE emergencies (no heat in February, water actively flooding) need a human in 5 minutes. The fix. Inbound → AI agent triages. Reads the answer back, classifies urgency, pages the on-call tech via SMS only if the situation is real. Logs everything to the CRM ticketing system.
// app/api/triage.ts — inbound webhook from Twilio import { promptAndRecord } from "crixin/voice"; import { TwilioClient, sendSms, transcribeRecording } from "crixin/voice"; import { classifyUrgency, pageOnCall, createTicket } from "./crm"; // 1. Inbound TwiML: ask what the issue is, record 30s. export const twimlPrompt = promptAndRecord({ prompt: "You've reached Houston HVAC after hours. Tell me what's going on — be specific.", voice: "Polly.Joanna-Neural", recordOptions: { maxLength: 30 }, }); // 2. Recording webhook: transcribe → classify → route. export async function onRecording(req, res) { const t = await transcribeRecording(client, { recordingSid: req.body.RecordingSid, }); const urgency = await classifyUrgency(t.transcript); await createTicket({ phone: req.body.From, transcript: t.transcript, urgency }); if (urgency === "emergency") await pageOnCall(t.transcript); }
The pain. Post-purchase email surveys hit 2% response rate. The product-page review widget gets 4%. The brand wants real NPS data + a Google review at-scale. The fix. 7 days post-delivery, AI agent calls the customer (with their checkout-time consent), asks two questions — *"Did the espresso machine arrive in good shape?"* and *"On a scale of 1–10, how likely are you to recommend us?"* — and offers to send a Google-review link via SMS if they say 9+. Calls take ~45 seconds.
// queues/post-delivery-nps.ts — fires 7 days after fulfillment import { TwilioClient, makeCall, sendSms, loadEnv } from "crixin/voice"; import { orderById, saveNPS } from "./shopify"; const client = new TwilioClient(loadEnv()); export async function processNPS(orderId: string) { const order = await orderById(orderId); const call = await makeCall(client, { to: order.customer.phone, prompt: `Hi ${order.customer.firstName}, this is Anna from ${order.brand}. Quick 30 seconds — did your ${order.itemName} arrive in good shape, and on a scale of 1 to 10, how likely are you to recommend us to a friend?`, voice: "Polly.Joanna-Neural", record: true, maxRecordingSeconds: 30, consented: true, // captured at checkout }); const { score, sentiment } = await saveNPS(call.sid); if (score >= 9) { await sendSms(client, { to: order.customer.phone, body: `Thanks! If you have 60s, would love a Google review: ${order.reviewUrl}`, }); } }
crixin voice ingest mirrors your Twilio history into local SQLite. crixin voice wrapped writes this as a single self-contained HTML file. Drop it into a client report; screenshot it for a deck; share it with your team.