Skip to main content
Glama

1MCP Server

registry-status.test.ts12.8 kB
import { TestFixtures } from '@test/e2e/fixtures/TestFixtures.js'; import { CliTestRunner, CommandTestEnvironment } from '@test/e2e/utils/index.js'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; describe('Registry Status Command E2E', () => { let environment: CommandTestEnvironment; let runner: CliTestRunner; beforeEach(async () => { environment = new CommandTestEnvironment(TestFixtures.createTestScenario('registry-status-test', 'basic')); await environment.setup(); runner = new CliTestRunner(environment); }); afterEach(async () => { await environment.cleanup(); }); describe('Basic Status Functionality', () => { it('should show registry status', async () => { const result = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout for basic status }); runner.assertSuccess(result); runner.assertOutputContains(result, 'MCP Registry Status'); runner.assertOutputContains(result, 'Status:'); runner.assertOutputContains(result, 'URL:'); runner.assertOutputContains(result, 'Response Time:'); runner.assertOutputContains(result, 'Last Checked:'); // Should show availability status const hasStatusIcon = result.stdout.includes('✅') || result.stdout.includes('❌'); expect(hasStatusIcon).toBe(true); }); it('should show status with statistics', async () => { const result = await runner.runRegistryCommand('status', { args: ['--stats'], timeout: 45000, // 45 second timeout for statistics }); runner.assertSuccess(result); runner.assertOutputContains(result, 'MCP Registry Status'); runner.assertOutputContains(result, 'Registry Statistics'); // Should include basic statistics runner.assertOutputContains(result, 'Total Servers:'); runner.assertOutputContains(result, 'Active Servers:'); runner.assertOutputContains(result, 'Deprecated Servers:'); }); it('should show status in JSON format', async () => { const result = await runner.runRegistryCommand('status', { args: ['--json'], timeout: 30000, // 30 second timeout for JSON }); runner.assertSuccess(result); const jsonResult = runner.parseJsonOutput(result); expect(jsonResult).toHaveProperty('available'); expect(jsonResult).toHaveProperty('url'); expect(jsonResult).toHaveProperty('response_time_ms'); expect(jsonResult).toHaveProperty('last_updated'); // Should be valid boolean, string, number expect(typeof jsonResult.available).toBe('boolean'); expect(typeof jsonResult.url).toBe('string'); expect(typeof jsonResult.response_time_ms).toBe('number'); }); it('should show status with statistics in JSON format', async () => { const result = await runner.runRegistryCommand('status', { args: ['--stats', '--json'], timeout: 60000, // 60 second timeout for stats + JSON }); runner.assertSuccess(result); const jsonResult = runner.parseJsonOutput(result); expect(jsonResult).toHaveProperty('available'); expect(jsonResult).toHaveProperty('stats'); if (jsonResult.stats) { expect(jsonResult.stats).toHaveProperty('total_servers'); expect(jsonResult.stats).toHaveProperty('active_servers'); expect(jsonResult.stats).toHaveProperty('deprecated_servers'); expect(typeof jsonResult.stats.total_servers).toBe('number'); expect(typeof jsonResult.stats.active_servers).toBe('number'); expect(typeof jsonResult.stats.deprecated_servers).toBe('number'); // Should have breakdown by type and transport if available if (jsonResult.stats.by_registry_type) { expect(typeof jsonResult.stats.by_registry_type).toBe('object'); } if (jsonResult.stats.by_transport) { expect(typeof jsonResult.stats.by_transport).toBe('object'); } } }); }); describe('Status Information Validation', () => { it('should show reasonable response time', async () => { const result = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); runner.assertSuccess(result); // Should show response time in milliseconds runner.assertOutputMatches(result, /Response Time:\s*\d+ms/); // Extract response time and validate it's reasonable (under 10 seconds) const responseTimeMatch = result.stdout.match(/Response Time:\s*(\d+)ms/); if (responseTimeMatch) { const responseTime = parseInt(responseTimeMatch[1]); expect(responseTime).toBeGreaterThan(0); expect(responseTime).toBeLessThan(10000); // Less than 10 seconds } }); it('should show valid URL format', async () => { const result = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); runner.assertSuccess(result); // Should show a valid HTTP/HTTPS URL runner.assertOutputMatches(result, /URL:\s*https?:\/\/[^\s]+/); }); it('should show timestamp format', async () => { const result = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); runner.assertSuccess(result); // Should show last checked timestamp runner.assertOutputContains(result, 'Last Checked:'); // The actual format is "Oct 23, 2025, 09:51:15 PM" runner.assertOutputMatches( result, /Last Checked:\s*[A-Za-z]{3}\s+\d{1,2},\s+\d{4},\s+\d{1,2}:\d{2}:\d{2}\s+[AP]M/, ); }); }); describe('Statistics Information', () => { it('should show detailed breakdown when stats requested', async () => { const result = await runner.runRegistryCommand('status', { args: ['--stats'], timeout: 45000, // 45 second timeout for statistics }); runner.assertSuccess(result); // Basic statistics should always be present runner.assertOutputContains(result, 'Total Servers:'); runner.assertOutputContains(result, 'Active Servers:'); runner.assertOutputContains(result, 'Deprecated Servers:'); // May include additional breakdowns if available const hasByType = result.stdout.includes('By Registry Type:'); const hasByTransport = result.stdout.includes('By Transport:'); // At least one breakdown should be present in normal operation expect(hasByType || hasByTransport).toBe(true); }); it('should handle empty statistics gracefully', async () => { const result = await runner.runRegistryCommand('status', { args: ['--stats', '--json'], timeout: 60000, // 60 second timeout for stats + JSON }); runner.assertSuccess(result); const jsonResult = runner.parseJsonOutput(result); expect(jsonResult).toHaveProperty('stats'); if (jsonResult.stats) { // Stats object should have expected properties even if empty expect(typeof jsonResult.stats.total_servers).toBe('number'); expect(typeof jsonResult.stats.active_servers).toBe('number'); expect(typeof jsonResult.stats.deprecated_servers).toBe('number'); } }); }); describe('Output Format Consistency', () => { it('should maintain consistent output structure', async () => { const result1 = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); const result2 = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); runner.assertSuccess(result1); runner.assertSuccess(result2); // Both outputs should have similar structure expect(result1.stdout).toContain('MCP Registry Status'); expect(result2.stdout).toContain('MCP Registry Status'); // Should include key sections in both const keySections = ['Status:', 'URL:', 'Response Time:']; keySections.forEach((section) => { expect(result1.stdout).toContain(section); expect(result2.stdout).toContain(section); }); }); it('should format JSON output consistently', async () => { const result1 = await runner.runRegistryCommand('status', { args: ['--json'], timeout: 30000, // 30 second timeout }); const result2 = await runner.runRegistryCommand('status', { args: ['--json'], timeout: 30000, // 30 second timeout }); runner.assertSuccess(result1); runner.assertSuccess(result2); const json1 = runner.parseJsonOutput(result1); const json2 = runner.parseJsonOutput(result2); // Both should have same structure const requiredKeys = ['available', 'url', 'response_time_ms', 'last_updated']; requiredKeys.forEach((key) => { expect(json1).toHaveProperty(key); expect(json2).toHaveProperty(key); }); }); }); describe('Error Handling', () => { it('should handle invalid flag combinations', async () => { const result = await runner.runRegistryCommand('status', { args: ['--invalid-flag'], expectError: true, }); // Yargs should handle unknown options gracefully // May succeed with warnings or fail with error expect(result.exitCode === 0 || result.exitCode !== 0).toBe(true); }); it('should handle network connectivity issues', async () => { // Test with very short timeout to simulate network issues const result = await runner.runRegistryCommand('status', { timeout: 1000, }); // May succeed if fast enough, or fail gracefully expect(result.exitCode === 0 || result.exitCode === -1).toBe(true); if (result.exitCode !== 0) { // Should either show error message or have empty output const hasErrorMessage = result.stdout.includes('Error') || result.stderr.includes('Error'); const hasEmptyOutput = result.stdout.trim().length === 0; expect(hasErrorMessage || hasEmptyOutput).toBe(true); } }); it('should handle malformed JSON output request', async () => { const result = await runner.runRegistryCommand('status', { args: ['--json', '--invalid-option'], expectError: true, }); // Should handle gracefully expect(result.exitCode !== 0 || result.exitCode === 0).toBe(true); }); }); describe('Help Command', () => { it('should show help for status command', async () => { const result = await runner.runRegistryCommand('status', { args: ['--help'], }); runner.assertSuccess(result); runner.assertOutputContains(result, 'Show registry availability status'); runner.assertOutputContains(result, 'Options:'); runner.assertOutputContains(result, '--stats'); runner.assertOutputContains(result, '--json'); // Should show examples runner.assertOutputMatches(result, /Examples?:/); }); }); describe('Performance and Reliability', () => { it('should complete status check within reasonable time', async () => { const startTime = Date.now(); const result = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); const duration = Date.now() - startTime; runner.assertSuccess(result); // Should complete within 10 seconds under normal conditions expect(duration).toBeLessThan(10000); }); it('should handle repeated status checks consistently', async () => { const results = []; // Run multiple status checks for (let i = 0; i < 3; i++) { const result = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); results.push(result); runner.assertSuccess(result); } // All should succeed results.forEach((result) => { expect(result.exitCode).toBe(0); expect(result.stdout).toContain('MCP Registry Status'); }); }); it('should cache results appropriately', async () => { const result1 = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); const startTime = Date.now(); const result2 = await runner.runRegistryCommand('status', { timeout: 30000, // 30 second timeout }); const duration = Date.now() - startTime; runner.assertSuccess(result1); runner.assertSuccess(result2); // Second request might be faster due to caching // But should still show recent timestamp expect(duration).toBeLessThan(5000); // Should be quite fast if cached expect(result2.stdout).toContain('Last Checked:'); }); }); });

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