MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / handleImpact

Method handleImpact

src/mcp/tools.ts:1715–1774  ·  view source on GitHub ↗

* Handle codegraph_impact

(args: Record<string, unknown>)

Source from the content-addressed store, hash-verified

1713 * Handle codegraph_impact
1714 */
1715 private async handleImpact(args: Record<string, unknown>): Promise<ToolResult> {
1716 const symbol = this.validateString(args.symbol, 'symbol');
1717 if (typeof symbol !== 'string') return symbol;
1718
1719 const cg = this.getCodeGraph(args.projectPath as string | undefined);
1720 const depth = clamp((args.depth as number) || 2, 1, 10);
1721 const fileFilter = typeof args.file === 'string' ? args.file : undefined;
1722
1723 const allMatches = this.findAllSymbols(cg, symbol);
1724 if (allMatches.nodes.length === 0) {
1725 return this.textResult(`Symbol "${symbol}" not found in the codebase`);
1726 }
1727
1728 const { groups, filteredOut } = this.groupDefinitions(allMatches.nodes, fileFilter);
1729 const filterNote = filteredOut
1730 ? `\n\n> **Note:** no definition of "${symbol}" matches file "${fileFilter}" — showing all definitions instead.`
1731 : '';
1732
1733 const impactOf = (defNodes: Node[]) => {
1734 const mergedNodes = new Map<string, Node>();
1735 const mergedEdges: Edge[] = [];
1736 const seenEdges = new Set<string>();
1737 for (const node of defNodes) {
1738 const impact = cg.getImpactRadius(node.id, depth);
1739 for (const [id, n] of impact.nodes) {
1740 mergedNodes.set(id, n);
1741 }
1742 for (const e of impact.edges) {
1743 const key = `${e.source}->${e.target}:${e.kind}`;
1744 if (!seenEdges.has(key)) {
1745 seenEdges.add(key);
1746 mergedEdges.push(e);
1747 }
1748 }
1749 }
1750 return { nodes: mergedNodes, edges: mergedEdges, roots: defNodes.map((n) => n.id) };
1751 };
1752
1753 // Single definition (or same-file overloads): the familiar merged report.
1754 if (groups.length === 1) {
1755 const formatted = this.formatImpact(symbol, impactOf(groups[0]!)) + (fileFilter && !filteredOut ? "" : allMatches.note) + filterNote;
1756 return this.textResult(this.truncateOutput(formatted));
1757 }
1758
1759 // Multiple DISTINCT definitions (#764): a blast radius PER definition —
1760 // merging unrelated same-named classes (one UserService per monorepo app)
1761 // overstated impact and confused agents. Narrow with `file`.
1762 const sections: string[] = [
1763 `**Impact of ${symbol} — ${groups.length} distinct definitions (each with its own blast radius; narrow with \`file\`)**`,
1764 ];
1765 for (const group of groups) {
1766 const head = group[0]!;
1767 const line = head.startLine ? `:${head.startLine}` : '';
1768 sections.push(
1769 '',
1770 this.formatImpact(`${head.qualifiedName} (${head.filePath}${line})`, impactOf(group))
1771 );
1772 }

Callers 1

dispatchToolMethod · 0.95

Calls 9

validateStringMethod · 0.95
getCodeGraphMethod · 0.95
findAllSymbolsMethod · 0.95
textResultMethod · 0.95
groupDefinitionsMethod · 0.95
formatImpactMethod · 0.95
truncateOutputMethod · 0.95
clampFunction · 0.90
joinMethod · 0.45

Tested by

no test coverage detected