Skip to main content
Glama

Prompt Auto-Optimizer MCP

by sloth-wq
e2e-test-runner.ts•33.2 kB
/** * End-to-End Test Runner for GEPA System * * This orchestrator manages comprehensive integration tests covering: * - Complete evolution workflows * - MCP tool integrations * - Performance benchmarks * - Memory system validation * - Concurrent operations * - Error handling and recovery */ import { describe, test, expect } from 'vitest'; // beforeAll, afterAll imported but not used import type { PromptCandidate, StartEvolutionParams, RecordTrajectoryParams, EvaluatePromptParams, ReflectParams, GetParetoFrontierParams, SelectOptimalParams, } from '../../types/gepa'; import { TrajectoryStore } from '../../core/trajectory-store'; import { ParetoFrontier } from '../../core/pareto-frontier'; import { ReflectionEngine } from '../../core/reflection-engine'; import { LLMAdapter } from '../../services/llm-adapter'; import { PromptMutator } from '../../services/prompt-mutator'; import { GEPAMCPServer } from '../../mcp/server'; import { TestScenarios } from './test-scenarios'; import { E2ETestHelpers } from './test-helpers'; import { PerformanceBenchmarks } from './performance-benchmarks'; /** * E2E Test Configuration */ export interface E2ETestConfig { maxConcurrentTests: number; defaultTimeout: number; performanceThresholds: { evolutionTime: number; trajectoryRecording: number; paretoFrontierQuery: number; memoryOperations: number; }; retryOptions: { maxRetries: number; baseDelay: number; }; } /** * E2E Test Results */ export interface E2ETestResults { totalTests: number; passedTests: number; failedTests: number; skippedTests: number; executionTime: number; performanceMetrics: { avgEvolutionTime: number; avgTrajectoryRecording: number; avgParetoQuery: number; avgMemoryOperation: number; concurrentOperations: number; }; memoryUsage: { peakUsage: number; averageUsage: number; leakDetected: boolean; }; errorSummary: { criticalErrors: string[]; warnings: string[]; recoveredErrors: string[]; }; } /** * Test Environment State */ interface TestEnvironment { mcpServer: GEPAMCPServer; trajectoryStore: TrajectoryStore; paretoFrontier: ParetoFrontier; reflectionEngine: ReflectionEngine; llmAdapter: LLMAdapter; promptMutator: PromptMutator; testHelpers: E2ETestHelpers; scenarios: TestScenarios; benchmarks: PerformanceBenchmarks; tempDir: string; isInitialized: boolean; } /** * Main E2E Test Runner Class */ export class E2ETestRunner { private config: E2ETestConfig; private environment: TestEnvironment | null = null; private testResults: E2ETestResults; private startTime: number = 0; constructor(config?: Partial<E2ETestConfig>) { this.config = { maxConcurrentTests: 3, defaultTimeout: 60000, performanceThresholds: { evolutionTime: 30000, trajectoryRecording: 1000, paretoFrontierQuery: 500, memoryOperations: 100, }, retryOptions: { maxRetries: 3, baseDelay: 1000, }, ...config, }; this.testResults = { totalTests: 0, passedTests: 0, failedTests: 0, skippedTests: 0, executionTime: 0, performanceMetrics: { avgEvolutionTime: 0, avgTrajectoryRecording: 0, avgParetoQuery: 0, avgMemoryOperation: 0, concurrentOperations: 0, }, memoryUsage: { peakUsage: 0, averageUsage: 0, leakDetected: false, }, errorSummary: { criticalErrors: [], warnings: [], recoveredErrors: [], }, }; } /** * Initialize test environment */ async initialize(): Promise<void> { try { this.startTime = Date.now(); // Create temporary directory for test data const tempDir = './temp/e2e-tests'; await this.createDirectory(tempDir); // Initialize core components const trajectoryStore = new TrajectoryStore({ dataDir: `${tempDir}/trajectories`, maxFileSize: 5 * 1024 * 1024, // 5MB for tests archiveAfterDays: 1, indexingEnabled: true, compressionEnabled: false, // Disable for faster tests }); const paretoFrontier = new ParetoFrontier({ maxSize: 50, // Smaller for tests objectives: [ { name: 'performance', direction: 'maximize', weight: 0.7, extractor: (candidate: PromptCandidate) => candidate.averageScore, }, { name: 'diversity', direction: 'maximize', weight: 0.3, extractor: (candidate: PromptCandidate) => candidate.generation / 10, }, ], archiveEnabled: true, samplingStrategy: { name: 'ucb', parameters: { confidence: 1.4 } }, }); const llmAdapter = new LLMAdapter({ maxConcurrentProcesses: 2, processTimeout: 10000, // Shorter for tests maxRetries: 2, retryBaseDelay: 500, executable: 'echo', // Mock for tests workingDir: tempDir, env: { NODE_ENV: 'test' }, }); const reflectionEngine = new ReflectionEngine({ trajectoryStore: { query: trajectoryStore.query.bind(trajectoryStore), load: trajectoryStore.load.bind(trajectoryStore), save: async (trajectory) => { await trajectoryStore.save(trajectory); }, }, llmAdapter, config: { maxAnalysisDepth: 3, confidenceThreshold: 0.6, patternMinFrequency: 2, batchSize: 5, enableCaching: true, cacheTimeout: 300000, // 5 minutes }, }); const promptMutator = new PromptMutator({ maxMutationsPerGeneration: 20, mutationRate: 0.2, crossoverRate: 0.6, adaptiveWeight: 0.15, fitnessThreshold: 0.7, maxPromptLength: 2000, minPromptLength: 10, requireRoleDefinition: false, // Relaxed for tests prohibitedTerms: [], maxConcurrentMutations: 3, enableCaching: true, }); const mcpServer = new GEPAMCPServer(); // Initialize test helpers and scenarios const testHelpers = new E2ETestHelpers({ tempDir, timeout: this.config.defaultTimeout, retryOptions: this.config.retryOptions, }); const scenarios = new TestScenarios({ trajectoryStore, paretoFrontier, reflectionEngine, llmAdapter, promptMutator, }); const benchmarks = new PerformanceBenchmarks({ thresholds: this.config.performanceThresholds, maxConcurrentTests: this.config.maxConcurrentTests, }); this.environment = { mcpServer, trajectoryStore, paretoFrontier, reflectionEngine, llmAdapter, promptMutator, testHelpers, scenarios, benchmarks, tempDir, isInitialized: true, }; // eslint-disable-next-line no-console console.log('āœ… E2E test environment initialized successfully'); } catch (error) { // eslint-disable-next-line no-console console.error('āŒ Failed to initialize E2E test environment:', error); throw error; } } /** * Run all E2E test suites */ async runAllTests(): Promise<E2ETestResults> { if (!this.environment?.isInitialized) { throw new Error('Test environment not initialized'); } try { // eslint-disable-next-line no-console console.log('šŸš€ Starting comprehensive E2E test suite...'); // Test Suite 1: Core Workflow Tests await this.runCoreWorkflowTests(); // Test Suite 2: MCP Tool Integration Tests await this.runMCPToolTests(); // Test Suite 3: Performance and Load Tests await this.runPerformanceTests(); // Test Suite 4: Memory System Tests await this.runMemorySystemTests(); // Test Suite 5: Concurrent Operations Tests await this.runConcurrentOperationTests(); // Test Suite 6: Error Handling and Recovery Tests await this.runErrorHandlingTests(); // Calculate final results this.testResults.executionTime = Date.now() - this.startTime; this.generateTestReport(); return this.testResults; } catch (error) { this.testResults.errorSummary.criticalErrors.push(`Test execution failed: ${error}`); throw error; } } /** * Core Workflow Tests - Complete evolution cycles */ private async runCoreWorkflowTests(): Promise<void> { if (!this.environment) throw new Error('Environment not initialized'); describe('Core Workflow Tests', () => { test('Complete Evolution Cycle', async () => { const scenario = await this.environment!.scenarios.createCompleteEvolutionScenario(); const result = await this.environment!.testHelpers.executeScenario(Promise.resolve(scenario)); expect(result.success).toBe(true); expect(result.evolutionResult).toBeDefined(); if (result.evolutionResult) { expect(result.evolutionResult.generations).toBeGreaterThan(0); expect(result.evolutionResult.bestPrompt).toBeDefined(); } this.testResults.passedTests++; }); test('Trajectory Recording and Analysis', async () => { const trajectory = await this.environment!.scenarios.createSampleTrajectory(); const saveResult = await this.environment!.trajectoryStore.save(trajectory); expect(saveResult.success).toBe(true); expect(saveResult.id).toBeDefined(); const loadedTrajectory = await this.environment!.trajectoryStore.load(saveResult.id!); expect(loadedTrajectory).toBeDefined(); expect(loadedTrajectory!.id).toBe(trajectory.id); this.testResults.passedTests++; }); test('Pareto Frontier Optimization', async () => { const candidates = await this.environment!.scenarios.createOptimizationCandidates(); for (const candidate of candidates) { await this.environment!.paretoFrontier.addCandidate(candidate); } const frontier = this.environment!.paretoFrontier.getFrontier(); expect(frontier.length).toBeGreaterThan(0); expect(frontier.length).toBeLessThanOrEqual(candidates.length); // Verify Pareto optimality for (let i = 0; i < frontier.length; i++) { for (let j = 0; j < frontier.length; j++) { if (i !== j) { const candidateI = frontier[i]?.candidate; const candidateJ = frontier[j]?.candidate; if (candidateI && candidateJ) { expect(this.environment!.paretoFrontier.isDominated( candidateI, candidateJ )).toBe(false); } } } } this.testResults.passedTests++; }); this.testResults.totalTests += 3; }); } /** * MCP Tool Integration Tests */ private async runMCPToolTests(): Promise<void> { if (!this.environment) throw new Error('Environment not initialized'); describe('MCP Tool Integration Tests', () => { test('gepa_start_evolution Tool', async () => { const params: StartEvolutionParams = { taskDescription: 'Test task for evolution', seedPrompt: 'Test seed prompt', config: { populationSize: 5, maxGenerations: 3, mutationRate: 0.2, }, }; const result = await this.environment!.testHelpers.callMCPTool( 'gepa_start_evolution', params as unknown as Record<string, unknown> ); expect(result.success).toBe(true); expect(result.content).toBeDefined(); if (result.content && result.content[0]) { expect(result.content[0].text).toContain('Evolution Process Started'); } this.testResults.passedTests++; }); test('gepa_record_trajectory Tool', async () => { const params: RecordTrajectoryParams = { promptId: 'test-prompt-1', taskId: 'test-task-1', executionSteps: [ { stepNumber: 1, action: 'initialize', timestamp: new Date(), }, { stepNumber: 2, action: 'execute', timestamp: new Date(), }, ], result: { success: true, score: 0.85, output: { result: 'test output' }, }, }; const result = await this.environment!.testHelpers.callMCPTool( 'gepa_record_trajectory', params as unknown as Record<string, unknown> ); expect(result.success).toBe(true); if (result.content && result.content[0]) { expect(result.content[0].text).toContain('Trajectory Recorded Successfully'); } this.testResults.passedTests++; }); test('gepa_evaluate_prompt Tool', async () => { const params: EvaluatePromptParams = { promptId: 'test-prompt-1', taskIds: ['task-1', 'task-2'], rolloutCount: 3, parallel: true, }; const result = await this.environment!.testHelpers.callMCPTool( 'gepa_evaluate_prompt', params as unknown as Record<string, unknown> ); expect(result.success).toBe(true); if (result.content && result.content[0]) { expect(result.content[0].text).toContain('Prompt Evaluation Complete'); } this.testResults.passedTests++; }); test('gepa_reflect Tool', async () => { // First create some test trajectories await this.environment!.scenarios.createFailureTrajectories(); const params: ReflectParams = { trajectoryIds: ['trajectory-1', 'trajectory-2'], targetPromptId: 'test-prompt-1', analysisDepth: 'deep', }; const result = await this.environment!.testHelpers.callMCPTool( 'gepa_reflect', params as unknown as Record<string, unknown> ); expect(result.success).toBe(true); if (result.content && result.content[0]) { expect(result.content[0].text).toContain('Reflection Analysis Complete'); } this.testResults.passedTests++; }); test('gepa_get_pareto_frontier Tool', async () => { // Populate frontier with test data await this.environment!.scenarios.populateParetoFrontier(); const params: GetParetoFrontierParams = { minPerformance: 0.5, limit: 5, }; const result = await this.environment!.testHelpers.callMCPTool( 'gepa_get_pareto_frontier', params as Record<string, unknown> ); expect(result.success).toBe(true); if (result.content && result.content[0]) { expect(result.content[0].text).toContain('Pareto Frontier Results'); } this.testResults.passedTests++; }); test('gepa_select_optimal Tool', async () => { const params: SelectOptimalParams = { taskContext: 'Test optimization context', performanceWeight: 0.8, diversityWeight: 0.2, }; const result = await this.environment!.testHelpers.callMCPTool( 'gepa_select_optimal', params as Record<string, unknown> ); expect(result.success).toBe(true); if (result.content && result.content[0]) { expect(result.content[0].text).toContain('Optimal Candidate Selected'); } this.testResults.passedTests++; }); this.testResults.totalTests += 6; }); } /** * Performance and Load Tests */ private async runPerformanceTests(): Promise<void> { if (!this.environment) throw new Error('Environment not initialized'); describe('Performance and Load Tests', () => { test('Concurrent Evolution Cycles', async () => { const concurrentEvolutions = 3; const evolutionPromises = []; for (let i = 0; i < concurrentEvolutions; i++) { const promise = this.environment!.scenarios.createConcurrentEvolutionScenario(i); evolutionPromises.push(promise); } const startTime = Date.now(); const results = await Promise.all(evolutionPromises); const executionTime = Date.now() - startTime; expect(results.length).toBe(concurrentEvolutions); expect(results.every(r => r.success)).toBe(true); expect(executionTime).toBeLessThan(this.config.performanceThresholds.evolutionTime * 2); this.testResults.performanceMetrics.concurrentOperations = concurrentEvolutions; this.testResults.passedTests++; }); test('Large Population Handling', async () => { const largePopulationSize = 100; const scenario = await this.environment!.scenarios.createLargePopulationScenario(largePopulationSize); const startTime = Date.now(); const result = await this.environment!.testHelpers.executeScenario(Promise.resolve(scenario)); const executionTime = Date.now() - startTime; expect(result.success).toBe(true); expect(executionTime).toBeLessThan(this.config.performanceThresholds.evolutionTime * 3); this.testResults.performanceMetrics.avgEvolutionTime = executionTime; this.testResults.passedTests++; }); test('Memory Usage Under Load', async () => { const initialMemory = process.memoryUsage().heapUsed; // Create high memory load scenario await this.environment!.scenarios.createHighMemoryLoadScenario(); const peakMemory = process.memoryUsage().heapUsed; const memoryIncrease = peakMemory - initialMemory; // Force garbage collection if available if (global.gc) { global.gc(); } const finalMemory = process.memoryUsage().heapUsed; const memoryLeakSuspected = (finalMemory - initialMemory) > (memoryIncrease * 0.5); expect(memoryIncrease).toBeLessThan(100 * 1024 * 1024); // Less than 100MB increase expect(memoryLeakSuspected).toBe(false); this.testResults.memoryUsage.peakUsage = peakMemory; this.testResults.memoryUsage.leakDetected = memoryLeakSuspected; this.testResults.passedTests++; }); test('Response Time Benchmarks', async () => { const benchmarks = await this.environment!.benchmarks.runComprehensiveBenchmarks(); expect(benchmarks.trajectoryRecording.averageTime).toBeLessThan( this.config.performanceThresholds.trajectoryRecording ); expect(benchmarks.paretoQuery.averageTime).toBeLessThan( this.config.performanceThresholds.paretoFrontierQuery ); expect(benchmarks.memoryOperations.averageTime).toBeLessThan( this.config.performanceThresholds.memoryOperations ); this.testResults.performanceMetrics.avgTrajectoryRecording = benchmarks.trajectoryRecording.averageTime; this.testResults.performanceMetrics.avgParetoQuery = benchmarks.paretoQuery.averageTime; this.testResults.performanceMetrics.avgMemoryOperation = benchmarks.memoryOperations.averageTime; this.testResults.passedTests++; }); this.testResults.totalTests += 4; }); } /** * Memory System Tests */ private async runMemorySystemTests(): Promise<void> { if (!this.environment) throw new Error('Environment not initialized'); describe('Memory System Tests', () => { test('Automated Memory Updates', async () => { const trajectory = await this.environment!.scenarios.createSampleTrajectory(); const saveResult = await this.environment!.trajectoryStore.save(trajectory); expect(saveResult.success).toBe(true); // Verify memory auto-updates const memoryStats = await this.environment!.testHelpers.getMemoryStats(); expect(memoryStats.totalTrajectories).toBeGreaterThan(0); expect(memoryStats.lastUpdateTime).toBeDefined(); this.testResults.passedTests++; }); test('Memory Optimization Triggers', async () => { // Fill memory to trigger optimization await this.environment!.scenarios.fillMemoryToCapacity(); const beforeOptimization = await this.environment!.testHelpers.getMemoryStats(); // Trigger optimization manually await this.environment!.testHelpers.triggerMemoryOptimization(); const afterOptimization = await this.environment!.testHelpers.getMemoryStats(); expect(afterOptimization.usedSpace).toBeLessThan(beforeOptimization.usedSpace); expect(afterOptimization.optimizationCount).toBeGreaterThan(beforeOptimization.optimizationCount); this.testResults.passedTests++; }); test('Cross-System Memory Sync', async () => { const trajectory1 = await this.environment!.scenarios.createSampleTrajectory(); const trajectory2 = await this.environment!.scenarios.createSampleTrajectory(); // Save to different systems await this.environment!.trajectoryStore.save(trajectory1); await this.environment!.paretoFrontier.addCandidate(trajectory2.steps[0] as any); // Verify cross-system sync const syncResult = await this.environment!.testHelpers.performCrossSystemSync(); expect(syncResult.success).toBe(true); expect(syncResult.synchronizedEntities).toBeGreaterThan(0); this.testResults.passedTests++; }); test('Recovery from Memory Errors', async () => { // Simulate memory corruption await this.environment!.scenarios.simulateMemoryCorruption(); const recoveryResult = await this.environment!.testHelpers.attemptMemoryRecovery(); expect(recoveryResult.success).toBe(true); expect(recoveryResult.recoveredEntities).toBeGreaterThan(0); // Verify system functionality after recovery const testTrajectory = await this.environment!.scenarios.createSampleTrajectory(); const saveResult = await this.environment!.trajectoryStore.save(testTrajectory); expect(saveResult.success).toBe(true); this.testResults.passedTests++; this.testResults.errorSummary.recoveredErrors.push('Memory corruption recovered successfully'); }); this.testResults.totalTests += 4; }); } /** * Concurrent Operations Tests */ private async runConcurrentOperationTests(): Promise<void> { if (!this.environment) throw new Error('Environment not initialized'); describe('Concurrent Operations Tests', () => { test('Concurrent Tool Execution', async () => { const concurrentCalls = 5; const toolPromises = []; for (let i = 0; i < concurrentCalls; i++) { const promise = this.environment!.testHelpers.callMCPTool('gepa_evaluate_prompt', { promptId: `concurrent-prompt-${i}`, taskIds: [`task-${i}`], rolloutCount: 2, }); toolPromises.push(promise); } const results = await Promise.all(toolPromises); expect(results.length).toBe(concurrentCalls); expect(results.every(r => r.success)).toBe(true); this.testResults.passedTests++; }); test('Parallel Memory Access', async () => { const parallelOperations = 10; const operationPromises = []; for (let i = 0; i < parallelOperations; i++) { const trajectory = await this.environment!.scenarios.createSampleTrajectory(); trajectory.id = `parallel-trajectory-${i}`; const promise = this.environment!.trajectoryStore.save(trajectory); operationPromises.push(promise); } const results = await Promise.all(operationPromises); expect(results.length).toBe(parallelOperations); expect(results.every(r => r.success)).toBe(true); // Verify no data corruption for (let i = 0; i < parallelOperations; i++) { const loaded = await this.environment!.trajectoryStore.load(`parallel-trajectory-${i}`); expect(loaded).toBeDefined(); expect(loaded!.id).toBe(`parallel-trajectory-${i}`); } this.testResults.passedTests++; }); test('Concurrent Evolution and Analysis', async () => { const evolutionPromise = this.environment!.scenarios.createCompleteEvolutionScenario(); const analysisPromise = this.environment!.scenarios.createReflectionAnalysisScenario(); const [evolutionResult, analysisResult] = await Promise.all([ this.environment!.testHelpers.executeScenario(evolutionPromise), this.environment!.testHelpers.executeScenario(analysisPromise), ]); expect(evolutionResult.success).toBe(true); expect(analysisResult.success).toBe(true); this.testResults.passedTests++; }); this.testResults.totalTests += 3; }); } /** * Error Handling and Recovery Tests */ private async runErrorHandlingTests(): Promise<void> { if (!this.environment) throw new Error('Environment not initialized'); describe('Error Handling and Recovery Tests', () => { test('Invalid MCP Tool Parameters', async () => { try { await this.environment!.testHelpers.callMCPTool('gepa_start_evolution', { // Missing required taskDescription seedPrompt: 'test', } as any); // Should not reach here expect(false).toBe(true); } catch (error) { expect(error).toBeDefined(); this.testResults.passedTests++; this.testResults.errorSummary.recoveredErrors.push('Invalid parameters handled correctly'); } }); test('Component Failure Recovery', async () => { // Simulate LLM adapter failure await this.environment!.scenarios.simulateComponentFailure('llmAdapter'); const recoveryResult = await this.environment!.testHelpers.attemptComponentRecovery('llmAdapter'); expect(recoveryResult.success).toBe(true); // Verify system still functions const testResult = await this.environment!.testHelpers.callMCPTool('gepa_evaluate_prompt', { promptId: 'recovery-test', taskIds: ['recovery-task'], }); expect(testResult.success).toBe(true); this.testResults.passedTests++; }); test('Resource Exhaustion Handling', async () => { // Simulate resource exhaustion const exhaustionScenario = await this.environment!.scenarios.createResourceExhaustionScenario(); const result = await this.environment!.testHelpers.executeScenario(Promise.resolve(exhaustionScenario)); // Should handle gracefully without crashing expect(result.completed).toBe(true); expect(result.errorHandled).toBe(true); this.testResults.passedTests++; }); test('Data Corruption Detection and Recovery', async () => { // Introduce data corruption await this.environment!.scenarios.introduceDataCorruption(); const detectionResult = await this.environment!.testHelpers.runCorruptionDetection(); expect(detectionResult.corruptionDetected).toBe(true); const recoveryResult = await this.environment!.testHelpers.attemptDataRecovery(); expect(recoveryResult.success).toBe(true); this.testResults.passedTests++; this.testResults.errorSummary.recoveredErrors.push('Data corruption detected and recovered'); }); this.testResults.totalTests += 4; }); } /** * Generate comprehensive test report */ private generateTestReport(): void { const successRate = (this.testResults.passedTests / this.testResults.totalTests) * 100; // eslint-disable-next-line no-console console.log('\nšŸ“Š E2E Test Results Summary'); // eslint-disable-next-line no-console console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); // eslint-disable-next-line no-console console.log(`Total Tests: ${this.testResults.totalTests}`); // eslint-disable-next-line no-console console.log(`Passed: ${this.testResults.passedTests} (${successRate.toFixed(1)}%)`); // eslint-disable-next-line no-console console.log(`Failed: ${this.testResults.failedTests}`); // eslint-disable-next-line no-console console.log(`Skipped: ${this.testResults.skippedTests}`); // eslint-disable-next-line no-console console.log(`Execution Time: ${(this.testResults.executionTime / 1000).toFixed(2)}s`); // eslint-disable-next-line no-console console.log('\n⚔ Performance Metrics'); // eslint-disable-next-line no-console console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); // eslint-disable-next-line no-console console.log(`Avg Evolution Time: ${this.testResults.performanceMetrics.avgEvolutionTime}ms`); // eslint-disable-next-line no-console console.log(`Avg Trajectory Recording: ${this.testResults.performanceMetrics.avgTrajectoryRecording}ms`); // eslint-disable-next-line no-console console.log(`Avg Pareto Query: ${this.testResults.performanceMetrics.avgParetoQuery}ms`); // eslint-disable-next-line no-console console.log(`Avg Memory Operation: ${this.testResults.performanceMetrics.avgMemoryOperation}ms`); // eslint-disable-next-line no-console console.log(`Concurrent Operations: ${this.testResults.performanceMetrics.concurrentOperations}`); // eslint-disable-next-line no-console console.log('\nšŸ’¾ Memory Usage'); // eslint-disable-next-line no-console console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); // eslint-disable-next-line no-console console.log(`Peak Usage: ${(this.testResults.memoryUsage.peakUsage / 1024 / 1024).toFixed(2)}MB`); // eslint-disable-next-line no-console console.log(`Leak Detected: ${this.testResults.memoryUsage.leakDetected ? 'āŒ' : 'āœ…'}`); if (this.testResults.errorSummary.criticalErrors.length > 0) { // eslint-disable-next-line no-console console.log('\n🚨 Critical Errors'); // eslint-disable-next-line no-console console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); this.testResults.errorSummary.criticalErrors.forEach(error => // eslint-disable-next-line no-console console.log(`āŒ ${error}`)); } if (this.testResults.errorSummary.recoveredErrors.length > 0) { // eslint-disable-next-line no-console console.log('\nšŸ”„ Recovered Errors'); // eslint-disable-next-line no-console console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); this.testResults.errorSummary.recoveredErrors.forEach(error => // eslint-disable-next-line no-console console.log(`āœ… ${error}`)); } } /** * Cleanup test environment */ async cleanup(): Promise<void> { if (!this.environment) return; try { await Promise.all([ this.environment.llmAdapter.shutdown(), this.environment.promptMutator.shutdown(), ]); // Clean up temporary files await this.removeDirectory(this.environment.tempDir); // eslint-disable-next-line no-console console.log('āœ… E2E test environment cleaned up successfully'); } catch (error) { // eslint-disable-next-line no-console console.error('āŒ Error during E2E test cleanup:', error); } } /** * Utility: Create directory */ private async createDirectory(path: string): Promise<void> { const { mkdir } = await import('fs/promises'); await mkdir(path, { recursive: true }); } /** * Utility: Remove directory */ private async removeDirectory(path: string): Promise<void> { const { rm } = await import('fs/promises'); await rm(path, { recursive: true, force: true }); } }

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/sloth-wq/prompt-auto-optimizer-mcp'

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