Skip to content

Commit 41bc62c

Browse files
committed
Added assistantOverrides and updated customer number
1 parent a45ebcb commit 41bc62c

File tree

5 files changed

+213
-6
lines changed

5 files changed

+213
-6
lines changed

README.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,40 @@ I'd like to speak with my ShopHelper assistant to talk about my recent order. Ca
7777
I need to schedule a call with Mary assistant for next Tuesday at 3:00 PM. My phone number is +1555123456.
7878
```
7979

80+
**Example 3:** Make a call with dynamic variables
81+
82+
```md
83+
I want to call +1234567890 with my appointment reminder assistant. Use these details:
84+
- Customer name: Sarah Johnson
85+
- Appointment date: March 25th
86+
- Appointment time: 2:30 PM
87+
- Doctor name: Dr. Smith
88+
```
89+
90+
## Using Variable Values in Assistant Prompts
91+
92+
The `create_call` action supports passing dynamic variables through `assistantOverrides.variableValues`. These variables can be used in your assistant's prompts using double curly braces: `{{variableName}}`.
93+
94+
### Example Assistant Prompt with Variables
95+
96+
```
97+
Hello {{customerName}}, this is a reminder about your appointment on {{appointmentDate}} at {{appointmentTime}} with {{doctorName}}.
98+
```
99+
100+
### Default Variables
101+
102+
The following variables are automatically available (no need to pass in variableValues):
103+
104+
- `{{now}}` - Current date and time (UTC)
105+
- `{{date}}` - Current date (UTC)
106+
- `{{time}}` - Current time (UTC)
107+
- `{{month}}` - Current month (UTC)
108+
- `{{day}}` - Current day of month (UTC)
109+
- `{{year}}` - Current year (UTC)
110+
- `{{customer.number}}` - Customer's phone number
111+
112+
For more details on default variables and advanced date/time formatting, see the [official Vapi documentation](https://docs.vapi.ai/assistants/dynamic-variables#default-variables).
113+
80114
## Remote MCP
81115

82116
To connect to Vapi's MCP server remotely:
@@ -187,10 +221,12 @@ The Vapi MCP Server provides the following tools for integration:
187221
### Call Tools
188222

189223
- `list_calls`: Lists all Vapi calls
190-
- `create_call`: Creates an outbound call
224+
- `create_call`: Creates an outbound call with support for:
225+
- Immediate or scheduled calls
226+
- Dynamic variable values through `assistantOverrides`
191227
- `get_call`: Gets details of a specific call
192228

193-
> **Note:** The `create_call` action supports scheduling calls for immediate execution or for a future time.
229+
> **Note:** The `create_call` action supports scheduling calls for immediate execution or for a future time. You can also pass dynamic variables using `assistantOverrides.variableValues` to personalize assistant messages.
194230
195231
### Phone Number Tools
196232

examples/shttp-client.ts

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#!/usr/bin/env node
2+
3+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
5+
import dotenv from 'dotenv';
6+
import { parseToolResponse } from '../src/utils/response.js';
7+
8+
// Load environment variables from .env file
9+
dotenv.config();
10+
11+
// Ensure API key is available
12+
if (!process.env.VAPI_TOKEN) {
13+
console.error('Error: VAPI_TOKEN environment variable is required');
14+
process.exit(1);
15+
}
16+
17+
async function main() {
18+
try {
19+
// Initialize MCP client
20+
const mcpClient = new Client({
21+
name: 'vapi-client-example',
22+
version: '1.0.0',
23+
});
24+
25+
// Create Streamable HTTP transport for connection to remote Vapi MCP server
26+
const serverUrl = 'https://mcp.vapi.ai/mcp';
27+
const headers = {
28+
Authorization: `Bearer ${process.env.VAPI_TOKEN}`,
29+
};
30+
31+
const transport = new StreamableHTTPClientTransport(new URL(serverUrl), {
32+
requestInit: { headers },
33+
});
34+
35+
console.log('Connecting to Vapi MCP server via Streamable HTTP...');
36+
await mcpClient.connect(transport);
37+
console.log('Connected successfully');
38+
39+
try {
40+
// List available tools
41+
const toolsResult = await mcpClient.listTools();
42+
console.log('Available tools:');
43+
toolsResult.tools.forEach((tool) => {
44+
console.log(`- ${tool.name}: ${tool.description}`);
45+
});
46+
47+
// List assistants
48+
console.log('\nListing assistants...');
49+
const assistantsResponse = await mcpClient.callTool({
50+
name: 'list_assistants',
51+
arguments: {},
52+
});
53+
54+
const assistants = parseToolResponse(assistantsResponse);
55+
56+
if (!(Array.isArray(assistants) && assistants.length > 0)) {
57+
console.log(
58+
'No assistants found. Please create an assistant in the Vapi dashboard first.'
59+
);
60+
return;
61+
}
62+
63+
console.log('Your assistants:');
64+
assistants.forEach((assistant: any) => {
65+
console.log(`- ${assistant.name} (${assistant.id})`);
66+
});
67+
68+
// List phone numbers
69+
console.log('\nListing phone numbers...');
70+
const phoneNumbersResponse = await mcpClient.callTool({
71+
name: 'list_phone_numbers',
72+
arguments: {},
73+
});
74+
75+
const phoneNumbers = parseToolResponse(phoneNumbersResponse);
76+
77+
if (!(Array.isArray(phoneNumbers) && phoneNumbers.length > 0)) {
78+
console.log(
79+
'No phone numbers found. Please add a phone number in the Vapi dashboard first.'
80+
);
81+
return;
82+
}
83+
84+
console.log('Your phone numbers:');
85+
phoneNumbers.forEach((phoneNumber: any) => {
86+
console.log(`- ${phoneNumber.phoneNumber} (${phoneNumber.id})`);
87+
});
88+
89+
// Create a call using the first assistant and first phone number
90+
const phoneNumberId = phoneNumbers[0].id;
91+
const assistantId = assistants[0].id;
92+
93+
console.log(
94+
`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`
95+
);
96+
const createCallResponse = await mcpClient.callTool({
97+
name: 'create_call',
98+
arguments: {
99+
assistantId: assistantId,
100+
phoneNumberId: phoneNumberId,
101+
customer: {
102+
phoneNumber: '+1234567890', // Replace with actual customer phone number
103+
},
104+
assistantOverrides: {
105+
variableValues: {
106+
name: 'John Doe',
107+
age: '25',
108+
},
109+
},
110+
// Optional: schedule a call for the future
111+
// scheduledAt: "2025-04-15T15:30:00Z"
112+
},
113+
});
114+
115+
const createdCall = parseToolResponse(createCallResponse);
116+
console.log('Call created:', JSON.stringify(createdCall, null, 2));
117+
118+
// List calls
119+
console.log('\nListing calls...');
120+
const callsResponse = await mcpClient.callTool({
121+
name: 'list_calls',
122+
arguments: {},
123+
});
124+
125+
const calls = parseToolResponse(callsResponse);
126+
127+
if (Array.isArray(calls) && calls.length > 0) {
128+
console.log('Your calls:');
129+
calls.forEach((call: any) => {
130+
const createdAt = call.createdAt
131+
? new Date(call.createdAt).toLocaleString()
132+
: 'N/A';
133+
const customerPhone = call.customer?.phoneNumber || 'N/A';
134+
const endedReason = call.endedReason || 'N/A';
135+
136+
console.log(
137+
`- ID: ${call.id} | Status: ${call.status} | Created: ${createdAt} | Customer: ${customerPhone} | Ended reason: ${endedReason}`
138+
);
139+
});
140+
} else {
141+
console.log('No calls found. Try creating a call first.');
142+
}
143+
} finally {
144+
console.log('\nDisconnecting from server...');
145+
await mcpClient.close();
146+
console.log('Disconnected');
147+
}
148+
} catch (error) {
149+
console.error('Error:', error);
150+
process.exit(1);
151+
}
152+
}
153+
154+
main();

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"dev": "tsx watch src/index.ts",
4040
"dev:stdio-example": "tsx examples/stdio-client.ts",
4141
"dev:sse-example": "tsx examples/sse-client.ts",
42+
"dev:shttp-example": "tsx examples/shttp-client.ts",
4243
"inspector": "mcp-inspector",
4344
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
4445
"test:unit": "NODE_OPTIONS=--experimental-vm-modules jest src/tests/mcp-server-mock.test.ts",

src/schemas/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ export const CallInputSchema = z.object({
264264
.describe('ID of the phone number to use for the call'),
265265
customer: z
266266
.object({
267-
phoneNumber: z.string().describe('Customer phone number'),
267+
number: z.string().describe('Customer phone number'),
268268
})
269269
.optional()
270270
.describe('Customer information'),
@@ -274,6 +274,17 @@ export const CallInputSchema = z.object({
274274
.describe(
275275
'ISO datetime string for when the call should be scheduled (e.g. "2025-03-25T22:39:27.771Z")'
276276
),
277+
assistantOverrides: z
278+
.object({
279+
variableValues: z
280+
.record(z.string(), z.any())
281+
.optional()
282+
.describe(
283+
'Key-value pairs for dynamic variables to use in the assistant\'s prompts (e.g. {"name": "Joe", "age": "24"})'
284+
),
285+
})
286+
.optional()
287+
.describe('Overrides for the assistant configuration'),
277288
});
278289

279290
export const CallOutputSchema = BaseResponseSchema.extend({
@@ -283,7 +294,7 @@ export const CallOutputSchema = BaseResponseSchema.extend({
283294
phoneNumberId: z.string().optional(),
284295
customer: z
285296
.object({
286-
phoneNumber: z.string(),
297+
number: z.string(),
287298
})
288299
.optional(),
289300
scheduledAt: z.string().optional(),

src/transformers/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export function transformCallInput(
187187
...(input.customer
188188
? {
189189
customer: {
190-
number: input.customer.phoneNumber,
190+
number: input.customer.number,
191191
},
192192
}
193193
: {}),
@@ -198,6 +198,11 @@ export function transformCallInput(
198198
},
199199
}
200200
: {}),
201+
...(input.assistantOverrides
202+
? {
203+
assistantOverrides: input.assistantOverrides,
204+
}
205+
: {}),
201206
};
202207
}
203208

@@ -214,7 +219,7 @@ export function transformCallOutput(
214219
phoneNumberId: call.phoneNumberId,
215220
customer: call.customer
216221
? {
217-
phoneNumber: call.customer.number || '',
222+
number: call.customer.number || '',
218223
}
219224
: undefined,
220225
scheduledAt: call.schedulePlan?.earliestAt,

0 commit comments

Comments
 (0)