Shannon Thinking MCP Server

  • src
import chalk from 'chalk'; import { ShannonThoughtData, ThoughtType } from './types.js'; export class ShannonThinkingServer { private thoughtHistory: ShannonThoughtData[] = []; private validateThoughtData(input: unknown): ShannonThoughtData { const data = input as Record<string, unknown>; if (!data.thought || typeof data.thought !== 'string') { throw new Error(`Invalid thought: must be a string, received ${typeof data.thought}`); } if (!data.thoughtType || !Object.values(ThoughtType).includes(data.thoughtType as ThoughtType)) { throw new Error(`Invalid thoughtType: must be one of: ${Object.values(ThoughtType).join(', ')}, received ${data.thoughtType}`); } if (!data.thoughtNumber || typeof data.thoughtNumber !== 'number') { throw new Error(`Invalid thoughtNumber: must be a number, received ${typeof data.thoughtNumber}`); } if (!data.totalThoughts || typeof data.totalThoughts !== 'number') { throw new Error(`Invalid totalThoughts: must be a number, received ${typeof data.totalThoughts}`); } if (typeof data.uncertainty !== 'number' || data.uncertainty < 0 || data.uncertainty > 1) { throw new Error(`Invalid uncertainty: must be a number between 0 and 1, received ${data.uncertainty}`); } if (!Array.isArray(data.dependencies)) { throw new Error(`Invalid dependencies: must be an array, received ${typeof data.dependencies}`); } if (!Array.isArray(data.assumptions)) { throw new Error(`Invalid assumptions: must be an array, received ${typeof data.assumptions}`); } if (typeof data.nextThoughtNeeded !== 'boolean') { throw new Error(`Invalid nextThoughtNeeded: must be a boolean, received ${typeof data.nextThoughtNeeded}`); } // Optional recheckStep validation if (data.recheckStep) { const recheck = data.recheckStep as Record<string, unknown>; if (!recheck.stepToRecheck || !Object.values(ThoughtType).includes(recheck.stepToRecheck as ThoughtType)) { throw new Error('Invalid recheckStep: stepToRecheck must be a valid ThoughtType'); } if (!recheck.reason || typeof recheck.reason !== 'string') { throw new Error('Invalid recheckStep: reason must be a string'); } if (recheck.newInformation && typeof recheck.newInformation !== 'string') { throw new Error('Invalid recheckStep: newInformation must be a string if provided'); } } // Optional proofElements validation if (data.proofElements) { const proof = data.proofElements as Record<string, unknown>; if (!proof.hypothesis || typeof proof.hypothesis !== 'string') { throw new Error('Invalid proofElements: hypothesis must be a string'); } if (!proof.validation || typeof proof.validation !== 'string') { throw new Error('Invalid proofElements: validation must be a string'); } } // Optional experimentalElements validation if (data.experimentalElements) { const exp = data.experimentalElements as Record<string, unknown>; if (!exp.testDescription || typeof exp.testDescription !== 'string') { throw new Error('Invalid experimentalElements: testDescription must be a string'); } if (!exp.results || typeof exp.results !== 'string') { throw new Error('Invalid experimentalElements: results must be a string'); } if (typeof exp.confidence !== 'number' || exp.confidence < 0 || exp.confidence > 1) { throw new Error('Invalid experimentalElements: confidence must be a number between 0 and 1'); } if (!Array.isArray(exp.limitations)) { throw new Error('Invalid experimentalElements: limitations must be an array'); } } // Optional implementationNotes validation if (data.implementationNotes) { const impl = data.implementationNotes as Record<string, unknown>; if (!Array.isArray(impl.practicalConstraints)) { throw new Error('Invalid implementationNotes: practicalConstraints must be an array'); } if (!impl.proposedSolution || typeof impl.proposedSolution !== 'string') { throw new Error('Invalid implementationNotes: proposedSolution must be a string'); } } // Optional revision validation if (data.isRevision !== undefined && typeof data.isRevision !== 'boolean') { throw new Error('Invalid isRevision: must be a boolean if provided'); } if (data.revisesThought !== undefined) { if (typeof data.revisesThought !== 'number' || data.revisesThought < 1) { throw new Error('Invalid revisesThought: must be a positive number if provided'); } if (!data.isRevision) { throw new Error('Invalid revisesThought: cannot be set without isRevision being true'); } } return { thought: data.thought as string, thoughtType: data.thoughtType as ThoughtType, thoughtNumber: data.thoughtNumber as number, totalThoughts: data.totalThoughts as number, uncertainty: data.uncertainty as number, dependencies: data.dependencies as number[], assumptions: data.assumptions as string[], nextThoughtNeeded: data.nextThoughtNeeded as boolean, recheckStep: data.recheckStep as ShannonThoughtData['recheckStep'], proofElements: data.proofElements as ShannonThoughtData['proofElements'], experimentalElements: data.experimentalElements as ShannonThoughtData['experimentalElements'], implementationNotes: data.implementationNotes as ShannonThoughtData['implementationNotes'], isRevision: data.isRevision as boolean | undefined, revisesThought: data.revisesThought as number | undefined, }; } private formatThought(thoughtData: ShannonThoughtData): string { const { thoughtNumber, totalThoughts, thought, thoughtType, uncertainty, dependencies } = thoughtData; // Enhanced console output for debugging console.error(`Processing thought ${thoughtNumber}/${totalThoughts}`); console.error(`Type: ${thoughtType}`); console.error(`Dependencies: ${dependencies.join(', ') || 'none'}`); console.error(`Uncertainty: ${uncertainty}`); if (thoughtData.proofElements) { console.error('Proof elements present'); } if (thoughtData.implementationNotes) { console.error('Implementation notes present'); } const typeColors: Record<ThoughtType, (text: string) => string> = { [ThoughtType.PROBLEM_DEFINITION]: chalk.blue, [ThoughtType.CONSTRAINTS]: chalk.yellow, [ThoughtType.MODEL]: chalk.green, [ThoughtType.PROOF]: chalk.magenta, [ThoughtType.IMPLEMENTATION]: chalk.cyan }; const typeSymbols: Record<ThoughtType, string> = { [ThoughtType.PROBLEM_DEFINITION]: 'šŸ”', [ThoughtType.CONSTRAINTS]: 'šŸ”’', [ThoughtType.MODEL]: 'šŸ“', [ThoughtType.PROOF]: 'āœ“', [ThoughtType.IMPLEMENTATION]: 'āš™ļø' }; const prefix = typeColors[thoughtType](`${typeSymbols[thoughtType]} ${thoughtType.toUpperCase()}`); const confidenceDisplay = `[Confidence: ${(uncertainty * 100).toFixed(1)}%]`; const dependencyDisplay = dependencies.length > 0 ? `[Builds on thoughts: ${dependencies.join(', ')}]` : ''; const header = `${prefix} ${thoughtNumber}/${totalThoughts} ${confidenceDisplay} ${dependencyDisplay}`; const border = 'ā”€'.repeat(Math.max(header.length, thought.length) + 4); let output = ` ā”Œ${border}ā” ā”‚ ${header} ā”‚`; if (thoughtData.isRevision) { output += `\nā”œ${border}ā”¤\nā”‚ šŸ”„ Revising thought ${thoughtData.revisesThought} ā”‚`; } output += `\nā”œ${border}ā”¤\nā”‚ ${thought.padEnd(border.length - 2)} ā”‚`; if (thoughtData.assumptions && thoughtData.assumptions.length > 0) { output += `\nā”œ${border}ā”¤\nā”‚ Assumptions: ${thoughtData.assumptions.join(', ')} ā”‚`; } if (thoughtData.recheckStep) { output += `\nā”œ${border}ā”¤ ā”‚ Rechecking Step: ${thoughtData.recheckStep.stepToRecheck.padEnd(border.length - 17)} ā”‚ ā”‚ Reason: ${thoughtData.recheckStep.reason.padEnd(border.length - 9)} ā”‚`; if (thoughtData.recheckStep.newInformation) { output += `\nā”‚ New Information: ${thoughtData.recheckStep.newInformation.padEnd(border.length - 17)} ā”‚`; } } if (thoughtData.proofElements) { output += `\nā”œ${border}ā”¤ ā”‚ Proof Hypothesis: ${thoughtData.proofElements.hypothesis.padEnd(border.length - 18)} ā”‚ ā”‚ Validation: ${thoughtData.proofElements.validation.padEnd(border.length - 13)} ā”‚`; } if (thoughtData.experimentalElements) { output += `\nā”œ${border}ā”¤ ā”‚ Test Description: ${thoughtData.experimentalElements.testDescription.padEnd(border.length - 18)} ā”‚ ā”‚ Results: ${thoughtData.experimentalElements.results.padEnd(border.length - 10)} ā”‚ ā”‚ Test Confidence: ${(thoughtData.experimentalElements.confidence * 100).toFixed(1)}% ā”‚ ā”‚ Limitations: ${thoughtData.experimentalElements.limitations.join(', ').padEnd(border.length - 13)} ā”‚`; } if (thoughtData.implementationNotes) { output += `\nā”œ${border}ā”¤ ā”‚ Practical Constraints: ${thoughtData.implementationNotes.practicalConstraints.join(', ').padEnd(border.length - 23)} ā”‚ ā”‚ Proposed Solution: ${thoughtData.implementationNotes.proposedSolution.padEnd(border.length - 19)} ā”‚`; } output += `\nā””${border}ā”˜`; return output; } public processThought(input: unknown): { content: Array<{ type: string; text: string }>; isError?: boolean } { try { const validatedInput = this.validateThoughtData(input); if (validatedInput.thoughtNumber > validatedInput.totalThoughts) { validatedInput.totalThoughts = validatedInput.thoughtNumber; } // Validate dependencies and revisions for (const depNumber of validatedInput.dependencies) { if (depNumber >= validatedInput.thoughtNumber) { throw new Error(`Invalid dependency: cannot depend on future thought ${depNumber}`); } if (!this.thoughtHistory.some(t => t.thoughtNumber === depNumber)) { throw new Error(`Invalid dependency: thought ${depNumber} does not exist`); } } // Validate revision target if (validatedInput.isRevision && validatedInput.revisesThought !== undefined) { if (validatedInput.revisesThought >= validatedInput.thoughtNumber) { throw new Error(`Invalid revision: cannot revise future thought ${validatedInput.revisesThought}`); } if (!this.thoughtHistory.some(t => t.thoughtNumber === validatedInput.revisesThought)) { throw new Error(`Invalid revision: thought ${validatedInput.revisesThought} does not exist`); } } this.thoughtHistory.push(validatedInput); const formattedThought = this.formatThought(validatedInput); console.error(formattedThought); return { content: [{ type: "text", text: JSON.stringify({ thoughtNumber: validatedInput.thoughtNumber, totalThoughts: validatedInput.totalThoughts, nextThoughtNeeded: validatedInput.nextThoughtNeeded, thoughtType: validatedInput.thoughtType, uncertainty: validatedInput.uncertainty, thoughtHistoryLength: this.thoughtHistory.length, isRevision: validatedInput.isRevision, revisesThought: validatedInput.revisesThought, hasExperimentalValidation: !!validatedInput.experimentalElements, hasRecheckStep: !!validatedInput.recheckStep }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), details: { receivedInput: JSON.stringify(input, null, 2), thoughtHistoryLength: this.thoughtHistory.length, lastValidThought: this.thoughtHistory.length > 0 ? this.thoughtHistory[this.thoughtHistory.length - 1].thoughtNumber : null }, status: 'failed' }, null, 2) }], isError: true }; } } }