Skip to main content
Glama
mcp-server-e2e.test.ts9.27 kB
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; import { join } from 'path'; import { jest } from '@jest/globals'; import dotenv from 'dotenv'; import { parseToolResponse } from '../utils/response.js'; dotenv.config(); jest.setTimeout(15000); describe('MCP Server E2E Test', () => { let mcpClient: Client; let transport: StdioClientTransport; beforeAll(async () => { const serverScriptPath = join(process.cwd(), 'src', 'index.ts'); console.log(`Using server source at: ${serverScriptPath}`); mcpClient = new Client({ name: 'vapi-e2e-test-client', version: '1.0.0' }); transport = new StdioClientTransport({ command: 'npx', args: ['tsx', serverScriptPath], env: { ...process.env, VAPI_TOKEN: process.env.VAPI_TOKEN || 'test-token', }, }); console.log('Connecting to MCP server...'); await mcpClient.connect(transport); console.log('Connected to server successfully'); }); afterAll(async () => { console.log('Disconnecting from server...'); await mcpClient.close(); console.log('Disconnected from server'); }); test('should list available tools', async () => { console.log('Requesting available tools...'); const toolsResult = await mcpClient.listTools(); expect(toolsResult.tools).toBeDefined(); expect(Array.isArray(toolsResult.tools)).toBe(true); const toolNames = toolsResult.tools.map((tool) => tool.name); console.log('Available tools:', toolNames); expect(toolNames).toContain('list_assistants'); expect(toolNames).toContain('create_assistant'); expect(toolNames).toContain('get_assistant'); expect(toolNames).toContain('list_phone_numbers'); expect(toolNames).toContain('get_phone_number'); expect(toolNames).toContain('list_calls'); expect(toolNames).toContain('create_call'); expect(toolNames).toContain('get_call'); }); describe('Assistant Tools', () => { test('should list all assistants', async () => { console.log('Calling list_assistants tool...'); const rawResult = await mcpClient.callTool({ name: 'list_assistants', arguments: {}, }); const result = parseToolResponse(rawResult); expect(result).toBeDefined(); if (Array.isArray(result)) { console.log(`Received ${result.length} assistants in array form`); } else { console.log(`Received assistants in non-array form:`, result); } }); test('should create a new assistant', async () => { console.log('Calling create_assistant tool...'); const assistantData = { name: `Test Assistant ${Date.now()}`, instructions: 'You are a helpful test assistant', llm: { provider: 'openai', model: 'gpt-4o', }, transcriber: { provider: 'deepgram', model: 'nova-3', }, voice: { provider: '11labs', model: 'eleven_turbo_v2_5', voiceId: 'sarah', }, firstMessage: "Hello, I'm your vapi assistant.", }; const rawResult = await mcpClient.callTool({ name: 'create_assistant', arguments: assistantData, }); const result = parseToolResponse(rawResult); expect(result).toBeDefined(); expect(result.id).toBeDefined(); expect(result.name).toBe(assistantData.name); expect(result.llm.provider).toBe(assistantData.llm.provider); expect(result.llm.model).toBe(assistantData.llm.model); console.log(`Successfully created assistant with ID: ${result.id}`); }); test('should get an assistant by ID', async () => { console.log('Listing assistants to get the first one...'); const rawListResult = await mcpClient.callTool({ name: 'list_assistants', arguments: {}, }); const listResult = parseToolResponse(rawListResult); expect(listResult).toBeDefined(); expect(Array.isArray(listResult)).toBe(true); if (listResult.length === 0) { console.log('No assistants found, skipping get_assistant test.'); // Optionally, you could fail the test here or create an assistant first return; } const firstAssistant = listResult[0]; expect(firstAssistant.id).toBeDefined(); const assistantId = firstAssistant.id; const assistantName = firstAssistant.name; console.log( `Attempting to fetch assistant with ID: ${assistantId} (Name: ${assistantName})` ); const rawGetResult = await mcpClient.callTool({ name: 'get_assistant', arguments: { assistantId: assistantId }, }); const getResult = parseToolResponse(rawGetResult); expect(getResult).toBeDefined(); expect(getResult.id).toBe(assistantId); expect(getResult.name).toBe(assistantName); // Verify name matches too console.log(`Successfully fetched assistant with ID: ${getResult.id}`); }); test('should handle invalid assistant ID', async () => { const invalidId = 'non-existent-assistant-id-' + Date.now(); console.log( `Testing error handling with invalid assistant ID: ${invalidId}` ); try { const rawResult = await mcpClient.callTool({ name: 'get_assistant', arguments: { assistantId: invalidId }, }); const result = parseToolResponse(rawResult); // Check for error in the result if ( result.error || (typeof result === 'string' && (result.includes('Error') || result.includes('error'))) ) { // Test passed - we got an error response expect(true).toBe(true); } else { // If we somehow got a successful result, fail the test expect(result).toContain('error'); } } catch (error) { // This is also acceptable - the API might throw instead of returning error expect(error).toBeDefined(); } }); }); describe('Phone Number Tools', () => { test('should list all phone numbers', async () => { console.log('Calling list_phone_numbers tool...'); const rawResult = await mcpClient.callTool({ name: 'list_phone_numbers', arguments: {}, }); const result = parseToolResponse(rawResult); expect(result).toBeDefined(); if (Array.isArray(result)) { console.log(`Received ${result.length} phone numbers in array form`); } else { console.log(`Received phone numbers in non-array form:`, result); } }); test('should handle invalid phone number ID', async () => { const invalidId = 'non-existent-phone-number-id-' + Date.now(); console.log( `Testing error handling with invalid phone number ID: ${invalidId}` ); try { const rawResult = await mcpClient.callTool({ name: 'get_phone_number', arguments: { phoneNumberId: invalidId }, }); const result = parseToolResponse(rawResult); // Check for error in the result if ( result.error || (typeof result === 'string' && (result.includes('Error') || result.includes('error'))) ) { // Test passed - we got an error response expect(true).toBe(true); } else { // If we somehow got a successful result, fail the test expect(result).toContain('error'); } } catch (error) { // This is also acceptable - the API might throw instead of returning error expect(error).toBeDefined(); } }); }); describe('Call Tools', () => { test('should list all calls', async () => { console.log('Calling list_calls tool...'); const rawResult = await mcpClient.callTool({ name: 'list_calls', arguments: {}, }); const result = parseToolResponse(rawResult); expect(result).toBeDefined(); if (Array.isArray(result)) { console.log(`Received ${result.length} calls in array form`); } else { console.log(`Received calls in non-array form:`, result); } }); test('should handle invalid call ID', async () => { const invalidId = 'non-existent-call-id-' + Date.now(); console.log(`Testing error handling with invalid call ID: ${invalidId}`); try { const rawResult = await mcpClient.callTool({ name: 'get_call', arguments: { callId: invalidId }, }); const result = parseToolResponse(rawResult); // Check for error in the result if ( result.error || (typeof result === 'string' && (result.includes('Error') || result.includes('error'))) ) { // Test passed - we got an error response expect(true).toBe(true); } else { // If we somehow got a successful result, fail the test expect(result).toContain('error'); } } catch (error) { // This is also acceptable - the API might throw instead of returning error expect(error).toBeDefined(); } }); }); });

Latest Blog Posts

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/KuchikiRenji/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server