Skip to main content
Glama
server-management.test.ts10.2 kB
import { mkdtemp, readFile, rm, writeFile } from 'fs/promises'; import { tmpdir } from 'os'; import { join } from 'path'; import { initializeConfigContext, serverExists, setServer } from '@src/commands/mcp/utils/mcpServerConfig.js'; import ConfigContext from '@src/config/configContext.js'; import { createServerInstallationService, getProgressTrackingService } from '@src/domains/server-management/index.js'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; /** * Integration tests for server management domain * Tests end-to-end workflows including service integration, * registry client integration, configuration management, and progress tracking */ describe('Server Management Domain Integration', () => { let tempDir: string; let configPath: string; beforeEach(async () => { // Create temporary directory for test configs tempDir = await mkdtemp(join(tmpdir(), 'server-mgmt-test-')); // Initialize config context with test directory const configContext = ConfigContext.getInstance(); configContext.setConfigDir(tempDir); configPath = configContext.getResolvedConfigPath(); // Create empty config file await writeFile( configPath, JSON.stringify({ mcpServers: {}, }), 'utf-8', ); }); afterEach(async () => { // Cleanup temp directory if (tempDir) { await rm(tempDir, { recursive: true, force: true }); } // Reset config context ConfigContext.getInstance().reset(); vi.clearAllMocks(); }); describe('ServerInstallationService Integration', () => { it('should create service instance', () => { const service = createServerInstallationService(); expect(service).toBeDefined(); }); it('should list installed servers', async () => { // Setup: Add some servers manually initializeConfigContext(undefined, tempDir); setServer('test-server-1', { type: 'stdio', command: 'echo', args: ['test1'], }); setServer('test-server-2', { type: 'stdio', command: 'echo', args: ['test2'], }); const service = createServerInstallationService(); const servers = await service.listInstalledServers(); expect(servers).toContain('test-server-1'); expect(servers).toContain('test-server-2'); }); it('should filter active servers when requested', async () => { // Setup: Add enabled and disabled servers initializeConfigContext(undefined, tempDir); setServer('enabled-server', { type: 'stdio', command: 'echo', args: ['enabled'], }); setServer('disabled-server', { type: 'stdio', command: 'echo', args: ['disabled'], disabled: true, }); const service = createServerInstallationService(); // Get all servers const allServers = await service.listInstalledServers(); expect(allServers.length).toBe(2); // Get only active servers const activeServers = await service.listInstalledServers({ filterActive: true }); expect(activeServers).toContain('enabled-server'); expect(activeServers).not.toContain('disabled-server'); }); it('should check for updates and return results', async () => { // Setup: Add a server initializeConfigContext(undefined, tempDir); setServer('updatable-server', { type: 'stdio', command: 'echo', args: ['test'], }); const service = createServerInstallationService(); // Mock registry client would be needed for actual update checking // For integration test, we verify the interface works const results = await service.checkForUpdates(['updatable-server']); expect(Array.isArray(results)).toBe(true); // Results may be empty if server not in registry or version unknown // But the method should complete without errors }); }); describe('Configuration Management Integration', () => { it('should persist server configuration changes', async () => { initializeConfigContext(undefined, tempDir); // Add a server setServer('persist-test', { type: 'stdio', command: 'echo', args: ['persist'], tags: ['test'], }); // Verify it was written to file const configContent = await readFile(configPath, 'utf-8'); const config = JSON.parse(configContent); expect(config.mcpServers).toBeDefined(); expect(config.mcpServers['persist-test']).toBeDefined(); expect(config.mcpServers['persist-test'].command).toBe('echo'); expect(config.mcpServers['persist-test'].tags).toContain('test'); }); it('should update existing server configuration', async () => { initializeConfigContext(undefined, tempDir); // Add initial server setServer('update-config-test', { type: 'stdio', command: 'echo', args: ['old'], }); // Update server setServer('update-config-test', { type: 'stdio', command: 'echo', args: ['new'], tags: ['updated'], }); // Verify update const configContent = await readFile(configPath, 'utf-8'); const config = JSON.parse(configContent); expect(config.mcpServers['update-config-test'].args).toContain('new'); expect(config.mcpServers['update-config-test'].tags).toContain('updated'); }); it('should verify server existence', () => { initializeConfigContext(undefined, tempDir); // Server doesn't exist yet expect(serverExists('new-server')).toBe(false); // Add server setServer('new-server', { type: 'stdio', command: 'echo', }); // Server should now exist expect(serverExists('new-server')).toBe(true); }); }); describe('Progress Tracking Integration', () => { it('should track operation progress', () => { const progressTracker = getProgressTrackingService(); const operationId = 'test-op-123'; progressTracker.startOperation(operationId, 'install', 5); progressTracker.updateProgress(operationId, 1, 'Step 1', 'Validating'); progressTracker.updateProgress(operationId, 2, 'Step 2', 'Installing'); // Verify operation is tracked (no errors thrown) expect(operationId).toBeTruthy(); }); it('should complete operations successfully', () => { const progressTracker = getProgressTrackingService(); const operationId = 'test-complete-op'; progressTracker.startOperation(operationId, 'install', 3); progressTracker.completeOperation(operationId, { success: true, operationId, duration: 1000, message: 'Test completed', }); // Verify completion without errors expect(operationId).toBeTruthy(); }); it('should handle failed operations', () => { const progressTracker = getProgressTrackingService(); const operationId = 'test-fail-op'; progressTracker.startOperation(operationId, 'install', 2); const error = new Error('Test error'); progressTracker.failOperation(operationId, error); // Verify failure handling without errors expect(operationId).toBeTruthy(); }); }); describe('Service Workflow Integration', () => { it('should handle complete install workflow', async () => { initializeConfigContext(undefined, tempDir); // Verify server doesn't exist expect(serverExists('workflow-test')).toBe(false); // Add server (simulating install) setServer('workflow-test', { type: 'stdio', command: 'echo', args: ['installed'], }); // Verify it exists expect(serverExists('workflow-test')).toBe(true); // Verify in service const service = createServerInstallationService(); const servers = await service.listInstalledServers(); expect(servers).toContain('workflow-test'); }); it('should handle update workflow with version checking', async () => { initializeConfigContext(undefined, tempDir); // Add server setServer('version-test', { type: 'stdio', command: 'echo', }); const service = createServerInstallationService(); // Check for updates const updateResults = await service.checkForUpdates(['version-test']); expect(Array.isArray(updateResults)).toBe(true); // May be empty or contain update info depending on registry }); it('should handle uninstall workflow', async () => { initializeConfigContext(undefined, tempDir); // Add server setServer('uninstall-workflow-test', { type: 'stdio', command: 'echo', }); // Verify exists expect(serverExists('uninstall-workflow-test')).toBe(true); const service = createServerInstallationService(); const result = await service.uninstallServer('uninstall-workflow-test'); expect(result.success).toBe(true); expect(result.serverName).toBe('uninstall-workflow-test'); }); }); describe('Error Handling', () => { it('should handle missing configuration gracefully', async () => { // Use invalid config path const invalidPath = join(tempDir, 'nonexistent', 'config.json'); initializeConfigContext(invalidPath); // Service should still be created const service = createServerInstallationService(); expect(service).toBeDefined(); // Operations may fail but should not crash await expect(service.listInstalledServers()).resolves.toBeInstanceOf(Array); }); it('should handle invalid server operations', async () => { initializeConfigContext(undefined, tempDir); const service = createServerInstallationService(); // Attempt to uninstall non-existent server const result = await service.uninstallServer('nonexistent-server'); // Should complete without throwing, result indicates outcome expect(result).toBeDefined(); expect(result.serverName).toBe('nonexistent-server'); }); }); });

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

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