Skip to main content
Glama

find_symbol

Locate function, class, or variable definitions in code projects to quickly find symbol implementations and understand code structure.

Instructions

find function|where is class|variable location|find function|where is|locate - Find symbol definitions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
symbolNameYesName of the symbol to find
projectPathYesProject directory path
symbolTypeNoType of symbol to search for

Implementation Reference

  • The main handler function that executes the 'find_symbol' tool. It searches for symbols in both TypeScript (using ts-morph) and Python files (using PythonParser), collects matching symbols, sorts by relevance, and returns formatted results.
    export async function findSymbol(args: { 
      symbolName: string; 
      projectPath: string; 
      symbolType?: string 
    }): Promise<ToolResult> {
      const { symbolName, projectPath, symbolType = 'all' } = args;
      
      try {
        // Use cached project for performance
        const projectCache = ProjectCache.getInstance();
        const project = projectCache.getOrCreate(projectPath);
    
        const symbols: SymbolInfo[] = [];
    
        // Check for Python files
        const glob = await import('glob');
        const pythonFiles = glob.globSync(path.join(projectPath, '**/*.py'), {
          ignore: ['**/node_modules/**', '**/.git/**', '**/venv/**', '**/__pycache__/**']
        });
    
        // Parse Python files
        for (const pyFile of pythonFiles) {
          try {
            const content = await readFile(pyFile, 'utf-8');
            const pythonSymbols = await PythonParser.findSymbols(content);
    
            for (const pySymbol of pythonSymbols) {
              if (pySymbol.name.includes(symbolName) &&
                  (symbolType === 'all' || symbolType === pySymbol.kind)) {
                symbols.push({
                  name: pySymbol.name,
                  kind: pySymbol.kind,
                  filePath: pyFile,
                  line: pySymbol.line,
                  column: pySymbol.column,
                  preview: pySymbol.docstring?.substring(0, 100) || `${pySymbol.kind} ${pySymbol.name}`
                });
              }
            }
          } catch (error) {
            // Skip files that can't be parsed
            console.error(`Error parsing Python file ${pyFile}:`, error);
          }
        }
    
        // Search through all source files
        for (const sourceFile of project.getSourceFiles()) {
          const filePath = sourceFile.getFilePath();
          
          // Skip node_modules and other irrelevant paths
          if (filePath.includes('node_modules') || filePath.includes('.git')) {
            continue;
          }
          
          // Find matching symbols based on type
          sourceFile.forEachDescendant((node) => {
            const nodeSymbol = extractSymbolInfo(node, symbolName, symbolType);
            if (nodeSymbol) {
              const start = node.getStartLinePos();
              const pos = sourceFile.getLineAndColumnAtPos(start);
              
              symbols.push({
                name: nodeSymbol.name,
                kind: nodeSymbol.kind,
                filePath: filePath,
                line: pos.line,
                column: pos.column,
                preview: node.getText().substring(0, 100)
              });
            }
          });
        }
        
        // Sort by relevance (exact matches first)
        symbols.sort((a, b) => {
          const aExact = a.name === symbolName ? 0 : 1;
          const bExact = b.name === symbolName ? 0 : 1;
          return aExact - bExact;
        });
        
        return {
          content: [{
            type: 'text',
            text: `Found ${symbols.length} symbols:\n${symbols.slice(0, 20).map(s =>
              `${s.name} (${s.kind}) - ${s.filePath}:${s.line}`
            ).join('\n')}`
          }]
        };
      } catch (error) {
        return {
          content: [{
            type: 'text',
            text: `Error finding symbol: ${error instanceof Error ? error.message : 'Unknown error'}` 
          }]
        };
      }
    }
  • The ToolDefinition object for 'find_symbol', including name, description, input schema with parameters symbolName, projectPath, and optional symbolType.
    export const findSymbolDefinition: ToolDefinition = {
      name: 'find_symbol',
      description: 'find function|where is class|variable location|find function|where is|locate - Find symbol definitions',
      inputSchema: {
        type: 'object',
        properties: {
          symbolName: { type: 'string', description: 'Name of the symbol to find' },
          projectPath: { type: 'string', description: 'Project directory path' },
          symbolType: {
            type: 'string',
            enum: ['all', 'function', 'class', 'interface', 'variable', 'type'],
            description: 'Type of symbol to search for'
          }
        },
        required: ['symbolName', 'projectPath']
      },
      annotations: {
        title: 'Find Symbol',
        audience: ['user', 'assistant']
      }
    };
  • src/index.ts:610-611 (registration)
    Registration in the executeToolCall switch statement that dispatches calls to the 'find_symbol' handler function.
    case 'find_symbol':
      return await findSymbol(args as any) as CallToolResult;
  • src/index.ts:109-109 (registration)
    Inclusion of findSymbolDefinition in the tools array, registering the tool for listing via MCP ListToolsRequest.
    findSymbolDefinition,
  • Helper function extractSymbolInfo that inspects TypeScript nodes to determine if they match the symbol query based on kind (function, class, etc.). Used in the main handler.
    function extractSymbolInfo(
      node: Node,
      symbolName: string,
      symbolType: string
    ): { name: string; kind: string } | null {
      const kind = node.getKind();
    
      // Function declarations and expressions
      if (symbolType === 'all' || symbolType === 'function') {
        if (Node.isFunctionDeclaration(node) || Node.isMethodDeclaration(node)) {
          const name = node.getName();
          if (name && name.includes(symbolName)) {
            return { name, kind: 'function' };
          }
        }
        if (Node.isVariableDeclaration(node)) {
          const name = node.getName();
          const initializer = node.getInitializer();
          if (name && name.includes(symbolName) &&
              (Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer))) {
            return { name, kind: 'function' };
          }
        }
      }
      
      // Class declarations
      if ((symbolType === 'all' || symbolType === 'class') && Node.isClassDeclaration(node)) {
            const name = node.getName();
            if (name && name.includes(symbolName)) {
              return { name, kind: 'class' };
            }
      }
      
      // Interface declarations
      if ((symbolType === 'all' || symbolType === 'interface') && Node.isInterfaceDeclaration(node)) {
            const name = node.getName();
            if (name && name.includes(symbolName)) {
              return { name, kind: 'interface' };
            }
      }
      
      // Type aliases
      if ((symbolType === 'all' || symbolType === 'type') && Node.isTypeAliasDeclaration(node)) {
            const name = node.getName();
            if (name && name.includes(symbolName)) {
              return { name, kind: 'type' };
            }
      }
      
      // Variables
      if (symbolType === 'all' || symbolType === 'variable') {
        if (Node.isVariableDeclaration(node)) {
          const name = node.getName();
          const initializer = node.getInitializer();
          if (name && name.includes(symbolName) && 
              !Node.isArrowFunction(initializer) && !Node.isFunctionExpression(initializer)) {
            return { name, kind: 'variable' };
          }
        }
      }
      
      return null;
    }

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/ssdeanx/ssd-ai'

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