feat: Add dynamic codegraph_explore call budgets based on project size

Replaces fixed 6-call limit with adaptive budgets that scale from 2 calls for small projects (
This commit is contained in:
Colby McHenry
2026-04-06 09:21:49 -05:00
parent 8e8759ff13
commit 77432fe4ea
4 changed files with 53 additions and 3 deletions
+1 -1
View File
@@ -262,7 +262,7 @@ CodeGraph builds a semantic knowledge graph of codebases for faster, smarter cod
> This project has CodeGraph initialized (.codegraph/ exists). Use `codegraph_explore` as your PRIMARY tool — it returns full source code sections from all relevant files in one call.
>
> **Rules:**
> 1. Make at most 6 `codegraph_explore` calls — one broad query, then up to 5 focused follow-ups.
> 1. Follow the explore call budget in the `codegraph_explore` tool description — it scales automatically based on project size.
> 2. Do NOT re-read files that codegraph_explore already returned source code for. The source sections are complete and authoritative.
> 3. Only fall back to grep/glob/read for files listed under "Additional relevant files" if you need more detail, or if codegraph returned no results.
+1 -1
View File
@@ -23,7 +23,7 @@ CodeGraph builds a semantic knowledge graph of codebases for faster, smarter cod
> This project has CodeGraph initialized (.codegraph/ exists). Use \`codegraph_explore\` as your PRIMARY tool — it returns full source code sections from all relevant files in one call.
>
> **Rules:**
> 1. Make at most 6 \`codegraph_explore\` calls — one broad query, then up to 5 focused follow-ups.
> 1. Follow the explore call budget in the \`codegraph_explore\` tool description — it scales automatically based on project size.
> 2. Do NOT re-read files that codegraph_explore already returned source code for. The source sections are complete and authoritative.
> 3. Only fall back to grep/glob/read for files listed under "Additional relevant files" if you need more detail, or if codegraph returned no results.
+2 -1
View File
@@ -255,8 +255,9 @@ export class MCPServer {
* Handle tools/list request
*/
private async handleToolsList(request: JsonRpcRequest): Promise<void> {
this.retryInitIfNeeded();
this.transport.sendResult(request.id, {
tools: tools,
tools: this.toolHandler.getTools(),
});
}
+49
View File
@@ -15,6 +15,19 @@ import { join } from 'path';
/** Maximum output length to prevent context bloat (characters) */
const MAX_OUTPUT_LENGTH = 15000;
/**
* Calculate the recommended number of codegraph_explore calls based on project size.
* Larger codebases need more exploration calls to cover their surface area,
* but smaller ones should use fewer to avoid unnecessary overhead.
*/
export function getExploreBudget(fileCount: number): number {
if (fileCount < 1000) return 2;
if (fileCount < 5000) return 3;
if (fileCount < 15000) return 4;
if (fileCount < 25000) return 5;
return 6;
}
/**
* Mark a Claude session as having consulted MCP tools.
* This enables Grep/Glob/Bash commands that would otherwise be blocked.
@@ -298,6 +311,32 @@ export class ToolHandler {
return this.cg !== null;
}
/**
* Get tool definitions with dynamic descriptions based on project size.
* The codegraph_explore tool description includes a budget recommendation
* scaled to the number of indexed files.
*/
getTools(): ToolDefinition[] {
if (!this.cg) return tools;
try {
const stats = this.cg.getStats();
const budget = getExploreBudget(stats.fileCount);
return tools.map(tool => {
if (tool.name === 'codegraph_explore') {
return {
...tool,
description: `${tool.description} Budget: make at most ${budget} calls for this project (${stats.fileCount.toLocaleString()} files indexed).`,
};
}
return tool;
});
} catch {
return tools;
}
}
/**
* Get CodeGraph instance for a project
*
@@ -854,6 +893,16 @@ export class ToolHandler {
lines.push('---');
lines.push(`> **Complete source code is included above for ${filesIncluded} files.** You do NOT need to re-read these files — the relevant sections are already shown in full. Only use Read/Grep for files listed under "Additional relevant files" if you need more detail.`);
// Add explore budget note based on project size
try {
const stats = cg.getStats();
const budget = getExploreBudget(stats.fileCount);
lines.push('');
lines.push(`> **Explore budget: ${budget} calls max for this project (${stats.fileCount.toLocaleString()} files indexed).** Stop exploring and synthesize your answer once you've used ${budget} calls — do NOT make additional explore calls beyond this budget.`);
} catch {
// Stats unavailable — skip budget note
}
return this.textResult(lines.join('\n'));
}