Skip to main content
Glama

think_done

Complete structured reasoning sessions by verifying logic, identifying gaps, and exporting reports before finalizing complex problem solutions.

Instructions

Finish thinking session: verify logic and optionally export.

MANDATORY before final answer on complex problems.

Checks:

  • Low confidence thoughts in path

  • Unaddressed blockers

  • Ignored thoughts ratio

Options:

  • exportReport: Get markdown/json report (replaces export_session)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
winningPathYesThought numbers leading to solution
summaryYesFinal logic summary
verdictYesReady for answer?
constraintCheckNoHow constraints were addressed
potentialFlawsNoWhat could go wrong
exportReportNoExport format (optional)
includeMermaidNoInclude diagram in export

Implementation Reference

  • MCP tool handler for 'think_done': processes input args, calls thinkingService.consolidate for path verification and issue detection, formats output with status/READY or BLOCKED, progress metrics, warnings; optionally appends exported session report.
    server.registerTool('think_done', { title: 'Think Done', description: THINK_DONE_DESCRIPTION, inputSchema: thinkDoneSchema }, async (args) => { try { const result = thinkingService.consolidate({ winningPath: args.winningPath as number[], summary: args.summary as string, constraintCheck: args.constraintCheck as string | undefined, potentialFlaws: args.potentialFlaws as string | undefined, verdict: args.verdict as 'ready' | 'needs_more_work', }); if (result.status === 'error') { return { content: [{ type: 'text' as const, text: `Error: ${result.errorMessage}` }], isError: true }; } const pa = result.pathAnalysis; const issues = [ pa.lowConfidenceInPath.length > 0 ? `lowConf:#${pa.lowConfidenceInPath.join(',')}` : '', pa.unaddressedBlockers.length > 0 ? `blockers:#${pa.unaddressedBlockers.join(',')}` : '', ].filter(Boolean).join(' | '); let text = [ result.canProceedToFinalAnswer ? 'βœ… READY' : 'πŸ›‘ BLOCKED', `πŸ“Š Path: ${pa.pathLength}/${pa.totalThoughts} (${Math.round(pa.ignoredRatio * 100)}% ignored)`, issues ? `⚠️ ${issues}` : '', '', '--- STATUS ---', `verdict: ${result.canProceedToFinalAnswer ? 'READY' : 'BLOCKED'}`, ].filter(Boolean).join('\n'); // Export if requested (merged from export_session) if (args.exportReport) { const report = thinkingService.exportSession({ format: args.exportReport as 'markdown' | 'json', includeMermaid: (args.includeMermaid as boolean) ?? true, }); text += '\n\n--- EXPORT ---\n' + report; } return { content: [{ type: 'text' as const, text }] }; } catch (error) { return { content: [{ type: 'text' as const, text: `Error: ${error instanceof Error ? error.message : 'Unknown'}` }], isError: true }; } }
  • Zod input schema for 'think_done' tool, defining required winningPath, summary, verdict and optional fields for checks and export.
    const thinkDoneSchema = { winningPath: z.array(z.number().int().min(1)).describe('Thought numbers leading to solution'), summary: z.string().describe('Final logic summary'), verdict: z.enum(['ready', 'needs_more_work']).describe('Ready for answer?'), constraintCheck: z.string().optional().describe('How constraints were addressed'), potentialFlaws: z.string().optional().describe('What could go wrong'), exportReport: z.enum(['markdown', 'json']).optional().describe('Export format (optional)'), includeMermaid: z.boolean().optional().describe('Include diagram in export'), };
  • src/index.ts:232-232 (registration)
    Registration of 'think_done' tool with McpServer, including title, description, and inputSchema.
    server.registerTool('think_done', { title: 'Think Done', description: THINK_DONE_DESCRIPTION, inputSchema: thinkDoneSchema },
  • ConsolidateService.consolidate(): Primary helper implementing think_done logic - validates winning path connectivity, detects low-confidence thoughts in path, unaddressed blockers/critical extensions, high ignored ratio, path discontinuities; computes canProceedToFinalAnswer and pathAnalysis.
    consolidate( input: ConsolidateInput, sessionThoughts: ThoughtRecord[], onDeadEnd?: (path: number[], reason: string) => void, onSuccess?: (path: number[], summary: string) => void ): ConsolidateResult { const { winningPath, verdict } = input; const warnings: string[] = []; // Validate: must have thoughts to consolidate if (sessionThoughts.length === 0) { return { status: 'error', evaluation: 'Cannot consolidate empty thought history.', warnings: [], canProceedToFinalAnswer: false, pathAnalysis: { totalThoughts: 0, pathLength: 0, ignoredRatio: 0, lowConfidenceInPath: [], unaddressedBlockers: [], unaddressedCritical: [], }, errorMessage: 'No thoughts recorded. Use sequentialthinking first.', }; } // Validate: winning path must reference existing thoughts in current session const existingNumbers = new Set(sessionThoughts.map((t) => t.thoughtNumber)); const invalidRefs = winningPath.filter((n) => !existingNumbers.has(n)); if (invalidRefs.length > 0) { return { status: 'error', evaluation: `Invalid thought references in winning path: ${invalidRefs.join(', ')}`, warnings: [], canProceedToFinalAnswer: false, pathAnalysis: { totalThoughts: sessionThoughts.length, pathLength: winningPath.length, ignoredRatio: 0, lowConfidenceInPath: [], unaddressedBlockers: [], unaddressedCritical: [], }, errorMessage: `Thoughts ${invalidRefs.join(', ')} do not exist in current session.`, }; } // Validate: path connectivity - thoughts must be logically connected const connectivityCheck = this.validationService.validatePathConnectivity( winningPath, sessionThoughts ); if (!connectivityCheck.valid) { warnings.push(`🚫 PATH DISCONTINUITY: ${connectivityCheck.error}`); } // Find low-confidence thoughts in winning path const lowConfidenceInPath = sessionThoughts .filter((t) => winningPath.includes(t.thoughtNumber)) .filter((t) => t.confidence !== undefined && t.confidence < 5) .map((t) => t.thoughtNumber); if (lowConfidenceInPath.length > 0) { warnings.push( `⚠️ LOW CONFIDENCE: Your winning path includes thoughts with confidence < 5: #${lowConfidenceInPath.join(', ')}. Are you sure about these steps?` ); } // Check ignored thoughts ratio const ignoredRatio = 1 - winningPath.length / sessionThoughts.length; if (ignoredRatio > 0.6) { warnings.push( `⚠️ HIGH DISCARD RATE: You are ignoring ${Math.round(ignoredRatio * 100)}% of your thoughts. Ensure you haven't missed important contradictions in discarded branches.` ); } // Find unaddressed BLOCKER and HIGH impact critique extensions const unaddressedBlockers: number[] = []; const unaddressedCritical: number[] = []; for (const thought of sessionThoughts) { if (thought.extensions) { const hasBlocker = thought.extensions.some((e) => e.impact === 'blocker'); const hasHighCritique = thought.extensions.some( (e) => e.impact === 'high' && e.type === 'critique' ); if (winningPath.includes(thought.thoughtNumber)) { const hasRevision = sessionThoughts.some( (t) => t.isRevision && t.revisesThought === thought.thoughtNumber ); if (hasBlocker && !hasRevision) { unaddressedBlockers.push(thought.thoughtNumber); } if (hasHighCritique && !hasRevision) { unaddressedCritical.push(thought.thoughtNumber); } } } } if (unaddressedBlockers.length > 0) { warnings.push( `🚫 UNADDRESSED BLOCKERS: Thoughts #${unaddressedBlockers.join(', ')} have BLOCKER extensions but no revisions. You MUST address these before proceeding.` ); } if (unaddressedCritical.length > 0) { warnings.push( `⚠️ UNADDRESSED CRITICAL: Thoughts #${unaddressedCritical.join(', ')} have HIGH impact critiques but no revisions. Address these issues with isRevision: true.` ); } // Check for missing revisions in winningPath const missingRevisions: number[] = []; for (const thought of sessionThoughts) { if (!winningPath.includes(thought.thoughtNumber)) continue; if (!thought.extensions) continue; const hasCritical = thought.extensions.some( (e) => (e.impact === 'high' || e.impact === 'blocker') && e.type === 'critique' ); if (!hasCritical) continue; const revision = sessionThoughts.find( (t) => t.isRevision && t.revisesThought === thought.thoughtNumber ); if (revision && !winningPath.includes(revision.thoughtNumber)) { missingRevisions.push(thought.thoughtNumber); } } if (missingRevisions.length > 0) { warnings.push( `🚫 MISSING REVISIONS IN PATH: Thoughts #${missingRevisions.join(', ')} have critical critiques with revisions, but those revisions are NOT in your winningPath. Include the revision thoughts or remove the flawed originals.` ); } // Check for empty or too short winning path if (winningPath.length === 0) { warnings.push('⚠️ EMPTY PATH: No thoughts selected in winning path. This seems wrong.'); } else if (winningPath.length < 2 && sessionThoughts.length > 3) { warnings.push( '⚠️ SUSPICIOUSLY SHORT PATH: Only 1 thought selected from a longer chain. Did you skip important reasoning?' ); } // Determine if can proceed const hasBlockerWarnings = unaddressedBlockers.length > 0; const hasCriticalWarnings = unaddressedCritical.length > 0; const hasMissingRevisions = missingRevisions.length > 0; const hasPathDiscontinuity = !connectivityCheck.valid; const canProceed = verdict === 'ready' && !hasBlockerWarnings && !hasCriticalWarnings && !hasMissingRevisions && !hasPathDiscontinuity && warnings.length <= 1; // Generate evaluation message let evaluation: string; if (canProceed) { evaluation = 'βœ… SYNTHESIS ACCEPTED: Your reasoning chain is coherent. You may proceed to final answer.'; // v4.1.0: Save insight via callback on successful consolidation if (onSuccess) { onSuccess(winningPath, input.summary); } } else if (verdict === 'needs_more_work') { evaluation = 'πŸ”„ ACKNOWLEDGED: You identified this needs more work. Continue with sequentialthinking or extend_thought.'; // Record dead end via callback if (onDeadEnd) { onDeadEnd(winningPath, input.summary); } } else { evaluation = `⚠️ SYNTHESIS REJECTED: ${warnings.length} issue(s) found. Address them before providing final answer.`; } // Log consolidation console.error( `🎯 Consolidation: verdict=${verdict}, path=[${winningPath.join(',')}], warnings=${warnings.length}, canProceed=${canProceed}` ); return { status: 'success', evaluation, warnings, canProceedToFinalAnswer: canProceed, pathAnalysis: { totalThoughts: sessionThoughts.length, pathLength: winningPath.length, ignoredRatio: Math.round(ignoredRatio * 100) / 100, lowConfidenceInPath, unaddressedBlockers, unaddressedCritical, disconnectedAt: connectivityCheck.disconnectedAt ? [connectivityCheck.disconnectedAt] : undefined, }, }; }
  • ExportService.export(): Generates Markdown or JSON session reports including thoughts, extensions, branches, dead ends, Mermaid diagram; invoked optionally in think_done handler.
    export(data: ExportSessionData, options: ExportOptions = {}): string { const { format = 'markdown', includeMermaid = true } = options; const { thoughts, branches, deadEnds, sessionGoal, averageConfidence, mermaidDiagram } = data; if (thoughts.length === 0) { return format === 'json' ? JSON.stringify({ error: 'No thoughts recorded in current session' }) : '# Think Session Report\n\n*No thoughts recorded in current session.*'; } if (format === 'json') { return JSON.stringify( { goal: sessionGoal, thoughts, branches: Array.from(branches.entries()), deadEnds, averageConfidence, exportedAt: new Date().toISOString(), }, null, 2 ); } // Markdown format return this.generateMarkdown(data, includeMermaid); }

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/GofMan5/think-mcp'

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