@kridaydave/code-mapper 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -0
  3. package/bin/code-mapper.mjs +86 -0
  4. package/dist/graph/GraphAnalyzer.js +32 -65
  5. package/dist/graph/GraphAnalyzer.js.map +1 -1
  6. package/dist/graph/GraphBuilder.js +18 -45
  7. package/dist/graph/GraphBuilder.js.map +1 -1
  8. package/dist/index.js +100 -23
  9. package/dist/index.js.map +1 -1
  10. package/dist/mcp/cache.js +8 -17
  11. package/dist/mcp/cache.js.map +1 -1
  12. package/dist/mcp/resources.js +5 -1
  13. package/dist/mcp/resources.js.map +1 -1
  14. package/dist/mcp/tools.js +190 -35
  15. package/dist/mcp/tools.js.map +1 -1
  16. package/dist/parser/ComplexityAnalyzer.js +19 -2
  17. package/dist/parser/ComplexityAnalyzer.js.map +1 -1
  18. package/dist/parser/FileAnalyzer.js +8 -30
  19. package/dist/parser/FileAnalyzer.js.map +1 -1
  20. package/dist/parser/ProjectParser.js +8 -5
  21. package/dist/parser/ProjectParser.js.map +1 -1
  22. package/dist/parser/ProjectParser.test.js +1 -17
  23. package/dist/parser/ProjectParser.test.js.map +1 -1
  24. package/dist/tui/index.js +239 -0
  25. package/dist/tui/index.js.map +1 -0
  26. package/package.json +82 -35
  27. package/AGENTS.md +0 -174
  28. package/docs/PHASE2_PLAN.md +0 -435
  29. package/fixtures/test-project/calculator.ts +0 -28
  30. package/fixtures/test-project/index.ts +0 -2
  31. package/fixtures/test-project/math.ts +0 -11
  32. package/src/graph/Graph.test.ts +0 -222
  33. package/src/graph/GraphAnalyzer.ts +0 -502
  34. package/src/graph/GraphBuilder.ts +0 -258
  35. package/src/graph/types.ts +0 -42
  36. package/src/index.ts +0 -38
  37. package/src/mcp/cache.ts +0 -89
  38. package/src/mcp/resources.ts +0 -137
  39. package/src/mcp/tools.test.ts +0 -104
  40. package/src/mcp/tools.ts +0 -529
  41. package/src/parser/ComplexityAnalyzer.ts +0 -275
  42. package/src/parser/FileAnalyzer.ts +0 -215
  43. package/src/parser/ProjectParser.test.ts +0 -96
  44. package/src/parser/ProjectParser.ts +0 -172
  45. package/src/parser/types.ts +0 -77
  46. package/src/types/graphology-pagerank.d.ts +0 -20
  47. package/tsconfig.json +0 -17
  48. package/vitest.config.ts +0 -15
package/dist/index.js CHANGED
@@ -1,29 +1,106 @@
1
1
  #!/usr/bin/env node
