Skip to main content
Glama

Vapi client MCP

A local stdio MCP server for provisioning client-level Vapi inbound answering assistants. It wraps the Vapi REST API rather than the smaller hosted Vapi MCP tool set.

The first template answers immediately, identifies itself as AI, captures the caller's name, callback number, reason, and callback window, then offers an available transfer or a clearly explained callback. End-of-call data can go to a public webhook or remain in Vapi for later CRM handling.

What is implemented

MCP tool

Vapi operation

provision_client

Render the answering template, POST /assistant, save local client state

apply_template

Render and PATCH /assistant/:id while retaining attached tool IDs

set_prompt_and_voice

Targeted assistant prompt, model, first-message, and voice update

attach_phone

PATCH /phone-number/:id or POST /phone-number, always binding assistantId

attach_tools

POST /tool, then attach IDs through the assistant model

set_structured_outputs

POST /structured-output with the client's assistantIds

smoke_test_call

Confirmed POST /call, with optional polling for transcript and structured data

list_client_status

Read assistant, bound number, and latest call; report partial errors

Client records live at clients/<slug>.json. They contain Vapi resource IDs and non-secret business configuration, never the Vapi key or provider credentials. These JSON files are suitable for config-as-code if the business metadata itself is acceptable to commit.

Related MCP server: RetellAI MCP Server

Install and run

Requires Node.js 20 or newer.

cd /home/blaine/projects/vapi-mcp
npm install
npm run check
npm run build
export VAPI_API_KEY="your private server-side Vapi key"
npm start

The server speaks MCP over stdio, so its standard output is reserved for protocol messages. Logs go to standard error.

For an MCP host, copy examples/mcp-client.json, replace the absolute paths, and put the real key only in the host's private configuration or secret manager. The checked-in example and .env.example contain placeholders only. This project does not automatically load .env files.

First client workflow

Call the tools in this order:

  1. provision_client

  2. set_structured_outputs

  3. attach_phone

  4. attach_tools for transfer, callback, calendar, or CRM actions

  5. smoke_test_call

  6. list_client_status

Example provision_client arguments:

{
  "clientSlug": "acme-hvac",
  "businessName": "Acme HVAC",
  "trade": "HVAC",
  "timezone": "America/New_York",
  "businessHours": "Monday-Friday 08:00-17:00; closed federal holidays",
  "transferNumber": "+12125550123",
  "crm": "GoHighLevel",
  "webhookUrl": "https://example.com/webhooks/vapi/end-of-call"
}

With no outputDefinitions, set_structured_outputs installs the schema from templates/inbound-answering.json. It extracts:

  • callerName

  • callbackNumber

  • reason

  • callbackWindow

  • transferOutcome

  • complete

Bind an existing number:

{
  "clientSlug": "acme-hvac",
  "phoneNumberId": "00000000-0000-4000-8000-000000000000"
}

Or pass a provider-specific POST /phone-number body as phoneConfiguration. The server overrides any supplied assistantId with the client's assistant ID. Prefer Vapi credential IDs over raw Twilio, Telnyx, Vonage, or SIP secrets; transient MCP arguments are not written to the client record.

attach_tools accepts complete Vapi POST /tool definitions, existing tool UUIDs, or both. This intentionally preserves Vapi's provider-specific tool unions instead of inventing a narrower local schema. A successful Vapi tool response is required before its ID is attached to the assistant.

Smoke path

smoke_test_call creates a real outbound phone call and may incur Vapi and carrier charges. It will not run unless confirmBillableCall is exactly true.

{
  "clientSlug": "acme-hvac",
  "customerNumber": "+12125550999",
  "waitSeconds": 45,
  "confirmBillableCall": true
}

At waitSeconds: 0, the tool returns the queued call immediately. At 1–55 seconds, it polls GET /call/:id and returns current status, ended reason, transcript, and structured data when available. Test only numbers you are authorized to call and follow applicable calling, recording-consent, and privacy rules.

Template behavior and limits

