Skip to main content
Glama
CognitiveMCPServer.additionalHandlers.test.ts19.7 kB
/** * Additional unit tests for CognitiveMCPServer tool handlers * Tests the implementation of missing handler methods to improve coverage */ import { promises as fs } from "fs"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { CognitiveMCPServer } from "../../server/CognitiveMCPServer.js"; import type { AnalyzeMemoryUsageArgs, AnalyzeSystematicallyArgs, DecomposeProblemArgs, ForgettingAuditArgs, ForgettingPolicyArgs, OptimizeMemoryArgs, RecoverMemoryArgs, ThinkParallelArgs, } from "../../types/mcp.js"; describe("CognitiveMCPServer Additional Tool Handlers", () => { let server: CognitiveMCPServer; let originalEnv: NodeJS.ProcessEnv; beforeEach(async () => { // Save original environment originalEnv = { ...process.env }; // Ensure tmp directory exists await fs.mkdir("./tmp", { recursive: true }); // Set up test environment with unique temporary brain directory const testId = Math.random().toString(36).substring(7); process.env.COGNITIVE_BRAIN_DIR = `./tmp/test-brain-${testId}`; server = new CognitiveMCPServer(); // Initialize without connecting to transport for testing await server.initialize(true); }); afterEach(async () => { await server.shutdown(); // Clean up test directory if ( process.env.COGNITIVE_BRAIN_DIR && process.env.COGNITIVE_BRAIN_DIR.startsWith("./tmp/test-brain-") ) { try { await fs.rm(process.env.COGNITIVE_BRAIN_DIR, { recursive: true, force: true, }); } catch (error) { // Ignore cleanup errors } } // Restore original environment process.env = originalEnv; }); describe("handleAnalyzeSystematically", () => { it("should analyze problems systematically with default mode", async () => { const args: AnalyzeSystematicallyArgs = { input: "How can we improve our software development process?", }; const result = await server.handleAnalyzeSystematically(args); expect(result).toBeDefined(); expect(result.problem_structure).toBeDefined(); expect(result.recommended_framework).toBeDefined(); expect(result.analysis_steps).toBeDefined(); expect(Array.isArray(result.analysis_steps)).toBe(true); expect(result.confidence).toBeGreaterThanOrEqual(0); expect(result.confidence).toBeLessThanOrEqual(1); expect(result.processing_time_ms).toBeGreaterThan(0); }); it("should analyze with specific context", async () => { const args: AnalyzeSystematicallyArgs = { input: "What are the risks of cloud migration?", context: { domain: "technology", urgency: 0.8, complexity: 0.9, }, }; const result = await server.handleAnalyzeSystematically(args); expect(result).toBeDefined(); expect(result.problem_structure).toBeDefined(); expect(result.recommended_framework).toBeDefined(); }); it("should handle complex problems", async () => { const args: AnalyzeSystematicallyArgs = { input: "Design a comprehensive strategy for digital transformation", mode: "auto", verbosity: "detailed", }; const result = await server.handleAnalyzeSystematically(args); expect(result).toBeDefined(); expect(result.analysis_steps.length).toBeGreaterThan(0); // Detailed analysis expect(result.recommended_framework).toBeDefined(); }); it("should throw error for empty input", async () => { const args: AnalyzeSystematicallyArgs = { input: "", }; await expect(server.handleAnalyzeSystematically(args)).rejects.toThrow(); }); }); describe("handleThinkParallel", () => { it("should process parallel thinking with default settings", async () => { const args: ThinkParallelArgs = { input: "What are the pros and cons of remote work?", }; const result = await server.handleThinkParallel(args); expect(result).toBeDefined(); expect(result.synthesized_conclusion).toBeDefined(); expect(typeof result.synthesized_conclusion).toBe("string"); expect(result.confidence).toBeGreaterThanOrEqual(0); expect(result.confidence).toBeLessThanOrEqual(1); expect(Array.isArray(result.stream_results)).toBe(true); expect(result.stream_results.length).toBeGreaterThan(0); expect(result.processing_time_ms).toBeGreaterThan(0); }); it("should handle paralg with context", async () => { const args: ThinkParallelArgs = { input: "How should we approach market expansion?", context: { domain: "business", urgency: 0.7, complexity: 0.8, }, enable_coordination: true, }; const result = await server.handleThinkParallel(args); expect(result).toBeDefined(); expect(result.synthesized_conclusion).toBeDefined(); expect(Array.isArray(result.stream_results)).toBe(true); expect(result.stream_results.length).toBeGreaterThan(0); }); it("should process with different verbosity levels", async () => { const args: ThinkParallelArgs = { input: "Analyze the impact of AI on education", verbosity: "summary", }; const result = await server.handleThinkParallel(args); expect(result).toBeDefined(); expect(result.synthesized_conclusion).toBeDefined(); expect(Array.isArray(result.stream_results)).toBe(true); }); it("should throw error for empty input", async () => { const args: ThinkParallelArgs = { input: "", }; await expect(server.handleThinkParallel(args)).rejects.toThrow(); }); }); describe("handleDecomposeProblem", () => { it("should decompose problems with default settings", async () => { const args: DecomposeProblemArgs = { input: "Build a scalable e-commerce platform", }; const result = await server.handleDecomposeProblem(args); expect(result).toBeDefined(); expect(result.original_problem).toBeDefined(); expect(Array.isArray(result.hierarchical_structure)).toBe(true); expect(result.hierarchical_structure.length).toBeGreaterThan(0); expect(result.processing_time_ms).toBeGreaterThan(0); }); it("should decompose with specific depth", async () => { const args: DecomposeProblemArgs = { input: "Implement a machine learning pipeline", max_depth: 3, }; const result = await server.handleDecomposeProblem(args); expect(result).toBeDefined(); expect(result.original_problem).toBeDefined(); expect(Array.isArray(result.hierarchical_structure)).toBe(true); }); it("should handle complex problems with context", async () => { const args: DecomposeProblemArgs = { input: "Modernize legacy enterprise software", context: { domain: "enterprise_software", complexity: 0.9, }, strategies: ["functional", "temporal"], }; const result = await server.handleDecomposeProblem(args); expect(result).toBeDefined(); expect(result.hierarchical_structure.length).toBeGreaterThan(0); }); it("should throw error for empty input", async () => { const args: DecomposeProblemArgs = { input: "", }; await expect(server.handleDecomposeProblem(args)).rejects.toThrow(); }); }); describe("handleAnalyzeMemoryUsage", () => { beforeEach(async () => { // Store some test memories first await server.handleRemember({ content: "Test memory for usage analysis", type: "episodic", importance: 0.8, }); await server.handleRemember({ content: "Another test memory", type: "semantic", importance: 0.6, }); }); it("should analyze memory usage with default settings", async () => { const args: AnalyzeMemoryUsageArgs = {}; const result = await server.handleAnalyzeMemoryUsage(args); expect(result).toBeDefined(); expect(result.analysis).toBeDefined(); expect(typeof result.analysis).toBe("object"); expect(result.recommendations).toBeDefined(); expect(Array.isArray(result.recommendations)).toBe(true); expect(result.analysis_time_ms).toBeGreaterThanOrEqual(0); }); it("should analyze with deep analysis", async () => { const args: AnalyzeMemoryUsageArgs = { analysis_depth: "deep", include_recommendations: true, }; const result = await server.handleAnalyzeMemoryUsage(args); expect(result).toBeDefined(); expect(result.analysis).toBeDefined(); expect(result.recommendations?.length ?? 0).toBeGreaterThanOrEqual(0); }); it("should analyze with context", async () => { const args: AnalyzeMemoryUsageArgs = { context: { domain: "test", session_id: "analysis_session", }, verbosity: "detailed", }; const result = await server.handleAnalyzeMemoryUsage(args); expect(result).toBeDefined(); expect(result.analysis).toBeDefined(); }); }); describe("handleOptimizeMemory", () => { beforeEach(async () => { // Store multiple test memories for (let i = 0; i < 10; i++) { await server.handleRemember({ content: `Test memory ${i} for optimization`, type: i % 2 === 0 ? "episodic" : "semantic", importance: 0.3 + i * 0.05, // Varying importance }); } }); it("should optimize memory with default settings", async () => { const args: OptimizeMemoryArgs = {}; const result = await server.handleOptimizeMemory(args); expect(result).toBeDefined(); expect(result.optimization_summary).toBeDefined(); expect(typeof result.optimization_summary).toBe("object"); expect( result.optimization_summary.memories_processed ).toBeGreaterThanOrEqual(0); expect( result.optimization_summary.memories_degraded ).toBeGreaterThanOrEqual(0); expect(result.optimization_time_ms).toBeGreaterThanOrEqual(0); }); it("should optimize with moderate settings", async () => { const args: OptimizeMemoryArgs = { optimization_mode: "moderate", target_memory_reduction: 0.2, preserve_important_memories: true, }; const result = await server.handleOptimizeMemory(args); expect(result).toBeDefined(); expect(result.optimization_summary).toBeDefined(); expect( result.optimization_summary.memories_processed ).toBeGreaterThanOrEqual(0); }); it("should optimize with context", async () => { const args: OptimizeMemoryArgs = { context: { domain: "test", }, verbosity: "detailed", }; const result = await server.handleOptimizeMemory(args); expect(result).toBeDefined(); expect(result.optimization_summary).toBeDefined(); }); }); describe("handleRecoverMemory", () => { let memoryId: string; beforeEach(async () => { // Store a memory that we can try to recover const result = await server.handleRemember({ content: "Important memory to recover", type: "episodic", importance: 0.9, emotional_tags: ["important", "recovery_test"], }); memoryId = result.memory_id; }); it("should attempt memory recovery with basic cues", async () => { const args: RecoverMemoryArgs = { memory_id: memoryId, recovery_cues: [ { type: "semantic", value: "important memory", }, { type: "emotional", value: "important", }, ], }; const result = await server.handleRecoverMemory(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); expect(typeof result.success).toBe("boolean"); expect(result.memory_id).toBeDefined(); expect(result.recovery_confidence).toBeGreaterThanOrEqual(0); expect(result.recovery_time_ms).toBeGreaterThanOrEqual(0); }); it("should handle recovery with multiple cue types", async () => { const args: RecoverMemoryArgs = { memory_id: memoryId, recovery_cues: [ { type: "semantic", value: "recovery test", strength: 0.8, }, { type: "temporal", value: "recent", strength: 0.6, }, { type: "contextual", value: "test environment", strength: 0.7, }, ], max_recovery_attempts: 3, }; const result = await server.handleRecoverMemory(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); expect(typeof result.success).toBe("boolean"); }); it("should handle recovery with context", async () => { const args: RecoverMemoryArgs = { memory_id: memoryId, recovery_cues: [ { type: "associative", value: "test memory", }, ], context: { domain: "test", }, verbosity: "detailed", }; const result = await server.handleRecoverMemory(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); }); it("should handle empty memory_id gracefully", async () => { const args: RecoverMemoryArgs = { memory_id: "", recovery_cues: [ { type: "semantic", value: "test", }, ], }; const result = await server.handleRecoverMemory(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); }); it("should throw error for empty recovery cues", async () => { const args: RecoverMemoryArgs = { memory_id: memoryId, recovery_cues: [], }; await expect(server.handleRecoverMemory(args)).rejects.toThrow(); }); }); describe("handleForgettingAudit", () => { it("should perform forgetting audit with default settings", async () => { const args: ForgettingAuditArgs = {}; const result = await server.handleForgettingAudit(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); expect(typeof result.success).toBe("boolean"); expect(Array.isArray(result.audit_entries)).toBe(true); expect(result.query_time_ms).toBeGreaterThanOrEqual(0); }); it("should perform audit with query filters", async () => { const args: ForgettingAuditArgs = { query: { limit: 10, execution_status: ["executed"], }, include_summary: true, }; const result = await server.handleForgettingAudit(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); expect(Array.isArray(result.audit_entries)).toBe(true); }); it("should handle audit with context", async () => { const args: ForgettingAuditArgs = { verbosity: "detailed", include_executive_summary: true, }; const result = await server.handleForgettingAudit(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); }); }); describe("handleForgettingPolicy", () => { it("should list forgetting policies", async () => { const args: ForgettingPolicyArgs = { action: "list", }; const result = await server.handleForgettingPolicy(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); expect(typeof result.success).toBe("boolean"); expect(result.action).toBe("list"); expect(result.processing_time_ms).toBeGreaterThanOrEqual(0); }); it("should create a new forgetting policy", async () => { const args: ForgettingPolicyArgs = { action: "create", policy_data: { policy_name: "test_policy", description: "Test policy for unit tests", active: true, rules: [ { rule_name: "test_rule", conditions: [ { condition_type: "importance_threshold", operator: "less_than", value: 0.3, }, ], condition_logic: "AND", action: "allow", priority: 1, }, ], }, }; const result = await server.handleForgettingPolicy(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); }); it("should handle policy evaluation", async () => { const args: ForgettingPolicyArgs = { action: "evaluate", evaluation_context: { memory_id: "test_memory_id", memory_type: "episodic", decision: {}, evaluation: {}, memory_metadata: { importance: 0.5, age_days: 30, }, }, }; const result = await server.handleForgettingPolicy(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); }); it("should throw error for invalid action", async () => { const args: ForgettingPolicyArgs = { action: "invalid_action" as any, }; await expect(server.handleForgettingPolicy(args)).rejects.toThrow(); }); }); describe("Integration Tests for Additional Handlers", () => { it("should handle systematic analysis -> parallel thinking workflow", async () => { // First, analyze systematically const systematicResult = await server.handleAnalyzeSystematically({ input: "How can we improve team productivity?", }); expect(systematicResult).toBeDefined(); // Then use parallel thinking on the same topic const parallelResult = await server.handleThinkParallel({ input: "How can we improve team productivity?", }); expect(parallelResult).toBeDefined(); expect(parallelResult.synthesized_conclusion).toBeDefined(); }); it("should handle problem decomposition -> memory optimization workflow", async () => { // Decompose a problem const decompositionResult = await server.handleDecomposeProblem({ input: "Optimize our development workflow", }); expect(decompositionResult).toBeDefined(); // Store the decomposition as memory await server.handleRemember({ content: JSON.stringify(decompositionResult.hierarchical_structure), type: "semantic", importance: 0.8, }); // Analyze memory usage const memoryAnalysis = await server.handleAnalyzeMemoryUsage({}); expect(memoryAnalysis).toBeDefined(); // Optimize memory const optimizationResult = await server.handleOptimizeMemory({ optimization_mode: "conservative", }); expect(optimizationResult).toBeDefined(); }); it("should handle forgetting policy -> audit workflow", async () => { // List existing policies const listResult = await server.handleForgettingPolicy({ action: "list", }); expect(listResult).toBeDefined(); // Perform audit const auditResult = await server.handleForgettingAudit({ include_summary: true, }); expect(auditResult).toBeDefined(); expect(auditResult.success).toBeDefined(); }); }); });

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/keyurgolani/ThoughtMcp'

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