programmatic api

Skip the MCP server. Use the library.

Need to call Twilio from a Node script, a Vercel Function, or a long-running worker? Import the same primitives the MCP server is built on. Full TypeScript types. Zero runtime dependencies beyond the MCP SDK (the Twilio REST wrapper is hand-rolled with fetch).

Install

npm i crixin

Three entry points

crixin/voice

Everything: Twilio client, calls, SMS, transcription, TwiML helpers.

crixin/voice/twilio

Just TwilioClient + REST helpers. Drop into existing infra.

crixin/voice/mcp

startMcpServer() if you want to embed the MCP server in a custom binary.

Place a call

import { TwilioClient, makeCall, loadEnv } from "crixin/voice";

const client = new TwilioClient(loadEnv());

const call = await makeCall(client, {
  to: "+15555550100",
  prompt: "Hi, is this Roses Island Club? I'm following up on basketball court hours.",
  voice: "Polly.Joanna-Neural",
  language: "en-US",
  maxRecordingSeconds: 60,
  machineDetection: "Enable",
});

console.log(call.sid, call.status); // CA94e1d8…3a02 → queued

Send an SMS

import { TwilioClient, sendSms, loadEnv } from "crixin/voice";

const client = new TwilioClient(loadEnv());
await sendSms(client, {
  to: "+15555550100",
  body: "Reminder: 3pm appointment.",
});

Transcribe a recording

import {
  TwilioClient, makeCall, listRecordingsForCall,
  transcribeRecording, loadEnv,
} from "crixin/voice";

const client = new TwilioClient(loadEnv());

const call = await makeCall(client, {
  to: "+201234567890",
  prompt: "السلام عليكم، هل ممكن نعرف مواعيد الملعب؟",
  voice: "Polly.Hala-Neural",
  language: "ar-EG",
  maxRecordingSeconds: 60,
});

// Wait for the call to complete (poll get_call or use status_callback)…
const recordings = await listRecordingsForCall(client, call.sid);
if (recordings[0]) {
  const result = await transcribeRecording(client, {
    recordingSid: recordings[0].sid,
    language: "ar",
  });
  console.log(result.transcript);
}

Build TwiML by hand

The same XML helpers the MCP server uses are exported. Compose anything Twilio supports.

import { say, record, hangup, wrap } from "crixin/voice";

const twiml = wrap(
  say("Press 1 for hours, 2 for prices.", { voice: "Polly.Joanna-Neural" }) +
  record({ maxLength: 30, transcribe: false }) +
  hangup()
);

// Pass to makeCall via { twiml }, or serve it from your own webhook.

Embed the MCP server in your own binary

#!/usr/bin/env node
import { startMcpServer } from "crixin/voice/mcp";

// Add custom auth, logging, or rate-limit middleware around it.
startMcpServer().catch((err) => {
  console.error(err);
  process.exit(1);
});

Audit trail

Every entry point is <200 LOC. The Twilio REST client is a single file with one fetch per HTTP verb — no generated SDK, no hidden state, no telemetry. Read it on GitHub.