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

Method getTools

src/mcp/tools.ts:1482–1551  ·  view source on GitHub ↗

* 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. Honors the CODEGRAPH_MCP_TOOLS * allowlist so a trimmed surface is reflected in ListTools.

()

Source from the content-addressed store, hash-verified

1480 * allowlist so a trimmed surface is reflected in ListTools.
1481 */
1482 getTools(): ToolDefinition[] {
1483 const allow = this.toolAllowlist();
1484 // No explicit allowlist → the default 4-tool surface (see
1485 // DEFAULT_MCP_TOOLS for the evidence). An allowlist replaces the
1486 // default entirely, so any defined tool can be re-enabled.
1487 let visible = allow
1488 ? tools.filter(t => allow.has(t.name.replace(/^codegraph_/, '')))
1489 : tools.filter(t => DEFAULT_MCP_TOOLS.has(t.name.replace(/^codegraph_/, '')));
1490 // No default project loaded → no-root-index case (#993): a gateway server
1491 // started outside any repo, or a monorepo root whose indexes live in
1492 // sub-projects. With nothing to fall back to, EVERY call needs an explicit
1493 // projectPath, so mark it required in the schema — a high-salience nudge the
1494 // agent acts on, where SERVER_INSTRUCTIONS_NO_ROOT_INDEX's prose alone
1495 // wasn't enough (the reporter had to add an AGENTS.md note). `this.cg` is
1496 // settled by `retryInitIfNeeded()` before `handleToolsList` calls us, so a
1497 // null here means "genuinely no default", not a startup race. When a default
1498 // IS open we leave projectPath optional (below): a bare call falls back to
1499 // it, exactly as in the common single-project launch.
1500 if (!this.cg) return withRequiredProjectPath(visible);
1501
1502 try {
1503 const stats = this.cg.getStats();
1504 const budget = getExploreBudget(stats.fileCount);
1505
1506 // Tiny-repo tool gating: on projects under TINY_REPO_FILE_THRESHOLD
1507 // files, only expose the core trio (search, node, explore) — one
1508 // below even the 4-tool default: at this scale callers, too, reduces
1509 // to one grep. (Historical note: the audit below ran when context and
1510 // trace still existed; its "5 core tools" are today's trio.)
1511 //
1512 // n=2 audits ruled out cutting below 5 tools:
1513 // - 3-tool gate (search + context + trace): cost regressed on
1514 // cobra/ky/sinatra. The agent fell back to raw Reads to cover
1515 // what codegraph_node + codegraph_explore would have answered.
1516 // - 1-tool gate (search only): catastrophic regression — express
1517 // went from -43% WIN to +107% LOSS. With only search, the agent
1518 // can't navigate the call graph structurally and reads everything.
1519 //
1520 // 5 is the empirical lower bound. Tools beyond search/context/
1521 // node/explore/trace pay overhead that the agent doesn't recoup
1522 // on tiny-repo flow questions.
1523 // ITER4: raise threshold 150 → 500 so single-file frameworks
1524 // (sinatra at 159, slim_framework around 200) also get the
1525 // 5-tool surface. The empirical 5-tool floor was set on <150
1526 // probes; iter3 measurement showed sinatra is structurally the
1527 // SAME problem as cobra (single-file WITHOUT-arm Read wins),
1528 // so it deserves the same gating.
1529 const TINY_REPO_FILE_THRESHOLD = 500;
1530 const TINY_REPO_CORE_TOOLS = new Set([
1531 'codegraph_explore',
1532 'codegraph_search',
1533 'codegraph_node',
1534 ]);
1535 if (stats.fileCount < TINY_REPO_FILE_THRESHOLD) {
1536 visible = visible.filter(t => TINY_REPO_CORE_TOOLS.has(t.name));
1537 }
1538
1539 return visible.map(tool => {

Callers 4

handleToolsListMethod · 0.80
listedFunction · 0.80

Calls 5

toolAllowlistMethod · 0.95
withRequiredProjectPathFunction · 0.85
getExploreBudgetFunction · 0.85
hasMethod · 0.80
getStatsMethod · 0.45

Tested by 1

listedFunction · 0.64