A budget pin over every MCP read tool (part of #4198) - #4224
Merged
Merged
Conversation
McpReadToolBudgetLiveTests reflects over every [McpServerTool] method on every [McpServerToolType] class in the Darling service assembly, excludes write tools/analyze_*/compare_*/audit_config, binds each tool's DI services and server_name generically, and asserts the reply stays under McpResponseBudget.DefaultBytes unless the tool is named in an explicit, byte-stamped exemption roster. A fix lands by deleting its row. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
erikdarlingdata
marked this pull request as ready for review
September 25, 2026 05:23
erikdarlingdata
enabled auto-merge (squash)
September 25, 2026 05:23
#4205 merged first and owns McpResponseBudget.cs. Its version adds CollectionLogFleetDefaultLimit alongside DefaultBytes. This PR's copy is dropped in favor of that version, as the PR body noted would be required. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
This was referenced Sep 25, 2026
Merged
erikdarlingdata
disabled auto-merge
September 25, 2026 12:25
…as merged After merging dev, the per-tool fixes for get_blocking (#4267), get_collection_log (#4265), get_query_store_regressions (#4264), get_collection_health (#4268), describe_custom_view_catalog (#4272) and get_query_store_top (#4273) are all in, and get_fleet_overview already fit (CI's stale-exemption message). Every row goes; CI's live run decides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
CI on 08e6e81 measured get_collection_health at 35,145 B, over the 32 KB default. #4268 compacts only healthy collectors with nothing to report, and this fixture's collectors are not healthy, so nothing compacts. The row goes back, under #4198, which stays open for it. Every other exempt tool fits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
This was referenced Sep 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #4198.
Why
#4198 measured every MCP read tool at default arguments on two busy production stores. It found 12 tools over 50 KB and 3 over 100 KB. The worst,
get_query_store_regressions, returned 211 KB. The ruling: at default arguments, every read tool stays under one shared 32 KB budget,McpResponseBudget.DefaultBytes. The per-tool PRs fixed each offender's defaults.This PR is the test that holds that line. It measures every MCP read tool on a seeded store and fails when a tool goes over the budget without a row on file.
What changes
The diff is one new test file,
Darling/Darling.Tests/McpReadToolBudgetLiveTests.cs. It uses theMcpResponseBudget.DefaultBytesconstant that #4205 added.[McpServerTool]method in the Darling service assembly by reflection. A new tool is measured with no change to the test.analyze_*,compare_*andaudit_configby name. It skips the 16 write tools through an exact list, because no name pattern catches them all. A new write tool must be added to that list, or the test calls it.server_nameset to the seeded server, and every other optional parameter at its default.get_fleet_overviewa fleet-sized answer.ExemptOffendersmust still be over the budget. When a fix brings a listed tool under, the test fails until its row is deleted.The exempt list
The list began with seven tools. The per-tool PRs fixed five of them:
get_query_store_regressions(#4264),get_collection_log(#4265),get_blocking(#4267),describe_custom_view_catalog(#4272) andget_query_store_top(#4273).get_fleet_overviewalready fit by the time this PR mergeddev.One row is left:
get_collection_healthIt stays open under #4198. CI run 36142467742 measured the fixed tools:
describe_custom_view_catalog30,215 bytes,get_query_store_clutter26,353,get_query_store_regressions24,510,get_collection_log21,929,get_query_store_top16,911 andget_fleet_overview2,087.Known gaps
Some tools pass without a real test:
get_custom_alert_rule,get_custom_view,get_perfmon_trend,get_plan_xml,get_query_trend,get_wait_trend,run_custom_view_panel,validate_custom_alert_ruleandvalidate_custom_view.get_query_heatmap(395 bytes) needs many time buckets, and the fixture has two.get_deadlock_detailmeasured 19,261 bytes andget_plan_corrections23,125.get_analysis_findings,get_index_usage,get_object_locking,get_active_queries, and every PostgreSQL-target read (get_pg_*).Left for #4198
get_collection_healthon a server whose collectors are not healthy (the row above).Test plan
180c2cdc: build, Darling PostgreSQL tests and Lite tests all pass.08e6e818, emptied the exempt list. The test failed there onget_collection_healthat 35,145 bytes, so180c2cdcput that row back. The same run's other failure,PgTargetBlockingTests, is the known flake CI flake: PgTarget anomaly/blocking worst-tile assertions fail on first attempts unrelated to the change #4274.McpReadToolBudgetLiveTestsandDocCommentHygieneagainst a local rig, 78 tests, 0 failed.CHANGELOG entry
None. This PR changes tests only.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