-
Notifications
You must be signed in to change notification settings - Fork 89
Expand file tree
/
Copy pathmcp-server.mdx
More file actions
610 lines (535 loc) · 19.4 KB
/
Copy pathmcp-server.mdx
File metadata and controls
610 lines (535 loc) · 19.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
---
title: Vapi MCP Server
subtitle: Connect Vapi to AI assistants with Model Context Protocol (MCP)
slug: sdk/mcp-server
description: Use the Vapi MCP Server to expose Vapi APIs as tools over the Model Context Protocol, managing assistants, phone numbers, and calls from any MCP client.
---
## Overview
The **Vapi MCP Server** exposes Vapi APIs as tools via the Model Context Protocol (MCP), so you can manage assistants, phone numbers, and calls from any MCP-compatible AI assistant (like Claude Desktop) or agent framework.
Use this server to connect your AI workflows to real-world telephony, automate voice tasks, and build richer conversational agents.
<Note>
Looking to use MCP tools *inside* a Vapi assistant? See the [MCP Tool documentation](/tools/mcp) for integrating *external* MCP servers with your Vapi agents.
</Note>
<Tip>
**Using the Vapi CLI?** Auto-configure MCP in your IDE with one command:
```bash
vapi mcp setup
```
This automatically configures Cursor, Windsurf, or VSCode with the Vapi MCP server. [Learn more →](/cli/mcp)
</Tip>
## Quickstart: Claude Desktop Config
**Fastest way to get started:** connect Claude Desktop to the Vapi MCP Server.
<Steps>
<Step title="Get your Vapi API key">
Follow the [Vapi API key guide](/security-and-privacy/api-keys) to create, view, or copy an API key.
</Step>
<Step title="Edit Claude Desktop config">
Open <b>Settings</b> → <b>Developer</b> tab → <b>Edit Config</b>.
</Step>
<Step title="Add the Vapi MCP server block">
Insert this into your <code>claude_desktop_config.json</code>:
```json
{
"mcpServers": {
"vapi-mcp": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp.vapi.ai/mcp",
"--header",
"Authorization: Bearer ${VAPI_TOKEN}"
],
"env": {
"VAPI_TOKEN": "YOUR_VAPI_API_KEY"
}
}
}
}
```
Replace <code>YOUR_VAPI_API_KEY</code> with your API key.
</Step>
<Step title="Restart Claude Desktop">
Save and restart Claude Desktop.
</Step>
</Steps>
**Example prompt:**
> "Have my customer support assistant call Jeremy at +1555123456."
---
## Core Tools
The Vapi MCP Server exposes these actions as MCP tools:
| Tool | Description | Example Usage |
|------------------------|--------------------------------------------------|-----------------------------------------------|
| `list_assistants` | List all Vapi assistants | Show all configured assistants |
| `create_assistant` | Create a new Vapi assistant | Add a new assistant for a use case |
| `get_assistant` | Get a Vapi assistant by ID | View assistant config |
| `list_calls` | List all calls | Review call activity |
| `create_call` | Create an outbound call (now or scheduled) | Initiate or schedule a call |
| `get_call` | Get details for a specific call | Check status or result of a call |
| `list_phone_numbers` | List all Vapi phone numbers | See available numbers |
| `get_phone_number` | Get details of a specific phone number | Inspect a phone number |
| `list_tools` | List all available Vapi tools | Tool discovery |
| `get_tool` | Get details of a specific tool | Tool integration info |
<Note>
<b>Scheduling calls:</b> The <code>create_call</code> action supports scheduling with the optional <code>scheduledAt</code> parameter.
</Note>
---
## Integration Options
<Tabs>
<Tab title="Remote (streamable-HTTP)">
Connect to the Vapi-hosted MCP server using the streamable-HTTP protocol.
<Note>
Recommended for most production use cases.
</Note>
<Warning>
Use this for clients or SDKs that support streamable-HTTP transport.
</Warning>
- **Endpoint:** `https://mcp.vapi.ai/mcp`
- **Authentication:** Pass your Vapi API key as a bearer token:
<br/><code>Authorization: Bearer YOUR_VAPI_API_KEY</code>
Example config:
```json
{
"mcpServers": {
"vapi-mcp": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp.vapi.ai/mcp",
"--header",
"Authorization: Bearer ${VAPI_TOKEN}"
],
"env": {
"VAPI_TOKEN": "YOUR_VAPI_API_KEY"
}
}
}
}
```
</Tab>
<Tab title="Remote (SSE)">
Connect to the Vapi-hosted MCP server using Server-Sent Events (SSE).
<Warning>
Use this for clients or SDKs that support SSE transport.
</Warning>
- **Endpoint:** `https://mcp.vapi.ai/sse`
- **Authentication:** Pass your Vapi API key as a bearer token:
<br/><code>Authorization: Bearer YOUR_VAPI_API_KEY</code>
Example config for Claude:
```json
{
"mcpServers": {
"vapi-sse": {
"command": "npx",
"args": [
"mcp-remote",
"https://mcp.vapi.ai/sse",
"--header",
"Authorization: Bearer ${VAPI_TOKEN}"
],
"env": {
"VAPI_TOKEN": "YOUR_VAPI_API_KEY"
}
}
}
}
```
</Tab>
<Tab title="OpenAI responses API">
<Note>
The OpenAI <code>responses</code> API now supports MCP. <a href="https://platform.openai.com/docs/guides/tools-remote-mcp#page-top" target="_blank" rel="noopener">Read more here</a>.
</Note>
<CodeBlocks>
```typescript title="typescript"
import OpenAI from 'openai';
// Replace with your actual OpenAI API key
const openai = new OpenAI({ apiKey: 'YOUR_OPENAI_API_KEY' });
async function main() {
const response = await openai.responses.create({
model: 'gpt-4.1',
tools: [
{
type: 'mcp',
server_label: 'vapi-mcp',
server_url: 'https://mcp.vapi.ai/mcp',
headers: { "Authorization": "Bearer YOUR_VAPI_API_KEY" }
},
],
input: 'What vapi tools do you have available?',
});
console.dir(response, { depth: null });
}
main();
```
```python title="python"
import openai
# Replace with your actual OpenAI API key
openai.api_key = 'YOUR_OPENAI_API_KEY'
response = openai.responses.create(
model="gpt-4.1",
tools=[
{
"type": "mcp",
"server_label": "vapi-mcp",
"server_url": "https://mcp.vapi.ai/mcp",
"headers": {"Authorization": "Bearer YOUR_VAPI_API_KEY"}
},
],
input="What vapi tools do you have available?",
)
print(response)
```
</CodeBlocks>
</Tab>
<Tab title="Local">
Run the MCP server on your own machine for development or testing.
- **Start locally:**
```bash
npx -y @vapi-ai/mcp-server
```
- **Authentication:** Set the `VAPI_TOKEN` environment variable to your API key.
Example config for Claude:
```json
{
"mcpServers": {
"vapi-mcp-server": {
"command": "npx",
"args": [
"-y",
"@vapi-ai/mcp-server"
],
"env": {
"VAPI_TOKEN": "YOUR_VAPI_API_KEY"
}
}
}
}
```
<Warning>
Use this for clients or SDKs that support local command-based MCP servers.
</Warning>
Connect your client or SDK to the local server endpoint (default: `http://localhost:3000`).
</Tab>
</Tabs>
---
## Custom MCP Client Integration
You can use any MCP-compatible client (SDKs available for multiple languages).
<Steps>
<Step title="Install an MCP client SDK">
Choose a language:
- [TypeScript](https://github.com/modelcontextprotocol/typescript-sdk)
- [Python](https://github.com/modelcontextprotocol/python-sdk)
- [Java](https://github.com/modelcontextprotocol/java-sdk)
- [Kotlin](https://github.com/modelcontextprotocol/kotlin-sdk)
- [C#](https://github.com/modelcontextprotocol/csharp-sdk)
</Step>
<Step title="Configure your connection">
Set up your SDK to connect to the Vapi MCP Server (<code>https://mcp.vapi.ai/sse</code>) and authenticate with your API key.
</Step>
<Step title="Use MCP tools">
Query available tools, list assistants, create calls, etc, via your SDK.
</Step>
</Steps>
---
### Example: Build a client with Node.js
<Tabs>
<Tab title="Streamable-HTTP">
```javascript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import dotenv from 'dotenv';
dotenv.config();
const mcpClient = new Client({ name: 'vapi-client', version: '1.0.0' });
const transport = new StreamableHTTPClientTransport(
new URL('https://mcp.vapi.ai/mcp'),
{ requestInit: { headers: { Authorization: `Bearer ${process.env.VAPI_TOKEN}` } } }
);
async function main() {
await mcpClient.connect(transport);
const assistants = await mcpClient.callTool({ name: 'list_assistants', arguments: {} });
console.log(assistants);
await mcpClient.close();
}
main();
```
</Tab>
<Tab title="SSE">
```javascript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import dotenv from 'dotenv';
dotenv.config();
const mcpClient = new Client({ name: 'vapi-client', version: '1.0.0' });
const transport = new SSEClientTransport(
new URL('https://mcp.vapi.ai/sse'),
{ requestInit: { headers: { Authorization: `Bearer ${process.env.VAPI_TOKEN}` } } }
);
async function main() {
await mcpClient.connect(transport);
const assistants = await mcpClient.callTool({ name: 'list_assistants', arguments: {} });
console.log(assistants);
await mcpClient.close();
}
main();
```
</Tab>
</Tabs>
### Detailed example: Build a client with Node.js
<Tabs>
<Tab title="Streamable-HTTP">
```javascript
#!/usr/bin/env node
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import dotenv from 'dotenv';
// Load environment variables from .env file
dotenv.config();
// Ensure API key is available
if (!process.env.VAPI_TOKEN) {
console.error('Error: VAPI_TOKEN environment variable is required');
process.exit(1);
}
async function main() {
try {
// Initialize MCP client
const mcpClient = new Client({
name: 'vapi-client-example',
version: '1.0.0',
});
// Create Streamable-HTTP transport for connection to remote Vapi MCP server
const serverUrl = 'https://mcp.vapi.ai/mcp';
const headers = {
Authorization: `Bearer ${process.env.VAPI_TOKEN}`,
};
const options = {
requestInit: { headers: headers },
};
const transport = new StreamableHTTPClientTransport(new URL(serverUrl), options);
console.log('Connecting to Vapi MCP server via Streamable HTTP...');
await mcpClient.connect(transport);
console.log('Connected successfully');
// Helper function to parse tool responses
function parseToolResponse(response) {
if (!response?.content) return response;
const textItem = response.content.find(item => item.type === 'text');
if (textItem?.text) {
try {
return JSON.parse(textItem.text);
} catch {
return textItem.text;
}
}
return response;
}
try {
// List available tools
const toolsResult = await mcpClient.listTools();
console.log('Available tools:');
toolsResult.tools.forEach((tool) => {
console.log(`- ${tool.name}: ${tool.description}`);
});
// List assistants
console.log('\nListing assistants...');
const assistantsResponse = await mcpClient.callTool({
name: 'list_assistants',
arguments: {},
});
const assistants = parseToolResponse(assistantsResponse);
if (!(Array.isArray(assistants) && assistants.length > 0)) {
console.log('No assistants found. Please create an assistant in the Vapi dashboard first.');
return;
}
console.log('Your assistants:');
assistants.forEach((assistant) => {
console.log(`- ${assistant.name} (${assistant.id})`);
});
// List phone numbers
console.log('\nListing phone numbers...');
const phoneNumbersResponse = await mcpClient.callTool({
name: 'list_phone_numbers',
arguments: {},
});
const phoneNumbers = parseToolResponse(phoneNumbersResponse);
if (!(Array.isArray(phoneNumbers) && phoneNumbers.length > 0)) {
console.log('No phone numbers found. Please add a phone number in the Vapi dashboard first.');
return;
}
console.log('Your phone numbers:');
phoneNumbers.forEach((phoneNumber) => {
console.log(`- ${phoneNumber.phoneNumber} (${phoneNumber.id})`);
});
// Create a call using the first assistant and first phone number
const phoneNumberId = phoneNumbers[0].id;
const assistantId = assistants[0].id;
console.log(`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`);
const createCallResponse = await mcpClient.callTool({
name: 'create_call',
arguments: {
assistantId: assistantId,
phoneNumberId: phoneNumberId,
customer: {
number: "+1234567890" // Replace with actual customer phone number
}
// Optional: schedule a call for the future
// scheduledAt: "2025-04-15T15:30:00Z"
// assistantOverrides: {
// variableValues: {
// name: 'John Doe',
// age: '25',
// },
// },
},
});
const createdCall = parseToolResponse(createCallResponse);
console.log('Call created:', JSON.stringify(createdCall, null, 2));
} finally {
console.log('\nDisconnecting from server...');
await mcpClient.close();
console.log('Disconnected');
}
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
}
main();
```
</Tab>
<Tab title="SSE">
```javascript
#!/usr/bin/env node
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import dotenv from 'dotenv';
// Load environment variables from .env file
dotenv.config();
// Ensure API key is available
if (!process.env.VAPI_TOKEN) {
console.error('Error: VAPI_TOKEN environment variable is required');
process.exit(1);
}
async function main() {
try {
// Initialize MCP client
const mcpClient = new Client({
name: 'vapi-client-example',
version: '1.0.0',
});
// Create SSE transport for connection to remote Vapi MCP server
const serverUrl = 'https://mcp.vapi.ai/sse';
const headers = {
Authorization: `Bearer ${process.env.VAPI_TOKEN}`,
};
const options = {
requestInit: { headers: headers },
eventSourceInit: {
fetch: (url, init) => {
return fetch(url, {
...(init || {}),
headers: {
...(init?.headers || {}),
...headers,
},
});
},
},
};
const transport = new SSEClientTransport(new URL(serverUrl), options);
console.log('Connecting to Vapi MCP server via SSE...');
await mcpClient.connect(transport);
console.log('Connected successfully');
// Helper function to parse tool responses
function parseToolResponse(response) {
if (!response?.content) return response;
const textItem = response.content.find(item => item.type === 'text');
if (textItem?.text) {
try {
return JSON.parse(textItem.text);
} catch {
return textItem.text;
}
}
return response;
}
try {
// List available tools
const toolsResult = await mcpClient.listTools();
console.log('Available tools:');
toolsResult.tools.forEach((tool) => {
console.log(`- ${tool.name}: ${tool.description}`);
});
// List assistants
console.log('\nListing assistants...');
const assistantsResponse = await mcpClient.callTool({
name: 'list_assistants',
arguments: {},
});
const assistants = parseToolResponse(assistantsResponse);
if (!(Array.isArray(assistants) && assistants.length > 0)) {
console.log('No assistants found. Please create an assistant in the Vapi dashboard first.');
return;
}
console.log('Your assistants:');
assistants.forEach((assistant) => {
console.log(`- ${assistant.name} (${assistant.id})`);
});
// List phone numbers
console.log('\nListing phone numbers...');
const phoneNumbersResponse = await mcpClient.callTool({
name: 'list_phone_numbers',
arguments: {},
});
const phoneNumbers = parseToolResponse(phoneNumbersResponse);
if (!(Array.isArray(phoneNumbers) && phoneNumbers.length > 0)) {
console.log('No phone numbers found. Please add a phone number in the Vapi dashboard first.');
return;
}
console.log('Your phone numbers:');
phoneNumbers.forEach((phoneNumber) => {
console.log(`- ${phoneNumber.phoneNumber} (${phoneNumber.id})`);
});
// Create a call using the first assistant and first phone number
const phoneNumberId = phoneNumbers[0].id;
const assistantId = assistants[0].id;
console.log(`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`);
const createCallResponse = await mcpClient.callTool({
name: 'create_call',
arguments: {
assistantId: assistantId,
phoneNumberId: phoneNumberId,
customer: {
phoneNumber: "+1234567890" // Replace with actual customer phone number
}
// Optional: schedule a call for the future
// scheduledAt: "2025-04-15T15:30:00Z"
},
});
const createdCall = parseToolResponse(createCallResponse);
console.log('Call created:', JSON.stringify(createdCall, null, 2));
} finally {
console.log('\nDisconnecting from server...');
await mcpClient.close();
console.log('Disconnected');
}
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
}
main();
```
</Tab>
</Tabs>
<Note> For more detailed examples and complete client implementations, see the [MCP Client Quickstart](https://modelcontextprotocol.io/quickstart/client). </Note>
## References
- [Github repo](https://github.com/VapiAI/mcp-server)
- [Model Context Protocol docs](https://modelcontextprotocol.io)
- [Vapi dashboard](https://dashboard.vapi.ai)
- [MCP client quickstart](https://modelcontextprotocol.io/quickstart/client)
<CardGroup cols={2}>
<Card title="Need help?" icon="question-circle" href="https://discord.gg/pUFNcf2WmH">
Join our Discord community for MCP support.
</Card>
<Card title="API reference" icon="book" href="/api-reference/tools/create">
Full API documentation for tools.
</Card>
</CardGroup>