Skip to main content
Glama
n-r-w

KnowledgeGraph MCP Server

by n-r-w
mcp-validation.test.ts8.57 kB
import { KnowledgeGraphManager } from '../core.js'; import { StorageType } from '../storage/types.js'; /** * Test suite for MCP layer validation logic * These tests simulate the validation that happens in index.ts for the MCP server */ describe('MCP Validation Layer Tests', () => { let manager: KnowledgeGraphManager; const testProject = 'mcp_validation_test'; beforeEach(async () => { // Use in-memory SQLite to avoid disk I/O issues manager = new KnowledgeGraphManager({ type: StorageType.SQLITE, connectionString: 'sqlite://:memory:' }); // Create test entities with tags for validation testing const testEntities = [ { name: 'MCP_Test_Entity_1', entityType: 'project', observations: ['Test entity for MCP validation'], tags: ['validation', 'mcp-test'] }, { name: 'MCP_Test_Entity_2', entityType: 'technology', observations: ['Another test entity'], tags: ['validation', 'testing'] } ]; await manager.createEntities(testEntities, testProject); }); afterEach(async () => { await manager.deleteEntities(['MCP_Test_Entity_1', 'MCP_Test_Entity_2'], testProject); await manager.close(); }); describe('Query Parameter Validation (Bug Fix)', () => { /** * Simulates the MCP validation logic from index.ts * This replicates the fixed validation behavior */ function simulateMCPValidation(query: any, exactTags: any): { isValid: boolean; error?: string; processedQuery?: string[] } { // Check if exactTags is provided for tag-only search const hasExactTags = exactTags && Array.isArray(exactTags) && exactTags.length > 0; // Handle multiple queries - allow empty/undefined query if exactTags is provided let queries: string[]; if (query === undefined || query === null) { if (hasExactTags) { queries = [""]; // Use empty string for tag-only search } else { return { isValid: false, error: "Query parameter is required when exactTags is not provided" }; } } else { queries = Array.isArray(query) ? query : [query as string]; } // Validate queries - allow empty strings only when exactTags is provided if (queries.length === 0 || queries.some((q: any) => typeof q !== 'string' || (!hasExactTags && q.trim() === ''))) { return { isValid: false, error: "Query must be a non-empty string or array of non-empty strings when exactTags is not provided" }; } return { isValid: true, processedQuery: queries }; } describe('Positive Cases - Should Pass Validation', () => { it('should allow undefined query with valid exactTags', () => { const result = simulateMCPValidation(undefined, ['validation']); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['']); }); it('should allow null query with valid exactTags', () => { const result = simulateMCPValidation(null, ['validation']); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['']); }); it('should allow empty string query with valid exactTags', () => { const result = simulateMCPValidation('', ['validation']); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['']); }); it('should allow whitespace-only query with valid exactTags', () => { const result = simulateMCPValidation(' ', ['validation']); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual([' ']); }); it('should allow array with empty strings when exactTags provided', () => { const result = simulateMCPValidation(['', ''], ['validation']); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['', '']); }); it('should allow normal query with exactTags (backward compatibility)', () => { const result = simulateMCPValidation('test', ['validation']); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['test']); }); it('should allow normal query without exactTags', () => { const result = simulateMCPValidation('test', undefined); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['test']); }); it('should allow array query without exactTags', () => { const result = simulateMCPValidation(['test1', 'test2'], undefined); expect(result.isValid).toBe(true); expect(result.processedQuery).toEqual(['test1', 'test2']); }); }); describe('Negative Cases - Should Fail Validation', () => { it('should reject undefined query without exactTags', () => { const result = simulateMCPValidation(undefined, undefined); expect(result.isValid).toBe(false); expect(result.error).toBe("Query parameter is required when exactTags is not provided"); }); it('should reject null query without exactTags', () => { const result = simulateMCPValidation(null, null); expect(result.isValid).toBe(false); expect(result.error).toBe("Query parameter is required when exactTags is not provided"); }); it('should reject empty string query without exactTags', () => { const result = simulateMCPValidation('', undefined); expect(result.isValid).toBe(false); expect(result.error).toBe("Query must be a non-empty string or array of non-empty strings when exactTags is not provided"); }); it('should reject whitespace-only query without exactTags', () => { const result = simulateMCPValidation(' ', undefined); expect(result.isValid).toBe(false); expect(result.error).toBe("Query must be a non-empty string or array of non-empty strings when exactTags is not provided"); }); it('should reject empty array query without exactTags', () => { const result = simulateMCPValidation([], undefined); expect(result.isValid).toBe(false); expect(result.error).toBe("Query must be a non-empty string or array of non-empty strings when exactTags is not provided"); }); it('should reject array with empty strings without exactTags', () => { const result = simulateMCPValidation(['', 'test'], undefined); expect(result.isValid).toBe(false); expect(result.error).toBe("Query must be a non-empty string or array of non-empty strings when exactTags is not provided"); }); it('should reject non-string query elements', () => { const result = simulateMCPValidation([123, 'test'], ['validation']); expect(result.isValid).toBe(false); expect(result.error).toBe("Query must be a non-empty string or array of non-empty strings when exactTags is not provided"); }); it('should reject undefined query with empty exactTags array', () => { const result = simulateMCPValidation(undefined, []); expect(result.isValid).toBe(false); expect(result.error).toBe("Query parameter is required when exactTags is not provided"); }); it('should reject undefined query with null exactTags', () => { const result = simulateMCPValidation(undefined, null); expect(result.isValid).toBe(false); expect(result.error).toBe("Query parameter is required when exactTags is not provided"); }); }); }); describe('Integration Tests - Actual Core Behavior', () => { it('should work with the actual core when validation passes', async () => { // Test the actual core behavior with the scenarios that should pass validation const result = await manager.searchNodes('', { exactTags: ['validation'] }, testProject); expect(result.entities).toHaveLength(2); expect(result.entities.map(e => e.name)).toContain('MCP_Test_Entity_1'); expect(result.entities.map(e => e.name)).toContain('MCP_Test_Entity_2'); }); it('should handle null query with exactTags in core', async () => { const result = await manager.searchNodes(null as any, { exactTags: ['validation'] }, testProject); expect(result.entities).toHaveLength(2); }); it('should handle undefined query with exactTags in core', async () => { const result = await manager.searchNodes(undefined as any, { exactTags: ['validation'] }, testProject); expect(result.entities).toHaveLength(2); }); }); });

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/n-r-w/knowledgegraph-mcp'

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