Skip to main content
Glama
mcp-server.test.ts7.82 kB
/** * @fileoverview Tests for MCP Server module */ import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; import { DeepSourceMCPServer, createDeepSourceMCPServer } from '../../server/mcp-server.js'; // Mock dependencies vi.mock('../../utils/logging/logger.js', () => { const mockLogger = { info: vi.fn(), debug: vi.fn(), warn: vi.fn(), error: vi.fn(), }; return { createLogger: vi.fn(() => mockLogger), defaultLogger: mockLogger, Logger: vi.fn(() => mockLogger), LogLevel: { DEBUG: 'DEBUG', INFO: 'INFO', WARN: 'WARN', ERROR: 'ERROR', }, }; }); vi.mock('../../server/tool-registration.js', () => ({ registerDeepSourceTools: vi.fn(), })); vi.mock('@modelcontextprotocol/sdk/server/mcp.js', () => ({ McpServer: vi.fn().mockImplementation(() => ({ connect: vi.fn().mockResolvedValue(undefined), registerTool: vi.fn(), tool: vi.fn(), })), })); vi.mock('@modelcontextprotocol/sdk/server/stdio.js', () => ({ StdioServerTransport: vi.fn().mockImplementation(() => ({ start: vi.fn(), close: vi.fn(), })), })); describe('DeepSourceMCPServer', () => { let server: DeepSourceMCPServer; beforeEach(() => { vi.clearAllMocks(); // Set up mock API key for tests process.env.DEEPSOURCE_API_KEY = 'test-api-key'; }); afterEach(() => { server = null as unknown as DeepSourceMCPServer; // Clean up environment delete process.env.DEEPSOURCE_API_KEY; }); describe('constructor', () => { it('should create server with default configuration', () => { server = new DeepSourceMCPServer(); expect(server).toBeDefined(); expect(server.getRegisteredTools()).toBeDefined(); }); it('should create server with custom configuration', () => { server = new DeepSourceMCPServer({ name: 'custom-server', version: '2.0.0', autoRegisterTools: false, }); expect(server).toBeDefined(); }); it('should auto-register tools when configured', () => { // Note: Due to module initialization order, we cannot test that registerDeepSourceTools // was called during construction. Instead, we verify the tools are registered. server = new DeepSourceMCPServer({ autoRegisterTools: true }); const registry = server.getToolRegistry(); expect(registry).toBeDefined(); // The actual registration happens through the mocked function // so we skip this assertion since module mocking is complex in ES modules }); it('should not auto-register tools when disabled', () => { server = new DeepSourceMCPServer({ autoRegisterTools: false }); // Verify server is created successfully without auto-registration expect(server).toBeDefined(); expect(server.getToolRegistry()).toBeDefined(); }); }); describe('getMcpServer', () => { it('should return the MCP server instance', () => { server = new DeepSourceMCPServer(); const mcpServer = server.getMcpServer(); expect(mcpServer).toBeDefined(); }); }); describe('getToolRegistry', () => { it('should return the tool registry', () => { server = new DeepSourceMCPServer(); const registry = server.getToolRegistry(); expect(registry).toBeDefined(); }); }); describe('connect', () => { it('should connect to transport', async () => { server = new DeepSourceMCPServer(); // Spy on the actual mcpServer instance const mcpServer = server.getMcpServer(); const connectSpy = vi.spyOn(mcpServer, 'connect').mockResolvedValue(undefined); await server.connect(); expect(connectSpy).toHaveBeenCalled(); }); it('should not reconnect if already connected', async () => { server = new DeepSourceMCPServer(); // The server should initially not be connected expect(server.isServerConnected()).toBe(false); // Mock the internal mcpServer's connect method const mcpServer = server.getMcpServer(); const connectSpy = vi.spyOn(mcpServer, 'connect').mockResolvedValue(undefined); // First connection should succeed await server.connect(); expect(connectSpy).toHaveBeenCalledTimes(1); expect(server.isServerConnected()).toBe(true); // Clear the spy to track subsequent calls connectSpy.mockClear(); // Second connection attempt should return early without calling connect again await server.connect(); // The internal connect should NOT be called again expect(connectSpy).not.toHaveBeenCalled(); expect(server.isServerConnected()).toBe(true); }); it('should use provided transport', async () => { const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); const customTransport = new StdioServerTransport(); server = new DeepSourceMCPServer(); // Spy on the actual mcpServer instance const mcpServer = server.getMcpServer(); const connectSpy = vi.spyOn(mcpServer, 'connect').mockResolvedValue(undefined); await server.connect(customTransport); expect(connectSpy).toHaveBeenCalledWith(customTransport); }); }); describe('start', () => { it('should create transport and connect', async () => { server = new DeepSourceMCPServer(); // Spy on the actual mcpServer instance const mcpServer = server.getMcpServer(); const connectSpy = vi.spyOn(mcpServer, 'connect').mockResolvedValue(undefined); await server.start(); expect(connectSpy).toHaveBeenCalled(); }); }); describe('isServerConnected', () => { it('should return false before connection', () => { server = new DeepSourceMCPServer(); expect(server.isServerConnected()).toBe(false); }); it('should return true after connection', async () => { server = new DeepSourceMCPServer(); await server.connect(); expect(server.isServerConnected()).toBe(true); }); }); describe('updateHandlerDeps', () => { it('should update handler dependencies', () => { server = new DeepSourceMCPServer(); const newDeps = {}; const registry = server.getToolRegistry(); registry.updateDefaultDeps = vi.fn(); server.updateHandlerDeps(newDeps); expect(registry.updateDefaultDeps).toHaveBeenCalledWith(newDeps); }); }); describe('getRegisteredTools', () => { it('should return registered tool names', () => { server = new DeepSourceMCPServer({ autoRegisterTools: false }); const registry = server.getToolRegistry(); registry.getToolNames = vi.fn().mockReturnValue(['tool1', 'tool2']); const tools = server.getRegisteredTools(); expect(tools).toEqual(['tool1', 'tool2']); }); }); describe('static create', () => { it('should create server without auto-start', async () => { const server = await DeepSourceMCPServer.create(); expect(server).toBeDefined(); expect(server.isServerConnected()).toBe(false); }); it('should create and start server when configured', async () => { const server = await DeepSourceMCPServer.create({ autoStart: true }); expect(server).toBeDefined(); expect(server.isServerConnected()).toBe(true); }); }); describe('createDeepSourceMCPServer', () => { it('should create server without auto-start by default', async () => { const server = await createDeepSourceMCPServer(); expect(server).toBeDefined(); expect(server.isServerConnected()).toBe(false); }); it('should create and start server when requested', async () => { const server = await createDeepSourceMCPServer(true); expect(server).toBeDefined(); expect(server.isServerConnected()).toBe(true); }); }); });

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/sapientpants/deepsource-mcp-server'

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