Skip to main content
Glama
connector-resources.test.ts17.6 kB
import { registerConnectorResources } from '../../src/resources/connector-resources'; import { SimplifierClient } from '../../src/client/simplifier-client'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { SimplifierConnectorListResponse, SimplifierConnectorDetails, SimplifierConnectorCallsResponse, SimplifierConnectorCallDetails } from '../../src/client/types'; // Mock the resourcesresult wrapper jest.mock('../../src/resources/resourcesresult', () => ({ wrapResourceResult: jest.fn() })); // Mock the SimplifierClient jest.mock('../../src/client/simplifier-client'); describe('Connector Resources', () => { let mockServer: jest.Mocked<McpServer>; let mockClient: jest.Mocked<SimplifierClient>; let mockWrapResourceResult: jest.MockedFunction<any>; beforeEach(() => { // Create mock server with resource method mockServer = { resource: jest.fn(), } as any; // Create mock client mockClient = { listConnectors: jest.fn(), getConnector: jest.fn(), listConnectorCalls: jest.fn(), getConnectorCall: jest.fn(), } as any; // Get the mocked wrapResourceResult mockWrapResourceResult = require('../../src/resources/resourcesresult').wrapResourceResult; mockWrapResourceResult.mockClear(); }); const createMockExtra = () => ({ signal: new AbortController().signal, requestId: 'test-request-id', sendNotification: jest.fn(), sendRequest: jest.fn() }); afterEach(() => { jest.clearAllMocks(); }); const mockConnectorListResponse: SimplifierConnectorListResponse = { connectors: [ { name: 'TestConnector', description: 'A test connector for API testing', connectorType: { technicalName: 'REST', i18n: 'REST API', descriptionI18n: 'REST API Connector' }, active: true, timeoutTime: 30000, amountOfCalls: 3, editable: true, deletable: true, tags: ['test', 'api'], assignedProjects: { projectsBefore: ['project1'], projectsAfterChange: ['project1'] } }, { name: 'DatabaseConnector', description: 'Database connector', connectorType: { technicalName: 'SQL', i18n: 'SQL Database', descriptionI18n: 'SQL Database Connector' }, active: true, timeoutTime: 60000, amountOfCalls: 5, editable: true, deletable: false, tags: ['database'], assignedProjects: { projectsBefore: [], projectsAfterChange: [] } } ] }; const mockConnectorDetails: SimplifierConnectorDetails = { name: 'TestConnector', description: 'A test connector for API testing', connectorType: { technicalName: 'REST', i18n: 'REST API', descriptionI18n: 'REST API Connector' }, active: true, timeoutTime: 30000, amountOfCalls: 3, editable: true, deletable: true, tags: ['test', 'api'], assignedProjects: { projectsBefore: ['project1'], projectsAfterChange: ['project1'] }, configuration: { endpoints: [ { endpointName: 'production', endpointType: 'REST' } ] } }; const mockConnectorCallsResponse: SimplifierConnectorCallsResponse = { connectorCalls: [ { name: 'getData', description: 'Fetch data from API', validateIn: true, validateOut: true, editable: true, executable: true, autoGenerated: false, amountOfInputParameters: 2, amountOfOutputParameters: 1 }, { name: 'postData', description: 'Send data to API', validateIn: true, validateOut: false, editable: true, executable: true, autoGenerated: false, amountOfInputParameters: 3, amountOfOutputParameters: 0 } ] }; const mockConnectorCallDetails: SimplifierConnectorCallDetails = { name: 'getData', description: 'Fetch data from API', validateIn: true, validateOut: true, editable: true, executable: true, autoGenerated: false, async: false, connectorName: 'TestConnector', connectorCallParameters: [ { name: 'id', alias: 'recordId', isInput: true, dataType: { name: 'String', category: 'base' }, optional: false, position: 0 }, { name: 'includeDetails', isInput: true, dataType: { name: 'Boolean', category: 'base' }, optional: true, position: 1 }, { name: 'result', isInput: false, dataType: { name: 'DataRecord', nameSpace: 'con/TestConnector', category: 'struct' }, optional: false, position: 0 } ] }; describe('registerConnectorResources', () => { it('should register six connector resources', () => { registerConnectorResources(mockServer, mockClient); expect(mockServer.resource).toHaveBeenCalledTimes(6); // Check that specific resources are registered const calls = mockServer.resource.mock.calls; const resourceNames = calls.map(call => call[0]); expect(resourceNames).toContain('connectors-list'); expect(resourceNames).toContain('connector-details'); expect(resourceNames).toContain('connector-calls-list'); expect(resourceNames).toContain('connector-call-details'); expect(resourceNames).toContain('connector-wsdl'); expect(resourceNames).toContain('connector-wizard-search-functions'); }); describe('connectors list handler', () => { let connectorsListHandler: any; beforeEach(() => { registerConnectorResources(mockServer, mockClient); connectorsListHandler = mockServer.resource.mock.calls[0][3]; // First resource (connectors list) }); it('should call wrapResourceResult with correct parameters', async () => { const testUri = new URL('simplifier://connectors'); mockWrapResourceResult.mockResolvedValue({ contents: [] }); await connectorsListHandler(testUri, {}, createMockExtra()); expect(mockWrapResourceResult).toHaveBeenCalledWith( testUri, expect.any(Function) ); }); it('should return connector list through wrapper', async () => { const testUri = new URL('simplifier://connectors'); mockClient.listConnectors.mockResolvedValue(mockConnectorListResponse); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { const result = await fn(); return { contents: [{ uri: uri.href, text: JSON.stringify(result, null, 2), mimeType: 'application/json' }] }; }); const result = await connectorsListHandler(testUri, {}, createMockExtra()); expect(mockClient.listConnectors).toHaveBeenCalled(); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.connectors).toHaveLength(2); expect(resultData.totalCount).toBe(2); expect(resultData.connectors[0].uri).toBe('simplifier://connector/TestConnector'); expect(resultData.connectors[0].name).toBe('TestConnector'); expect(resultData.resourcePatterns).toHaveLength(5); }); it('should handle API errors through wrapper', async () => { const testUri = new URL('simplifier://connectors'); const testError = new Error('API Error'); mockClient.listConnectors.mockRejectedValue(testError); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { try { await fn(); return { contents: [] }; } catch (e) { return { contents: [{ uri: uri.href, text: JSON.stringify({ error: `Failed to fetch: ${e}` }), mimeType: 'application/json' }] }; } }); const result = await connectorsListHandler(testUri, {}, createMockExtra()); expect(mockClient.listConnectors).toHaveBeenCalled(); expect(result.contents[0].text).toContain('Failed to fetch'); expect(result.contents[0].text).toContain('API Error'); }); }); describe('connector details handler', () => { let connectorDetailsHandler: any; beforeEach(() => { registerConnectorResources(mockServer, mockClient); connectorDetailsHandler = mockServer.resource.mock.calls[1][3]; // Second resource (connector details) }); it('should return connector details', async () => { const testUri = new URL('simplifier://connector/TestConnector'); mockClient.getConnector.mockResolvedValue(mockConnectorDetails); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { const result = await fn(); return { contents: [{ uri: uri.href, text: JSON.stringify(result, null, 2), mimeType: 'application/json' }] }; }); const result = await connectorDetailsHandler(testUri, {}, createMockExtra()); expect(mockClient.getConnector).toHaveBeenCalledWith('TestConnector', 'MCP Resource: connector-details', true); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.connector.name).toBe('TestConnector'); expect(resultData.connector.active).toBe(true); expect(resultData.relatedResources).toHaveLength(1); expect(resultData.relatedResources[0].uri).toBe('simplifier://connector/TestConnector/calls'); }); it('should throw error if connector name is missing', async () => { const testUri = new URL('simplifier://connector/'); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { try { await fn(); return { contents: [] }; } catch (e: any) { return { contents: [{ uri: uri.href, text: JSON.stringify({ error: e.message }), mimeType: 'application/json' }] }; } }); const result = await connectorDetailsHandler(testUri, {}, createMockExtra()); expect(mockClient.getConnector).not.toHaveBeenCalled(); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.error).toBe('Connector name is required'); }); }); describe('connector calls list handler', () => { let connectorCallsListHandler: any; beforeEach(() => { registerConnectorResources(mockServer, mockClient); connectorCallsListHandler = mockServer.resource.mock.calls[2][3]; // Third resource (calls list) }); it('should return connector calls list', async () => { const testUri = new URL('simplifier://connector/TestConnector/calls'); mockClient.listConnectorCalls.mockResolvedValue(mockConnectorCallsResponse); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { const result = await fn(); return { contents: [{ uri: uri.href, text: JSON.stringify(result, null, 2), mimeType: 'application/json' }] }; }); const result = await connectorCallsListHandler(testUri, {}, createMockExtra()); expect(mockClient.listConnectorCalls).toHaveBeenCalledWith('TestConnector', 'MCP Resource: connector-calls-list'); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.connectorName).toBe('TestConnector'); expect(resultData.calls).toHaveLength(2); expect(resultData.calls[0].name).toBe('getData'); expect(resultData.calls[0].uri).toBe('simplifier://connector/TestConnector/call/getData'); expect(resultData.totalCount).toBe(2); }); }); describe('connector call details handler', () => { let connectorCallDetailsHandler: any; beforeEach(() => { registerConnectorResources(mockServer, mockClient); connectorCallDetailsHandler = mockServer.resource.mock.calls[3][3]; // Fourth resource (call details) }); it('should return connector call details', async () => { const testUri = new URL('simplifier://connector/TestConnector/call/getData'); mockClient.getConnectorCall.mockResolvedValue(mockConnectorCallDetails); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { const result = await fn(); return { contents: [{ uri: uri.href, text: JSON.stringify(result, null, 2), mimeType: 'application/json' }] }; }); const result = await connectorCallDetailsHandler(testUri, {}, createMockExtra()); expect(mockClient.getConnectorCall).toHaveBeenCalledWith('TestConnector', 'getData', 'MCP Resource: connector-call-details'); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.call.name).toBe('getData'); expect(resultData.call.connectorCallParameters).toHaveLength(3); expect(resultData.usage.note).toContain('Business Object functions'); expect(resultData.usage.example).toContain('Simplifier.Connector.TestConnector.getData'); }); it('should throw error if connector name is missing', async () => { const testUri = new URL('simplifier://connector//call/getData'); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { try { await fn(); return { contents: [] }; } catch (e: any) { return { contents: [{ uri: uri.href, text: JSON.stringify({ error: e.message }), mimeType: 'application/json' }] }; } }); const result = await connectorCallDetailsHandler(testUri, {}, createMockExtra()); expect(mockClient.getConnectorCall).not.toHaveBeenCalled(); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.error).toBe('Connector name and call name are required'); }); it('should throw error if call name is missing', async () => { const testUri = new URL('simplifier://connector/TestConnector/call/'); mockWrapResourceResult.mockImplementation(async (uri: URL, fn: () => any) => { try { await fn(); return { contents: [] }; } catch (e: any) { return { contents: [{ uri: uri.href, text: JSON.stringify({ error: e.message }), mimeType: 'application/json' }] }; } }); const result = await connectorCallDetailsHandler(testUri, {}, createMockExtra()); expect(mockClient.getConnectorCall).not.toHaveBeenCalled(); const resultData = JSON.parse(result.contents[0].text as string); expect(resultData.error).toBe('Connector name and call name are required'); }); }); }); describe('resource registration configuration', () => { it('should register connectors-list as a simple resource', () => { registerConnectorResources(mockServer, mockClient); // First call should be simple resource (string URI) expect(mockServer.resource).toHaveBeenNthCalledWith( 1, 'connectors-list', 'simplifier://connectors', expect.objectContaining({ title: 'List All Connectors', mimeType: 'application/json' }), expect.any(Function) ); }); it('should register connector-details as a template resource', () => { registerConnectorResources(mockServer, mockClient); // Second call should be template resource const secondCall = mockServer.resource.mock.calls[1]; expect(secondCall[0]).toBe('connector-details'); expect(secondCall[1]).toHaveProperty('uriTemplate'); expect(secondCall[2]).toHaveProperty('title', 'Connector Details'); }); it('should register connector-calls-list as a template resource', () => { registerConnectorResources(mockServer, mockClient); // Third call should be template resource const thirdCall = mockServer.resource.mock.calls[2]; expect(thirdCall[0]).toBe('connector-calls-list'); expect(thirdCall[1]).toHaveProperty('uriTemplate'); expect(thirdCall[2]).toHaveProperty('title', 'Connector Calls List'); }); it('should register connector-call-details as a template resource', () => { registerConnectorResources(mockServer, mockClient); // Fourth call should be template resource const fourthCall = mockServer.resource.mock.calls[3]; expect(fourthCall[0]).toBe('connector-call-details'); expect(fourthCall[1]).toHaveProperty('uriTemplate'); expect(fourthCall[2]).toHaveProperty('title', 'Connector Call Details'); }); }); });

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/SimplifierIO/simplifier-mcp'

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