UNPKG

@emmahyde/thinking-patterns

Version:

MCP server combining systematic thinking, mental models, debugging approaches, and stochastic algorithms for comprehensive cognitive pattern support

148 lines (147 loc) 5.95 kB
import { BaseToolServer } from '../base/BaseToolServer.js'; import { ScientificMethodSchema } from '../schemas/index.js'; import { boxed } from '../utils/index.js'; /** * Scientific Method Server using thinking-patterns tools approach * Extends BaseToolServer for standardized validation and error handling */ export class ScientificMethodServer extends BaseToolServer { constructor() { super(ScientificMethodSchema); } handle(validInput) { return this.process(validInput); } /** * Standardized process method for scientific method * @param validInput - Validated scientific method data * @returns Processed scientific method result */ process(validInput) { // Format output using boxed utility const formattedOutput = this.formatScientificOutput(validInput); // Log formatted output to console (suppress during tests) if (process.env.NODE_ENV !== 'test' && process.env.JEST_WORKER_ID === undefined) { console.error(formattedOutput); } return { inquiryId: validInput.inquiryId, stage: validInput.stage, iteration: validInput.iteration, nextStageNeeded: validInput.nextStageNeeded, observation: validInput.observation, question: validInput.question, hypothesis: validInput.hypothesis, experiment: validInput.experiment, analysis: validInput.analysis, conclusion: validInput.conclusion, status: 'success', hasObservation: !!validInput.observation, hasQuestion: !!validInput.question, hasHypothesis: !!validInput.hypothesis, hasExperiment: !!validInput.experiment, hasAnalysis: !!validInput.analysis, hasConclusion: !!validInput.conclusion, timestamp: new Date().toISOString(), }; } // Backward compatibility method for tests processScientificMethod(input) { try { const validatedInput = this.validate(input); const result = this.handle(validatedInput); const response = this.run(input); return { ...response, data: validatedInput // Add the validated input data for test compatibility }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), status: 'failed' }, null, 2) }], isError: true }; } } formatScientificOutput(data) { const sections = { 'Inquiry ID': data.inquiryId, 'Stage': data.stage.toUpperCase(), 'Iteration': data.iteration.toString() }; // Observation if (data.observation) { sections['Observation'] = data.observation; } // Question if (data.question) { sections['Research Question'] = data.question; } // Hypothesis if (data.hypothesis) { const h = data.hypothesis; sections['Hypothesis'] = [ `Statement: ${h.statement}`, `Domain: ${h.domain}`, `Status: ${h.status.toUpperCase()}`, `Confidence: ${(h.confidence * 100).toFixed(1)}%`, `ID: ${h.hypothesisId}` ]; if (h.variables.length > 0) { sections['Variables'] = h.variables.map(variable => `• ${variable.name} (${variable.type})${variable.operationalization ? ': ' + variable.operationalization : ''}`); } if (h.assumptions.length > 0) { sections['Assumptions'] = h.assumptions.map(assumption => `• ${assumption}`); } if (h.alternativeTo && h.alternativeTo.length > 0) { sections['Alternative To'] = h.alternativeTo.map(alt => `• ${alt}`); } } // Experiment if (data.experiment) { const e = data.experiment; sections['Experiment'] = [ `Design: ${e.design}`, `Methodology: ${e.methodology}`, `ID: ${e.experimentId}`, `Hypothesis ID: ${e.hypothesisId}` ]; if (e.predictions.length > 0) { sections['Predictions'] = e.predictions.map(pred => `• If ${pred.if}, then ${pred.then}${pred.else ? `, else ${pred.else}` : ''}`); } if (e.controlMeasures.length > 0) { sections['Control Measures'] = e.controlMeasures.map(measure => `• ${measure}`); } if (e.results) { sections['Results'] = e.results; } if (e.outcomeMatched !== undefined) { sections['Outcome Matched Prediction'] = e.outcomeMatched ? 'YES' : 'NO'; } if (e.unexpectedObservations && e.unexpectedObservations.length > 0) { sections['Unexpected Observations'] = e.unexpectedObservations.map(obs => `• ${obs}`); } if (e.limitations && e.limitations.length > 0) { sections['Limitations'] = e.limitations.map(limitation => `• ${limitation}`); } if (e.nextSteps && e.nextSteps.length > 0) { sections['Next Steps'] = e.nextSteps.map(step => `• ${step}`); } } // Analysis if (data.analysis) { sections['Analysis'] = data.analysis; } // Conclusion if (data.conclusion) { sections['Conclusion'] = data.conclusion; } return boxed('🔬 Scientific Method', sections); } }