2
- import { McpServer } from "@modelcontextprotocol/server";
3
- import { StdioServerTransport } from "@modelcontextprotocol/server";
4
- import { registerTools } from "./mcp/tools.js";
5
- import { registerResources } from "./mcp/resources.js";
6
- async function main() {
7
- const server = new McpServer({
8
- name: "code-mapper",
9
- version: "1.0.0",
10
- }, {
11
- instructions: "CodeMapper analyzes TypeScript/JavaScript codebases using AST parsing. " +
12
- "Always start by calling scan_codebase with the target directory. " +
13
- "Then use find_function to locate symbols, analyze_dependencies to see the graph, " +
14
- "rank_impact to find central files, or trace_call_chain to follow dependency paths. " +
15
- "The codebase://summary and codebase://graph/{format} resources provide cached views.",
16
- });
17
- // Register all tools and resources
2
+ import fs from "fs";
3
+ import path from "path";
4
+ const MIN_NODE_VERSION = 18;
5
+ const nodeVersion = process.versions.node;
6
+ const major = parseInt(nodeVersion.split(".")[0], 10);
7
+ const RED = "\x1b[31m";
8
+ const GREEN = "\x1b[32m";
9
+ const YELLOW = "\x1b[33m";
10
+ const CYAN = "\x1b[36m";
11
+ const BOLD = "\x1b[1m";
12
+ function log(...args) { console.error(...args); }
13
+ function err(...args) { console.error(...args); }
14
+ if (major < MIN_NODE_VERSION) {
15
+ err(`${RED}${BOLD}Node ${nodeVersion} not supported. Need 18+.`);
16
+ process.exit(1);
17
+ }
18
+ const pkgRoot = process.cwd();
19
+ const distIndex = path.join(pkgRoot, "dist", "index.js");
20
+ if (!fs.existsSync(distIndex)) {
21
+ log(`${YELLOW}Building...`);
22
+ const srcIndex = path.join(pkgRoot, "src", "index.ts");
23
+ if (!fs.existsSync(srcIndex)) {
24
+ err(`${RED}Source not found. Reinstall.`);
25
+ process.exit(1);
26
+ }
27
+ if (fs.existsSync(path.join(pkgRoot, "node_modules", "typescript"))) {
28
+ try {
29
+ const { execSync } = await import("child_process");
30
+ execSync("npm run build", { cwd: pkgRoot, stdio: "inherit" });
31
+ }
32
+ catch (e) {
33
+ const msg = e instanceof Error ? e.message : String(e);
34
+ err(`${RED}Build failed: ${msg}`);
35
+ process.exit(1);
36
+ }
37
+ }
38
+ else {
39
+ err(`${RED}Install incomplete. Reinstall.`);
40
+ process.exit(1);
41
+ }
42
+ }
43
+ const nodeModules = path.join(pkgRoot, "node_modules");
44
+ const missing = ["@modelcontextprotocol/sdk", "chalk", "zod"].filter(d => !fs.existsSync(path.join(nodeModules, d)));
45
+ if (missing.length) {
46
+ err(`${RED}Missing: ${missing.join(", ")}`);
47
+ err(`Run: npm install`);
48
+ process.exit(1);
49
+ }
50
+ const args = process.argv.slice(2);
51
+ if (args.includes("--help") || args.includes("-h")) {
52
+ log(`
53
+ code-mapper v1.0.1
54
+
55
+ npx code-mapper - start server
56
+ npx code-mapper --setup - setup wizard
57
+ `);
58
+ process.exit(0);
59
+ }
60
+ if (args.includes("--version") || args.includes("-v")) {
61
+ log("1.0.1");
62
+ process.exit(0);
63
+ }
64
+ if (args.includes("--setup") || args.includes("-s")) {
65
+ const tuiDist = path.join(pkgRoot, "dist", "tui", "index.js");
66
+ const tuiSrc = path.join(pkgRoot, "src", "tui", "index.ts");
67
+ if (fs.existsSync(tuiDist)) {
68
+ const { startSetupWizard } = await import("./tui/index.js");
69
+ await startSetupWizard();
70
+ }
71
+ else if (fs.existsSync(tuiSrc)) {
72
+ log(`${YELLOW}Building...`);
73
+ const { execSync } = await import("child_process");
74
+ execSync("npm run build", { cwd: pkgRoot, stdio: "inherit" });
75
+ const { startSetupWizard } = await import("./tui/index.js");
76
+ await startSetupWizard();
77
+ }
78
+ else {
79
+ log(`${YELLOW}Setup not available.`);
80
+ }
81
+ process.exit(0);
82
+ }
83
+ else {
84
+ const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
85
+ const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
86
+ const { registerTools } = await import("./mcp/tools.js");
87
+ const { registerResources } = await import("./mcp/resources.js");
88
+ const server = new McpServer({ name: "code-mapper", version: "1.0.1" }, { instructions: "CodeMapper analyzes TypeScript/JavaScript codebases. Start with scan_codebase." });
18
89
  registerTools(server);
19
90
  registerResources(server);
20
- // Connect via stdio
21
91
  const transport = new StdioServerTransport();
22
- await server.connect(transport);
23
- console.error("CodeMapper MCP server running on stdio");
92
+ transport.onerror = (e) => log(`Error: ${e.message}`);
93
+ transport.onclose = () => { log("Closed"); process.exit(0); };
94
+ try {
95
+ await server.connect(transport);
96
+ log("CodeMapper running on stdio");
97
+ }
98
+ catch (e) {
99
+ const msg = e instanceof Error ? e.message : String(e);
100
+ err(`${RED}Failed: ${msg}`);
101
+ process.exit(1);
102
+ }
103
+ process.on("SIGINT", () => { log("Shutting down..."); process.exit(0); });
104
+ process.on("SIGTERM", () => { log("Shutting down..."); process.exit(0); });
24
105
  }
25
- main().catch((error) => {
26
- console.error("Fatal error:", error);
27
- process.exit(1);
28
- });
29
106
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CACzB;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EACV,yEAAyE;YACzE,mEAAmE;YACnE,mFAAmF;YACnF,qFAAqF;YACrF,sFAAsF;KACzF,CACH,CAAC;IAEF,mCAAmC;IACnC,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC1D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/mcp/cache.js CHANGED
@@ -15,17 +15,8 @@ export function normalizeCacheKey(directory) {
15
15
  }
16
16
  function evictIfNeeded() {
17
17
  if (analyzerCache.size >= MAX_CACHE_SIZE) {
18
- let oldestKey = null;
19
- let oldestTime = Infinity;
20
- for (const [key, entry] of analyzerCache) {
21
- if (entry.timestamp < oldestTime) {
22
- oldestTime = entry.timestamp;
23
- oldestKey = key;
24
- }
25
- }
26
- if (oldestKey) {
27
- analyzerCache.delete(oldestKey);
28
- }
18
+ const entries = [...analyzerCache.entries()].sort((a, b) => a[1].timestamp - b[1].timestamp);
19
+ analyzerCache.delete(entries[0][0]);
29
20
  }
30
21
  }
31
22
  function isEntryExpired(entry) {
@@ -34,13 +25,13 @@ function isEntryExpired(entry) {
34
25
  export function getAnalyzerFromCache(directory) {
35
26
  const normalizedDir = normalizeCacheKey(directory);
36
27
  const entry = analyzerCache.get(normalizedDir);
37
- if (entry && !isEntryExpired(entry)) {
38
- return entry.analyzer;
39
- }
40
- if (entry) {
41
- analyzerCache.delete(normalizedDir);
28
+ if (!entry || isEntryExpired(entry)) {
29
+ if (entry) {
30
+ analyzerCache.delete(normalizedDir);
31
+ }
32
+ return undefined;
42
33
  }
43
- return undefined;
34
+ return entry.analyzer;
44
35
  }
45
36
  export function setAnalyzerInCache(directory, analyzer) {
46
37
  evictIfNeeded();
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/mcp/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/mcp/cache.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,11 @@
1
- import { ResourceTemplate } from "@modelcontextprotocol/server";
1
+ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { analyzerCache, getLastScannedDirectory } from "./cache.js";
3
3
  const RANK_CACHE_LIMIT = 100;
4
4
  const rankCache = new Map();
5
+ /**
6
+ * Registers all MCP resources with the server.
7
+ * Provides: codebase://summary, codebase://graph/{format}
8
+ */
5
9
  export function registerResources(server) {
6
10
  // Resource 1: codebase://summary
7
11
  server.registerResource("codebase-summary", "codebase://summary", {
@@ -1 +1 @@
1
- {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/mcp/resources.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/mcp/resources.ts"],"names":[],"mappings":"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"}
package/dist/mcp/tools.js CHANGED
@@ -2,8 +2,6 @@ import { resolve } from "node:path";
2
2
  import * as fs from "node:fs";
3
3
  import { z } from "zod";
4
4
  import { ProjectParser } from "../parser/ProjectParser.js";
5
- import { Project } from "ts-morph";
6
- import { ComplexityAnalyzer } from "../parser/ComplexityAnalyzer.js";
7
5
  import { GraphBuilder } from "../graph/GraphBuilder.js";
8
6
  import { GraphAnalyzer } from "../graph/GraphAnalyzer.js";
9
7
  import { normalizeCacheKey, clearAnalyzerCache, setLastScannedDirectory, getAnalyzerFromCache, setAnalyzerInCache, getPendingAnalyzer, setPendingAnalyzer } from "./cache.js";
@@ -54,14 +52,60 @@ async function getAnalyzer(directory) {
54
52
  setPendingAnalyzer(normalizedDir, analyzerPromise);
55
53
  return analyzerPromise;
56
54
  }
57
- function safeHandler(fn) {
58
- return fn().then((result) => result, (error) => {
55
+ /**
56
+ * Wraps MCP tool handlers to catch errors and return structured error responses.
57
+ * Ensures all tool responses have consistent format regardless of success/failure.
58
+ */
59
+ function getErrorMessage(error) {
60
+ const msg = error.message;
61
+ if (msg.includes("does not exist")) {
62
+ return {
63
+ message: `${msg}. Please check that the path is correct and try again.`,
64
+ errorCode: "ERR_DIRECTORY_NOT_FOUND",
65
+ };
66
+ }
67
+ if (msg.includes("Too many files")) {
68
+ return {
69
+ message: `${msg}. Try scanning a subdirectory to reduce the file count.`,
70
+ errorCode: "ERR_TOO_MANY_FILES",
71
+ };
72
+ }
73
+ if (msg.includes("Path is not a directory")) {
74
+ return {
75
+ message: `${msg}. Please provide a directory path, not a file path.`,
76
+ errorCode: "ERR_NOT_A_DIRECTORY",
77
+ };
78
+ }
79
+ if (msg.includes("no TypeScript files") || msg.includes("No files found") || msg.includes("no files found")) {
80
+ return {
81
+ message: `${msg}. Ensure the directory contains TypeScript files and try again.`,
82
+ errorCode: "ERR_NO_FILES_FOUND",
83
+ };
84
+ }
85
+ if (msg.includes("Invalid regex pattern")) {
86
+ return {
87
+ message: `${msg}. Regex patterns must be valid JavaScript regular expressions.`,
88
+ errorCode: "ERR_INVALID_REGEX",
89
+ };
90
+ }
91
+ return {
92
+ message: msg,
93
+ errorCode: "ERR_UNKNOWN",
94
+ };
95
+ }
96
+ async function safeHandler(fn) {
97
+ try {
98
+ return await fn();
99
+ }
100
+ catch (error) {
59
101
  const message = error instanceof Error ? error.message : String(error);
102
+ const result = getErrorMessage(error instanceof Error ? error : new Error(message));
60
103
  return {
61
- content: [{ type: "text", text: `Error: ${message}` }],
104
+ content: [{ type: "text", text: `Error: ${result.message}` }],
105
+ structuredContent: { errorCode: result.errorCode, message: result.message },
62
106
  isError: true,
63
107
  };
64
- });
108
+ }
65
109
  }
66
110
  export { validateDirectory, getAnalyzer, safeHandler, clearAnalyzerCache };
67
111
  export function registerTools(server) {
@@ -70,7 +114,7 @@ export function registerTools(server) {
70
114
  title: "Scan Codebase",
71
115
  description: "Scan a directory and return a summary of all files, functions, classes, and their relationships. Use this first before any other analysis.",
72
116
  inputSchema: z.object({
73
- directory: z.string().describe("Path to the directory to scan (relative or absolute)"),
117
+ directory: z.string().min(1).describe("Path to the directory to scan (relative or absolute)"),
74
118
  }),
75
119
  outputSchema: z.object({
76
120
  directory: z.string(),
@@ -118,11 +162,12 @@ export function registerTools(server) {
118
162
  // Tool 2: find_function
119
163
  server.registerTool("find_function", {
120
164
  title: "Find Function or Class",
121
- description: "Search for a function or class by name across the codebase. Returns location, signature, callers, and callees.",
165
+ description: "Search for a function or class by name across the codebase. Returns location, signature, callers, and callees. When useRegex is true, the name is treated as a case-insensitive regex pattern.",
122
166
  inputSchema: z.object({
123
- name: z.string().describe("Name of the function or class to search for (case-insensitive partial match)"),
167
+ name: z.string().min(1).describe("Name of the function or class to search for"),
124
168
  directory: z.string().describe("Path to the codebase directory (must be scanned first)"),
125
169
  type: z.enum(["function", "class", "any"]).default("any").describe("Type of symbol to search for"),
170
+ useRegex: z.boolean().default(false).describe("Whether to treat name as a regex pattern (case-insensitive)"),
126
171
  }),
127
172
  outputSchema: z.object({
128
173
  matches: z.array(z.object({
@@ -139,11 +184,11 @@ export function registerTools(server) {
139
184
  callees: z.array(z.string()),
140
185
  totalMatches: z.number(),
141
186
  }),
142
- }, async ({ name, directory, type }) => {
187
+ }, async ({ name, directory, type, useRegex }) => {
143
188
  return await safeHandler(async () => {
144
189
  const validatedDir = validateDirectory(directory);
145
190
  const analyzer = await getAnalyzer(validatedDir);
146
- const matches = analyzer.findFunction(name, type);
191
+ const matches = analyzer.findFunction(name, type, useRegex);
147
192
  const callers = [];
148
193
  const callees = [];
149
194
  for (const match of matches) {
@@ -181,7 +226,7 @@ export function registerTools(server) {
181
226
  title: "Analyze Dependencies",
182
227
  description: "Returns the dependency graph between files. Can return the full graph or a subgraph for a specific file. Supports JSON, Mermaid, DOT, and PlantUML output formats.",
183
228
  inputSchema: z.object({
184
- directory: z.string().describe("Path to the codebase directory (must be scanned first)"),
229
+ directory: z.string().min(1).describe("Path to the codebase directory (must be scanned first)"),
185
230
  targetFile: z.string().optional().describe("Optional: filter to show only nodes related to this file"),
186
231
  format: z.enum(["json", "mermaid", "dot", "plantuml"]).default("json").describe("Output format: json for data, mermaid/dot/plantuml for visual diagram"),
187
232
  }),
@@ -214,7 +259,10 @@ export function registerTools(server) {
214
259
  let edges = analyzer.getEdges();
215
260
  let cycles = [];
216
261
  if (targetFile) {
217
- const sanitizedTarget = targetFile.replace(/[\/\\]/g, "").replace(/\.\./g, ".");
262
+ const sanitizedTarget = targetFile
263
+ .replace(/[\/\\]/g, "")
264
+ .replace(/\.\./g, ".")
265
+ .slice(0, 200);
218
266
  const matchingNodes = nodes.filter((n) => n.filePath.includes(targetFile) || n.label.includes(targetFile));
219
267
  const matchingIds = new Set(matchingNodes.map((n) => n.id));
220
268
  const expandedIds = new Set(matchingIds);
@@ -262,9 +310,9 @@ export function registerTools(server) {
262
310
  title: "Rank Impact",
263
311
  description: "Ranks files by centrality to identify the most important/central files in the codebase. Use this to answer questions like 'Where should I add a new feature?' or 'Which files are most critical?'",
264
312
  inputSchema: z.object({
265
- directory: z.string().describe("Path to the codebase directory (must be scanned first)"),
313
+ directory: z.string().min(1).describe("Path to the codebase directory (must be scanned first)"),
266
314
  metric: z.enum(["inDegree", "outDegree", "betweenness", "pagerank"]).default("inDegree").describe("Centrality metric: inDegree (most depended upon), outDegree (most dependencies), betweenness (most on critical paths), pagerank (most influential based on random walk)"),
267
- topN: z.number().default(10).describe("Number of top results to return"),
315
+ topN: z.number().min(1).default(10).describe("Number of top results to return"),
268
316
  }),
269
317
  outputSchema: z.object({
270
318
  metric: z.string(),
@@ -301,6 +349,7 @@ export function registerTools(server) {
301
349
  ranked: top.map((r) => ({
302
350
  relativePath: r.relativePath,
303
351
  score: r.score,
352
+ metric: r.metric,
304
353
  functionCount: r.functionCount,
305
354
  classCount: r.classCount,
306
355
  importCount: r.importCount,
@@ -319,9 +368,9 @@ export function registerTools(server) {
319
368
  title: "Trace Call Chain",
320
369
  description: "Traces the call chain / dependency path from one function or file to another. Shows the full path through the codebase.",
321
370
  inputSchema: z.object({
322
- from: z.string().describe("Starting function, class, or file name (case-insensitive partial match)"),
323
- to: z.string().describe("Target function, class, or file name (case-insensitive partial match)"),
324
- directory: z.string().describe("Path to the codebase directory (must be scanned first)"),
371
+ from: z.string().min(1).describe("Starting function, class, or file name"),
372
+ to: z.string().min(1).describe("Target function, class, or file name"),
373
+ directory: z.string().min(1).describe("Path to the codebase directory (must be scanned first)"),
325
374
  }),
326
375
  outputSchema: z.object({
327
376
  found: z.boolean(),
@@ -358,9 +407,9 @@ export function registerTools(server) {
358
407
  title: "Analyze Code Complexity",
359
408
  description: "Analyze code complexity metrics for each file in the codebase. Identifies files that may need refactoring based on cyclomatic complexity, cognitive complexity, nesting depth, and size.",
360
409
  inputSchema: z.object({
361
- directory: z.string().describe("Path to the codebase directory (must be scanned first)"),
410
+ directory: z.string().min(1).describe("Path to the codebase directory (must be scanned first)"),
362
411
  threshold: z.number().optional().describe("Minimum complexity score to report (0-100)"),
363
- topN: z.number().default(10).describe("Number of most complex files to return"),
412
+ topN: z.number().min(1).default(10).describe("Number of most complex files to return"),
364
413
  }),
365
414
  outputSchema: z.object({
366
415
  totalFiles: z.number(),
@@ -386,22 +435,42 @@ export function registerTools(server) {
386
435
  const validatedDir = validateDirectory(directory);
387
436
  const parser = new ProjectParser();
388
437
  const parseResult = await parser.parse(validatedDir);
389
- const project = new Project({
390
- skipAddingFilesFromTsConfig: true,
391
- compilerOptions: {
392
- allowJs: true,
393
- checkJs: false,
394
- noEmit: true,
395
- },
438
+ const results = parseResult.files.map((fileInfo) => {
439
+ const cyclomaticComplexity = calculateCyclomaticComplexityFromBodies(fileInfo.functions);
440
+ const cognitiveComplexity = calculateCognitiveComplexityFromBodies(fileInfo.functions);
441
+ const nestingDepth = calculateNestingDepthFromBodies(fileInfo.functions);
442
+ const linesOfCode = fileInfo.totalLines;
443
+ const functionCount = fileInfo.functions.length;
444
+ const classCount = fileInfo.classes.length;
445
+ const issues = identifyComplexityIssues({
446
+ cyclomaticComplexity,
447
+ cognitiveComplexity,
448
+ nestingDepth,
449
+ linesOfCode,
450
+ functionCount,
451
+ classCount,
452
+ });
453
+ const overallScore = calculateComplexityScore({
454
+ cyclomaticComplexity,
455
+ cognitiveComplexity,
456
+ nestingDepth,
457
+ linesOfCode,
458
+ functionCount,
459
+ classCount,
460
+ });
461
+ return {
462
+ filePath: fileInfo.filePath,
463
+ relativePath: fileInfo.relativePath,
464
+ cyclomaticComplexity,
465
+ cognitiveComplexity,
466
+ nestingDepth,
467
+ linesOfCode,
468
+ functionCount,
469
+ classCount,
470
+ overallScore,
471
+ issues,
472
+ };
396
473
  });
397
- const sourceFiles = project.getSourceFiles();
398
- for (const sf of sourceFiles) {
399
- project.removeSourceFile(sf);
400
- }
401
- const files = parseResult.files.map(f => f.filePath);
402
- project.addSourceFilesAtPaths(files);
403
- const complexityAnalyzer = new ComplexityAnalyzer(project, validatedDir);
404
- const results = complexityAnalyzer.analyzeProject(parseResult);
405
474
  const filteredResults = threshold
406
475
  ? results.filter(r => r.overallScore >= threshold)
407
476
  : results;
@@ -440,5 +509,91 @@ export function registerTools(server) {
440
509
  };
441
510
  });
442
511
  });
512
+ function calculateCyclomaticComplexityFromBodies(functions) {
513
+ let complexity = 1;
514
+ for (const fn of functions) {
515
+ const body = fn.body;
516
+ const keywords = ['if ', 'for ', 'while ', 'switch ', 'catch ', '&&', '||', '? '];
517
+ for (const kw of keywords) {
518
+ const count = (body.match(new RegExp(kw.replace(' ', '\\b'), 'g')) || []).length;
519
+ complexity += count;
520
+ }
521
+ }
522
+ return complexity;
523
+ }
524
+ function calculateCognitiveComplexityFromBodies(functions) {
525
+ let complexity = 0;
526
+ let nestingLevel = 0;
527
+ for (const fn of functions) {
528
+ const body = fn.body;
529
+ let i = 0;
530
+ while (i < body.length) {
531
+ const char = body[i];
532
+ if (char === '{') {
533
+ nestingLevel++;
534
+ }
535
+ else if (char === '}') {
536
+ nestingLevel = Math.max(0, nestingLevel - 1);
537
+ }
538
+ const remaining = body.slice(i);
539
+ if (remaining.startsWith('if ') || remaining.startsWith('for ') ||
540
+ remaining.startsWith('while ') || remaining.startsWith('switch ') ||
541
+ remaining.startsWith('catch ') || remaining.startsWith('try ')) {
542
+ complexity++;
543
+ complexity += nestingLevel;
544
+ }
545
+ i++;
546
+ }
547
+ }
548
+ return complexity;
549
+ }
550
+ function calculateNestingDepthFromBodies(functions) {
551
+ let maxNesting = 0;
552
+ let currentNesting = 0;
553
+ for (const fn of functions) {
554
+ for (const char of fn.body) {
555
+ if (char === '{') {
556
+ currentNesting++;
557
+ maxNesting = Math.max(maxNesting, currentNesting);
558
+ }
559
+ else if (char === '}') {
560
+ currentNesting = Math.max(0, currentNesting - 1);
561
+ }
562
+ }
563
+ }
564
+ return maxNesting;
565
+ }
566
+ function identifyComplexityIssues(metrics) {
567
+ const issues = [];
568
+ if (metrics.cyclomaticComplexity > 10) {
569
+ issues.push(`Cyclomatic complexity (${metrics.cyclomaticComplexity}) exceeds threshold of 10`);
570
+ }
571
+ if (metrics.cognitiveComplexity > 15) {
572
+ issues.push(`Cognitive complexity (${metrics.cognitiveComplexity}) exceeds threshold of 15`);
573
+ }
574
+ if (metrics.nestingDepth > 4) {
575
+ issues.push(`Nesting depth (${metrics.nestingDepth}) exceeds threshold of 4`);
576
+ }
577
+ if (metrics.linesOfCode > 500) {
578
+ issues.push(`Lines of code (${metrics.linesOfCode}) exceeds 500 - file is large`);
579
+ }
580
+ if (metrics.functionCount > 20) {
581
+ issues.push(`Function count (${metrics.functionCount}) exceeds 20 - too many functions`);
582
+ }
583
+ if (metrics.classCount > 10) {
584
+ issues.push(`Class count (${metrics.classCount}) exceeds 10 - too many classes`);
585
+ }
586
+ return issues;
587
+ }
588
+ function calculateComplexityScore(metrics) {
589
+ let score = 0;
590
+ score += Math.min(metrics.cyclomaticComplexity * 4, 25);
591
+ score += Math.min(metrics.cognitiveComplexity * 3, 25);
592
+ score += Math.min(metrics.nestingDepth * 5, 25);
593
+ score += Math.min((metrics.linesOfCode / 500) * 15, 15);
594
+ score += Math.min((metrics.functionCount / 20) * 5, 5);
595
+ score += Math.min((metrics.classCount / 10) * 5, 5);
596
+ return Math.min(Math.round(score), 100);
597
+ }
443
598
  }
444
599
  //# sourceMappingURL=tools.js.map