| 1 | #!/usr/bin/env node |
| 2 | import { Client } from '@modelcontextprotocol/sdk/client/index.js'; |
| 3 | import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; |
| 4 | import dotenv from 'dotenv'; |
| 5 | |
| 6 | // Load environment variables from .env file |
| 7 | dotenv.config(); |
| 8 | |
| 9 | // Ensure API key is available |
| 10 | if (!process.env.VAPI_TOKEN) { |
| 11 | console.error('Error: VAPI_TOKEN environment variable is required'); |
| 12 | process.exit(1); |
| 13 | } |
| 14 | |
| 15 | async function main() { |
| 16 | try { |
| 17 | // Initialize MCP client |
| 18 | const mcpClient = new Client({ |
| 19 | name: 'vapi-client-example', |
| 20 | version: '1.0.0', |
| 21 | }); |
| 22 | // Create Streamable-HTTP transport for connection to remote Vapi MCP server |
| 23 | const serverUrl = 'https://mcp.vapi.ai/mcp'; |
| 24 | const headers = { |
| 25 | Authorization: `Bearer ${process.env.VAPI_TOKEN}`, |
| 26 | }; |
| 27 | const options = { |
| 28 | requestInit: { headers: headers }, |
| 29 | }; |
| 30 | const transport = new StreamableHTTPClientTransport(new URL(serverUrl), options); |
| 31 | console.log('Connecting to Vapi MCP server via Streamable HTTP...'); |
| 32 | await mcpClient.connect(transport); |
| 33 | console.log('Connected successfully'); |
| 34 | |
| 35 | // Helper function to parse tool responses |
| 36 | function parseToolResponse(response) { |
| 37 | if (!response?.content) return response; |
| 38 | const textItem = response.content.find(item => item.type === 'text'); |
| 39 | if (textItem?.text) { |
| 40 | try { |
| 41 | return JSON.parse(textItem.text); |
| 42 | } catch { |
| 43 | return textItem.text; |
| 44 | } |
| 45 | } |
| 46 | return response; |
| 47 | } |
| 48 | |
| 49 | try { |
| 50 | // List available tools |
| 51 | const toolsResult = await mcpClient.listTools(); |
| 52 | console.log('Available tools:'); |
| 53 | toolsResult.tools.forEach((tool) => { |
| 54 | console.log(`- ${tool.name}: ${tool.description}`); |
| 55 | }); |
| 56 | |
| 57 | // List assistants |
| 58 | console.log('\nListing assistants...'); |
| 59 | const assistantsResponse = await mcpClient.callTool({ |
| 60 | name: 'list_assistants', |
| 61 | arguments: {}, |
| 62 | }); |
| 63 | const assistants = parseToolResponse(assistantsResponse); |
| 64 | if (!(Array.isArray(assistants) && assistants.length > 0)) { |
| 65 | console.log('No assistants found. Please create an assistant in the Vapi dashboard first.'); |
| 66 | return; |
| 67 | } |
| 68 | console.log('Your assistants:'); |
| 69 | assistants.forEach((assistant) => { |
| 70 | console.log(`- ${assistant.name} (${assistant.id})`); |
| 71 | }); |
| 72 | |
| 73 | // List phone numbers |
| 74 | console.log('\nListing phone numbers...'); |
| 75 | const phoneNumbersResponse = await mcpClient.callTool({ |
| 76 | name: 'list_phone_numbers', |
| 77 | arguments: {}, |
| 78 | }); |
| 79 | const phoneNumbers = parseToolResponse(phoneNumbersResponse); |
| 80 | if (!(Array.isArray(phoneNumbers) && phoneNumbers.length > 0)) { |
| 81 | console.log('No phone numbers found. Please add a phone number in the Vapi dashboard first.'); |
| 82 | return; |
| 83 | } |
| 84 | console.log('Your phone numbers:'); |
| 85 | phoneNumbers.forEach((phoneNumber) => { |
| 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 | console.log(`\nCreating a call using assistant (${assistantId}) and phone number (${phoneNumberId})...`); |
| 93 | const createCallResponse = await mcpClient.callTool({ |
| 94 | name: 'create_call', |
| 95 | arguments: { |
| 96 | assistantId: assistantId, |
| 97 | phoneNumberId: phoneNumberId, |
| 98 | customer: { |
| 99 | number: "+1234567890" // Replace with actual customer phone number |
| 100 | } |
| 101 | // Optional: schedule a call for the future |
| 102 | // scheduledAt: "2025-04-15T15:30:00Z" |
| 103 | // assistantOverrides: { |
| 104 | // variableValues: { |
| 105 | // name: 'John Doe', |
| 106 | // age: '25', |
| 107 | // }, |
| 108 | // }, |
| 109 | }, |
| 110 | }); |
| 111 | const createdCall = parseToolResponse(createCallResponse); |
| 112 | console.log('Call created:', JSON.stringify(createdCall, null, 2)); |
| 113 | } finally { |
| 114 | console.log('\nDisconnecting from server...'); |
| 115 | await mcpClient.close(); |
| 116 | console.log('Disconnected'); |
| 117 | } |
| 118 | } catch (error) { |
| 119 | console.error('Error:', error); |
| 120 | process.exit(1); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | main(); |