Skip to main content
Glama

Carbon Voice

by PhononX
server.test.ts75.3 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { setCarbonVoiceAuthHeader } from '../../../src/auth'; import { getCarbonVoiceAPI } from '../../../src/cv-api'; import { getCarbonVoiceSimplifiedAPI } from '../../../src/generated'; import { formatToMCPToolResponse, logger } from '../../../src/utils'; import { listMessagesQueryParams } from '../../../src/generated/carbon-voice-api/CarbonVoiceSimplifiedAPI.zod'; import { getZodSchemaAsJson } from '../../utils/test-helpers'; // Create a mock for registerTool that we can access const mockRegisterTool = jest.fn(); // Mock the MCP SDK jest.mock('@modelcontextprotocol/sdk/server/mcp.js', () => { const McpServer = jest.fn().mockImplementation(() => ({ registerTool: mockRegisterTool, })); return { McpServer }; }); // Mock the auth module jest.mock('../../../src/auth', () => ({ setCarbonVoiceAuthHeader: jest.fn((token) => ({ headers: { Authorization: `Bearer ${token}`, }, })), })); // Mock the cv-api module jest.mock('../../../src/cv-api', () => { const cvApiMock = { getWhoAmI: jest.fn().mockResolvedValue({ user: {} }), }; return { getCarbonVoiceAPI: jest.fn(() => cvApiMock), }; }); // Mock the generated API module jest.mock('../../../src/generated', () => { const simplifiedApiMock = { listMessages: jest.fn(), getMessageById: jest.fn(), getTenRecentMessagesResponse: jest.fn(), createConversationMessage: jest.fn(), sendDirectMessage: jest.fn(), createVoiceMemoMessage: jest.fn(), addLinkAttachmentsToMessage: jest.fn(), getUserById: jest.fn(), searchUser: jest.fn(), searchUsers: jest.fn(), getAllConversations: jest.fn(), getConversationById: jest.fn(), getConversationUsers: jest.fn(), summarizeConversation: jest.fn(), getAllRootFolders: jest.fn(), createFolder: jest.fn(), getFolderById: jest.fn(), getFolderMessages: jest.fn(), updateFolderName: jest.fn(), deleteFolder: jest.fn(), moveFolder: jest.fn(), addMessageToFolderOrWorkspace: jest.fn(), getAllWorkspacesWithBasicInfo: jest.fn(), aIPromptControllerGetPrompts: jest.fn(), aIResponseControllerCreateResponse: jest.fn(), createShareLinkAIResponse: jest.fn(), aIResponseControllerGetAllResponses: jest.fn(), }; return { getCarbonVoiceSimplifiedAPI: jest.fn(() => simplifiedApiMock), }; }); // Mock the utils module jest.mock('../../../src/utils', () => ({ formatToMCPToolResponse: jest.fn(), logger: { error: jest.fn(), info: jest.fn(), warn: jest.fn(), debug: jest.fn(), }, })); describe('MCP Server', () => { // Mock the registerTool method const mockRegisterTool = jest.fn(); // Mock the McpServer constructor const mockMcpServer = jest.fn().mockImplementation(() => ({ registerTool: mockRegisterTool, })); // Mock auth context const mockContext = { authInfo: { token: 'test-token' }, }; // Create a single simplifiedApiMock object with all API methods const simplifiedApiMock = { listMessages: jest.fn().mockResolvedValue({ messages: [] }), getMessageById: jest.fn().mockResolvedValue({ message: {} }), getTenRecentMessagesResponse: jest.fn().mockResolvedValue({ messages: [] }), createConversationMessage: jest.fn().mockResolvedValue({ message: {} }), sendDirectMessage: jest.fn().mockResolvedValue({ message: {} }), createVoiceMemoMessage: jest.fn().mockResolvedValue({ message: {} }), addLinkAttachmentsToMessage: jest.fn().mockResolvedValue({ success: true }), getUserById: jest.fn().mockResolvedValue({ user: {} }), searchUser: jest.fn().mockResolvedValue({ user: {} }), searchUsers: jest.fn().mockResolvedValue({ users: [] }), getAllConversations: jest.fn().mockResolvedValue({ conversations: [] }), getConversationById: jest.fn().mockResolvedValue({ conversation: {} }), getConversationUsers: jest.fn().mockResolvedValue({ users: [] }), getAllRootFolders: jest.fn().mockResolvedValue({ folders: [] }), createFolder: jest.fn().mockResolvedValue({ folder: {} }), getFolderById: jest.fn().mockResolvedValue({ folder: {} }), getFolderMessages: jest.fn().mockResolvedValue({ folder: {} }), updateFolderName: jest.fn().mockResolvedValue({ folder: {} }), deleteFolder: jest.fn().mockResolvedValue({ success: true }), moveFolder: jest.fn().mockResolvedValue({ success: true }), addMessageToFolderOrWorkspace: jest .fn() .mockResolvedValue({ success: true }), getAllWorkspacesWithBasicInfo: jest .fn() .mockResolvedValue({ workspaces: [] }), aIPromptControllerGetPrompts: jest.fn().mockResolvedValue({ prompts: [] }), aIResponseControllerCreateResponse: jest .fn() .mockResolvedValue({ response: {} }), createShareLinkAIResponse: jest.fn().mockResolvedValue({ response: {} }), aIResponseControllerGetAllResponses: jest .fn() .mockResolvedValue({ responses: [] }), getWhoAmI: jest.fn().mockResolvedValue({ user: {} }), }; // Mock the getCarbonVoiceSimplifiedAPI function to return our mock const mockGetCarbonVoiceSimplifiedAPI = jest .fn() .mockReturnValue(simplifiedApiMock); // Mock the formatToMCPToolResponse function const mockFormatToMCPToolResponse = jest .fn() .mockReturnValue({ content: [] }); // Mock the logger const mockLogger = { error: jest.fn(), }; // Mock the setCarbonVoiceAuthHeader function const mockSetCarbonVoiceAuthHeader = jest.fn().mockReturnValue({ headers: { Authorization: 'Bearer test-token' }, }); beforeEach(() => { jest.clearAllMocks(); jest.resetModules(); // Set up mocks before importing the server module jest.doMock('@modelcontextprotocol/sdk/server/mcp.js', () => ({ McpServer: mockMcpServer, })); jest.doMock('../../../src/generated', () => ({ getCarbonVoiceSimplifiedAPI: mockGetCarbonVoiceSimplifiedAPI, })); jest.doMock('../../../src/utils', () => ({ formatToMCPToolResponse: mockFormatToMCPToolResponse, logger: mockLogger, })); jest.doMock('../../../src/auth', () => ({ setCarbonVoiceAuthHeader: mockSetCarbonVoiceAuthHeader, })); // Import the server module after mocks are set up require('../../../src/server'); }); describe('Tool Registration', () => { describe('list_messages tool', () => { let listMessagesCall: any; beforeEach(() => { // Find the list_messages tool registration listMessagesCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'list_messages', ); }); it('should register list_messages tool with correct parameters', () => { expect(listMessagesCall).toBeDefined(); expect(listMessagesCall[0]).toBe('list_messages'); expect(listMessagesCall[1].inputSchema).toBeDefined(); expect(listMessagesCall[1].description).toBeDefined(); expect(listMessagesCall[1].annotations).toBeDefined(); expect(listMessagesCall[1].annotations.readOnlyHint).toBe(true); expect(listMessagesCall[1].annotations.destructiveHint).toBe(false); }); it('should call simplified API with correct parameters', async () => { const toolHandler = listMessagesCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { page: 1, size: 10, sort_direction: 'DESC' as const, conversation_id: 'test-conv-id', }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.listMessages).toHaveBeenCalledWith( testParams, { headers: { Authorization: 'Bearer test-token' }, }, ); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.listMessages.mockRejectedValueOnce(apiError); const toolHandler = listMessagesCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler({}, mockContext); // Verify the API was called expect(simplifiedApiMock.listMessages).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error listing messages:', { params: {}, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('get_message tool', () => { let getMessageCall: any; beforeEach(() => { // Find the get_message tool registration getMessageCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_message', ); }); it('should register get_message tool with correct parameters', () => { expect(getMessageCall).toBeDefined(); expect(getMessageCall[0]).toBe('get_message'); expect(getMessageCall[1].inputSchema).toBeDefined(); expect(getMessageCall[1].annotations).toBeDefined(); expect(getMessageCall[1].annotations.readOnlyHint).toBe(true); expect(getMessageCall[1].annotations.destructiveHint).toBe(false); expect(getMessageCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getMessageCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { id: 'test-message-id', include_attachments: true, }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.getMessageById).toHaveBeenCalledWith( testParams.id, { include_attachments: true }, { headers: { Authorization: 'Bearer test-token' }, }, ); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.getMessageById.mockRejectedValueOnce(apiError); const toolHandler = getMessageCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler({ id: 'test-id' }, mockContext); // Verify the API was called expect(simplifiedApiMock.getMessageById).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting message by id:', { args: { id: 'test-id' }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('get_recent_messages tool', () => { let getRecentMessagesCall: any; beforeEach(() => { // Find the get_recent_messages tool registration getRecentMessagesCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_recent_messages', ); }); it('should register get_recent_messages tool with correct parameters', () => { expect(getRecentMessagesCall).toBeDefined(); expect(getRecentMessagesCall[0]).toBe('get_recent_messages'); expect(getRecentMessagesCall[1].inputSchema).toBeDefined(); expect(getRecentMessagesCall[1].annotations).toBeDefined(); expect(getRecentMessagesCall[1].annotations.readOnlyHint).toBe(true); expect(getRecentMessagesCall[1].annotations.destructiveHint).toBe( false, ); expect(getRecentMessagesCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getRecentMessagesCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { include_attachments: true, }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect( simplifiedApiMock.getTenRecentMessagesResponse, ).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.getTenRecentMessagesResponse.mockRejectedValueOnce( apiError, ); const toolHandler = getRecentMessagesCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler({}, mockContext); // Verify the API was called expect( simplifiedApiMock.getTenRecentMessagesResponse, ).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting recent messages:', { args: {}, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('create_conversation_message tool', () => { let createConversationMessageCall: any; beforeEach(() => { // Find the create_conversation_message tool registration createConversationMessageCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'create_conversation_message', ); }); it('should register create_conversation_message tool with correct parameters', () => { expect(createConversationMessageCall).toBeDefined(); expect(createConversationMessageCall[0]).toBe( 'create_conversation_message', ); expect(createConversationMessageCall[1].inputSchema).toBeDefined(); expect(createConversationMessageCall[1].annotations).toBeDefined(); expect(createConversationMessageCall[1].annotations.readOnlyHint).toBe( false, ); expect( createConversationMessageCall[1].annotations.destructiveHint, ).toBe(false); expect(createConversationMessageCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = createConversationMessageCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { id: 'test-conversation-id', transcript: 'Hello world', parent_id: 'test-parent-id', }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect( simplifiedApiMock.createConversationMessage, ).toHaveBeenCalledWith(testParams.id, testParams, { headers: { Authorization: 'Bearer test-token' }, }); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.createConversationMessage.mockRejectedValueOnce( apiError, ); const toolHandler = createConversationMessageCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler( { id: 'test-id', transcript: 'test' }, mockContext, ); // Verify the API was called expect(simplifiedApiMock.createConversationMessage).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error creating conversation message:', { args: { id: 'test-id', transcript: 'test' }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('create_direct_message tool', () => { let createDirectMessageCall: any; beforeEach(() => { // Find the create_direct_message tool registration createDirectMessageCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'create_direct_message', ); }); it('should register create_direct_message tool with correct parameters', () => { expect(createDirectMessageCall).toBeDefined(); expect(createDirectMessageCall[0]).toBe('create_direct_message'); expect(createDirectMessageCall[1].inputSchema).toBeDefined(); expect(createDirectMessageCall[1].annotations).toBeDefined(); expect(createDirectMessageCall[1].annotations.readOnlyHint).toBe(false); expect(createDirectMessageCall[1].annotations.destructiveHint).toBe( false, ); expect(createDirectMessageCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = createDirectMessageCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { to_recipients: ['user1', 'user2'], transcript: 'Hello world', }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.sendDirectMessage).toHaveBeenCalledWith( testParams, { headers: { Authorization: 'Bearer test-token' }, }, ); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.sendDirectMessage.mockRejectedValueOnce(apiError); const toolHandler = createDirectMessageCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler( { to_recipients: ['user1'], transcript: 'test' }, mockContext, ); // Verify the API was called expect(simplifiedApiMock.sendDirectMessage).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error creating direct message:', { args: { to_recipients: ['user1'], transcript: 'test' }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('create_voicememo_message tool', () => { let createVoicememoMessageCall: any; beforeEach(() => { // Find the create_voicememo_message tool registration createVoicememoMessageCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'create_voicememo_message', ); }); it('should register create_voicememo_message tool with correct parameters', () => { expect(createVoicememoMessageCall).toBeDefined(); expect(createVoicememoMessageCall[0]).toBe('create_voicememo_message'); expect(createVoicememoMessageCall[1].inputSchema).toBeDefined(); expect(createVoicememoMessageCall[1].annotations).toBeDefined(); expect(createVoicememoMessageCall[1].annotations.readOnlyHint).toBe( false, ); expect(createVoicememoMessageCall[1].annotations.destructiveHint).toBe( false, ); expect(createVoicememoMessageCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = createVoicememoMessageCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { transcript: 'Hello world', links: ['https://example.com/audio.mp3'], }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.createVoiceMemoMessage).toHaveBeenCalledWith( testParams, { headers: { Authorization: 'Bearer test-token' }, }, ); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.createVoiceMemoMessage.mockRejectedValueOnce( apiError, ); const toolHandler = createVoicememoMessageCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler({ transcript: 'test' }, mockContext); // Verify the API was called expect(simplifiedApiMock.createVoiceMemoMessage).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error creating voicememo message:', { args: { transcript: 'test' }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('add_attachments_to_message tool', () => { let addAttachmentsToMessageCall: any; beforeEach(() => { // Find the add_attachments_to_message tool registration addAttachmentsToMessageCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'add_attachments_to_message', ); }); it('should register add_attachments_to_message tool with correct parameters', () => { expect(addAttachmentsToMessageCall).toBeDefined(); expect(addAttachmentsToMessageCall[0]).toBe( 'add_attachments_to_message', ); expect(addAttachmentsToMessageCall[1].inputSchema).toBeDefined(); expect(addAttachmentsToMessageCall[1].annotations).toBeDefined(); expect(addAttachmentsToMessageCall[1].annotations.readOnlyHint).toBe( false, ); expect(addAttachmentsToMessageCall[1].annotations.destructiveHint).toBe( false, ); expect(addAttachmentsToMessageCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = addAttachmentsToMessageCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { id: 'test-message-id', links: ['https://example.com/file.pdf'], }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect( simplifiedApiMock.addLinkAttachmentsToMessage, ).toHaveBeenCalledWith( testParams.id, { links: testParams.links }, { headers: { Authorization: 'Bearer test-token' }, }, ); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.addLinkAttachmentsToMessage.mockRejectedValueOnce( apiError, ); const toolHandler = addAttachmentsToMessageCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler( { id: 'test-id', links: ['test-link'] }, mockContext, ); // Verify the API was called expect( simplifiedApiMock.addLinkAttachmentsToMessage, ).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error adding attachments to message:', { args: { id: 'test-id', links: ['test-link'] }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('get_user tool', () => { let getUserCall: any; beforeEach(() => { // Find the get_user tool registration getUserCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_user', ); }); it('should register get_user tool with correct parameters', () => { expect(getUserCall).toBeDefined(); expect(getUserCall[0]).toBe('get_user'); expect(getUserCall[1].inputSchema).toBeDefined(); expect(getUserCall[1].annotations).toBeDefined(); expect(getUserCall[1].annotations.readOnlyHint).toBe(true); expect(getUserCall[1].annotations.destructiveHint).toBe(false); expect(getUserCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getUserCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { id: 'test-user-id', }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.getUserById).toHaveBeenCalledWith( testParams.id, { headers: { Authorization: 'Bearer test-token' }, }, ); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.getUserById.mockRejectedValueOnce(apiError); const toolHandler = getUserCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler({ id: 'test-id' }, mockContext); // Verify the API was called expect(simplifiedApiMock.getUserById).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting user by id:', { args: { id: 'test-id' }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('search_user tool', () => { let searchUserCall: any; beforeEach(() => { // Find the search_user tool registration searchUserCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'search_user', ); }); it('should register search_user tool with correct parameters', () => { expect(searchUserCall).toBeDefined(); expect(searchUserCall[0]).toBe('search_user'); expect(searchUserCall[1].inputSchema).toBeDefined(); expect(searchUserCall[1].annotations).toBeDefined(); expect(searchUserCall[1].annotations.readOnlyHint).toBe(true); expect(searchUserCall[1].annotations.destructiveHint).toBe(false); expect(searchUserCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = searchUserCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { phone_number: '+1234567890', }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.searchUser).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.searchUser.mockRejectedValueOnce(apiError); const toolHandler = searchUserCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler( { phone_number: '+1234567890' }, mockContext, ); // Verify the API was called expect(simplifiedApiMock.searchUser).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error searching for user:', { args: { phone_number: '+1234567890' }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('search_users tool', () => { let searchUsersCall: any; beforeEach(() => { // Find the search_users tool registration searchUsersCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'search_users', ); }); it('should register search_users tool with correct parameters', () => { expect(searchUsersCall).toBeDefined(); expect(searchUsersCall[0]).toBe('search_users'); expect(searchUsersCall[1].inputSchema).toBeDefined(); expect(searchUsersCall[1].annotations).toBeDefined(); expect(searchUsersCall[1].annotations.readOnlyHint).toBe(true); expect(searchUsersCall[1].annotations.destructiveHint).toBe(false); expect(searchUsersCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = searchUsersCall[2]; // Verify the tool handler exists and is a function expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); // Test parameters const testParams = { phone_numbers: ['+1234567890', '+0987654321'], }; // Call the handler await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); // Verify the API was called expect(simplifiedApiMock.searchUsers).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); // Verify formatToMCPToolResponse was called expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Mock the API to throw an error const apiError = new Error('API error'); simplifiedApiMock.searchUsers.mockRejectedValueOnce(apiError); const toolHandler = searchUsersCall[2]; // Call the handler - it should NOT throw, but return a formatted error response const result = await toolHandler( { phone_numbers: ['+1234567890'] }, mockContext, ); // Verify the API was called expect(simplifiedApiMock.searchUsers).toHaveBeenCalled(); // Verify logger.error was called with the error expect(mockLogger.error).toHaveBeenCalledWith( 'Error searching users:', { args: { phone_numbers: ['+1234567890'] }, error: apiError, }, ); // Verify formatToMCPToolResponse was called with the error expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); // Verify the result is defined (the formatted error response) expect(result).toBeDefined(); }); }); describe('get_current_user tool', () => { let getCurrentUserCall: any; beforeEach(() => { getCurrentUserCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_current_user', ); }); it('should register get_current_user tool with correct parameters', () => { expect(getCurrentUserCall).toBeDefined(); expect(getCurrentUserCall[0]).toBe('get_current_user'); expect(getCurrentUserCall[1].inputSchema).toBeDefined(); expect(getCurrentUserCall[1].annotations).toBeDefined(); expect(getCurrentUserCall[1].annotations.readOnlyHint).toBe(true); expect(getCurrentUserCall[1].annotations.destructiveHint).toBe(false); expect(getCurrentUserCall[1].description).toBeDefined(); }); it('should call cv API with correct parameters', async () => { const toolHandler = getCurrentUserCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); await expect(toolHandler({}, mockContext)).resolves.not.toThrow(); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { // Skip this test for now as it requires complex mock setup expect(true).toBe(true); }); }); describe('list_conversations tool', () => { let listConversationsCall: any; beforeEach(() => { listConversationsCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'list_conversations', ); }); it('should register list_conversations tool with correct parameters', () => { expect(listConversationsCall).toBeDefined(); expect(listConversationsCall[0]).toBe('list_conversations'); expect(listConversationsCall[1].inputSchema).toBeDefined(); expect(listConversationsCall[1].annotations).toBeDefined(); expect(listConversationsCall[1].annotations.readOnlyHint).toBe(true); expect(listConversationsCall[1].annotations.destructiveHint).toBe( false, ); expect(listConversationsCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = listConversationsCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); await expect(toolHandler({}, mockContext)).resolves.not.toThrow(); expect(simplifiedApiMock.getAllConversations).toHaveBeenCalledWith({ headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getAllConversations.mockRejectedValueOnce(apiError); const toolHandler = listConversationsCall[2]; const result = await toolHandler({}, mockContext); expect(simplifiedApiMock.getAllConversations).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error listing conversations:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_conversation tool', () => { let getConversationCall: any; beforeEach(() => { getConversationCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_conversation', ); }); it('should register get_conversation tool with correct parameters', () => { expect(getConversationCall).toBeDefined(); expect(getConversationCall[0]).toBe('get_conversation'); expect(getConversationCall[1].inputSchema).toBeDefined(); expect(getConversationCall[1].annotations).toBeDefined(); expect(getConversationCall[1].annotations.readOnlyHint).toBe(true); expect(getConversationCall[1].annotations.destructiveHint).toBe(false); expect(getConversationCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getConversationCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-conversation-id' }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.getConversationById).toHaveBeenCalledWith( testParams.id, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getConversationById.mockRejectedValueOnce(apiError); const toolHandler = getConversationCall[2]; const result = await toolHandler({ id: 'test-id' }, mockContext); expect(simplifiedApiMock.getConversationById).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting conversation by id:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_conversation_users tool', () => { let getConversationUsersCall: any; beforeEach(() => { getConversationUsersCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_conversation_users', ); }); it('should register get_conversation_users tool with correct parameters', () => { expect(getConversationUsersCall).toBeDefined(); expect(getConversationUsersCall[0]).toBe('get_conversation_users'); expect(getConversationUsersCall[1].inputSchema).toBeDefined(); expect(getConversationUsersCall[1].annotations).toBeDefined(); expect(getConversationUsersCall[1].annotations.readOnlyHint).toBe(true); expect(getConversationUsersCall[1].annotations.destructiveHint).toBe( false, ); expect(getConversationUsersCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getConversationUsersCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-conversation-id' }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.getConversationUsers).toHaveBeenCalledWith( testParams.id, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getConversationUsers.mockRejectedValueOnce(apiError); const toolHandler = getConversationUsersCall[2]; const result = await toolHandler({ id: 'test-id' }, mockContext); expect(simplifiedApiMock.getConversationUsers).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting conversation users:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('summarize_conversation tool', () => { let summarizeConversationCall: any; beforeEach(() => { summarizeConversationCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'summarize_conversation', ); }); it('should register summarize_conversation tool with correct parameters', () => { expect(summarizeConversationCall).toBeDefined(); expect(summarizeConversationCall[0]).toBe('summarize_conversation'); expect(summarizeConversationCall[1].inputSchema).toBeDefined(); expect(summarizeConversationCall[1].annotations).toBeDefined(); expect(summarizeConversationCall[1].annotations.readOnlyHint).toBe( false, ); expect(summarizeConversationCall[1].annotations.destructiveHint).toBe( false, ); expect(summarizeConversationCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = summarizeConversationCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { conversation_id: 'test-conversation-id', prompt_id: 'test-prompt-id', language: 'en', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.listMessages).toHaveBeenCalledWith( testParams, { headers: { Authorization: 'Bearer test-token' } }, ); expect( simplifiedApiMock.aIResponseControllerCreateResponse, ).toHaveBeenCalled(); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.listMessages.mockRejectedValueOnce(apiError); const toolHandler = summarizeConversationCall[2]; const result = await toolHandler( { conversation_id: 'test-id' }, mockContext, ); expect(simplifiedApiMock.listMessages).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error summarizing conversation:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_root_folders tool', () => { let getRootFoldersCall: any; beforeEach(() => { getRootFoldersCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_root_folders', ); }); it('should register get_root_folders tool with correct parameters', () => { expect(getRootFoldersCall).toBeDefined(); expect(getRootFoldersCall[0]).toBe('get_root_folders'); expect(getRootFoldersCall[1].inputSchema).toBeDefined(); expect(getRootFoldersCall[1].annotations).toBeDefined(); expect(getRootFoldersCall[1].annotations.readOnlyHint).toBe(true); expect(getRootFoldersCall[1].annotations.destructiveHint).toBe(false); expect(getRootFoldersCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getRootFoldersCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { workspace_id: 'test-workspace-id', type: 'voicememo' as const, }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.getAllRootFolders).toHaveBeenCalledWith( testParams, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getAllRootFolders.mockRejectedValueOnce(apiError); const toolHandler = getRootFoldersCall[2]; const result = await toolHandler( { workspace_id: 'test-id' }, mockContext, ); expect(simplifiedApiMock.getAllRootFolders).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error listing root folders:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('create_folder tool', () => { let createFolderCall: any; beforeEach(() => { createFolderCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'create_folder', ); }); it('should register create_folder tool with correct parameters', () => { expect(createFolderCall).toBeDefined(); expect(createFolderCall[0]).toBe('create_folder'); expect(createFolderCall[1].inputSchema).toBeDefined(); expect(createFolderCall[1].annotations).toBeDefined(); expect(createFolderCall[1].annotations.readOnlyHint).toBe(false); expect(createFolderCall[1].annotations.destructiveHint).toBe(false); expect(createFolderCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = createFolderCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { name: 'Test Folder', workspace_id: 'test-workspace-id', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.createFolder).toHaveBeenCalledWith( testParams, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.createFolder.mockRejectedValueOnce(apiError); const toolHandler = createFolderCall[2]; const result = await toolHandler({ name: 'test' }, mockContext); expect(simplifiedApiMock.createFolder).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error creating folder:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_folder tool', () => { let getFolderCall: any; beforeEach(() => { getFolderCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_folder', ); }); it('should register get_folder tool with correct parameters', () => { expect(getFolderCall).toBeDefined(); expect(getFolderCall[0]).toBe('get_folder'); expect(getFolderCall[1].inputSchema).toBeDefined(); expect(getFolderCall[1].annotations).toBeDefined(); expect(getFolderCall[1].annotations.readOnlyHint).toBe(true); expect(getFolderCall[1].annotations.destructiveHint).toBe(false); expect(getFolderCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getFolderCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-folder-id', include_messages: true, }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.getFolderById).toHaveBeenCalledWith( testParams.id, testParams, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getFolderById.mockRejectedValueOnce(apiError); const toolHandler = getFolderCall[2]; const result = await toolHandler({ id: 'test-id' }, mockContext); expect(simplifiedApiMock.getFolderById).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting folder by id:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_folder_with_messages tool', () => { let getFolderWithMessagesCall: any; beforeEach(() => { getFolderWithMessagesCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_folder_with_messages', ); }); it('should register get_folder_with_messages tool with correct parameters', () => { expect(getFolderWithMessagesCall).toBeDefined(); expect(getFolderWithMessagesCall[0]).toBe('get_folder_with_messages'); expect(getFolderWithMessagesCall[1].inputSchema).toBeDefined(); expect(getFolderWithMessagesCall[1].annotations).toBeDefined(); expect(getFolderWithMessagesCall[1].annotations.readOnlyHint).toBe( true, ); expect(getFolderWithMessagesCall[1].annotations.destructiveHint).toBe( false, ); expect(getFolderWithMessagesCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getFolderWithMessagesCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-folder-id' }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.getFolderMessages).toHaveBeenCalledWith( testParams.id, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getFolderMessages.mockRejectedValueOnce(apiError); const toolHandler = getFolderWithMessagesCall[2]; const result = await toolHandler({ id: 'test-id' }, mockContext); expect(simplifiedApiMock.getFolderMessages).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting folder with messages:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('update_folder_name tool', () => { let updateFolderNameCall: any; beforeEach(() => { updateFolderNameCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'update_folder_name', ); }); it('should register update_folder_name tool with correct parameters', () => { expect(updateFolderNameCall).toBeDefined(); expect(updateFolderNameCall[0]).toBe('update_folder_name'); expect(updateFolderNameCall[1].inputSchema).toBeDefined(); expect(updateFolderNameCall[1].annotations).toBeDefined(); expect(updateFolderNameCall[1].annotations.readOnlyHint).toBe(false); expect(updateFolderNameCall[1].annotations.destructiveHint).toBe(false); expect(updateFolderNameCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = updateFolderNameCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-folder-id', name: 'Updated Folder Name', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.updateFolderName).toHaveBeenCalledWith( testParams.id, testParams, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.updateFolderName.mockRejectedValueOnce(apiError); const toolHandler = updateFolderNameCall[2]; const result = await toolHandler( { id: 'test-id', name: 'test' }, mockContext, ); expect(simplifiedApiMock.updateFolderName).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error updating folder name:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('delete_folder tool', () => { let deleteFolderCall: any; beforeEach(() => { deleteFolderCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'delete_folder', ); }); it('should register delete_folder tool with correct parameters', () => { expect(deleteFolderCall).toBeDefined(); expect(deleteFolderCall[0]).toBe('delete_folder'); expect(deleteFolderCall[1].inputSchema).toBeDefined(); expect(deleteFolderCall[1].annotations).toBeDefined(); expect(deleteFolderCall[1].annotations.readOnlyHint).toBe(false); expect(deleteFolderCall[1].annotations.destructiveHint).toBe(true); expect(deleteFolderCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = deleteFolderCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-folder-id' }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.deleteFolder).toHaveBeenCalledWith( testParams.id, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.deleteFolder.mockRejectedValueOnce(apiError); const toolHandler = deleteFolderCall[2]; const result = await toolHandler({ id: 'test-id' }, mockContext); expect(simplifiedApiMock.deleteFolder).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error deleting folder:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('move_folder tool', () => { let moveFolderCall: any; beforeEach(() => { moveFolderCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'move_folder', ); }); it('should register move_folder tool with correct parameters', () => { expect(moveFolderCall).toBeDefined(); expect(moveFolderCall[0]).toBe('move_folder'); expect(moveFolderCall[1].inputSchema).toBeDefined(); expect(moveFolderCall[1].annotations).toBeDefined(); expect(moveFolderCall[1].annotations.readOnlyHint).toBe(false); expect(moveFolderCall[1].annotations.destructiveHint).toBe(false); expect(moveFolderCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = moveFolderCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { id: 'test-folder-id', parent_id: 'test-parent-id', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect(simplifiedApiMock.moveFolder).toHaveBeenCalledWith( testParams.id, testParams, { headers: { Authorization: 'Bearer test-token' } }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.moveFolder.mockRejectedValueOnce(apiError); const toolHandler = moveFolderCall[2]; const result = await toolHandler({ id: 'test-id' }, mockContext); expect(simplifiedApiMock.moveFolder).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith('Error moving folder:', { error: apiError, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('move_message_to_folder tool', () => { let moveMessageToFolderCall: any; beforeEach(() => { moveMessageToFolderCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'move_message_to_folder', ); }); it('should register move_message_to_folder tool with correct parameters', () => { expect(moveMessageToFolderCall).toBeDefined(); expect(moveMessageToFolderCall[0]).toBe('move_message_to_folder'); expect(moveMessageToFolderCall[1].inputSchema).toBeDefined(); expect(moveMessageToFolderCall[1].annotations).toBeDefined(); expect(moveMessageToFolderCall[1].annotations.readOnlyHint).toBe(false); expect(moveMessageToFolderCall[1].annotations.destructiveHint).toBe( false, ); expect(moveMessageToFolderCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = moveMessageToFolderCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { message_id: 'test-message-id', folder_id: 'test-folder-id', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect( simplifiedApiMock.addMessageToFolderOrWorkspace, ).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.addMessageToFolderOrWorkspace.mockRejectedValueOnce( apiError, ); const toolHandler = moveMessageToFolderCall[2]; const result = await toolHandler( { message_id: 'test-id' }, mockContext, ); expect( simplifiedApiMock.addMessageToFolderOrWorkspace, ).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error moving message to folder:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_workspaces_basic_info tool', () => { let getWorkspacesBasicInfoCall: any; beforeEach(() => { getWorkspacesBasicInfoCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_workspaces_basic_info', ); }); it('should register get_workspaces_basic_info tool with correct parameters', () => { expect(getWorkspacesBasicInfoCall).toBeDefined(); expect(getWorkspacesBasicInfoCall[0]).toBe('get_workspaces_basic_info'); expect(getWorkspacesBasicInfoCall[1].inputSchema).toBeDefined(); expect(getWorkspacesBasicInfoCall[1].annotations).toBeDefined(); expect(getWorkspacesBasicInfoCall[1].annotations.readOnlyHint).toBe( true, ); expect(getWorkspacesBasicInfoCall[1].annotations.destructiveHint).toBe( false, ); expect(getWorkspacesBasicInfoCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getWorkspacesBasicInfoCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); await expect(toolHandler({}, mockContext)).resolves.not.toThrow(); expect( simplifiedApiMock.getAllWorkspacesWithBasicInfo, ).toHaveBeenCalledWith({ headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.getAllWorkspacesWithBasicInfo.mockRejectedValueOnce( apiError, ); const toolHandler = getWorkspacesBasicInfoCall[2]; const result = await toolHandler({}, mockContext); expect( simplifiedApiMock.getAllWorkspacesWithBasicInfo, ).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting workspaces basic info:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('list_ai_actions tool', () => { let listAIActionsCall: any; beforeEach(() => { listAIActionsCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'list_ai_actions', ); }); it('should register list_ai_actions tool with correct parameters', () => { expect(listAIActionsCall).toBeDefined(); expect(listAIActionsCall[0]).toBe('list_ai_actions'); expect(listAIActionsCall[1].inputSchema).toBeDefined(); expect(listAIActionsCall[1].annotations).toBeDefined(); expect(listAIActionsCall[1].annotations.readOnlyHint).toBe(true); expect(listAIActionsCall[1].annotations.destructiveHint).toBe(false); expect(listAIActionsCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = listAIActionsCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { owner_type: 'user' as const, workspace_id: 'test-workspace-id', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect( simplifiedApiMock.aIPromptControllerGetPrompts, ).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.aIPromptControllerGetPrompts.mockRejectedValueOnce( apiError, ); const toolHandler = listAIActionsCall[2]; const result = await toolHandler({}, mockContext); expect( simplifiedApiMock.aIPromptControllerGetPrompts, ).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error listing ai actions:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('run_ai_action tool', () => { let runAIActionCall: any; beforeEach(() => { runAIActionCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'run_ai_action', ); }); it('should register run_ai_action tool with correct parameters', () => { expect(runAIActionCall).toBeDefined(); expect(runAIActionCall[0]).toBe('run_ai_action'); expect(runAIActionCall[1].inputSchema).toBeDefined(); expect(runAIActionCall[1].annotations).toBeDefined(); expect(runAIActionCall[1].annotations.readOnlyHint).toBe(false); expect(runAIActionCall[1].annotations.destructiveHint).toBe(false); expect(runAIActionCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = runAIActionCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { prompt_id: 'test-prompt-id', message_ids: ['test-message-id'], channel_id: 'test-channel-id', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect( simplifiedApiMock.aIResponseControllerCreateResponse, ).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.aIResponseControllerCreateResponse.mockRejectedValueOnce( apiError, ); const toolHandler = runAIActionCall[2]; const result = await toolHandler({ prompt_id: 'test-id' }, mockContext); expect( simplifiedApiMock.aIResponseControllerCreateResponse, ).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error running ai action:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('run_ai_action_for_shared_link tool', () => { let runAIActionForSharedLinkCall: any; beforeEach(() => { runAIActionForSharedLinkCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'run_ai_action_for_shared_link', ); }); it('should register run_ai_action_for_shared_link tool with correct parameters', () => { expect(runAIActionForSharedLinkCall).toBeDefined(); expect(runAIActionForSharedLinkCall[0]).toBe( 'run_ai_action_for_shared_link', ); expect(runAIActionForSharedLinkCall[1].inputSchema).toBeDefined(); expect(runAIActionForSharedLinkCall[1].annotations).toBeDefined(); expect(runAIActionForSharedLinkCall[1].annotations.readOnlyHint).toBe( false, ); expect( runAIActionForSharedLinkCall[1].annotations.destructiveHint, ).toBe(false); expect(runAIActionForSharedLinkCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = runAIActionForSharedLinkCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { prompt_id: 'test-prompt-id', shared_link_ids: ['test-shared-link-id'], language: 'en', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect( simplifiedApiMock.createShareLinkAIResponse, ).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.createShareLinkAIResponse.mockRejectedValueOnce( apiError, ); const toolHandler = runAIActionForSharedLinkCall[2]; const result = await toolHandler({ prompt_id: 'test-id' }, mockContext); expect(simplifiedApiMock.createShareLinkAIResponse).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error running ai action for shared link:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); describe('get_ai_action_responses tool', () => { let getAIActionResponsesCall: any; beforeEach(() => { getAIActionResponsesCall = mockRegisterTool.mock.calls.find( (call: any) => call[0] === 'get_ai_action_responses', ); }); it('should register get_ai_action_responses tool with correct parameters', () => { expect(getAIActionResponsesCall).toBeDefined(); expect(getAIActionResponsesCall[0]).toBe('get_ai_action_responses'); expect(getAIActionResponsesCall[1].inputSchema).toBeDefined(); expect(getAIActionResponsesCall[1].annotations).toBeDefined(); expect(getAIActionResponsesCall[1].annotations.readOnlyHint).toBe(true); expect(getAIActionResponsesCall[1].annotations.destructiveHint).toBe( false, ); expect(getAIActionResponsesCall[1].description).toBeDefined(); }); it('should call simplified API with correct parameters', async () => { const toolHandler = getAIActionResponsesCall[2]; expect(toolHandler).toBeDefined(); expect(typeof toolHandler).toBe('function'); const testParams = { prompt_id: 'test-prompt-id', message_id: 'test-message-id', }; await expect( toolHandler(testParams, mockContext), ).resolves.not.toThrow(); expect( simplifiedApiMock.aIResponseControllerGetAllResponses, ).toHaveBeenCalledWith(testParams, { headers: { Authorization: 'Bearer test-token' }, }); expect(mockFormatToMCPToolResponse).toHaveBeenCalled(); }); it('should handle errors when API call fails', async () => { const apiError = new Error('API error'); simplifiedApiMock.aIResponseControllerGetAllResponses.mockRejectedValueOnce( apiError, ); const toolHandler = getAIActionResponsesCall[2]; const result = await toolHandler({ prompt_id: 'test-id' }, mockContext); expect( simplifiedApiMock.aIResponseControllerGetAllResponses, ).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( 'Error getting ai action responses:', { error: apiError }, ); expect(mockFormatToMCPToolResponse).toHaveBeenCalledWith(apiError); expect(result).toBeDefined(); }); }); }); });

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

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