feat(context-budget): surface unused MCP server overhead per project#79
feat(context-budget): surface unused MCP server overhead per project#79lfl1337 wants to merge 8 commits intogetagentseal:mainfrom
Conversation
Claude Code CLI (`claude mcp add ...`) writes MCP server configs to ~/.claude.json, not to settings.json. The existing settings.json-only discovery missed this common config path, making the unused-server detection effectively invisible for users who configure MCPs via the CLI. Reads both the top-level mcpServers (user scope) and the per-project projects[cwd].mcpServers block (local scope). Falls back to a slash- normalized key lookup to match Windows path variants. Scope: Claude Code only. Codex/Cursor/OpenCode MCP configs use different file formats (TOML, custom JSON) and need their own reader; tracked as follow-up.
Mirrors the countMcpTools fix (previous commit) in the sibling loadMcpConfigs used by detectUnusedMcp. Without this, the optimize view never flagged unused MCP servers for users who configure MCPs via claude mcp add (which writes to ~/.claude.json, not settings.json). Reads top-level mcpServers for user scope and projects[cwd].mcpServers for local scope, with slash-normalized lookup for Windows paths. Also adds a file-level beforeEach that cleans stale ~/.claude.json from the mocked home directory between tests to prevent state bleed across test suites.
|
Closing this pending further review - the feature doesn't surface MCP servers as expected in their setup. Will reopen after investigating the actual rendering path. |
firstlook
Details
|
|
Hi, In src/context-budget.ts, countMcpTools treats an empty calledServers Set the same as calledServers being undefined and returns unused=[], so projects that made zero MCP calls will never report unused declared servers or unusedTokens. Severity: action required | Category: correctness How to fix: Differentiate undefined vs empty Agent prompt to fix - you can give this to your LLM of choice:
Found by Qodo code review. FYI, Qodo is free for open-source. |
…empty set An empty Set means zero MCP calls were made in the period - all declared servers are unused. Previously this case was collapsed with calledServers=undefined (no usage data), so countMcpTools returned unused=[] instead of the full server list. Adds a test covering the empty-Set path.
|
Fixed in 3357df4. The root cause: Added a test covering the empty-Set case. |

Summary
Closes #2. The context budget now distinguishes between MCP servers declared in config and MCP servers actually called during the scanned period, and surfaces the waste as both a dashboard signal and enhanced wording in
codeburn optimize.Changes
ContextBudget.mcpToolsextended withdeclared,used,unused,unusedTokensestimateContextBudget(cwd, modelContext, calledServers?)- third parameter optional, backward compatibledashboard.tsxloadBudgetsaggregatesmcpBreakdownkeys per project and passes them to the estimatordetectUnusedMcpexplanation now shows per-session token cost in addition to the totalcountMcpToolsalso reads~/.claude.json- both the top-levelmcpServers(user scope) andprojects[cwd].mcpServers(project scope). This is whereclaude mcp add <name>writes config, and the previoussettings.json-only discovery missed it.Scope
Currently Claude Code only. Codex (
~/.codex/config.tomlTOML), Cursor (~/.cursor/mcp.json), and OpenCode (~/.config/opencode/opencode.json) each use their own MCP config format. Multi-provider MCP config reading is tracked as a follow-up PR because each format needs its own reader and the--providerflag scoping deserves its own design discussion.Before / After
Dashboard overhead column stays blue when all declared MCP servers are in use, orange when at least one is declared but never called.
codeburn optimizefinding:Test plan
npm testgreen (240/240, +9 new tests coveringcalledServersbreakdown and~/.claude.jsondiscovery)detectUnusedMcpbehavior unchanged when no MCPs are configuredplugin:foo:barserver names correctly normalize toplugin_foo_barfor comparison with session data~/.claude.jsontop-levelmcpServerspicked up~/.claude.jsonprojects[cwd].mcpServerspicked up.mcp.json+~/.claude.jsonmerged into union set