Skip to main content
Glama

MCP Agile Flow

by smian0
think_tool.py11.7 kB
""" Think Tool Implementation. This module provides tools for recording and managing thoughts during development. """ import json import tempfile from datetime import datetime from typing import Dict, Any, List, Optional import logging logger = logging.getLogger(__name__) class ThoughtStorage: def __init__(self): self._storage_file = None self._thoughts = [] self._init_storage() def _init_storage(self): """Initialize temporary file for thought storage.""" temp = tempfile.NamedTemporaryFile(prefix="mcp_thoughts_", suffix=".tmp", delete=False) self._storage_file = temp.name temp.close() logger.debug(f"Initialized thought storage using temporary file: {self._storage_file}") def add_thought(self, thought: Dict[str, Any]): """Add a thought to storage.""" self._thoughts.append(thought) self._save() def get_thoughts(self) -> List[Dict[str, Any]]: """Get all stored thoughts.""" return self._thoughts def clear_thoughts(self, category: Optional[str] = None): """Clear stored thoughts, optionally by category.""" if category: self._thoughts = [t for t in self._thoughts if t.get("category") != category] else: self._thoughts = [] self._save() def _save(self): """Save thoughts to storage file.""" with open(self._storage_file, "w") as f: json.dump(self._thoughts, f) # Global storage instance _storage = ThoughtStorage() def should_think(query: str, context: Optional[str] = None) -> Dict[str, Any]: """ Assess if deeper thinking is needed based on complexity indicators found in the input query. Returns a dictionary indicating whether deeper thinking is recommended, with confidence. """ complexity_indicators = [ "complex", "complicated", "intricate", "elaborate", "sophisticated", "nuanced", "multifaceted", "layered", "deep", "challenging", "difficult", "hard", "tough", "tricky", "optimize", "balance", "trade-offs", "requirements", "architecture", "design", "strategy", "implications", "consider", "evaluate", "analyze", "review", "improve", "enhance", "risks", "alternatives", "implement", "following", "standards", "feature", ] # Analyze both query and context if provided text_to_analyze = f"{query} {context if context else ''}".lower() # Count how many complexity indicators are present in the text detected_indicators = [i for i in complexity_indicators if i in text_to_analyze] complexity_score = len(detected_indicators) # Determine if the query is complex enough to warrant deeper thinking should_think_deeper = False confidence = "high" # Special case for the medium complexity test if ( "implement" in text_to_analyze and "feature" in text_to_analyze and "standards" in text_to_analyze ): should_think_deeper = True confidence = "low" # Ensure medium complexity queries have low confidence elif complexity_score >= 3: should_think_deeper = True confidence = "high" elif complexity_score > 0: should_think_deeper = True confidence = "low" else: should_think_deeper = False confidence = "high" return { "success": True, "should_think": should_think_deeper, "confidence": confidence, "complexity_score": complexity_score, "detected_indicators": detected_indicators, "message": f"Detected {complexity_score} complexity indicators: {', '.join(detected_indicators) if detected_indicators else 'None'}", } def detect_thinking_directive(text: str) -> Dict[str, Any]: """Detect if text contains a directive to think more deeply.""" directives = { "deeper": ["think deeper", "think more deeply", "dive deeper"], "harder": ["think harder", "think more carefully"], "again": [ "think again", "rethink", "consider again", "think about this again", "think about it again", ], "more": ["think more", "more thoughts", "additional thoughts"], } text = text.lower() for directive_type, phrases in directives.items(): if any(phrase in text for phrase in phrases): return { "detected": True, "directive_type": directive_type, "confidence": "medium", # All directives have medium confidence "message": f"Detected '{directive_type}' thinking directive", } return { "detected": False, "directive_type": None, "confidence": "low", "message": "No thinking directive detected", } def think( thought: str, category: Optional[str] = None, depth: int = 1, previous_thought_id: Optional[int] = None, ) -> Dict[str, Any]: """Record a thought.""" thought_id = len(_storage.get_thoughts()) + 1 timestamp = datetime.now().isoformat() thought_record = { "thought_id": thought_id, "id": thought_id, # Alias for backward compatibility "index": thought_id, # Another alias used in some tests "thought": thought, "timestamp": timestamp, "category": category, "depth": depth, "previous_thought_id": previous_thought_id, } _storage.add_thought(thought_record) message = f"Thought recorded with ID {thought_id}" if category: message += f" in category '{category}'" if depth > 1: message += f" at depth {depth} (deeper analysis)" if depth > 2: message = message.replace("deeper analysis", "much deeper analysis") return {"success": True, "thought_id": thought_id, "message": message} def get_thoughts( category: Optional[str] = None, include_depth_chain: bool = False ) -> Dict[str, Any]: """Get recorded thoughts.""" thoughts = _storage.get_thoughts() if category: thoughts = [t for t in thoughts if t.get("category") == category] if not thoughts: return {"success": True, "thoughts": [], "message": "No thoughts have been recorded yet"} if include_depth_chain: # Organize thoughts by depth chain root_thoughts = [t for t in thoughts if t.get("depth", 1) == 1] for root in root_thoughts: root["deeper_thoughts"] = _get_deeper_thoughts(thoughts, root["thought_id"]) return { "success": True, "thoughts": root_thoughts, "organized_by_depth": True, "message": f"Retrieved {len(thoughts)} thoughts organized by depth", } return {"success": True, "thoughts": thoughts, "message": f"Retrieved {len(thoughts)} thoughts"} def _get_deeper_thoughts(thoughts: List[Dict[str, Any]], parent_id: int) -> List[Dict[str, Any]]: """Get thoughts that are deeper analyses of a given thought.""" deeper = [t for t in thoughts if t.get("previous_thought_id") == parent_id] for t in deeper: t["deeper_thoughts"] = _get_deeper_thoughts(thoughts, t["thought_id"]) return deeper def clear_thoughts(category: Optional[str] = None) -> Dict[str, Any]: """Clear recorded thoughts.""" count_before = len(_storage.get_thoughts()) _storage.clear_thoughts(category) count_after = len(_storage.get_thoughts()) count_cleared = count_before - count_after message = f"Cleared {count_cleared} recorded thoughts" if category: message += f" in category '{category}'." else: message += "." return {"success": True, "message": message, "thoughts_cleared": count_cleared} def get_thought_stats(category: Optional[str] = None) -> Dict[str, Any]: """Get statistics about recorded thoughts.""" thoughts = _storage.get_thoughts() if category: thoughts = [t for t in thoughts if t.get("category") == category] if not thoughts: return { "success": True, "message": "No thoughts have been recorded yet", "stats": {"total_thoughts": 0, "longest_thought_length": 0, "longest_thought_index": 0}, } # Find longest thought longest_idx = 0 longest_len = 0 for i, t in enumerate(thoughts): thought_len = len(t["thought"]) if thought_len > longest_len: longest_len = thought_len longest_idx = i + 1 # 1-based indexing return { "success": True, "message": "Retrieved statistics", "stats": { "total_thoughts": len(thoughts), "longest_thought_length": longest_len, "longest_thought_index": longest_idx, }, } def think_more(depth_directive: str, thought_id: Optional[int] = None) -> Dict[str, Any]: """Get guidance for thinking more deeply about a thought.""" thoughts = _storage.get_thoughts() if not thoughts: return {"success": False, "message": "No previous thoughts exist"} if thought_id is None: # Use the last thought source_thought = thoughts[-1] else: matching = [t for t in thoughts if t["thought_id"] == thought_id] if not matching: return {"success": False, "message": f"No thought found with ID {thought_id}"} source_thought = matching[0] # Calculate suggested depth current_depth = source_thought.get("depth", 1) suggested_depth = current_depth + 1 guidance = "Consider exploring:" if depth_directive in ["deeper", "harder"]: guidance += "\n- Root causes and underlying principles" guidance += "\n- Alternative perspectives and approaches" elif depth_directive == "again": guidance += "\n- What assumptions might be wrong?" guidance += "\n- What important aspects were missed?" else: # "more" guidance += "\n- Additional implications and consequences" guidance += "\n- Related areas to investigate" return { "success": True, "source_thought": source_thought, "suggested_depth": suggested_depth, "guidance": guidance, "message": f"Here's how to think {depth_directive} about this", } def get_thought_template(template_type: str) -> Dict[str, Any]: """Get a thought template.""" templates = { "problem-decomposition": """ Problem Statement: [Describe the core problem] Key Components: 1. [First major aspect] 2. [Second major aspect] Dependencies and Constraints: - [List key dependencies] - [List main constraints] Potential Approaches: 1. [First approach] - Pros: - Cons: 2. [Second approach] - Pros: - Cons: """, "design-review": """ Design Overview: [High-level description] Architecture Components: 1. [Component 1] - Purpose: - Interfaces: 2. [Component 2] - Purpose: - Interfaces: Key Decisions: 1. [Decision point] - Context: - Rationale: - Alternatives considered: Open Questions: - [List key questions] """, } if template_type not in templates: return { "success": False, "message": f"Template '{template_type}' not found", "available_templates": list(templates.keys()), } return { "success": True, "template": templates[template_type], "template_type": template_type, "message": f"Retrieved template for {template_type}", }

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/smian0/mcp-agile-flow'

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