Skip to main content
Glama
SequentialThinkingServer.ts18.3 kB
import { ThoughtStage } from "./types.js"; import { ThoughtData } from "./types.js"; import { thoughtStageFromString } from "./utils.js"; import { DateTime } from "luxon"; // Classes for memory management, reasoning, and metacognition class MemoryManager { private shortTermBuffer: ThoughtData[] = []; private longTermStorage: Record<string, ThoughtData[]> = {}; private importanceThreshold: number = 0.7; private maxBufferSize: number = 10; consolidateMemory(thought: ThoughtData): void { this.shortTermBuffer.push(thought); if (this.shortTermBuffer.length > this.maxBufferSize) { this.processBuffer(); } if (thought.score && thought.score >= this.importanceThreshold) { const category = thought.stage; if (!this.longTermStorage[category]) { this.longTermStorage[category] = []; } this.longTermStorage[category].push(thought); } } private processBuffer(): void { this.shortTermBuffer = this.shortTermBuffer.slice(-this.maxBufferSize); } retrieveRelevantThoughts(currentThought: ThoughtData): ThoughtData[] { const relevant: ThoughtData[] = []; for (const thoughts of Object.values(this.longTermStorage)) { for (const thought of thoughts) { if (thought.tags.some(tag => currentThought.tags.includes(tag))) { relevant.push(thought); } } } return relevant; } clear(): void { this.shortTermBuffer = []; this.longTermStorage = {}; } } class ReasoningEngine { private reasoningPatterns: Record<string, (thought: ThoughtData) => ThoughtData> = { deductive: this.applyDeductiveReasoning.bind(this), inductive: this.applyInductiveReasoning.bind(this), abductive: this.applyAbductiveReasoning.bind(this), analogical: this.applyAnalogicalReasoning.bind(this), creative: this.applyCreativeReasoning.bind(this) }; applyDeductiveReasoning(thought: ThoughtData): ThoughtData { thought.tags.push("deductive"); return thought; } applyInductiveReasoning(thought: ThoughtData): ThoughtData { thought.tags.push("inductive"); return thought; } applyAbductiveReasoning(thought: ThoughtData): ThoughtData { thought.tags.push("abductive"); return thought; } applyAnalogicalReasoning(thought: ThoughtData): ThoughtData { thought.tags.push("analogical"); return thought; } applyCreativeReasoning(thought: ThoughtData): ThoughtData { thought.tags.push("creative"); return thought; } analyzeThoughtPattern(thought: ThoughtData): string { // Simple pattern matching based on stage if (thought.stage === ThoughtStage.ANALYSIS || thought.stage === ThoughtStage.EVALUATION) { return "deductive"; } else if (thought.stage === ThoughtStage.IDEATION) { return "creative"; } else if (thought.stage === ThoughtStage.SYNTHESIS) { return "inductive"; } return "deductive"; } applyReasoningStrategy(thought: ThoughtData): ThoughtData { const pattern = this.analyzeThoughtPattern(thought); return this.reasoningPatterns[pattern](thought); } } class MetacognitiveMonitor { private qualityMetrics = { coherence: 0.0, depth: 0.0, creativity: 0.0, practicality: 0.0, relevance: 0.0, clarity: 0.0 }; evaluateThoughtQuality(thought: ThoughtData): Record<string, number> { const metrics = { ...this.qualityMetrics }; // Basic metric calculation if (thought.score) { const baseScore = thought.score; metrics.coherence = baseScore; metrics.depth = baseScore * 0.8; metrics.creativity = baseScore * 0.7; metrics.practicality = baseScore * 0.9; metrics.relevance = baseScore * 0.85; metrics.clarity = baseScore * 0.95; } // Adjust based on stage if (thought.stage === ThoughtStage.IDEATION) { metrics.creativity *= 1.2; } else if (thought.stage === ThoughtStage.EVALUATION) { metrics.practicality *= 1.2; } return metrics; } generateImprovementSuggestions(metrics: Record<string, number>): string[] { const suggestions: string[] = []; for (const [metric, value] of Object.entries(metrics)) { if (value < 0.7) { if (metric === "coherence") { suggestions.push("Consider strengthening logical connections"); } else if (metric === "depth") { suggestions.push("Try exploring the concept more thoroughly"); } else if (metric === "creativity") { suggestions.push("Consider adding more innovative elements"); } else if (metric === "practicality") { suggestions.push("Focus on practical applications"); } else if (metric === "relevance") { suggestions.push("Ensure alignment with main objectives"); } else if (metric === "clarity") { suggestions.push("Try expressing ideas more clearly"); } } } return suggestions; } suggestImprovements(thought: ThoughtData): string[] { const metrics = this.evaluateThoughtQuality(thought); return this.generateImprovementSuggestions(metrics); } } class SequentialThinkingServer { protected thoughtHistory: ThoughtData[] = []; protected branches: Record<string, ThoughtData[]> = {}; protected activeBranchId: string | null = null; protected validateThoughtData(inputData: any): ThoughtData { try { // Convert stage string to enum const stage = thoughtStageFromString(inputData.stage); const thoughtData: ThoughtData = { thought: inputData.thought, thoughtNumber: inputData.thoughtNumber, totalThoughts: inputData.totalThoughts, nextThoughtNeeded: inputData.nextThoughtNeeded, stage: stage, isRevision: inputData.isRevision, revisesThought: inputData.revisesThought, branchFromThought: inputData.branchFromThought, branchId: inputData.branchId, needsMoreThoughts: inputData.needsMoreThoughts, score: inputData.score, tags: inputData.tags || [], createdAt: DateTime.now() }; // Validate the created thought data this.validateThought(thoughtData); return thoughtData; } catch (e) { if (e instanceof Error) { throw new Error(`Invalid thought data: ${e.message}`); } throw new Error(`Invalid thought data: Unknown error`); } } protected validateThought(thought: ThoughtData): void { if (thought.thoughtNumber < 1) { throw new Error("Thought number must be positive"); } if (thought.totalThoughts < thought.thoughtNumber) { throw new Error("Total thoughts must be greater than or equal to thought number"); } if (thought.score !== undefined && (thought.score < 0 || thought.score > 1)) { throw new Error("Score must be between 0 and 1"); } if (thought.revisesThought !== undefined && thought.revisesThought >= thought.thoughtNumber) { throw new Error("Cannot revise a future thought"); } } generateSummary(): string { if (!this.thoughtHistory.length) { return JSON.stringify({ summary: "No thoughts recorded yet" }); } const stages: Record<string, ThoughtData[]> = {}; for (const thought of this.thoughtHistory) { const stageName = thought.stage; if (!stages[stageName]) { stages[stageName] = []; } stages[stageName].push(thought); } // Calculate various metrics const summary = { totalThoughts: this.thoughtHistory.length, stages: Object.entries(stages).reduce((acc, [stage, thoughts]) => { acc[stage] = { count: thoughts.length, averageScore: thoughts.reduce((sum, t) => sum + (t.score || 0), 0) / thoughts.length }; return acc; }, {} as Record<string, { count: number, averageScore: number }>), branches: Object.entries(this.branches).reduce((acc, [branchId, thoughts]) => { acc[branchId] = thoughts.length; return acc; }, {} as Record<string, number>), revisions: this.thoughtHistory.filter(t => t.isRevision).length, timeline: this.thoughtHistory.map(t => ({ number: t.thoughtNumber, stage: t.stage, score: t.score, branch: t.branchId })) }; return JSON.stringify({ summary }, null, 2); } } export class EnhancedSequentialThinkingServer extends SequentialThinkingServer { private memoryManager = new MemoryManager(); private reasoningEngine = new ReasoningEngine(); private metacognitiveMonitor = new MetacognitiveMonitor(); // Find thought by ID (thought number) private findThoughtById(thoughtId: number): ThoughtData | undefined { return this.thoughtHistory.find(t => t.thoughtNumber === thoughtId); } // Update thought in history private updateThought(updatedThought: ThoughtData): void { const idx = this.thoughtHistory.findIndex(t => t.thoughtNumber === updatedThought.thoughtNumber); if (idx !== -1) { this.thoughtHistory[idx] = updatedThought; } } // 1. Capture a new thought captureThought(inputData: any): any { try { // Validate and create thought data const thoughtData = this.validateThoughtData(inputData); // Apply reasoning strategy const enhancedThought = this.reasoningEngine.applyReasoningStrategy(thoughtData); // Store in memory this.memoryManager.consolidateMemory(enhancedThought); // Get metacognitive insights const improvements = this.metacognitiveMonitor.suggestImprovements(enhancedThought); // Get related thoughts const relatedThoughts = this.memoryManager.retrieveRelevantThoughts(enhancedThought); // Store thought in history this.thoughtHistory.push(enhancedThought); // Handle branching if (enhancedThought.branchFromThought && enhancedThought.branchId) { if (!this.branches[enhancedThought.branchId]) { this.branches[enhancedThought.branchId] = []; } this.branches[enhancedThought.branchId].push(enhancedThought); } // Return in the format expected by tests return { content: [{ type: "text", text: JSON.stringify({ thoughtAnalysis: { currentThought: { thoughtNumber: enhancedThought.thoughtNumber, totalThoughts: enhancedThought.totalThoughts, nextThoughtNeeded: enhancedThought.nextThoughtNeeded, stage: enhancedThought.stage, score: enhancedThought.score, tags: enhancedThought.tags, timestamp: enhancedThought.createdAt.toISO(), branch: enhancedThought.branchId }, analysis: { relatedThoughtsCount: relatedThoughts.length, qualityMetrics: this.metacognitiveMonitor.evaluateThoughtQuality(enhancedThought), suggestedImprovements: improvements }, context: { activeBranches: Object.keys(this.branches), thoughtHistoryLength: this.thoughtHistory.length, currentStage: enhancedThought.stage } } }, null, 2) }] }; } catch (e) { return this.handleError(e); } } // Revise thought reviseThought(input: { thought_id: number; thought?: string; thought_number?: number; total_thoughts?: number; next_thought_needed?: boolean; stage?: string; is_revision?: boolean; revises_thought?: number; branch_from_thought?: number; branch_id?: string; needs_more_thoughts?: boolean; score?: number; tags?: string[]; }): any { try { // Find the thought to revise const thought = this.findThoughtById(input.thought_id); if (!thought) { throw new Error(`Thought with ID ${input.thought_id} not found`); } // Update thought properties with any provided values if (input.thought !== undefined) thought.thought = input.thought; if (input.next_thought_needed !== undefined) thought.nextThoughtNeeded = input.next_thought_needed; if (input.stage !== undefined) thought.stage = thoughtStageFromString(input.stage); if (input.is_revision !== undefined) thought.isRevision = input.is_revision; if (input.revises_thought !== undefined) thought.revisesThought = input.revises_thought; if (input.branch_from_thought !== undefined) thought.branchFromThought = input.branch_from_thought; if (input.branch_id !== undefined) thought.branchId = input.branch_id; if (input.needs_more_thoughts !== undefined) thought.needsMoreThoughts = input.needs_more_thoughts; if (input.score !== undefined) thought.score = input.score; if (input.tags !== undefined) thought.tags = input.tags; // Set revision flag thought.isRevision = true; // Update thought in history this.updateThought(thought); return { content: [{ type: "text", text: JSON.stringify({ status: "success", revision: { thoughtNumber: thought.thoughtNumber, stage: thought.stage, updated: true, timestamp: DateTime.now().toISO() } }, null, 2) }] }; } catch (e) { return this.handleError(e); } } // 1. Apply reasoning to a thought applyReasoning(input: { thought_id: number; reasoning_type?: string }): any { try { // Find the thought const thought = this.findThoughtById(input.thought_id); if (!thought) { throw new Error(`Thought with ID ${input.thought_id} not found`); } // Apply reasoning strategy const pattern = input.reasoning_type || this.reasoningEngine.analyzeThoughtPattern(thought); const updatedThought = this.reasoningEngine.applyReasoningStrategy(thought); // Update thought in history this.updateThought(updatedThought); return { content: [{ type: "text", text: JSON.stringify({ status: "success", reasoningApplied: { thoughtNumber: updatedThought.thoughtNumber, pattern: pattern, tags: updatedThought.tags } }, null, 2) }] }; } catch (e) { return this.handleError(e); } } // 2. Evaluate thought quality evaluateThoughtQuality(input: { thought_id: number }): any { try { // Find the thought const thought = this.findThoughtById(input.thought_id); if (!thought) { throw new Error(`Thought with ID ${input.thought_id} not found`); } // Get quality metrics and improvement suggestions const metrics = this.metacognitiveMonitor.evaluateThoughtQuality(thought); const improvements = this.metacognitiveMonitor.generateImprovementSuggestions(metrics); return { content: [{ type: "text", text: JSON.stringify({ status: "success", evaluation: { thoughtNumber: thought.thoughtNumber, qualityMetrics: metrics, suggestedImprovements: improvements } }, null, 2) }] }; } catch (e) { return this.handleError(e); } } // 3. Retrieve relevant thoughts retrieveRelevantThoughts(input: { thought_id: number }): any { try { // Find the thought const thought = this.findThoughtById(input.thought_id); if (!thought) { throw new Error(`Thought with ID ${input.thought_id} not found`); } // Get related thoughts const relatedThoughts = this.memoryManager.retrieveRelevantThoughts(thought); return { content: [{ type: "text", text: JSON.stringify({ status: "success", retrieval: { thoughtNumber: thought.thoughtNumber, relatedThoughtsCount: relatedThoughts.length, relatedThoughts: relatedThoughts.map(t => ({ thoughtNumber: t.thoughtNumber, stage: t.stage, tags: t.tags })) } }, null, 2) }] }; } catch (e) { return this.handleError(e); } } // 4. Branch thought branchThought(input: { parent_thought_id: number; branch_id: string }): any { try { // Find the parent thought const parentThought = this.findThoughtById(input.parent_thought_id); if (!parentThought) { throw new Error(`Parent thought with ID ${input.parent_thought_id} not found`); } // Create branch if it doesn't exist if (!this.branches[input.branch_id]) { this.branches[input.branch_id] = []; this.activeBranchId = input.branch_id; } return { content: [{ type: "text", text: JSON.stringify({ status: "success", branching: { parentThoughtNumber: parentThought.thoughtNumber, branchId: input.branch_id, isActive: this.activeBranchId === input.branch_id } }, null, 2) }] }; } catch (e) { return this.handleError(e); } } // Helper method for error handling private handleError(e: unknown): any { console.error(`Error: ${e instanceof Error ? e.message : String(e)}`); return { content: [{ type: "text", text: JSON.stringify({ error: e instanceof Error ? e.message : String(e), status: "failed", errorType: e instanceof Error ? e.constructor.name : "Unknown", timestamp: DateTime.now().toISO() }, null, 2) }], isError: true }; } clearHistory(): void { this.thoughtHistory = []; this.branches = {}; this.memoryManager.clear(); this.activeBranchId = null; } }

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/Promptly-Technologies-LLC/mcp-structured-thinking'

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