find_symbol
Locate function, class, variable, or interface definitions within a project directory by specifying symbol name and type.
Instructions
find function|where is class|variable location|find function|where is|locate - Find symbol definitions
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| symbolName | Yes | Name of the symbol to find | |
| projectPath | Yes | Project directory path | |
| symbolType | No | Type of symbol to search for |
Implementation Reference
- src/tools/semantic/findSymbol.ts:42-138 (handler)The main handler function that implements the 'find_symbol' tool. It scans TypeScript projects using ts-morph and Python files using PythonParser to find symbol definitions matching the given name and type.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'}` }] }; } }
- ToolDefinition object defining the schema, description, and metadata for the 'find_symbol' tool.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 of the 'find_symbol' tool handler in the main switch statement for tool execution within executeToolCall 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 for MCP tool listing (ListToolsRequest).findSymbolDefinition,
- Helper function to extract symbol information from TypeScript nodes using ts-morph, filtering by name and type.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; }