@1mcp/agent
Version:
One MCP server to aggregate them all - A unified Model Context Protocol server implementation
159 lines (158 loc) • 6.89 kB
JavaScript
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();
});
});
});