codebase_graph_query
Query code dependency graphs to see a file's imports and dependents, enabling understanding of codebase structure and impact analysis.
Instructions
Query the code dependency graph for a specific file. Returns what the file imports and what files depend on it.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectPath | No | Absolute path to the project directory. | |
| filePath | Yes | Relative path of the file to query (e.g. 'src/index.ts'). |
Implementation Reference
- src/index.ts:190-203 (registration)Tool registration for 'codebase_graph_query' using the MCP server.tool() method. Defines the name, description, and Zod schema (projectPath optional, filePath required). The handler delegates to handleGraphTool('codebase_graph_query', args).
server.tool( "codebase_graph_query", "Query the code dependency graph for a specific file. Returns what the file imports and what files depend on it.", { projectPath: z .string() .describe("Absolute path to the project directory.") .optional(), filePath: z.string().describe("Relative path of the file to query (e.g. 'src/index.ts')."), }, async (args) => ({ content: [{ type: "text", text: await handleGraphTool("codebase_graph_query", args) }], }), ); - src/tools/graph-tools.ts:22-105 (handler)The handleGraphTool function dispatches to the 'codebase_graph_query' case (lines 78-105). It retrieves the graph via getOrBuildGraph, calls getFileDependencies(graph, filePath), and formats output showing imports (→) and dependents (←).
export async function handleGraphTool( name: string, args: Record<string, unknown>, ): Promise<string> { const projectPath = path.resolve((args.projectPath as string) || process.cwd()); // Auto-start watcher on any graph interaction (fire-and-forget) ensureWatcherStarted(projectPath); switch (name) { case "codebase_graph_build": { const resolved = path.resolve(projectPath); // Concurrency guard: if already building, show progress if (isGraphBuildInProgress(resolved)) { const progress = getGraphBuildProgress(resolved); const lines = [ `⚠ Graph build already in progress for: ${resolved}`, ]; if (progress) { const elapsed = ((Date.now() - progress.startedAt) / 1000).toFixed(0); const pct = progress.filesTotal > 0 ? ` (${Math.round((progress.filesProcessed / progress.filesTotal) * 100)}%)` : ""; lines.push(`Phase: ${progress.phase}`); lines.push(`Progress: ${progress.filesProcessed}/${progress.filesTotal} files${pct}`); lines.push(`Elapsed: ${elapsed}s`); } lines.push("", "Call codebase_graph_status to check progress."); return lines.join("\n"); } // Fire-and-forget: start graph build in the background const extraExts = mergeExtraExtensions(args.extraExtensions as string | undefined); rebuildGraph(resolved, extraExts.size > 0 ? extraExts : undefined) .then((graph) => { logger.info("Background graph build completed", { projectPath: resolved, nodes: graph.nodes.length, edges: graph.edges.length, }); }) .catch((err) => { const message = err instanceof Error ? err.message : String(err); logger.error("Background graph build failed", { projectPath: resolved, error: message }); }); return [ `Graph build started in the background for: ${resolved}`, "", "IMPORTANT: The graph is now building asynchronously.", "Call codebase_graph_status to check progress. Keep calling it periodically until the build completes.", "Once complete, you can use codebase_graph_query, codebase_graph_stats, etc. to explore the graph.", ].join("\n"); } case "codebase_graph_query": { const filePath = args.filePath as string; const graph = await getOrBuildGraph(projectPath); const deps = getFileDependencies(graph, filePath); const lines = [`Dependencies for: ${filePath}\n`]; if (deps.imports.length === 0 && deps.importedBy.length === 0) { lines.push("No dependency information found for this file."); lines.push("Make sure codebase_graph_build has been run and the file path is relative."); } else { if (deps.imports.length > 0) { lines.push(`Imports (${deps.imports.length}):`); for (const imp of deps.imports) { lines.push(` → ${imp}`); } } if (deps.importedBy.length > 0) { lines.push(`\nImported by (${deps.importedBy.length}):`); for (const dep of deps.importedBy) { lines.push(` ← ${dep}`); } } } return lines.join("\n"); } - src/services/graph-analysis.ts:10-22 (helper)getFileDependencies helper: looks up a CodeGraph node by relativePath and returns its 'imports' (what the file imports) and 'importedBy' (what files depend on it).
export function getFileDependencies(graph: CodeGraph, relativePath: string): { imports: string[]; importedBy: string[]; } { const node = graph.nodes.find((n) => n.relativePath === relativePath); if (!node) { return { imports: [], importedBy: [] }; } return { imports: node.dependencies, importedBy: node.dependents, }; } - src/types.ts:14-21 (schema)CodeGraphNode type definition used by the graph: contains 'dependencies' (what this file imports) and 'dependents' (files that import this file).
export interface CodeGraphNode { filePath: string; relativePath: string; imports: string[]; exports: string[]; dependencies: string[]; dependents: string[]; } - src/services/code-graph.ts:40-41 (helper)Re-exports getFileDependencies from graph-analysis.ts so it can be imported by the graph-tools handler.
// Re-export analysis functions for external consumers export { findCircularDependencies, generateMermaidDiagram, getFileDependencies, getGraphStats } from "./graph-analysis.js";