UNPKG

@1mcp/agent

Version:

One MCP server to aggregate them all - A unified Model Context Protocol server implementation

159 lines (158 loc) 6.89 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { ServerManager } from './serverManager.js'; import logger from './logger/logger.js'; import configReloadService from './services/configReloadService.js'; import { setupCapabilities } from './capabilities/capabilityManager.js'; import { enhanceServerWithLogging } from './middleware/loggingMiddleware.js'; // Mock dependencies jest.mock('@modelcontextprotocol/sdk/server/index.js', () => ({ Server: jest.fn(), })); jest.mock('@modelcontextprotocol/sdk/shared/transport.js', () => ({ Transport: jest.fn(), })); jest.mock('./logger/logger.js', () => { const mockLogger = { info: jest.fn(), error: jest.fn(), }; return { __esModule: true, default: mockLogger, }; }); jest.mock('./services/configReloadService.js', () => ({ __esModule: true, default: { initialize: jest.fn(), }, })); jest.mock('./capabilities/capabilityManager.js', () => ({ setupCapabilities: jest.fn(), })); jest.mock('./middleware/loggingMiddleware.js', () => ({ enhanceServerWithLogging: jest.fn(), })); describe('ServerManager', () => { let mockConfig; let mockCapabilities; let mockClients; let mockTransports; let mockTransport; let mockServer; beforeEach(() => { // Reset all mocks jest.clearAllMocks(); // Setup test data mockConfig = { name: 'test-server', version: '1.0.0' }; mockCapabilities = { capabilities: { test: true } }; mockClients = {}; mockTransports = {}; mockTransport = { // Add any required Transport properties here }; mockServer = { connect: jest.fn().mockResolvedValue(undefined), transport: mockTransport, }; // Setup mocks Server.mockImplementation(() => mockServer); setupCapabilities.mockResolvedValue(undefined); enhanceServerWithLogging.mockReturnValue(undefined); configReloadService.initialize.mockImplementation(() => undefined); }); describe('getInstance', () => { it('should create a singleton instance', () => { const instance1 = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports); const instance2 = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports); expect(instance1).toBe(instance2); }); }); describe('connectTransport', () => { let serverManager; const sessionId = 'test-session'; const tags = ['tag1', 'tag2']; beforeEach(() => { serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports); }); it('should successfully connect a transport', async () => { await serverManager.connectTransport(mockTransport, sessionId, tags); expect(Server).toHaveBeenCalledWith(mockConfig, mockCapabilities); expect(enhanceServerWithLogging).toHaveBeenCalledWith(mockServer); expect(setupCapabilities).toHaveBeenCalled(); expect(configReloadService.initialize).toHaveBeenCalled(); expect(mockServer.connect).toHaveBeenCalledWith(mockTransport); expect(logger.info).toHaveBeenCalledWith(`Connected transport for session ${sessionId}`); }); it('should handle connection errors', async () => { const error = new Error('Connection failed'); mockServer.connect.mockRejectedValueOnce(error); await expect(serverManager.connectTransport(mockTransport, sessionId, tags)).rejects.toThrow('Connection failed'); expect(logger.error).toHaveBeenCalled(); }); }); describe('disconnectTransport', () => { let serverManager; const sessionId = 'test-session'; beforeEach(() => { serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports); }); it('should successfully disconnect a transport', async () => { await serverManager.connectTransport(mockTransport, sessionId); jest.clearAllMocks(); // Clear the logs from connectTransport serverManager.disconnectTransport(sessionId); expect(logger.info).toHaveBeenCalledWith(`Disconnected transport for session ${sessionId}`); }); it('should handle non-existent session gracefully', () => { serverManager.disconnectTransport('non-existent'); expect(logger.info).not.toHaveBeenCalled(); }); }); describe('transport management methods', () => { let serverManager; const sessionId = 'test-session'; beforeEach(async () => { serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports); await serverManager.connectTransport(mockTransport, sessionId); }); it('should get transport by session id', () => { const transport = serverManager.getTransport(sessionId); expect(transport).toBe(mockTransport); }); it('should return undefined for non-existent session', () => { const transport = serverManager.getTransport('non-existent'); expect(transport).toBeUndefined(); }); it('should get all transports', () => { const transports = serverManager.getTransports(); expect(transports.size).toBe(1); expect(transports.get(sessionId)).toBe(mockTransport); }); it('should get client transports', () => { const clientTransports = serverManager.getClientTransports(); expect(clientTransports).toEqual(mockTransports); }); it('should get active transports count', () => { expect(serverManager.getActiveTransportsCount()).toBe(1); }); }); describe('getServer', () => { let serverManager; const sessionId = 'test-session'; const tags = ['tag1', 'tag2']; beforeEach(async () => { serverManager = ServerManager.getInstance(mockConfig, mockCapabilities, mockClients, mockTransports); await serverManager.connectTransport(mockTransport, sessionId, tags); }); it('should return server info for existing session', () => { const serverInfo = serverManager.getServer(sessionId); expect(serverInfo).toBeDefined(); expect(serverInfo?.server).toBe(mockServer); expect(serverInfo?.tags).toEqual(tags); }); it('should return undefined for non-existent session', () => { const serverInfo = serverManager.getServer('non-existent'); expect(serverInfo).toBeUndefined(); }); }); });