The template uses an assistant-first message so disclosure is immediate. The prompt uses spoken intent routing and tells the model not to claim a transfer, booking, callback, or CRM write succeeded without tool confirmation. When open/closed status is uncertain, it captures a callback rather than guessing.

The included hours are prompt context, not a deterministic holiday/calendar engine. Actual transfer and callback execution require attached Vapi tools. A webhook must be public and able to accept Vapi end-of-call-report payloads. For regulated businesses, add the required recording-consent, retention, and professional-advice controls before production.

Verification

npm run check

The focused tests enumerate all eight MCP tools, inspect the template contract, exercise the REST workflow against a mock Vapi client, and verify bearer-key redaction. They do not make a real Vapi call because no private key, provisioned number, or consented destination is included in this repository.

Sources

Implementation contracts follow Vapi's current official documentation for assistants, phone numbers, custom tools, structured outputs, calls, and server events.

Available Tools

8 tools
apply_templateApply Vapi answering templateA
DestructiveIdempotent

Render a local template with the client's settings and PATCH the existing Vapi assistant. Optional overrides are deep-merged last.

Inputs: clientSlug (required), templateId, assistantOverrides.

attach_phoneAttach inbound Vapi phoneA
Destructive

Bind an existing Vapi phone-number ID, or create/import a number from a provider-specific Vapi REST body. The client assistantId is always enforced.

Inputs: clientSlug (required), phoneNumberId, phoneConfiguration.

attach_toolsAttach Vapi toolsA
Destructive

Create reusable Vapi tools and/or attach existing tool IDs, preserving current assistant model configuration. Supports transfer, callback, calendar, CRM, API-request, and MCP tool payloads accepted by Vapi.

Inputs: clientSlug (required), replace, existingToolIds, toolDefinitions.

list_client_statusList Vapi client statusA
Read-onlyIdempotent

Read the local client record and current Vapi assistant, bound phone, and latest call. Partial remote failures are returned in errors.

Inputs: clientSlug (required).

provision_clientProvision Vapi clientA
Idempotent

Create the client's Vapi assistant from the inbound answering template and save a secret-free local client record. Reuses an existing local record by default.

Inputs: trade (required), timezone (required), clientSlug (required), businessName (required), +6 more.

set_prompt_and_voiceSet Vapi prompt and voiceB
DestructiveIdempotent

Update selected first-message, system-prompt, model, and voice fields while preserving the assistant's other model settings and attached tool IDs.

Inputs: clientSlug (required), voiceId, modelName, firstMessage, +3 more.

set_structured_outputsSet Vapi structured outputsA

Create structured outputs attached to the client assistant. With no definitions, uses the template schema for name, number, reason, callback window, and transfer outcome.

Inputs: clientSlug (required), replaceLocalIds, outputDefinitions.

smoke_test_callPlace Vapi smoke-test callA
Destructive

Place a real, potentially billable outbound call using the client assistant. Requires explicit confirmation. Optionally poll and return transcript and structured data.

Inputs: clientSlug (required), customerNumber (required), confirmBillableCall (required), waitSeconds, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 8 tools

    Disambiguation4/5

    Each tool focuses on a distinct aspect of client provisioning (creation, calling, templates, prompts, phone, tools, outputs, status), but 'apply_template' and 'set_prompt_and_voice' both modify assistant settings, which could cause minor confusion. 'smoke_test_call' is clearly separate.

    Naming Consistency3/5

    All names use snake_case with verb_noun pattern (provision_client, attach_phone, list_client_status), but verbs vary in style: 'provision' and 'apply' are less conventional than 'set', 'attach', 'list'. 'smoke_test_call' is a multi-word verb, a minor deviation.

    Tool Count4/5

    8 tools is within the ideal range for a client lifecycle management server, covering provisioning, configuration, and testing. It feels slightly heavy but each tool serves a clear purpose, so it is well-scoped.

    Completeness3/5

    The tools cover create, read/status, update (apply_template, set_prompt_and_voice), and attach resources, but there is no explicit delete/deprovision tool, which is a notable gap for a lifecycle. The smoke_test and structured outputs are nice-to-haves, but the missing teardown functionality is a gap.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers