Skip to main content
Glama

Think

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'),
    };
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It does well by explaining key features (subSteps, alternatives, quickExtension), mentioning it replaces extend_thought tool, and describing what it returns (progress bar, confidence, next action hint). However, it doesn't cover all behavioral aspects like error conditions, performance characteristics, or side effects that might be relevant for a complex tool with 14 parameters.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections ('Use for:', 'Features:', 'Returns...'), front-loaded with the core purpose, and every sentence earns its place by providing specific guidance or information. No wasted words or redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 14 parameters, no annotations, and no output schema, the description does a good job of explaining the tool's purpose, usage context, key features, and return information. However, given the complexity and lack of output schema, it could provide more detail about the structure of returned data or error conditions to be fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds some context about subSteps ('Micro-action plan'), alternatives ('Quick options comparison'), and quickExtension ('Inline critique/elaboration'), but doesn't provide significant additional parameter semantics beyond what's in the schema. This meets the baseline expectation when schema coverage is complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Add a thought to the reasoning chain.' This is a specific verb+resource combination that explains what the tool does. However, it doesn't explicitly differentiate this from its siblings (think_batch, think_done, think_recall, think_reset), which would be needed for a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Use for:' section provides clear context about when to use this tool: for complex multi-step problems, planning with revision, and analysis needing course correction. This gives good guidance but doesn't explicitly mention when NOT to use it or provide specific alternatives among the sibling tools, preventing a perfect score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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