Skip to main content
Glama

1MCP Server

templateEdgeCases.test.ts17.8 kB
import type { InboundConnectionConfig, OutboundConnections } from '@src/core/types/index.js'; import { TagQueryParser } from '@src/domains/preset/parsers/tagQueryParser.js'; import { beforeEach, describe, expect, it } from 'vitest'; import { InstructionAggregator } from './instructionAggregator.js'; // Helper function to create test connections function createTestConnection(name: string, tags: string[] = []) { return { name, transport: { tags, timeout: 5000 }, client: {} as any, status: 'connected' as any, } as any; } describe('InstructionAggregator - Edge Cases and Mixed States', () => { let instructionAggregator: InstructionAggregator; beforeEach(() => { instructionAggregator = new InstructionAggregator(); }); describe('Dynamic Server State Changes', () => { it('should handle servers losing and gaining instructions dynamically', () => { const template = ` State: {{#if hasServers}}ACTIVE{{else}}INACTIVE{{/if}} Counts: {{instructionalServerCount}}/{{connectedServerCount}} {{#if hasServers}}Servers: {{#each serverNames}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}{{/if}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; const connections = new Map([ ['server1', createTestConnection('server1')], ['server2', createTestConnection('server2')], ]) as OutboundConnections; // Initial state: no instructions const result1 = instructionAggregator.getFilteredInstructions(config, connections); expect(result1).toContain('State: INACTIVE'); expect(result1).toContain('Counts: 0/2'); expect(result1).not.toContain('Servers: '); // Empty server list // Add instruction to server1 instructionAggregator.setInstructions('server1', 'Server 1 instructions'); const result2 = instructionAggregator.getFilteredInstructions(config, connections); expect(result2).toContain('State: ACTIVE'); expect(result2).toContain('Counts: 1/2'); expect(result2).toContain('Servers: server1'); // Add instruction to server2 instructionAggregator.setInstructions('server2', 'Server 2 instructions'); const result3 = instructionAggregator.getFilteredInstructions(config, connections); expect(result3).toContain('State: ACTIVE'); expect(result3).toContain('Counts: 2/2'); expect(result3).toContain('Servers: server1, server2'); // Remove instruction from server1 (set to empty) instructionAggregator.setInstructions('server1', ''); const result4 = instructionAggregator.getFilteredInstructions(config, connections); expect(result4).toContain('State: ACTIVE'); expect(result4).toContain('Counts: 1/2'); expect(result4).toContain('Servers: server2'); // Remove all instructions instructionAggregator.clear(); const result5 = instructionAggregator.getFilteredInstructions(config, connections); expect(result5).toContain('State: INACTIVE'); expect(result5).toContain('Counts: 0/2'); }); it('should handle connection changes with existing instructions', () => { const template = `Connected: {{connectedServerCount}}, Active: {{instructionalServerCount}}`; const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; // Start with one server and add instruction const connections1 = new Map([['server1', createTestConnection('server1')]]) as OutboundConnections; instructionAggregator.setInstructions('server1', 'Server 1 instructions'); const result1 = instructionAggregator.getFilteredInstructions(config, connections1); expect(result1).toContain('Connected: 1, Active: 1'); // Add more servers (some with instructions, some without) const connections2 = new Map([ ['server1', createTestConnection('server1')], // Has instructions ['server2', createTestConnection('server2')], // No instructions yet ['server3', createTestConnection('server3')], // Will get instructions ]) as OutboundConnections; instructionAggregator.setInstructions('server3', 'Server 3 instructions'); const result2 = instructionAggregator.getFilteredInstructions(config, connections2); expect(result2).toContain('Connected: 3, Active: 2'); // Remove a server from connections but keep its instructions const connections3 = new Map([ ['server1', createTestConnection('server1')], ['server3', createTestConnection('server3')], ]) as OutboundConnections; const result3 = instructionAggregator.getFilteredInstructions(config, connections3); expect(result3).toContain('Connected: 2, Active: 2'); }); }); describe('Instruction Content Edge Cases', () => { it('should handle various whitespace and empty instruction scenarios', () => { const template = ` {{#each servers}} {{name}}: {{#if hasInstructions}}"{{instructions}}"{{else}}EMPTY{{/if}} {{/each}} Active: {{instructionalServerCount}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; const connections = new Map([ ['server1', createTestConnection('server1')], ['server2', createTestConnection('server2')], ['server3', createTestConnection('server3')], ['server4', createTestConnection('server4')], ['server5', createTestConnection('server5')], ]) as OutboundConnections; // Various empty/whitespace scenarios instructionAggregator.setInstructions('server1', 'Valid instructions'); instructionAggregator.setInstructions('server2', ''); // Empty string instructionAggregator.setInstructions('server3', ' '); // Spaces only instructionAggregator.setInstructions('server4', '\n\t \n'); // Whitespace chars // server5 - no instructions set at all const result = instructionAggregator.getFilteredInstructions(config, connections); expect(result).toContain('server1: "Valid instructions"'); expect(result).toContain('server2: EMPTY'); expect(result).toContain('server3: EMPTY'); expect(result).toContain('server4: EMPTY'); expect(result).toContain('server5: EMPTY'); expect(result).toContain('Active: 1'); // Only server1 counts }); it('should handle instructions with special characters and formatting', () => { const template = ` {{#if hasServers}} {{#each servers}} {{#if hasInstructions}} ## {{name}} {{instructions}} {{/if}} {{/each}} {{/if}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; const connections = new Map([ ['json-server', createTestConnection('json-server')], ['xml-server', createTestConnection('xml-server')], ['markdown-server', createTestConnection('markdown-server')], ]) as OutboundConnections; instructionAggregator.setInstructions( 'json-server', '{"type": "api", "endpoints": ["/users", "/posts"], "auth": "bearer"}', ); instructionAggregator.setInstructions( 'xml-server', '<config>\n <endpoint>http://api.example.com</endpoint>\n <timeout>30s</timeout>\n</config>', ); instructionAggregator.setInstructions( 'markdown-server', '# API Server\n\n**Features:**\n- Authentication\n- Rate limiting\n- Caching\n\n`GET /api/v1/status`', ); const result = instructionAggregator.getFilteredInstructions(config, connections); expect(result).toContain('## json-server'); expect(result).toContain('"type": "api"'); expect(result).toContain('## xml-server'); expect(result).toContain('<config>'); expect(result).toContain('## markdown-server'); expect(result).toContain('# API Server'); expect(result).toContain('`GET /api/v1/status`'); }); }); describe('Complex Filtering Scenarios', () => { it('should handle multiple tag filtering with mixed instruction states', () => { const template = ` Filter: {{filterContext}} Results: {{connectedServerCount}} connected, {{instructionalServerCount}} active {{#if hasServers}} Active filtered servers: {{#each serverNames}} - {{this}} {{/each}} {{else}} {{#if connectedServerCount}} No active servers match filter ({{connectedServerCount}} connected) {{else}} No servers match filter {{/if}} {{/if}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'advanced', tagExpression: TagQueryParser.parseAdvanced('production AND backend'), customTemplate: template, }; const connections = new Map([ ['prod-api', createTestConnection('prod-api', ['production', 'backend', 'api'])], ['dev-api', createTestConnection('dev-api', ['development', 'backend', 'api'])], ['prod-frontend', createTestConnection('prod-frontend', ['production', 'frontend'])], ['prod-db', createTestConnection('prod-db', ['production', 'backend', 'database'])], ['staging-backend', createTestConnection('staging-backend', ['staging', 'backend'])], ]) as OutboundConnections; // Only some servers have instructions instructionAggregator.setInstructions('prod-api', 'Production API instructions'); instructionAggregator.setInstructions('dev-api', 'Development API instructions'); instructionAggregator.setInstructions('prod-frontend', 'Frontend instructions'); // prod-db and staging-backend have no instructions const result = instructionAggregator.getFilteredInstructions(config, connections); // Should filter to production+backend servers: prod-api, prod-db // But only prod-api has instructions expect(result).toContain('(filtered by advanced expression)'); expect(result).toContain('Results: 2 connected, 1 active'); expect(result).toContain('- prod-api'); expect(result).not.toContain('- prod-db'); // No instructions expect(result).not.toContain('dev-api'); // Wrong tags expect(result).not.toContain('prod-frontend'); // Wrong tags }); it('should handle advanced tag expressions with mixed states', () => { const template = ` Expression filter{{filterContext}} {{#if hasServers}} Matching servers with instructions: {{instructionalServerCount}} {{else}} {{#if connectedServerCount}} {{connectedServerCount}} servers match filter but none have instructions {{else}} No servers match the expression {{/if}} {{/if}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'advanced', tagExpression: TagQueryParser.parseAdvanced( '(backend AND (production OR staging)) OR (frontend AND production)', ), customTemplate: template, }; const connections = new Map([ ['prod-api', createTestConnection('prod-api', ['production', 'backend'])], ['staging-api', createTestConnection('staging-api', ['staging', 'backend'])], ['prod-web', createTestConnection('prod-web', ['production', 'frontend'])], ['dev-api', createTestConnection('dev-api', ['development', 'backend'])], ['staging-web', createTestConnection('staging-web', ['staging', 'frontend'])], ]) as OutboundConnections; // Test case 1: Some matching servers have instructions instructionAggregator.setInstructions('prod-api', 'Prod API instructions'); instructionAggregator.setInstructions('prod-web', 'Prod web instructions'); const result1 = instructionAggregator.getFilteredInstructions(config, connections); // Should match: prod-api, staging-api, prod-web (3 total, 2 with instructions) expect(result1).toContain('(filtered by advanced expression)'); expect(result1).toContain('Matching servers with instructions: 2'); // Test case 2: No matching servers have instructions instructionAggregator.clear(); const result2 = instructionAggregator.getFilteredInstructions(config, connections); expect(result2).toContain('3 servers match filter but none have instructions'); }); }); describe('Template Rendering Edge Cases', () => { it('should handle deeply nested conditionals correctly', () => { const template = ` {{#if connectedServerCount}} {{#if hasServers}} Multiple active servers ({{instructionalServerCount}}) {{#each serverNames}} {{#if @first}}First: {{this}}{{/if}} {{#if @last}}Last: {{this}}{{/if}} {{/each}} {{else}} {{connectedServerCount}} servers connected but none active {{/if}} {{else}} No servers connected {{/if}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; // Test multiple scenarios const connections = new Map([ ['server1', createTestConnection('server1')], ['server2', createTestConnection('server2')], ['server3', createTestConnection('server3')], ]) as OutboundConnections; // Scenario 1: Multiple active servers instructionAggregator.setInstructions('server1', 'Instructions 1'); instructionAggregator.setInstructions('server3', 'Instructions 3'); const result1 = instructionAggregator.getFilteredInstructions(config, connections); expect(result1).toContain('Multiple active servers (2)'); expect(result1).toContain('First: server1'); expect(result1).toContain('Last: server3'); // Scenario 2: Single active server instructionAggregator.clear(); instructionAggregator.setInstructions('server2', 'Instructions 2'); const result2 = instructionAggregator.getFilteredInstructions(config, connections); expect(result2).toContain('Multiple active servers (1)'); // Scenario 3: Connected but none active instructionAggregator.clear(); const result3 = instructionAggregator.getFilteredInstructions(config, connections); expect(result3).toContain('3 servers connected but none active'); // Scenario 4: No connections const emptyConnections = new Map() as OutboundConnections; const result4 = instructionAggregator.getFilteredInstructions(config, emptyConnections); expect(result4).toContain('No servers connected'); }); it('should handle template with loops and conditions', () => { const template = ` {{#if connectedServerCount}} Server Status Report: {{#each servers}} {{@index}}. {{name}} Connection: ✓ Instructions: {{#if hasInstructions}}✓ ({{instructions}}){{else}}✗ (waiting){{/if}} Status: {{#if hasInstructions}}ACTIVE{{else}}STANDBY{{/if}} {{/each}} Summary: - Total Connected: {{connectedServerCount}} - Active: {{instructionalServerCount}} {{else}} No servers to report {{/if}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; const connections = new Map([ ['alpha', createTestConnection('alpha')], ['beta', createTestConnection('beta')], ['gamma', createTestConnection('gamma')], ]) as OutboundConnections; instructionAggregator.setInstructions('alpha', 'Alpha service ready'); instructionAggregator.setInstructions('gamma', 'Gamma service operational'); const result = instructionAggregator.getFilteredInstructions(config, connections); expect(result).toContain('0. alpha'); expect(result).toContain('Instructions: ✓ (Alpha service ready)'); expect(result).toContain('Status: ACTIVE'); expect(result).toContain('1. beta'); expect(result).toContain('Instructions: ✗ (waiting)'); expect(result).toContain('Status: STANDBY'); expect(result).toContain('2. gamma'); expect(result).toContain('Instructions: ✓ (Gamma service operational)'); expect(result).toContain('Status: ACTIVE'); expect(result).toContain('- Total Connected: 3'); expect(result).toContain('- Active: 2'); }); }); describe('Variable Consistency and State Management', () => { it('should maintain consistent variable relationships across all operations', () => { const template = ` Consistency Check Values: - hasServers: {{hasServers}} - hasInstructionalServers: {{hasInstructionalServers}} - serverCount: {{serverCount}} - instructionalServerCount: {{instructionalServerCount}} - connectedServerCount: {{connectedServerCount}} - serverNames: {{#each serverNames}}{{this}}{{#unless @last}}, {{/unless}}{{/each}} `.trim(); const config: InboundConnectionConfig = { tagFilterMode: 'none', customTemplate: template, }; const connections = new Map([ ['server1', createTestConnection('server1')], ['server2', createTestConnection('server2')], ['server3', createTestConnection('server3')], ['server4', createTestConnection('server4')], ]) as OutboundConnections; instructionAggregator.setInstructions('server1', 'Instructions 1'); instructionAggregator.setInstructions('server3', 'Instructions 3'); const result = instructionAggregator.getFilteredInstructions(config, connections); // Verify actual values expect(result).toContain('hasServers: true'); expect(result).toContain('hasInstructionalServers: true'); expect(result).toContain('serverCount: 2'); expect(result).toContain('instructionalServerCount: 2'); expect(result).toContain('connectedServerCount: 4'); expect(result).toContain('serverNames: server1, server3'); }); }); });

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