codebase-analyzer-mcp 2.2.0 → 2.3.0
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.
- package/README.md +19 -0
- package/dist/cli/index.js +120 -44
- package/dist/mcp/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,11 +55,30 @@ Results include expandable sections — you only pay for what you drill into.
|
|
|
55
55
|
npx codebase-analyzer-mcp analyze . # Standard analysis
|
|
56
56
|
npx codebase-analyzer-mcp analyze . -d surface # Fast, free overview
|
|
57
57
|
npx codebase-analyzer-mcp analyze . -d deep -s # Full semantic analysis
|
|
58
|
+
npx codebase-analyzer-mcp analyze . -o analysis.md # Write structured markdown to file
|
|
59
|
+
npx codebase-analyzer-mcp analyze . -o analysis.json # Write JSON to file
|
|
58
60
|
npx codebase-analyzer-mcp query . "how is auth handled?" # Ask a question
|
|
59
61
|
npx codebase-analyzer-mcp patterns . # Find design patterns
|
|
60
62
|
npx codebase-analyzer-mcp dataflow . "user login" # Trace data flow
|
|
61
63
|
```
|
|
62
64
|
|
|
65
|
+
## Usage with Claude Code
|
|
66
|
+
|
|
67
|
+
Dump an analysis and reference it from your CLAUDE.md:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx codebase-analyzer-mcp analyze . -o docs/codebase-analysis.md
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then add to your project's CLAUDE.md:
|
|
74
|
+
|
|
75
|
+
```markdown
|
|
76
|
+
## Codebase Analysis
|
|
77
|
+
See [docs/codebase-analysis.md](docs/codebase-analysis.md) for full analysis.
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Claude Code will read the summary (~50 lines) for context, then drill into specific module sections as needed using `Read` with offset/limit.
|
|
81
|
+
|
|
63
82
|
## Development
|
|
64
83
|
|
|
65
84
|
```bash
|
package/dist/cli/index.js
CHANGED
|
@@ -44251,7 +44251,7 @@ var package_default;
|
|
|
44251
44251
|
var init_package = __esm(() => {
|
|
44252
44252
|
package_default = {
|
|
44253
44253
|
name: "codebase-analyzer-mcp",
|
|
44254
|
-
version: "2.
|
|
44254
|
+
version: "2.3.0",
|
|
44255
44255
|
description: "Multi-layer codebase analysis MCP server with Gemini AI and progressive disclosure.",
|
|
44256
44256
|
type: "module",
|
|
44257
44257
|
main: "dist/mcp/server.js",
|
|
@@ -74129,7 +74129,7 @@ function extractSourceName3(source) {
|
|
|
74129
74129
|
}
|
|
74130
74130
|
var program2 = new Command;
|
|
74131
74131
|
program2.name("cba").description("Codebase Analyzer - Multi-layer repository analysis with Gemini AI").version(package_default.version);
|
|
74132
|
-
program2.command("analyze").description("Perform architectural analysis of a repository").argument("<source>", "Local path or GitHub URL").option("-d, --depth <depth>", "Analysis depth: surface, standard, deep", "standard").option("-f, --focus <areas...>", "Specific areas to focus on").option("-e, --exclude <patterns...>", "Glob patterns to exclude").option("-t, --token-budget <tokens>", "Maximum token budget", "800000").option("-s, --semantics", "Include deep semantic analysis (uses LLM)").option("-v, --verbose", "Show detailed progress and subagent activity").option("-q, --quiet", "Only output the final result (no progress)").option("--format <format>", "Output format (json or markdown)", "json").action(async (source, options) => {
|
|
74132
|
+
program2.command("analyze").description("Perform architectural analysis of a repository").argument("<source>", "Local path or GitHub URL").option("-d, --depth <depth>", "Analysis depth: surface, standard, deep", "standard").option("-f, --focus <areas...>", "Specific areas to focus on").option("-e, --exclude <patterns...>", "Glob patterns to exclude").option("-t, --token-budget <tokens>", "Maximum token budget", "800000").option("-s, --semantics", "Include deep semantic analysis (uses LLM)").option("-v, --verbose", "Show detailed progress and subagent activity").option("-q, --quiet", "Only output the final result (no progress)").option("--format <format>", "Output format (json or markdown)", "json").option("-o, --output <path>", "Write analysis to a file (markdown by default, .json for JSON)").action(async (source, options) => {
|
|
74133
74133
|
try {
|
|
74134
74134
|
if (options.verbose)
|
|
74135
74135
|
logger.setVerbose(true);
|
|
@@ -74146,7 +74146,12 @@ program2.command("analyze").description("Perform architectural analysis of a rep
|
|
|
74146
74146
|
includeSemantics: options.semantics,
|
|
74147
74147
|
sourceName
|
|
74148
74148
|
});
|
|
74149
|
-
if (options.
|
|
74149
|
+
if (options.output) {
|
|
74150
|
+
const { writeFile: writeFile2 } = await import("fs/promises");
|
|
74151
|
+
const content = options.output.endsWith(".json") ? JSON.stringify(result, null, 2) : formatAnalysisAsMarkdown(result);
|
|
74152
|
+
await writeFile2(options.output, content, "utf-8");
|
|
74153
|
+
console.error(`Analysis written to ${options.output}`);
|
|
74154
|
+
} else if (options.format === "markdown") {
|
|
74150
74155
|
console.log(formatAnalysisAsMarkdown(result));
|
|
74151
74156
|
} else {
|
|
74152
74157
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -74220,66 +74225,137 @@ program2.command("capabilities").description("Show available analysis capabiliti
|
|
|
74220
74225
|
const { formatCapabilitiesResponse: formatCapabilitiesResponse2 } = await Promise.resolve().then(() => (init_capabilities(), exports_capabilities));
|
|
74221
74226
|
console.log(JSON.stringify(formatCapabilitiesResponse2(), null, 2));
|
|
74222
74227
|
});
|
|
74228
|
+
function renderTree(node, depth, maxDepth) {
|
|
74229
|
+
const SKIP_DIRS = new Set(["node_modules", ".git", "dist", ".next", "__pycache__", ".cache", "coverage"]);
|
|
74230
|
+
const lines = [];
|
|
74231
|
+
const indent = " ".repeat(depth);
|
|
74232
|
+
if (depth > 0) {
|
|
74233
|
+
lines.push(`${indent}${node.name}${node.type === "directory" ? "/" : ""}`);
|
|
74234
|
+
}
|
|
74235
|
+
if (node.type === "directory" && node.children && depth < maxDepth) {
|
|
74236
|
+
const dirs = node.children.filter((c) => c.type === "directory" && !SKIP_DIRS.has(c.name)).sort((a, b) => a.name.localeCompare(b.name));
|
|
74237
|
+
const files = node.children.filter((c) => c.type === "file").sort((a, b) => a.name.localeCompare(b.name));
|
|
74238
|
+
for (const dir of dirs) {
|
|
74239
|
+
lines.push(...renderTree(dir, depth + 1, maxDepth));
|
|
74240
|
+
}
|
|
74241
|
+
if (depth === 0 || files.length <= 5) {
|
|
74242
|
+
for (const file2 of files) {
|
|
74243
|
+
lines.push(`${" ".repeat(depth + 1)}${file2.name}`);
|
|
74244
|
+
}
|
|
74245
|
+
} else if (files.length > 5) {
|
|
74246
|
+
lines.push(`${" ".repeat(depth + 1)}... ${files.length} files`);
|
|
74247
|
+
}
|
|
74248
|
+
}
|
|
74249
|
+
return lines;
|
|
74250
|
+
}
|
|
74223
74251
|
function formatAnalysisAsMarkdown(result) {
|
|
74224
74252
|
const lines = [];
|
|
74225
|
-
|
|
74253
|
+
const name = result.repositoryMap?.name || "Repository";
|
|
74254
|
+
const date6 = new Date().toISOString().split("T")[0];
|
|
74255
|
+
lines.push(`<!-- codebase-analyzer-mcp | ${date6} | depth: ${result.depth} | id: ${result.analysisId} -->`);
|
|
74226
74256
|
lines.push("");
|
|
74227
|
-
lines.push(
|
|
74228
|
-
lines.push(`**Depth:** ${result.depth}`);
|
|
74229
|
-
lines.push(`**Duration:** ${result.durationMs}ms`);
|
|
74257
|
+
lines.push(`# ${name}`);
|
|
74230
74258
|
lines.push("");
|
|
74231
|
-
if (result.
|
|
74232
|
-
lines.push(
|
|
74233
|
-
lines.push(
|
|
74234
|
-
|
|
74235
|
-
|
|
74236
|
-
|
|
74259
|
+
if (result.forAgent?.quickSummary) {
|
|
74260
|
+
lines.push(result.forAgent.quickSummary);
|
|
74261
|
+
lines.push("");
|
|
74262
|
+
}
|
|
74263
|
+
const repoMap = result.repositoryMap;
|
|
74264
|
+
const summary = result.summary;
|
|
74265
|
+
if (repoMap || summary) {
|
|
74266
|
+
lines.push("## Overview");
|
|
74267
|
+
lines.push("");
|
|
74268
|
+
lines.push("| Metric | Value |");
|
|
74269
|
+
lines.push("|--------|-------|");
|
|
74270
|
+
if (repoMap?.fileCount != null) {
|
|
74271
|
+
lines.push(`| Files | ${repoMap.fileCount} |`);
|
|
74272
|
+
}
|
|
74273
|
+
if (repoMap?.languages?.length > 0) {
|
|
74274
|
+
const langs = repoMap.languages.map((l) => `${l.language} (${l.percentage}%)`).join(", ");
|
|
74275
|
+
lines.push(`| Languages | ${langs} |`);
|
|
74276
|
+
}
|
|
74277
|
+
if (summary?.architectureType) {
|
|
74278
|
+
lines.push(`| Architecture | ${summary.architectureType} |`);
|
|
74279
|
+
}
|
|
74280
|
+
if (summary?.complexity) {
|
|
74281
|
+
lines.push(`| Complexity | ${summary.complexity} |`);
|
|
74282
|
+
}
|
|
74283
|
+
if (repoMap?.entryPoints?.length > 0) {
|
|
74284
|
+
lines.push(`| Entry points | ${repoMap.entryPoints.slice(0, 5).join(", ")} |`);
|
|
74237
74285
|
}
|
|
74238
|
-
if (
|
|
74239
|
-
lines.push(
|
|
74286
|
+
if (summary?.techStack?.length > 0) {
|
|
74287
|
+
lines.push(`| Tech stack | ${summary.techStack.join(", ")} |`);
|
|
74288
|
+
}
|
|
74289
|
+
if (summary?.primaryPatterns?.length > 0) {
|
|
74290
|
+
lines.push(`| Patterns | ${summary.primaryPatterns.join(", ")} |`);
|
|
74240
74291
|
}
|
|
74241
74292
|
lines.push("");
|
|
74242
74293
|
}
|
|
74243
|
-
if (result.
|
|
74244
|
-
lines.push("##
|
|
74245
|
-
lines.push(`- **Total Files:** ${result.repositoryMap.fileCount}`);
|
|
74246
|
-
lines.push(`- **Estimated Tokens:** ${result.repositoryMap.estimatedTokens}`);
|
|
74247
|
-
lines.push(`- **Languages:** ${result.repositoryMap.languages?.map((l) => `${l.language} (${l.percentage}%)`).join(", ")}`);
|
|
74248
|
-
lines.push(`- **Entry Points:** ${result.repositoryMap.entryPoints?.slice(0, 5).join(", ")}`);
|
|
74294
|
+
if (result.forAgent?.keyInsights?.length > 0) {
|
|
74295
|
+
lines.push("## Key Insights");
|
|
74249
74296
|
lines.push("");
|
|
74250
|
-
|
|
74251
|
-
|
|
74252
|
-
lines.push("## Sections");
|
|
74253
|
-
for (const section of result.sections) {
|
|
74254
|
-
lines.push(`### ${section.title}`);
|
|
74255
|
-
lines.push(section.summary);
|
|
74256
|
-
if (section.canExpand) {
|
|
74257
|
-
lines.push(`*Expandable (detail: ~${section.expansionCost?.detail} tokens, full: ~${section.expansionCost?.full} tokens)*`);
|
|
74258
|
-
}
|
|
74259
|
-
lines.push("");
|
|
74297
|
+
for (const insight of result.forAgent.keyInsights) {
|
|
74298
|
+
lines.push(`- ${insight}`);
|
|
74260
74299
|
}
|
|
74300
|
+
lines.push("");
|
|
74261
74301
|
}
|
|
74262
|
-
if (
|
|
74263
|
-
lines.push("##
|
|
74264
|
-
lines.push(result.forAgent.quickSummary);
|
|
74302
|
+
if (repoMap?.structure) {
|
|
74303
|
+
lines.push("## Structure");
|
|
74265
74304
|
lines.push("");
|
|
74266
|
-
|
|
74267
|
-
|
|
74268
|
-
|
|
74269
|
-
|
|
74270
|
-
|
|
74305
|
+
lines.push("```");
|
|
74306
|
+
const treeLines = renderTree(repoMap.structure, 0, 3);
|
|
74307
|
+
lines.push(...treeLines);
|
|
74308
|
+
lines.push("```");
|
|
74309
|
+
lines.push("");
|
|
74310
|
+
}
|
|
74311
|
+
const moduleSections = result.sections?.filter((s2) => s2.type === "module") || [];
|
|
74312
|
+
if (moduleSections.length > 0) {
|
|
74313
|
+
lines.push("## Modules");
|
|
74314
|
+
lines.push("");
|
|
74315
|
+
for (const section of moduleSections) {
|
|
74316
|
+
const modulePath = section.id.replace("module_", "").replace(/_/g, "/");
|
|
74317
|
+
const detail = section.detail;
|
|
74318
|
+
let header = `### ${modulePath}`;
|
|
74319
|
+
const meta3 = [];
|
|
74320
|
+
if (section.summary)
|
|
74321
|
+
meta3.push(section.summary);
|
|
74322
|
+
if (meta3.length)
|
|
74323
|
+
header += ` — ${meta3.join(", ")}`;
|
|
74324
|
+
lines.push(header);
|
|
74271
74325
|
lines.push("");
|
|
74272
|
-
|
|
74273
|
-
|
|
74274
|
-
|
|
74275
|
-
|
|
74276
|
-
|
|
74326
|
+
if (detail) {
|
|
74327
|
+
if (detail.type === "documentation") {
|
|
74328
|
+
if (detail.headings?.length > 0) {
|
|
74329
|
+
lines.push(`Headings: ${detail.headings.map((h2) => h2.title).join(", ")}`);
|
|
74330
|
+
}
|
|
74331
|
+
} else {
|
|
74332
|
+
if (detail.exports?.length > 0) {
|
|
74333
|
+
lines.push(`Exports: ${detail.exports.slice(0, 10).join(", ")}${detail.exports.length > 10 ? ", ..." : ""}`);
|
|
74334
|
+
}
|
|
74335
|
+
const cx = detail.complexity;
|
|
74336
|
+
if (cx) {
|
|
74337
|
+
lines.push(`Complexity: ${cx.cyclomaticComplexity} cyclomatic | ${cx.linesOfCode} LOC | ${cx.functionCount} functions | ${cx.classCount} classes`);
|
|
74338
|
+
}
|
|
74339
|
+
if (detail.symbolCount != null || detail.importCount != null) {
|
|
74340
|
+
lines.push(`Symbols: ${detail.symbolCount ?? 0} | Imports: ${detail.importCount ?? 0}`);
|
|
74341
|
+
}
|
|
74342
|
+
}
|
|
74343
|
+
lines.push("");
|
|
74277
74344
|
}
|
|
74345
|
+
}
|
|
74346
|
+
}
|
|
74347
|
+
const otherSections = result.sections?.filter((s2) => s2.type !== "module") || [];
|
|
74348
|
+
if (otherSections.length > 0) {
|
|
74349
|
+
for (const section of otherSections) {
|
|
74350
|
+
lines.push(`## ${section.title}`);
|
|
74351
|
+
lines.push("");
|
|
74352
|
+
lines.push(section.summary);
|
|
74278
74353
|
lines.push("");
|
|
74279
74354
|
}
|
|
74280
74355
|
}
|
|
74281
74356
|
if (result.warnings?.length > 0) {
|
|
74282
74357
|
lines.push("## Warnings");
|
|
74358
|
+
lines.push("");
|
|
74283
74359
|
for (const warning of result.warnings) {
|
|
74284
74360
|
lines.push(`- ${warning}`);
|
|
74285
74361
|
}
|
package/dist/mcp/server.js
CHANGED
|
@@ -71136,7 +71136,7 @@ function buildFallbackAnswer(question, analysisId, cached2, scored, fileContents
|
|
|
71136
71136
|
// package.json
|
|
71137
71137
|
var package_default = {
|
|
71138
71138
|
name: "codebase-analyzer-mcp",
|
|
71139
|
-
version: "2.
|
|
71139
|
+
version: "2.3.0",
|
|
71140
71140
|
description: "Multi-layer codebase analysis MCP server with Gemini AI and progressive disclosure.",
|
|
71141
71141
|
type: "module",
|
|
71142
71142
|
main: "dist/mcp/server.js",
|