MCP Vapi Caller
Used as the default text-to-speech provider for generating natural-sounding voice output in phone calls.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Vapi CallerCall +33142000000 and book a haircut for next Tuesday afternoon."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Vapi Caller
MCP server that lets Claude make AI-powered outbound phone calls via Vapi. Works with any type of call — customer service, sales, surveys, scheduling, etc. — in any language.
How It Works
Claude → make_call(phone, goal, script) → Vapi API → AI voice agent calls the number
Claude → get_call_result(call_id) → transcript, summary, structured data, recordingThe caller (Claude) provides domain-specific building blocks — goal, script, caller identity. The server wraps them in a voice-optimized system prompt (language enforcement, natural-speech style, goodbye handling) and sends the call to Vapi.
Related MCP server: Vapi MCP Server
Tools
make_call
Initiate an outbound call. Required parameters:
phone_number— E.164 format (e.g.+33142000000)call_goal— What the call should achieve (one sentence, used for automatic success evaluation)call_script— Behavioral instructions for the voice agent
Optional: language, caller_name, caller_context, first_message, structured_data_schema, structured_data_prompt, end_call_phrases, voice_id, customer_name, system_prompt_override.
Returns a call_id.
get_call_result
Poll for the call outcome. Pass wait_seconds (e.g. 180) to poll every 5s until the call ends. Returns status, transcript, AI summary, success evaluation, structured extracted data, and recording URL.
Supported Languages
Built-in voice tuning (end-call phrases, goodbye rules, natural-speech style) for: French (fr, default), English (en), Spanish (es), German (de), Italian (it), Portuguese (pt). Any other BCP-47 code still works — it falls back to English conversation rules while instructing the agent to speak the requested language.
Setup
1. Prerequisites
uv — Python package manager (
curl -LsSf https://astral.sh/uv/install.sh | sh)A Vapi account
An ElevenLabs voice ID (Vapi's default TTS provider here)
2. Get Vapi credentials
From the Vapi dashboard:
API key → Settings → API Keys
Phone number ID → Phone Numbers. Buy a Vapi number or import a Twilio one, then copy its ID (a UUID, not the phone number itself).
Pick a voice ID from the ElevenLabs voice library.
3. Install
git clone git@github.com:sebastienfi/mcp-vapi-generic-caller.git
cd mcp-vapi-generic-caller
uv sync4. Configure secrets
Create ~/.config/mcp/secrets.env (and chmod 600 it):
VAPI_API_KEY=your-vapi-api-key
VAPI_PHONE_NUMBER_ID=your-phone-number-id
VAPI_VOICE_ID=your-elevenlabs-voice-idThese three are required. See .env.example for all optional variables (default language, caller name, LLM provider/model, voice tuning).
5. Run (optional smoke test)
uv run python server.py # stdio transport; Ctrl-C to stop
# or, using PEP 723 inline metadata:
uv run --script server.pyThe server communicates over stdio and is normally launched by Claude, not run manually — this just confirms it starts without errors.
6. Register with Claude
Claude Code
Add to ~/.claude.json under mcpServers:
{
"mcpServers": {
"vapi-caller": {
"command": "/bin/bash",
"args": ["-c", "set -a; source ~/.config/mcp/secrets.env; set +a; exec uv run --directory /path/to/mcp-vapi-generic-caller python server.py"]
}
}
}Replace /path/to/mcp-vapi-generic-caller with the absolute clone path. Restart Claude Code and verify with /mcp — vapi-caller should list two tools.
Claude Desktop
Add the same block to claude_desktop_config.json
(macOS: ~/Library/Application Support/Claude/claude_desktop_config.json).
Use absolute paths for both bash and uv (e.g. /opt/homebrew/bin/uv) — Claude Desktop is an Electron app and does not inherit your shell PATH. The source secrets.env wrapper is what makes env vars available at runtime.
Usage Example
You: Call +33142000000 and book a haircut for next Tuesday afternoon.
My name is Jean Dupont.
Claude: [make_call with goal, script, language="fr"]
Call initiated, waiting for result...
[get_call_result(call_id=..., wait_seconds=180)]
The salon confirmed a haircut appointment for Tuesday at 15:00
with stylist Marie. Recording: [link]Docker (HTTP / cloud deployment)
For non-local deployments, run the server over Streamable HTTP instead of stdio:
cp .env.example .env # fill in your secrets
docker compose up --buildThis exposes the MCP server on http://localhost:8000 (MCP_TRANSPORT=streamable-http). Point an HTTP-capable MCP client at it. For local Claude Code/Desktop use, the stdio setup above is simpler.
Environment Variables
Variable | Required | Default | Description |
| ✅ | — | Vapi API key |
| ✅ | — | Vapi phone number ID (UUID) |
| ✅ | — | ElevenLabs voice ID |
|
| Default BCP-47 call language | |
| — | Who the agent calls on behalf of | |
|
| Vapi LLM provider | |
|
| LLM model (validated against Vapi's Anthropic list) | |
|
| TTS provider | |
|
| ElevenLabs TTS model | |
|
| Voice stability (0.0–1.0) | |
|
| Voice similarity boost (0.0–1.0) | |
|
| Speech speed | |
|
|
|
Project Structure
server.py # MCP server (single file, PEP 723 inline metadata)
pyproject.toml # Project metadata & dependencies
uv.lock # Locked dependency versions
.env.example # Environment variable template
Dockerfile # Multi-stage Docker build
docker-compose.yml # HTTP/cloud deployment
CLAUDE.md # Claude Code guidanceNo test suite or linter is configured.
Available Tools
2 toolsget_call_resultA
Check the outcome of a call initiated by make_call().
Returns the call status, transcript, AI-generated summary, success evaluation, structured extracted data, and recording URL.
USAGE:
For a quick status check: get_call_result(call_id="...")
To wait for completion: get_call_result(call_id="...", wait_seconds=180) This polls every 5 seconds until the call ends or the timeout is reached.
TYPICAL CALL DURATION: 1-3 minutes. Use wait_seconds=180 for most calls.
RETURNED FIELDS (when call has ended):
call_id: The call identifier
status: "ended" when complete
ended_reason: Why the call ended (e.g. "assistant-ended", "customer-ended")
summary: AI-generated summary of the conversation
success: Success evaluation based on the call_goal
structured_data: Extracted data matching the schema from make_call (if provided)
transcript: Full conversation transcript
recording: URL to the call recording audio file
If the call is still in progress, returns the current status without the analysis fields. Call again with wait_seconds to poll.
Args: call_id: The call ID returned by make_call wait_seconds: If > 0, poll every 5s up to this duration waiting for the call to end. 0 means check once and return immediately.
| Name | Required | Description | Default |
|---|---|---|---|
| call_id | Yes | ||
| wait_seconds | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, but the description fully discloses polling behavior, timeout, and the conditional return of fields. It shows exactly what is returned when the call has ended versus in progress, adding rich behavioral context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (USAGE, TYPICAL CALL DURATION, RETURNED FIELDS, Args). It is detailed but every sentence contributes, with no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all key aspects: status check, waiting, return fields, polling behavior, and conditional responses. Despite having an output schema, the description adds essential context about the tool's runtime behavior, making it complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no property descriptions (0% coverage), but the description explains both parameters thoroughly: call_id as the ID returned by make_call, and wait_seconds with its polling semantics and default behavior. This compensates fully for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Check the outcome of a call initiated by make_call()', which is a specific verb+resource statement. It clearly distinguishes from the sibling make_call tool by focusing on result retrieval rather than initiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit usage patterns: quick status check with call_id only, or waiting via wait_seconds=180 for typical 1-3 minute calls. Explains polling interval (5 seconds) and timeout behavior, plus what to do if the call is still in progress.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
make_callA
Make an outbound phone call with an AI voice agent via Vapi.
The voice agent will call the given phone number, follow your script, and extract structured data from the conversation. After initiating the call, use get_call_result() to retrieve the outcome.
WORKFLOW:
Call make_call() with your parameters → get back a call_id
Wait 1-3 minutes (typical call duration)
Call get_call_result(call_id=..., wait_seconds=180) to get results
REQUIRED PARAMETERS:
phone_number: E.164 format ("+33142000000" for France, "+15551234567" for US)
call_goal: One clear sentence describing what the call should achieve. This is used for automatic success evaluation. Example: "Prendre un rendez-vous coiffeur pour mardi prochain après-midi"
call_script: Detailed behavioral instructions for the voice agent. Write this as if briefing a human assistant before a phone call. Be specific about what to say, what to ask, how to respond to common scenarios, and when to end the call. Example: "Appelle le salon et demande un rendez-vous coiffure pour mardi prochain après-midi. Si mardi est complet, demande mercredi. Accepte tout créneau entre 14h et 18h. Refuse les créneaux du matin. Réserve au nom de Jean Dupont."
RECOMMENDED PARAMETERS:
first_message: The exact opening line. If omitted, one is auto-generated, but providing your own gives much better results. Example: "Bonjour ! J'appelle pour prendre un rendez-vous coiffure s'il vous plaît."
caller_name: Who the agent represents. Example: "Jean Dupont"
structured_data_schema: JSON string of a JSON Schema defining what to extract from the conversation. Without this, you still get a transcript and summary but no structured fields. Example: '{"type":"object","properties":{"appointment_date":{"type":"string","description":"YYYY-MM-DD"},"appointment_time":{"type":"string","description":"HH:MM 24h"},"confirmed":{"type":"boolean"}}}'
language: BCP-47 code. Default: "fr". Use "en" for English, "es" for Spanish, etc. The voice agent will speak exclusively in this language.
OPTIONAL PARAMETERS:
caller_context: Additional identity context. Example: "Tu es l'assistant personnel de Jean Dupont"
structured_data_prompt: Instructions for the extraction model. Example: "Aujourd'hui c'est le 2026-04-11. Résoudre les dates relatives."
end_call_phrases: Comma-separated phrases that signal the call should end. Default per language (e.g. "au revoir,bonne journée" for French).
voice_id: ElevenLabs voice ID override (default from env VAPI_VOICE_ID).
customer_name: Label for the person/business being called (Vapi dashboard).
system_prompt_override: Replaces the entire auto-generated system prompt. Use only when you need full control over the voice agent's instructions.
TIPS FOR GOOD CALLS:
Keep call_script focused and concise — voice agents work best with clear, simple instructions
Always provide a first_message — auto-generated ones are generic
Include fallback behavior in call_script (what to do if the main goal fails)
For data extraction, keep schemas simple with clear field descriptions
Args: phone_number: Phone number in E.164 format (e.g. "+33142000000") call_goal: One sentence describing what the call should achieve call_script: Detailed behavioral instructions for the voice agent language: BCP-47 language code (default: "fr") caller_name: Who the agent calls on behalf of caller_context: Additional identity context for the voice agent first_message: Opening line when the call connects structured_data_schema: JSON string of a JSON Schema for data extraction structured_data_prompt: Instructions for the extraction model end_call_phrases: Comma-separated end-call phrases voice_id: ElevenLabs voice ID override customer_name: Name of the person/business being called system_prompt_override: Full system prompt (replaces auto-generated one)
| Name | Required | Description | Default |
|---|---|---|---|
| language | No | ||
| voice_id | No | ||
| call_goal | Yes | ||
| call_script | Yes | ||
| caller_name | No | ||
| phone_number | Yes | ||
| customer_name | No | ||
| first_message | No | ||
| caller_context | No | ||
| end_call_phrases | No | ||
| structured_data_prompt | No | ||
| structured_data_schema | No | ||
| system_prompt_override | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral burden. It discloses async behavior (wait 1-3 minutes), indicates what happens when optional params are omitted (auto-generated first_message, no structured fields without a schema), specifies defaults (language='fr', voice_id from env), and notes the call duration. This is rich behavioral detail that helps the agent anticipate outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear sections and front-loads the main purpose. However, the final 'Args' block redundantly repeats parameter descriptions already covered in the REQUIRED/RECOMMENDED/OPTIONAL sections. The TIPS section adds value but also lengthens the text. Overall structured, but slightly overlong due to redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (13 params, 0% schema coverage, no annotations), the description is remarkably complete. It covers all parameters, workflow, timing, tool dependencies, and best-practice tips. The existence of an output schema reduces the need to detail return values, and the description still notes the call_id response. No critical gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description compensates exhaustively: it groups parameters into required/recommended/optional, provides format examples (E.164, BCP-47, JSON Schema string), explains each parameter's purpose (e.g., call_goal for automatic success evaluation), and includes usage examples for call_script and first_message. This is far beyond what the schema offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Make an outbound phone call with an AI voice agent via Vapi', clearly stating a specific verb, resource, and service. It differentiates itself from the sibling tool 'get_call_result' by framing it as the initiating step that returns a call_id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WORKFLOW section explicitly lays out when to call make_call (step 1) and when to call get_call_result (step 3), including a recommended wait time. This provides clear usage context and names the alternative tool for result retrieval, satisfying the 'when/when-not/alternatives' criterion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
2 tool updates
v0.1.0- First observed
get_call_result - First observed
make_call
TDQS
The two tools have entirely distinct purposes: one initiates a call, the other retrieves its result. There is no overlap or ambiguity between them.
Both tools follow the verb_noun pattern: make_call and get_call_result. The naming is consistent and predictable.
With only two tools, the set feels thin but the scope is narrow. The two tools cover the primary workflow, though additional utilities (like cancelling a call) could be expected.
The core lifecycle of initiating a call and retrieving its result is well covered. A minor gap exists in lack of cancellation or management of calls, but agents can work around this by waiting for completion.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Claude makes real phone calls for you — in many languages, with transcript and outcome back in chat.
Give AI agents a phone: outbound AI calls that return a summary, transcript, and extracted fields.
- DialMCPOAuthcom.dialmcp
Let AI agents place real phone calls from your verified number, with transcripts and recordings.
Give your AI agent a phone: place calls, navigate IVRs, wait on hold, get structured answers.
Related MCP Servers
- FlicenseNot gradedqualityFmaintenanceEnables AI assistants to make real phone calls on your behalf using VoIP, handling conversations automatically through OpenAI's Real-Time Voice API. Simply tell Claude what you want to accomplish and it will call and manage the entire conversation for you.24-
- AlicenseNot gradedqualityDmaintenanceEnables integration with Vapi's voice AI platform to manage assistants, create and schedule phone calls with dynamic variables, and manage phone numbers through function calling.601MIT
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to make voice calls and send SMS messages through the Vonage API, allowing AI assistants to perform real-world telephony operations with support for speech recognition and multi-language conversations.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables Claude to make and manage real phone calls through Twilio, allowing it to think, search, and respond in real-time conversations.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/sebastienfi/mcp-vapi-generic-caller'
If you have feedback or need assistance with the MCP directory API, please join our Discord server