Skip to main content
Glama

1MCP Server

serverManager.test.ts8.26 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import configReloadService from '@src/application/services/configReloadService.js'; import { setupCapabilities } from '@src/core/capabilities/capabilityManager.js'; import { OutboundConnections } from '@src/core/types/index.js'; import logger from '@src/logger/logger.js'; import { enhanceServerWithLogging } from '@src/logger/mcpLoggingEnhancer.js'; import { beforeEach, describe, expect, it, MockInstance, vi } from 'vitest'; import { ServerManager } from './serverManager.js'; // Mock dependencies vi.mock('@modelcontextprotocol/sdk/server/index.js', () => ({ Server: vi.fn(), })); vi.mock('@modelcontextprotocol/sdk/shared/transport.js', () => ({ Transport: vi.fn(), })); vi.mock('@src/logger/logger.js', () => { const mockLogger = { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn(), }; return { __esModule: true, default: mockLogger, debugIf: vi.fn(), }; }); vi.mock('@src/application/services/configReloadService.js', () => ({ __esModule: true, default: { updateServerInfo: vi.fn(), removeServerInfo: vi.fn(), }, })); vi.mock('../capabilities/capabilityManager.js', () => ({ setupCapabilities: vi.fn(), })); vi.mock('../../logger/mcpLoggingEnhancer.js', () => ({ enhanceServerWithLogging: vi.fn(), })); vi.mock('@src/domains/preset/services/presetNotificationService.js', () => ({ PresetNotificationService: { getInstance: vi.fn().mockReturnValue({ trackClient: vi.fn(), untrackClient: vi.fn(), }), }, })); describe('ServerManager', () => { let mockConfig: { name: string; version: string }; let mockCapabilities: { capabilities: Record<string, unknown> }; let mockOutboundConns: OutboundConnections; let mockTransports: Record<string, Transport>; let mockTransport: Transport; let mockServer: Server; beforeEach(() => { // Reset all mocks vi.clearAllMocks(); // Reset singleton state for test isolation ServerManager.resetInstance(); // Setup test data mockConfig = { name: 'test-server', version: '1.0.0' }; mockCapabilities = { capabilities: { test: true } }; mockOutboundConns = new Map(); mockTransports = {}; mockTransport = { // Add any required Transport properties here } as Transport; mockServer = { connect: vi.fn().mockImplementation(async (transport: Transport) => { // Simulate setting transport property on connection (mockServer as any).transport = transport; }), transport: undefined, } as unknown as Server; // Setup mocks (Server as unknown as MockInstance).mockImplementation(() => mockServer); (setupCapabilities as unknown as MockInstance).mockResolvedValue(undefined); (enhanceServerWithLogging as unknown as MockInstance).mockReturnValue(undefined); (configReloadService.updateServerInfo as unknown as MockInstance).mockImplementation(() => undefined); (configReloadService.removeServerInfo as unknown as MockInstance).mockImplementation(() => undefined); }); describe('getInstance', () => { it('should create a singleton instance', () => { const instance1 = ServerManager.getOrCreateInstance( mockConfig, mockCapabilities, mockOutboundConns, mockTransports, ); const instance2 = ServerManager.getOrCreateInstance( mockConfig, mockCapabilities, mockOutboundConns, mockTransports, ); expect(instance1).toBe(instance2); }); }); describe('connectTransport', () => { let serverManager: ServerManager; const sessionId = 'test-session'; const tags = ['tag1', 'tag2']; beforeEach(() => { serverManager = ServerManager.getOrCreateInstance( mockConfig, mockCapabilities, mockOutboundConns, mockTransports, ); }); it('should successfully connect a transport', async () => { await serverManager.connectTransport(mockTransport, sessionId, { tags, enablePagination: false }); expect(Server).toHaveBeenCalledWith(mockConfig, mockCapabilities); expect(enhanceServerWithLogging).toHaveBeenCalledWith(mockServer); expect(setupCapabilities).toHaveBeenCalled(); expect(configReloadService.updateServerInfo).toHaveBeenCalledWith(sessionId, expect.any(Object)); 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 as unknown as MockInstance).mockRejectedValueOnce(error); await expect( serverManager.connectTransport(mockTransport, sessionId, { tags, enablePagination: false }), ).rejects.toThrow('Connection failed'); expect(logger.error).toHaveBeenCalled(); }); }); describe('disconnectTransport', () => { let serverManager: ServerManager; const sessionId = 'test-session'; beforeEach(() => { serverManager = ServerManager.getOrCreateInstance( mockConfig, mockCapabilities, mockOutboundConns, mockTransports, ); }); it('should successfully disconnect a transport', async () => { await serverManager.connectTransport(mockTransport, sessionId, { enablePagination: false }); vi.clearAllMocks(); // Clear the logs from connectTransport serverManager.disconnectTransport(sessionId); expect(configReloadService.removeServerInfo).toHaveBeenCalledWith(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: ServerManager; const sessionId = 'test-session'; beforeEach(async () => { serverManager = ServerManager.getOrCreateInstance( mockConfig, mockCapabilities, mockOutboundConns, mockTransports, ); await serverManager.connectTransport(mockTransport, sessionId, { enablePagination: false }); }); 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: ServerManager; const sessionId = 'test-session'; const tags = ['tag1', 'tag2']; beforeEach(async () => { serverManager = ServerManager.getOrCreateInstance( mockConfig, mockCapabilities, mockOutboundConns, mockTransports, ); await serverManager.connectTransport(mockTransport, sessionId, { tags, enablePagination: false }); }); 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(); }); }); });

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/1mcp-app/agent'

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