Skip to content

MCP budget: size get_active_queries defaults to the response budget (#4198) - #4261

Merged
erikdarlingdata merged 10 commits into
devfrom
fix/4198-active-queries-default
Sep 25, 2026
Merged

erikdarlingdata merged 10 commits into
devfrom
fix/4198-active-queries-default

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Part of #4198.

Why

get_active_queries had no default response-size budget. A busy production store's default call (limit 50, hours_back 1) measured 56,586 bytes on 2026-09-25, well over the shared 32 KB McpResponseBudget.DefaultBytes.

Unlike get_deadlock_detail (#4254), this tool has no single dominant wide field. Each row carries twenty-three fields. The fixed columns (collection_time, every wait/blocking/memory field, login_name, host_name, program_name) add up across the page even before query_text is counted. A synthetic 50-row page of this shape measured 81,489 bytes with the old code. Every optional field was populated, a fifth of rows carrying a long literal list. Isolating the fixed-column cost: even at query_text = "", 50 rows of this shape run close to the budget on their own.

What changes

Both Darling (DarlingMcpSessionTools.GetActiveQueries) and Lite (McpSessionTools.GetActiveQueries), matching the shape #4254 established:

  • Default limit comes down from 50 to 25, sized so a full default page of wide rows fits the budget.
  • query_text previews to 500 characters by default (down from a flat, unconditional 2000-character cap) with a new per-row query_text_truncated flag.
  • A new full_text opt-in argument (default false) returns every row's whole text. This is the same shape get_store_query_stats' full_text and get_deadlock_detail's full_graph use.
  • truncated / total_snapshots already told a caller who wants more to raise limit or narrow hours_back. That is unchanged.

Lane W2 (this update)

The tool's served head description is unchanged at 616 bytes. The new preview/opt-in note went after the <<GUIDE>> marker instead. A separate pin, McpToolGuideTests.EveryConvertedHead_StaysAtOrUnder620Characters, caps converted heads at 620 characters, tighter than the general 1,000-byte cap this repo's skill notes describe.

Test plan

New live test Darling/Darling.Tests/DarlingMcpActiveQueriesBudgetLiveTests.cs plants 50 rows shaped like a busy server. It is its own file, not the shared seeding helpers, because many #4198 lanes ran against this rig tonight.

  • Before the fix: 81,489 bytes (over budget).
  • After the fix: 29,821 bytes (under the 32,768-byte budget, about 2,900 bytes of headroom).
  • full_query_text: true opts back into the whole text, and query_text_truncated is never true on that call.

New Lite test GetActiveQueries_Default_StaysUnderResponseBudget_WithFiftyRealisticRows in Lite.Tests/McpPageContractTests.cs asserts the same shape and the same opt-in behavior (DuckDB, no rig needed).

  • Darling.Tests build: 0 Warning(s), 0 Error(s).
  • Lite.Tests build: 0 Warning(s), 0 Error(s).
  • Full Darling.Tests suite (rig on port 55983, UTC, seeded fresh darlingtest): 13,849 total, 5 failed, 47 skipped, 1 not run. Every failure traced back to this change. All fixed in a follow-up commit: a param-order pin, the 620-char head cap noted above, and a <see cref> type/file error.
  • Targeted re-run after the fixes (DarlingMcpSessionToolsSurfaceAndSqlTests, McpToolGuideTests, McpToolGuideHeadsSqlCoreActiveQueriesTests, DocCommentHygieneTests, McpToolsListBudgetTests, McpPayloadContractCensusTests, DarlingMcpSessionToolsTests, DarlingMcpActiveQueriesBudgetLiveTests, McpFilterSemanticsLivePostgresTests): 181 total, 0 failed.
  • The full Darling.Tests suite was not re-run a second time after the follow-up fixes, because of the context budget. The targeted re-run above covers every class that failed plus the directly related ones. Worth a final full run before merge.
  • Full Lite.Tests suite (after the same fixes): 5,340 total, 0 failed.
  • git merge origin/dev done. One conflict, in McpToolsListBudgetTests.cs's ceiling constant, resolved by keeping both change-log comments and re-measuring the constant.

Lane W2 (this update, no rig: DARLING_TEST_PG unset, live classes skip)

  • Darling.Tests build: 0 Warning(s), 0 Error(s).
  • Lite.Tests build: 0 Warning(s), 0 Error(s).
  • New pin (ReadEndpoints_ActiveQueries_KeepsTheTwoThousandCharacterWebPreview) proven to fail on the pre-fix row shape, then confirmed passing again after restoring the fix.
  • Targeted Darling.Tests run: every class this update touches, every class reading DarlingWebEndpoints.cs (50 classes, grep-derived), plus McpToolsListBudgetTests, McpPayloadContractCensusTests, and DocCommentHygiene. 1,506 total, 0 failed, 33 skipped (all live, no rig).
  • Full Lite.Tests suite, run once: 5,340 total, 0 failed, 0 skipped.
  • Full Darling.Tests live suite against a real rig: CI decides (no rig in this lane).

CHANGELOG entry

SECTION: Fixed
ENTRY:


Generated with Claude Code

https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ

erikdarlingdata and others added 7 commits September 25, 2026 03:21
A busy production store's default call (limit 50) measured 56,586 bytes,
over McpResponseBudget.DefaultBytes (32 KB). Twenty-three fields per row
mean the fixed columns alone run about 700 bytes/row before query_text is
counted, so both the default row limit (50 -> 25) and query_text's preview
(now 500 chars, full_query_text opts back in) come down, on both Darling
and Lite.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
…s-default

# Conflicts:
#	Darling/Darling.Tests/McpToolsListBudgetTests.cs
The full-suite run surfaced five failures, all from the active-queries
budget change: a hardcoded param-order pin missing full_query_text, the
served head over its own separate 620-character target (moved the preview
note after <<GUIDE>> instead, keeping the head at its original 616 bytes),
and a doc comment that crefed a file name instead of a real type.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
DarlingMcpSessionTools.GetActiveQueries now delegates to an internal
overload that takes an explicit query-text preview length (the split
#3897's trend tools use: one MCP-facing method, one budget-taking
overload). The MCP tool passes 500 (or null for full_query_text), and
DarlingWebEndpoints' /api/read row passes 2000 - the pre-#4198 budget
every caller got - so the web viewer's page doesn't shrink under the
new MCP default. query_text_truncated stays honest on both paths.

Adds a no-rig source-text pin (ReadEndpoints_ActiveQueries_
KeepsTheTwoThousandCharacterWebPreview) that fails if the web row
stops calling the overload with 2000; verified it fails against the
pre-fix row shape, then confirmed it passes again after restoring
the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
Matches get_store_query_stats' full_text (the #4198 precedent) and
the other #4198 tools, on both Darling and Lite. Description text is
unchanged, so each param's pinned byte count stays 84; the shorter
property name shrinks the served tools/list JSON by 6 bytes on each
product, banked by lowering TotalCeilingBytes to the measured total
(171,906 Darling, 90,057 Lite).

Lite's UI reads LocalDataService directly, not this MCP tool (grep
confirms no Lite UI call site), so no UI-facing change there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
…CutKeys

All deltas: audit+plan_corrections+deadlock_detail (dev) + active_queries TH+W2
(HEAD). query_text_truncated merges session+plan_correction files into one entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
Lane W2 added ReadRepoFileLf to DarlingWebEndpointsTests.cs for a
single-line dispatch-table pin; no line-break anchor, so it belongs in
s_lfSubjects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
@erikdarlingdata erikdarlingdata changed the title DO NOT MERGE (MCP budget): size get_active_queries defaults to the response budget (#4198) MCP budget: size get_active_queries defaults to the response budget (#4198) Sep 25, 2026
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 25, 2026 09:14
@erikdarlingdata
erikdarlingdata enabled auto-merge (squash) September 25, 2026 09:14
erikdarlingdata and others added 3 commits September 25, 2026 06:17
Darling: HEAD=172,407 (active_queries +187) + dev=172,367 -> 172,554
Lite: HEAD=90,447 (active_queries +176) + dev=90,418 -> 90,594
Census: merge active_queries files into query_text_truncated + keep top_query_text_truncated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
@erikdarlingdata
erikdarlingdata merged commit 5f9a167 into dev Sep 25, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4198-active-queries-default branch September 25, 2026 11:17
erikdarlingdata added a commit that referenced this pull request Sep 25, 2026
Measured with McpToolsListBudgetTests after merging origin/dev (#4261,
#4258, #4265, #4267, #4264, #4266 and #4268) plus this PR's catalog
changes. Budget, census and tool-guide classes: 219/219.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
erikdarlingdata added a commit that referenced this pull request Sep 25, 2026
…nder the response budget (#4198) (#4272)

* MCP budget: describe_custom_view_catalog default groups measures by source (#4198)

Default default-argument call was 98,173 bytes (#4198's own measurement), three
times the tool's 32 KB budget. It is pure static reference data (no server/store
read), so the cut groups the 179 measures by source and keeps only
key/displayName/kind/unitFamily/validAggregates per measure; source=<name>
drills into one source's full detail, full_detail=true returns the original
shape unfiltered. /api/catalog (the web Custom Views editor) calls the
underlying builder directly, never this MCP method, so it is unaffected -
pinned in DarlingComposeTests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3

* Trigger CI (draft PR skipped the Build workflow)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ

* Add comment to DarlingMcpCustomViewCatalogSizeTests.cs to trigger Build CI

GitHub did not fire pull_request events for this draft-opened PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ

* fix(#4272): reword validAggregates description - compact drops allowedDimensions, source=<name> returns it

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3

* #4272: set TotalCeilingBytes to the measured 174,236 after merging dev

Measured with McpToolsListBudgetTests after merging origin/dev (#4261,
#4258, #4265, #4267, #4264, #4266 and #4268) plus this PR's catalog
changes. Budget, census and tool-guide classes: 219/219.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant