enhanced-thinking-mcp
Version:
Enhanced sequential thinking MCP server for advanced reasoning and problem-solving with Cursor AI
592 lines (584 loc) • 25.7 kB
JavaScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
import chalk from 'chalk';
import { env, exit } from 'process';
import { join } from 'path';
import { homedir } from 'os';
import { LLMEnhancer } from './llm-integration.js';
import { ThinkingDatabase } from './database.js';
class EnhancedThinkingServer {
thoughtHistory = [];
branches = {};
sessionStart;
disableThoughtLogging;
llmEnhancer;
database;
currentSessionId = null;
constructor() {
this.disableThoughtLogging = (env.DISABLE_THOUGHT_LOGGING || "").toLowerCase() === "true";
this.sessionStart = Date.now();
this.llmEnhancer = new LLMEnhancer();
// Use fixed path in user's home directory for central database
const centralDbPath = join(homedir(), '.enhanced-thinking-sessions.json');
const dashboardUrl = env.DASHBOARD_URL || 'https://enhanced-thinking-dashboard.vercel.app';
this.database = new ThinkingDatabase(centralDbPath, dashboardUrl);
if (!this.disableThoughtLogging) {
console.error(`💾 Central database: ${centralDbPath}`);
}
}
generateSessionId() {
return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
validateThoughtData(input) {
const data = input;
if (!data.thought || typeof data.thought !== 'string') {
throw new Error('Invalid thought: must be a string');
}
if (!data.thoughtNumber || typeof data.thoughtNumber !== 'number') {
throw new Error('Invalid thoughtNumber: must be a number');
}
if (!data.totalThoughts || typeof data.totalThoughts !== 'number') {
throw new Error('Invalid totalThoughts: must be a number');
}
if (typeof data.nextThoughtNeeded !== 'boolean') {
throw new Error('Invalid nextThoughtNeeded: must be a boolean');
}
return {
thought: data.thought,
thoughtNumber: data.thoughtNumber,
totalThoughts: data.totalThoughts,
nextThoughtNeeded: data.nextThoughtNeeded,
isRevision: data.isRevision,
revisesThought: data.revisesThought,
branchFromThought: data.branchFromThought,
branchId: data.branchId,
needsMoreThoughts: data.needsMoreThoughts,
confidence: data.confidence,
tags: data.tags,
timestamp: Date.now(),
};
}
calculateQualityScore(thought) {
// Enhanced quality scoring algorithm
let score = 0;
// Length and structure (20 points)
const wordCount = thought.split(/\s+/).length;
if (wordCount >= 10 && wordCount <= 100)
score += 20;
else if (wordCount >= 5)
score += 10;
// Question marks indicate exploratory thinking (15 points)
const questionCount = (thought.match(/\?/g) || []).length;
score += Math.min(questionCount * 5, 15);
// Keywords indicating analysis (25 points)
const analysisKeywords = ['because', 'therefore', 'however', 'although', 'consider', 'analyze', 'examine', 'evaluate'];
const keywordCount = analysisKeywords.filter(keyword => thought.toLowerCase().includes(keyword)).length;
score += Math.min(keywordCount * 5, 25);
// Structure indicators (20 points)
const structureIndicators = ['first', 'second', 'then', 'next', 'finally', 'step', 'phase'];
const structureCount = structureIndicators.filter(indicator => thought.toLowerCase().includes(indicator)).length;
score += Math.min(structureCount * 4, 20);
// Hypothesis/solution language (20 points)
const solutionKeywords = ['solution', 'approach', 'strategy', 'hypothesis', 'conclusion', 'answer'];
const solutionCount = solutionKeywords.filter(keyword => thought.toLowerCase().includes(keyword)).length;
score += Math.min(solutionCount * 4, 20);
return Math.min(score, 100);
}
generateProgressBar(current, total) {
const percentage = (current / total) * 100;
const filled = Math.round(percentage / 10);
const empty = 10 - filled;
const bar = '█'.repeat(filled) + '░'.repeat(empty);
return `${bar} ${percentage.toFixed(1)}%`;
}
async generateSummary() {
if (this.thoughtHistory.length === 0)
return "No thoughts processed yet.";
const analytics = this.calculateAnalytics();
const keyInsights = await this.extractKeyInsights();
return `
🧠 THINKING SESSION SUMMARY
${chalk.cyan('─'.repeat(50))}
📊 Analytics:
• Total Thoughts: ${analytics.totalThoughts}
• Average Quality: ${analytics.averageQuality.toFixed(1)}/100
• Branches Created: ${analytics.totalBranches}
• Session Duration: ${(analytics.sessionDuration / 1000 / 60).toFixed(1)} min
• Revisions Made: ${analytics.revisionCount}
• LLM Enhancements: ${analytics.llmEnhancementsUsed}
💡 Key Insights:
${keyInsights.map(insight => ` • ${insight}`).join('\n')}
🎯 Final Confidence: ${analytics.confidenceProgression[analytics.confidenceProgression.length - 1] || 'N/A'}%
${chalk.cyan('─'.repeat(50))}
`;
}
calculateAnalytics() {
const totalThoughts = this.thoughtHistory.length;
const averageQuality = totalThoughts > 0
? this.thoughtHistory.reduce((sum, t) => sum + (t.qualityScore || 0), 0) / totalThoughts
: 0;
const totalBranches = Object.keys(this.branches).length;
const sessionDuration = Date.now() - this.sessionStart;
const revisionCount = this.thoughtHistory.filter(t => t.isRevision).length;
const llmEnhancementsUsed = this.thoughtHistory.filter(t => t.enhancedThought).length;
const confidenceProgression = this.thoughtHistory
.filter(t => t.confidence !== undefined)
.map(t => t.confidence);
return {
totalThoughts,
averageQuality,
totalBranches,
sessionDuration,
revisionCount,
confidenceProgression,
llmEnhancementsUsed
};
}
async extractKeyInsights() {
const insights = [];
// Try LLM-powered insights first
if (this.llmEnhancer.isEnabled() && this.thoughtHistory.length > 2) {
try {
const llmInsights = await this.llmEnhancer.generateInsights(this.thoughtHistory.map(t => ({ thought: t.thought, qualityScore: t.qualityScore })));
if (llmInsights.length > 0) {
insights.push(...llmInsights);
}
}
catch (error) {
console.error("🤖 LLM: Failed to generate insights:", error);
}
}
// Fallback to traditional insights
if (insights.length === 0) {
// Find high-quality thoughts
const highQualityThoughts = this.thoughtHistory
.filter(t => (t.qualityScore || 0) >= 80)
.slice(-3);
highQualityThoughts.forEach((thought, index) => {
const preview = thought.thought.substring(0, 60) + (thought.thought.length > 60 ? '...' : '');
insights.push(`High-quality insight #${index + 1}: "${preview}"`);
});
// Identify solution patterns
const solutionThoughts = this.thoughtHistory.filter(t => t.thought.toLowerCase().includes('solution') ||
t.thought.toLowerCase().includes('conclusion') ||
t.thought.toLowerCase().includes('answer'));
if (solutionThoughts.length > 0) {
insights.push(`${solutionThoughts.length} solution-oriented thoughts identified`);
}
// Branch analysis
if (Object.keys(this.branches).length > 0) {
insights.push(`Explored ${Object.keys(this.branches).length} alternative reasoning paths`);
}
// LLM enhancement info
const enhancedCount = this.thoughtHistory.filter(t => t.enhancedThought).length;
if (enhancedCount > 0) {
insights.push(`${enhancedCount} thoughts enhanced by AI for improved clarity`);
}
}
return insights.length > 0 ? insights : ["Session completed with systematic thinking approach"];
}
formatThought(thoughtData) {
const { thoughtNumber, totalThoughts, thought, isRevision, revisesThought, branchFromThought, branchId, qualityScore, confidence, enhancedThought, llmImprovements } = thoughtData;
let prefix = '';
let context = '';
if (isRevision) {
prefix = chalk.yellow('🔄 Revision');
context = ` (revising thought ${revisesThought})`;
}
else if (branchFromThought) {
prefix = chalk.green('🌿 Branch');
context = ` (from thought ${branchFromThought}, ID: ${branchId})`;
}
else {
prefix = chalk.blue('💭 Thought');
context = '';
}
const progress = this.generateProgressBar(thoughtNumber, totalThoughts);
const quality = qualityScore ? chalk.magenta(`Q:${qualityScore}/100`) : '';
const conf = confidence ? chalk.cyan(`C:${confidence}%`) : '';
const aiEnhanced = enhancedThought ? chalk.green('🤖AI') : '';
const metrics = [quality, conf, aiEnhanced].filter(Boolean).join(' ');
const header = `${prefix} ${thoughtNumber}/${totalThoughts}${context} ${metrics}`;
const progressLine = `${chalk.gray('Progress:')} ${progress}`;
const displayThought = enhancedThought || thought;
const maxWidth = Math.max(header.length, displayThought.length, progressLine.length) + 4;
const border = '─'.repeat(maxWidth);
let output = `
┌${border}┐
│ ${header.padEnd(maxWidth - 2)} │
│ ${progressLine.padEnd(maxWidth - 2)} │
├${border}┤
│ ${displayThought.padEnd(maxWidth - 2)} │`;
if (llmImprovements && llmImprovements.length > 0) {
output += `\n├${border}┤`;
llmImprovements.forEach(improvement => {
output += `\n│ ${chalk.green('✨')} ${improvement.padEnd(maxWidth - 4)} │`;
});
}
output += `\n└${border}┘`;
return output;
}
async processThought(input) {
try {
const validatedInput = this.validateThoughtData(input);
if (validatedInput.thoughtNumber > validatedInput.totalThoughts) {
validatedInput.totalThoughts = validatedInput.thoughtNumber;
}
// Create new session if this is the first thought
if (validatedInput.thoughtNumber === 1 && !this.currentSessionId) {
this.currentSessionId = this.generateSessionId();
await this.database.createSession(this.currentSessionId);
console.error(`💾 New thinking session: ${this.currentSessionId}`);
}
// Calculate quality score
validatedInput.qualityScore = this.calculateQualityScore(validatedInput.thought);
// Try LLM enhancement if enabled
if (this.llmEnhancer.isEnabled()) {
try {
const enhancement = await this.llmEnhancer.enhanceThought({
thought: validatedInput.thought,
quality_score: validatedInput.qualityScore,
confidence: validatedInput.confidence,
previous_thoughts: this.thoughtHistory.slice(-3).map(t => t.thought)
});
if (enhancement) {
validatedInput.enhancedThought = enhancement.enhanced_thought;
validatedInput.llmImprovements = enhancement.reasoning_improvements;
// Boost confidence if LLM provided improvements
if (validatedInput.confidence && enhancement.confidence_boost > 0) {
validatedInput.confidence = Math.min(100, validatedInput.confidence + enhancement.confidence_boost);
}
}
}
catch (error) {
console.error("🤖 LLM: Enhancement failed, continuing with original thought");
}
}
this.thoughtHistory.push(validatedInput);
// Save thought to database
if (this.currentSessionId) {
await this.database.saveThought(this.currentSessionId, validatedInput);
}
if (validatedInput.branchFromThought && validatedInput.branchId) {
if (!this.branches[validatedInput.branchId]) {
this.branches[validatedInput.branchId] = [];
}
this.branches[validatedInput.branchId].push(validatedInput);
}
if (!this.disableThoughtLogging) {
const formattedThought = this.formatThought(validatedInput);
console.error(formattedThought);
// Show summary if this is the final thought
if (!validatedInput.nextThoughtNeeded) {
const summary = await this.generateSummary();
console.error(summary);
// Complete session in database
if (this.currentSessionId) {
const analytics = this.calculateAnalytics();
const insights = await this.extractKeyInsights();
await this.database.completeSession(this.currentSessionId, analytics, insights);
console.error(`💾 Session ${this.currentSessionId} completed and saved`);
}
}
}
const analytics = this.calculateAnalytics();
return {
content: [{
type: "text",
text: JSON.stringify({
thoughtNumber: validatedInput.thoughtNumber,
totalThoughts: validatedInput.totalThoughts,
nextThoughtNeeded: validatedInput.nextThoughtNeeded,
qualityScore: validatedInput.qualityScore,
confidence: validatedInput.confidence,
enhancedThought: validatedInput.enhancedThought,
llmImprovements: validatedInput.llmImprovements,
branches: Object.keys(this.branches),
thoughtHistoryLength: this.thoughtHistory.length,
analytics: analytics,
isComplete: !validatedInput.nextThoughtNeeded,
sessionId: this.currentSessionId,
summary: !validatedInput.nextThoughtNeeded ? await this.generateSummary() : undefined
}, null, 2)
}]
};
}
catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
error: error instanceof Error ? error.message : String(error),
status: 'failed'
}, null, 2)
}],
isError: true
};
}
}
resetSession() {
this.thoughtHistory = [];
this.branches = {};
this.sessionStart = Date.now();
this.currentSessionId = null;
return {
content: [{
type: "text",
text: JSON.stringify({
message: "Thinking session reset successfully",
status: "reset",
timestamp: new Date().toISOString(),
llmEnabled: this.llmEnhancer.isEnabled()
}, null, 2)
}]
};
}
async getAnalytics() {
const analytics = this.calculateAnalytics();
const insights = await this.extractKeyInsights();
return {
content: [{
type: "text",
text: JSON.stringify({
analytics,
insights,
llmEnabled: this.llmEnhancer.isEnabled(),
currentSessionId: this.currentSessionId,
thoughtHistory: this.thoughtHistory.map(t => ({
number: t.thoughtNumber,
quality: t.qualityScore,
confidence: t.confidence,
isRevision: t.isRevision,
timestamp: t.timestamp,
enhanced: !!t.enhancedThought
}))
}, null, 2)
}]
};
}
}
const ENHANCED_THINKING_TOOL = {
name: "enhancedthinking",
description: `🧠 Enhanced Sequential Thinking Tool - Advanced reasoning and problem-solving with quality analytics
This enhanced version provides structured, step-by-step thinking with:
✨ Real-time quality scoring of thoughts
📊 Progress tracking with visual indicators
🎯 Confidence level monitoring
🌿 Advanced branch management
📈 Session analytics and insights
📝 Automatic summarization
🤖 LLM-powered thought enhancement (when API keys provided)
Perfect for:
• Complex problem decomposition
• Strategic planning and analysis
• Research and investigation
• Creative brainstorming with structure
• Decision-making processes
• Learning and knowledge synthesis
Enhanced Features:
- Quality scoring algorithm evaluates thought depth and structure
- Visual progress bars show completion status
- Confidence tracking shows certainty progression
- Branch visualization for alternative reasoning paths
- Session analytics with key insights extraction
- Auto-generated summaries of thinking sessions
- Optional AI enhancement with OpenAI integration
Parameters:
- thought: Your current thinking step (analyzed for quality)
- nextThoughtNeeded: Whether more thinking is required
- thoughtNumber: Current step number (progress tracking)
- totalThoughts: Estimated total (dynamically adjustable)
- confidence: Your certainty level 0-100% (optional)
- tags: Keywords for categorization (optional)
- isRevision: Mark as revision of previous thought
- revisesThought: Which thought number to revise
- branchFromThought: Create alternative reasoning branch
- branchId: Identifier for reasoning branch
Usage Tips:
1. Start with initial thought estimate, adjust as needed
2. Use confidence levels to track certainty progression
3. Branch when exploring alternatives
4. Revise when new insights emerge
5. Set nextThoughtNeeded=false when satisfied with solution
6. Set OPENAI_API_KEY environment variable for AI enhancements`,
inputSchema: {
type: "object",
properties: {
thought: {
type: "string",
description: "Your current thinking step (will be analyzed for quality and structure)"
},
nextThoughtNeeded: {
type: "boolean",
description: "Whether another thought step is needed"
},
thoughtNumber: {
type: "integer",
description: "Current thought number (for progress tracking)",
minimum: 1
},
totalThoughts: {
type: "integer",
description: "Estimated total thoughts needed (adjustable)",
minimum: 1
},
confidence: {
type: "integer",
description: "Your confidence level in this thought (0-100%)",
minimum: 0,
maximum: 100
},
tags: {
type: "array",
items: {
type: "string"
},
description: "Keywords or categories for this thought"
},
isRevision: {
type: "boolean",
description: "Whether this revises previous thinking"
},
revisesThought: {
type: "integer",
description: "Which thought number is being revised",
minimum: 1
},
branchFromThought: {
type: "integer",
description: "Create branch from this thought number",
minimum: 1
},
branchId: {
type: "string",
description: "Identifier for this reasoning branch"
},
needsMoreThoughts: {
type: "boolean",
description: "Flag if more thoughts are needed beyond estimate"
}
},
required: ["thought", "nextThoughtNeeded", "thoughtNumber", "totalThoughts"]
}
};
// Backward compatibility tool - original sequential thinking interface
const SEQUENTIAL_THINKING_TOOL = {
name: "sequentialthinking",
description: `Original Sequential Thinking tool for backward compatibility.
This provides the same interface as @modelcontextprotocol/server-sequential-thinking
but with enhanced quality scoring and analytics under the hood.
Use 'enhancedthinking' tool for full feature access including confidence tracking,
quality scoring, and advanced analytics.`,
inputSchema: {
type: "object",
properties: {
thought: {
type: "string",
description: "Your current thinking step"
},
nextThoughtNeeded: {
type: "boolean",
description: "Whether another thought step is needed"
},
thoughtNumber: {
type: "integer",
description: "Current thought number",
minimum: 1
},
totalThoughts: {
type: "integer",
description: "Estimated total thoughts needed",
minimum: 1
},
isRevision: {
type: "boolean",
description: "Whether this revises previous thinking"
},
revisesThought: {
type: "integer",
description: "Which thought is being reconsidered",
minimum: 1
},
branchFromThought: {
type: "integer",
description: "Branching point thought number",
minimum: 1
},
branchId: {
type: "string",
description: "Branch identifier"
},
needsMoreThoughts: {
type: "boolean",
description: "If more thoughts are needed"
}
},
required: ["thought", "nextThoughtNeeded", "thoughtNumber", "totalThoughts"]
}
};
const SESSION_TOOLS = [
{
name: "reset_thinking_session",
description: "Reset the current thinking session, clearing all thoughts and starting fresh",
inputSchema: {
type: "object",
properties: {},
required: []
}
},
{
name: "get_thinking_analytics",
description: "Get detailed analytics about the current thinking session including quality metrics, insights, and progress",
inputSchema: {
type: "object",
properties: {},
required: []
}
}
];
const server = new Server({
name: "enhanced-thinking-server",
version: "1.0.0",
}, {
capabilities: {
tools: {},
},
});
const thinkingServer = new EnhancedThinkingServer();
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [ENHANCED_THINKING_TOOL, SEQUENTIAL_THINKING_TOOL, ...SESSION_TOOLS],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case "enhancedthinking":
return await thinkingServer.processThought(request.params.arguments);
case "sequentialthinking":
return await thinkingServer.processThought(request.params.arguments);
case "reset_thinking_session":
return thinkingServer.resetSession();
case "get_thinking_analytics":
return await thinkingServer.getAnalytics();
default:
return {
content: [{
type: "text",
text: `Unknown tool: ${request.params.name}`
}],
isError: true
};
}
});
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("🧠 Enhanced Thinking MCP Server v1.0.0 running on stdio");
console.error("✨ Features: Quality scoring, Progress tracking, Analytics, Summarization");
console.error("🤖 LLM Integration: " + (new LLMEnhancer().isEnabled() ? "ENABLED (OpenAI)" : "Disabled (set OPENAI_API_KEY to enable)"));
}
runServer().catch((error) => {
console.error("Fatal error running server:", error);
exit(1);
});
//# sourceMappingURL=index.js.map