Skip to main content
Glama

think

Break down complex problems into manageable steps with structured reasoning, enabling planning with revisions, analysis with course correction, and confidence tracking for multi-step challenges.

Instructions

Add a thought to the reasoning chain.

Use for:

  • Complex multi-step problems

  • Planning with room for revision

  • Analysis that might need course correction

Features:

  • subSteps: Micro-action plan (max 5)

  • alternatives: Quick options comparison

  • quickExtension: Inline critique/elaboration (replaces extend_thought tool)

Returns progress bar, confidence, and next action hint.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
thoughtYesYour thinking step
nextThoughtNeededYesMore thinking needed?
thoughtNumberYesCurrent number
totalThoughtsYesEstimated total
confidenceNoConfidence 1-10
subStepsNoMicro-actions (max 5)
alternativesNoOptions to compare
goalNoSession goal (set on first thought)
quickExtensionNoInline extension (replaces extend_thought)
isRevisionNoRevising previous thought?
revisesThoughtNoWhich thought to revise
branchFromThoughtNoBranch point
branchIdNoBranch identifier
showTreeNoShow ASCII tree

Implementation Reference

  • The core handler function processThought in ThinkingService that executes the logic for the 'think' tool. Handles validation, branching, stagnation detection, coaching nudges, quick extensions, dead-end warnings, and returns progress information.
    processThought(input: ThoughtInput): ThinkingResult {
      // Smart auto-reset: if thoughtNumber=1 and history not empty, start fresh session
      // SYNCHRONOUS reset to avoid race conditions
      if (input.thoughtNumber === 1 && this.thoughtHistory.length > 0 && !input.isRevision) {
        console.error('πŸ”„ New session detected (thought #1), clearing previous state...');
        this.reset(); // Synchronous clear
        // Clear persistence file asynchronously (non-blocking)
        this.clearSession().catch((err) => console.error('Failed to clear session:', err));
      }
    
      // Generate new sessionId for first thought of session (v2.11.0)
      if (input.thoughtNumber === 1 && !input.isRevision) {
        this.currentSessionId = new Date().toISOString();
        console.error(`πŸ†” New session ID: ${this.currentSessionId}`);
      }
    
      // Auto-adjust totalThoughts if exceeded
      if (input.thoughtNumber > input.totalThoughts) {
        input.totalThoughts = input.thoughtNumber;
      }
    
      // EMPTY THOUGHT VALIDATION - reject meaningless input
      if (!input.thought || !input.thought.trim()) {
        return {
          thoughtNumber: input.thoughtNumber,
          totalThoughts: input.totalThoughts,
          nextThoughtNeeded: true,
          branches: Array.from(this.branches.keys()),
          thoughtHistoryLength: this.thoughtHistory.length,
          contextSummary: this.generateContextSummary(),
          thoughtTree: this.generateAsciiTree(),
          isError: true,
          errorMessage: '🚫 REJECTED: Empty thought. Provide meaningful content.',
          warning: '🚫 REJECTED: Empty thought. Provide meaningful content.',
        };
      }
    
      // SESSION GOAL (v2.10.0) - Save goal from first thought
      if (input.goal && input.thoughtNumber === 1) {
        this.sessionGoal = input.goal;
        console.error(`🎯 Session goal set: ${input.goal.substring(0, 50)}...`);
      }
    
      // HARD DUPLICATE REJECTION - reject before adding to history
      const duplicateError = this.checkDuplicateStrict(input);
      if (duplicateError) {
        return {
          thoughtNumber: input.thoughtNumber,
          totalThoughts: input.totalThoughts,
          nextThoughtNeeded: true,
          branches: Array.from(this.branches.keys()),
          thoughtHistoryLength: this.thoughtHistory.length,
          contextSummary: this.generateContextSummary(),
          thoughtTree: this.generateAsciiTree(),
          isError: true,
          errorMessage: duplicateError,
          warning: duplicateError,
        };
      }
    
      // BRANCH VALIDATION - reject if branchFromThought references non-existent thought
      const branchError = this.validateBranchSource(input);
      if (branchError) {
        return {
          thoughtNumber: input.thoughtNumber,
          totalThoughts: input.totalThoughts,
          nextThoughtNeeded: true,
          branches: Array.from(this.branches.keys()),
          thoughtHistoryLength: this.thoughtHistory.length,
          contextSummary: this.generateContextSummary(),
          thoughtTree: this.generateAsciiTree(),
          isError: true,
          errorMessage: branchError,
          warning: branchError,
        };
      }
    
      // Validate sequence (includes shallow/circular revision check)
      const validation = this.validateSequence(input);
      
      // HARD REJECTION for invalid revisions (shallow, circular, non-existent target)
      if (!validation.valid && input.isRevision) {
        return {
          thoughtNumber: input.thoughtNumber,
          totalThoughts: input.totalThoughts,
          nextThoughtNeeded: true,
          branches: Array.from(this.branches.keys()),
          thoughtHistoryLength: this.thoughtHistory.length,
          contextSummary: this.generateContextSummary(),
          thoughtTree: this.generateAsciiTree(),
          isError: true,
          errorMessage: validation.warning,
          warning: validation.warning,
        };
      }
    
      // Check for stagnation before adding new thought
      const stagnationWarning = this.detectStagnation(input.thought);
    
      // Create record with timestamp and sessionId (v2.11.0)
      const record: ThoughtRecord = {
        ...input,
        timestamp: Date.now(),
        sessionId: this.currentSessionId,
      };
    
      this.thoughtHistory.push(record);
      this.lastThoughtNumber = input.thoughtNumber;
    
      // Invalidate Fuse index for recall_thought (v3.4.0)
      this.invalidateFuseIndex();
    
      // Handle branching
      if (input.branchFromThought && input.branchId) {
        const branchHistory = this.branches.get(input.branchId) ?? [];
        branchHistory.push(record);
        this.branches.set(input.branchId, branchHistory);
      }
    
      // Log to stderr for debugging
      const prefix = input.isRevision
        ? 'πŸ”„ Revision'
        : input.branchFromThought
          ? '🌿 Branch'
          : 'πŸ’­ Thought';
      const confidenceStr = input.confidence ? ` [conf: ${input.confidence}/10]` : '';
      console.error(
        `${prefix} ${input.thoughtNumber}/${input.totalThoughts}${confidenceStr}: ${input.thought.substring(0, 80)}...`
      );
    
      // Save session asynchronously (fire and forget)
      this.saveSession().catch((err) => console.error('Failed to save session:', err));
    
      // Combine warnings
      const warning = [validation.warning, stagnationWarning].filter(Boolean).join('\n');
    
      // QUICK EXTENSION (v3.1.0) - Process inline extension if provided
      if (input.quickExtension) {
        this.processQuickExtension(input.thoughtNumber, input.quickExtension);
      }
    
      // LATERAL THINKING TRIGGER - check for overly linear thinking
      // v5.0.1: Pass isFinishing flag to show subSteps check only at end
      let systemAdvice = this.checkLateralThinking(!input.nextThoughtNeeded);
    
      // DEAD ENDS CHECK (v3.3.0) - Warn if heading towards rejected path
      const deadEndWarning = this.checkDeadEnds(input.thoughtNumber);
      if (deadEndWarning) {
        systemAdvice = systemAdvice ? `${systemAdvice}\n${deadEndWarning}` : deadEndWarning;
      }
    
      // PROACTIVE COACH v3.1.0 - Enhanced nudges for thought quality
      const coachNudges = this.generateProactiveNudges(input);
      if (coachNudges) {
        systemAdvice = systemAdvice ? `${systemAdvice}\n${coachNudges}` : coachNudges;
      }
    
      // PRE-CONSOLIDATION AUDIT (v2.9.2) - Quality gate before finishing
      if (!input.nextThoughtNeeded) {
        const auditAdvice = this.performPreConsolidationAudit();
        if (auditAdvice) {
          systemAdvice = systemAdvice ? `${systemAdvice}\n${auditAdvice}` : auditAdvice;
        }
      }
    
      // v4.6.0: Generate nudge only if no other warnings/advice (avoid noise)
      const shouldSkipNudge = !!(warning || systemAdvice);
      const nudge = this.nudgeService.generateNudge(input, this.getCurrentSessionThoughts(), shouldSkipNudge);
    
      return {
        thoughtNumber: input.thoughtNumber,
        totalThoughts: input.totalThoughts,
        nextThoughtNeeded: input.nextThoughtNeeded,
        branches: Array.from(this.branches.keys()),
        thoughtHistoryLength: this.thoughtHistory.length,
        contextSummary: this.generateContextSummary(),
        thoughtTree: this.generateAsciiTree(),
        // v4.2.0: Lazy Mermaid - removed from hot path, use export_session for diagrams
        thoughtTreeMermaid: undefined,
        warning: warning || undefined,
        averageConfidence: this.calculateAverageConfidence(),
        systemAdvice,
        sessionGoal: this.sessionGoal,
        nudge,
      };
    }
  • src/index.ts:68-127 (registration)
    Registration of the 'think' tool using McpServer.registerTool, including title, description, inputSchema, and the handler callback.
    server.registerTool('think', { title: 'Think', description: THINK_DESCRIPTION, inputSchema: thinkSchema },
      async (args) => {
        try {
          const result = thinkingService.processThought({
            thought: args.thought as string,
            nextThoughtNeeded: args.nextThoughtNeeded as boolean,
            thoughtNumber: args.thoughtNumber as number,
            totalThoughts: args.totalThoughts as number,
            isRevision: args.isRevision as boolean | undefined,
            revisesThought: args.revisesThought as number | undefined,
            branchFromThought: args.branchFromThought as number | undefined,
            branchId: args.branchId as string | undefined,
            confidence: args.confidence as number | undefined,
            subSteps: args.subSteps as string[] | undefined,
            alternatives: args.alternatives as string[] | undefined,
            goal: args.goal as string | undefined,
            quickExtension: args.quickExtension as QuickExtension | undefined,
          });
    
          if (result.isError) {
            return { content: [{ type: 'text' as const, text: `Error: ${result.errorMessage}` }], isError: true };
          }
    
          // Progress bar
          const current = result.thoughtNumber;
          const total = result.totalThoughts;
          const filled = Math.round((current / total) * 10);
          const progressBar = 'β–ˆ'.repeat(filled) + 'β–‘'.repeat(10 - filled);
    
          // Status detection
          const hasBlocker = result.warning?.includes('BLOCKER') || result.warning?.includes('STAGNATION');
          const status = hasBlocker ? 'BLOCKED' : result.warning ? 'WARNING' : 'OK';
          const nearEnd = current >= total - 1;
          const nextAction = hasBlocker ? 'revise' : nearEnd ? 'think_done' : 'continue';
    
          // Conditional tree - ONLY when explicitly requested
          const showTree = args.showTree === true;
    
          // v5.0.1: Show systemAdvice ONLY when there are real issues
          const conf = result.averageConfidence ?? 10;
          const hasRealIssue = status !== 'OK' || conf < 7;
          const showAdvice = hasRealIssue && result.systemAdvice;
    
          const text = [
            result.sessionGoal ? `🎯 ${result.sessionGoal}\n` : '',
            `[${progressBar}] ${current}/${total}`,
            result.averageConfidence ? ` | conf: ${result.averageConfidence}/10` : '',
            result.warning ? `\n⚠️ ${result.warning}` : '',
            showTree ? `\n\n${result.thoughtTree}` : '',
            showAdvice ? `\n${result.systemAdvice}` : '',
            result.nudge ? `\nπŸ’‘ ${result.nudge}` : '',
            `\n[${status}|next:${nextAction}]`,
          ].filter(Boolean).join('');
    
          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 definition for the 'think' tool parameters.
    const thinkSchema = {
      thought: z.string().describe('Your thinking step'),
      nextThoughtNeeded: z.boolean().describe('More thinking needed?'),
      thoughtNumber: z.number().int().min(1).describe('Current number'),
      totalThoughts: z.number().int().min(1).describe('Estimated total'),
      confidence: z.number().min(1).max(10).optional().describe('Confidence 1-10'),
      subSteps: z.array(z.string()).max(5).optional().describe('Micro-actions (max 5)'),
      alternatives: z.array(z.string()).max(5).optional().describe('Options to compare'),
      goal: z.string().optional().describe('Session goal (set on first thought)'),
      quickExtension: z.object({
        type: z.enum(['critique', 'elaboration', 'correction', 'alternative_scenario', 'assumption_testing', 'innovation', 'optimization', 'polish']),
        content: z.string(),
        impact: z.enum(['low', 'medium', 'high', 'blocker']).optional(),
      }).optional().describe('Inline extension (replaces extend_thought)'),
      isRevision: z.boolean().optional().describe('Revising previous thought?'),
      revisesThought: z.number().int().min(1).optional().describe('Which thought to revise'),
      branchFromThought: z.number().int().min(1).optional().describe('Branch point'),
      branchId: z.string().optional().describe('Branch identifier'),
      showTree: z.boolean().optional().describe('Show ASCII tree'),
    };

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