Skip to main content
Glama

find_tool_patterns

Analyze tool usage patterns, workflows, and successful practices from Claude Code conversation history to identify effective approaches.

Instructions

Analyze tool usage patterns, workflows, and successful practices

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tool_nameNoOptional specific tool name to analyze
pattern_typeNoType of patterns: tools, workflows, or solutionstools
limitNoMaximum number of patterns (default: 12)

Implementation Reference

  • MCP CallToolRequest handler for find_tool_patterns: delegates to UniversalHistorySearchEngine.getToolPatterns, formats with BeautifulFormatter
    case 'find_tool_patterns': {
      const universalResult = await this.universalEngine.getToolPatterns(
        args?.tool_name as string,
        (args?.limit as number) || 12
      );
    
      const patternType = (args?.pattern_type as string) || 'tools';
      const formattedResult = this.formatter.formatToolPatterns(
        universalResult.results as any,
        args?.tool_name as string,
        patternType
      );
    
      return {
        content: [{ type: 'text', text: formattedResult }],
      };
    }
  • Input schema definition for find_tool_patterns tool in ListTools response
      name: 'find_tool_patterns',
      description: 'Analyze tool usage patterns, workflows, and successful practices',
      inputSchema: {
        type: 'object',
        properties: {
          tool_name: {
            type: 'string',
            description: 'Optional specific tool name to analyze',
          },
          pattern_type: {
            type: 'string',
            description: 'Type of patterns: tools, workflows, or solutions',
            enum: ['tools', 'workflows', 'solutions'],
            default: 'tools',
          },
          limit: {
            type: 'number',
            description: 'Maximum number of patterns (default: 12)',
            default: 12,
          },
        },
      },
    },
  • Core implementation in HistorySearchEngine.getToolPatterns: scans conversation history, identifies tool usage patterns and workflows, constructs ToolPattern results
    async getToolPatterns(toolName?: string, limit: number = 20): Promise<ToolPattern[]> {
      const toolMap = new Map<string, CompactMessage[]>();
      const workflowMap = new Map<string, CompactMessage[]>();
    
      try {
        const projectDirs = await findProjectDirectories();
        const limitedDirs = projectDirs.slice(0, 15);
    
        // Focus on core Claude Code tools that GLOBAL would recognize
        const coreTools = new Set([
          'Edit',
          'Read',
          'Bash',
          'Grep',
          'Glob',
          'Write',
          'Task',
          'MultiEdit',
          'Notebook',
        ]);
    
        // PARALLEL PROCESSING: Process all projects concurrently
        const projectResults = await Promise.allSettled(
          limitedDirs.map(async (projectDir) => {
            const jsonlFiles = await findJsonlFiles(projectDir);
            const limitedFiles = jsonlFiles.slice(0, 8);
    
            const projectToolMap = new Map<string, CompactMessage[]>();
            const projectWorkflowMap = new Map<string, CompactMessage[]>();
    
            // PARALLEL: Process files within project simultaneously
            const fileResults = await Promise.allSettled(
              limitedFiles.map(async (file) => {
                const messages = await this.parser.parseJsonlFile(projectDir, file);
    
                // Extract individual tool usage patterns
                for (const msg of messages) {
                  if (msg.context?.toolsUsed?.length) {
                    for (const tool of msg.context.toolsUsed) {
                      // If toolName specified, only track that tool
                      // Otherwise, track all core tools
                      const shouldTrack = toolName ? tool === toolName : coreTools.has(tool);
    
                      if (shouldTrack) {
                        if (!projectToolMap.has(tool)) {
                          projectToolMap.set(tool, []);
                        }
                        projectToolMap.get(tool)!.push(msg);
                      }
                    }
                  }
                }
    
                // Extract workflow patterns (tool sequences)
                for (let i = 0; i < messages.length - 1; i++) {
                  const current = messages[i];
                  const next = messages[i + 1];
    
                  if (current.context?.toolsUsed?.length && next.context?.toolsUsed?.length) {
                    // Create focused workflow patterns
                    for (const currentTool of current.context.toolsUsed) {
                      for (const nextTool of next.context.toolsUsed) {
                        // If toolName specified, workflow must involve that tool
                        // Otherwise, workflows between core tools
                        const shouldTrack = toolName
                          ? currentTool === toolName || nextTool === toolName
                          : coreTools.has(currentTool) && coreTools.has(nextTool);
    
                        if (shouldTrack) {
                          const workflowKey = `${currentTool} → ${nextTool}`;
                          if (!projectWorkflowMap.has(workflowKey)) {
                            projectWorkflowMap.set(workflowKey, []);
                          }
                          projectWorkflowMap.get(workflowKey)!.push(current, next);
                        }
                      }
                    }
                  }
                }
    
                // Also create longer sequences for complex workflows
                for (let i = 0; i < messages.length - 2; i++) {
                  const first = messages[i];
                  const second = messages[i + 1];
                  const third = messages[i + 2];
    
                  if (
                    first.context?.toolsUsed?.length &&
                    second.context?.toolsUsed?.length &&
                    third.context?.toolsUsed?.length
                  ) {
                    for (const firstTool of first.context.toolsUsed) {
                      for (const secondTool of second.context.toolsUsed) {
                        for (const thirdTool of third.context.toolsUsed) {
                          // If toolName specified, 3-step workflow must involve that tool
                          const shouldTrack = toolName
                            ? firstTool === toolName ||
                              secondTool === toolName ||
                              thirdTool === toolName
                            : coreTools.has(firstTool) &&
                              coreTools.has(secondTool) &&
                              coreTools.has(thirdTool);
    
                          if (shouldTrack) {
                            const workflowKey = `${firstTool} → ${secondTool} → ${thirdTool}`;
                            if (!projectWorkflowMap.has(workflowKey)) {
                              projectWorkflowMap.set(workflowKey, []);
                            }
                            projectWorkflowMap.get(workflowKey)!.push(first, second, third);
                          }
                        }
                      }
                    }
                  }
                }
              })
            );
    
            return { tools: projectToolMap, workflows: projectWorkflowMap };
          })
        );
    
        // Aggregate results from parallel processing
        for (const result of projectResults) {
          if (result.status === 'fulfilled') {
            // Aggregate individual tools
            for (const [tool, messages] of result.value.tools.entries()) {
              if (!toolMap.has(tool)) {
                toolMap.set(tool, []);
              }
              toolMap.get(tool)!.push(...messages);
            }
    
            // Aggregate workflows
            for (const [workflow, messages] of result.value.workflows.entries()) {
              if (!workflowMap.has(workflow)) {
                workflowMap.set(workflow, []);
              }
              workflowMap.get(workflow)!.push(...messages);
            }
          }
        }
    
        const patterns: ToolPattern[] = [];
    
        // ENHANCED: Create diverse patterns like GLOBAL showing related tools with workflows
        const toolFrequency = new Map<string, number>();
    
        // First pass: Calculate tool frequencies for prioritization
        for (const [tool, messages] of toolMap.entries()) {
          toolFrequency.set(tool, messages.length);
        }
    
        // Add diverse individual tool patterns (different tools, not just highest frequency)
        const usedTools = new Set<string>();
        for (const [tool, messages] of Array.from(toolMap.entries()).sort(
          (a, b) => b[1].length - a[1].length
        )) {
          if (messages.length >= 1 && !usedTools.has(tool) && patterns.length < limit) {
            const uniqueMessages = SearchHelpers.deduplicateByContent(messages);
    
            // Extract actual patterns and practices instead of generic text
            const actualPatterns = this.extractActualToolPatterns(tool, uniqueMessages);
            const actualPractices = this.extractActualBestPractices(tool, uniqueMessages);
    
            patterns.push({
              toolName: tool,
              successfulUsages: uniqueMessages.slice(0, 10),
              commonPatterns: actualPatterns.length > 0 ? actualPatterns : [`${tool} usage pattern`],
              bestPractices:
                actualPractices.length > 0
                  ? actualPractices
                  : [`${tool} used ${uniqueMessages.length}x successfully`],
            });
            usedTools.add(tool);
          }
        }
    
        // Add related workflow patterns for each tool (like GLOBAL's approach)
        for (const tool of usedTools) {
          // Find workflows involving this tool
          for (const [workflow, messages] of workflowMap.entries()) {
            if (workflow.includes(tool) && workflow.includes('→') && messages.length >= 1) {
              const uniqueMessages = SearchHelpers.deduplicateByContent(messages);
              // Only add if not already added and we have space
              if (!patterns.some((p) => p.toolName === workflow) && patterns.length < limit) {
                patterns.push({
                  toolName: workflow,
                  successfulUsages: uniqueMessages.slice(0, 10),
                  commonPatterns: [workflow],
                  bestPractices: [`${workflow} workflow (${uniqueMessages.length}x successful)`],
                });
              }
            }
          }
        }
    
        // If we still have space, add any remaining high-frequency workflows
        for (const [workflow, messages] of Array.from(workflowMap.entries()).sort(
          (a, b) => b[1].length - a[1].length
        )) {
          if (workflow.includes('→') && messages.length >= 1 && patterns.length < limit) {
            if (!patterns.some((p) => p.toolName === workflow)) {
              const uniqueMessages = SearchHelpers.deduplicateByContent(messages);
              patterns.push({
                toolName: workflow,
                successfulUsages: uniqueMessages.slice(0, 10),
                commonPatterns: [workflow],
                bestPractices: [`${workflow} workflow (${uniqueMessages.length}x successful)`],
              });
            }
          }
        }
    
        // Sort to prioritize individual tools, then their related workflows
        return patterns
          .sort((a, b) => {
            const aIsWorkflow = a.toolName.includes('→');
            const bIsWorkflow = b.toolName.includes('→');
    
            // Individual tools first, then workflows, then by usage frequency
            if (aIsWorkflow !== bIsWorkflow) {
              return aIsWorkflow ? 1 : -1;
            }
    
            return b.successfulUsages.length - a.successfulUsages.length;
          })
          .slice(0, limit);
      } catch (error) {
        console.error('Tool pattern search error:', error);
        return [];
      }
    }
  • UniversalHistorySearchEngine.getToolPatterns delegates to HistorySearchEngine.getToolPatterns
    async getToolPatterns(toolName?: string, limit?: number): Promise<UniversalSearchResult> {
      await this.initialize();
    
      const claudeCodePatterns = await this.claudeCodeEngine.getToolPatterns(toolName, limit || 12);
    
      if (!this.claudeDesktopAvailable) {
        return {
          source: 'claude-code',
          results: claudeCodePatterns as any,
          enhanced: false,
        };
      }
    
      // For tool patterns, Desktop doesn't have tool usage data, so we focus on Code
      // But we mark as enhanced if Desktop is available for future Desktop tool analysis
      return {
        source: 'claude-code',
        results: claudeCodePatterns as any,
        enhanced: this.claudeDesktopAvailable,
      };
    }
  • BeautifulFormatter.formatToolPatterns: formats and ranks tool pattern results for output
    formatToolPatterns(
      patterns: ToolPattern[],
      toolName?: string,
      _patternType: string = 'tools'
    ): string {
      const filter = toolName ? `"${toolName}"` : 'all';
      const header = `${robots.toolPatterns} ${filter} | ${patterns.length} patterns`;
    
      if (patterns.length === 0) {
        return `${header}\n\n{"patterns":[]}`;
      }
    
      const rankedPatterns = this.rankToolPatternsByValue(patterns);
      const topPatterns = rankedPatterns.slice(0, 8);
    
      const structured = {
        tool: toolName || 'all',
        patterns: topPatterns.map((p) => ({
          name: p.toolName,
          uses: p.successfulUsages.length,
          workflow: p.commonPatterns[0] || null,
          practice: p.bestPractices[0] || null,
          example: p.successfulUsages[0]?.content || null,
          ctx: p.successfulUsages[0]?.context || null,
        })),
      };
    
      return `${header}\n\n${JSON.stringify(structured, null, 2)}`;
    }

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/Vvkmnn/claude-historian'

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