Skip to content

MCP budget: add get_collection_log per-server response budget and error_message preview (#4198) - #4265

Merged
erikdarlingdata merged 6 commits into
devfrom
fix/4198-collection-log-default
Sep 25, 2026
Merged

erikdarlingdata merged 6 commits into
devfrom
fix/4198-collection-log-default

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Part of #4198.

Why

get_collection_log's one-server form had no response-size budget. At the old 200-row
default it measured 90,514 bytes on a seeded SQL Server-target store and 89,593 bytes on
a seeded PostgreSQL-target store. Both are about 2.7x the shared 32 KB
McpResponseBudget.DefaultBytes target #4198 set. The fleet-wide form (server_name
omitted) was already sized in #4205. This is the per-server form's own pass.

What changes

  • New McpResponseBudget.CollectionLogPerServerDefaultLimit (58), shared by Darling and
    Lite. Sized against the wider of the two target-kind row shapes. A SQL Server target's
    query_store rows carry the plan_fetch/text_fetch deferred-fetch split that a
    PostgreSQL target's collectors never populate. That makes the SQL Server shape
    consistently the heavier one.
  • error_message is the tool's one unbounded text field. It is capped at 4000 characters
    at write time but was never previewed at read time. It is now a 500-character preview by
    default, with a new error_message_truncated flag marking a cut. Pass full_text (the
    same shape get_store_query_stats already uses) to get the whole field back. This
    guards cases a lower row limit alone does not. An unhealthy server's default
    (unfiltered) page is mostly ERROR rows near the 4000-character ceiling.
  • Both changes are mirrored field-for-field in the Lite twin
    (Lite/Mcp/McpHealthTools.cs), including the tool-guide prose.
  • The web viewer's /api/read row for get_collection_log (DarlingWebEndpoints.cs)
    keeps today's behavior. It already passed limit: 200 (unaffected by the new lower MCP
    default) and now also passes full_text: true. An operator reading the Collection Log
    grid still gets the whole error_message, not a preview. The two
    wwwroot/js/pages/server-tabs.js panels (Collection Log tables) call this row with
    their own explicit limit: 200 and need no change. Pinned by a new no-rig source-text
    test (CollectionLogWebRowPreservesFullTextPinTests) so a future edit to that row
    cannot drop either argument silently.
  • Added FieldPreviewCutKeys to McpPayloadContractCensusTests (origin/dev did not have
    it when this lane started) and rostered error_message_truncated there. Merged with
    the two entries MCP read tools have no default response-size budget: at default arguments 12 tools return >50 KB and 3 return >100 KB for one server, more than an agent client's per-result cap #4198 lanes TB and the get_plan_corrections lane added concurrently.
  • McpToolsListBudget pins and TotalCeilingBytes updated on both products for the new
    full_text parameter. Merged with the concurrent deltas from the same wave (see the
    change-log comments above each constant).

The fleet-wide form (server_name omitted) is untouched, as #4205 already sized it.

Test plan

Darling, against a rig seeded on both target kinds (200 rows/server, mixing server-scoped
and enumerated collectors, 10% carrying a moderate error_message):

  • New McpCollectionLogPerServerResponseBudgetLivePostgresTests: before the fix, SQL
    Server target measured 90,514 bytes and PostgreSQL target 89,593 bytes (both over
    budget). After the fix: 28,340 bytes and 28,057 bytes (both under the 32,768-byte
    budget).
  • After the merge with origin/dev, these all passed: McpPayloadContractCensusTests,
    McpToolsListBudgetTests, PgCappedReadSurfaceTests,
    CollectionLogWebRowPreservesFullTextPinTests (new), DarlingCollectionLogReadTests,
    McpFleetResponseBudgetLivePostgresTests, McpFilterSemanticsLivePostgresTests,
    AsOfWindowAnchorTests. 73 tests in the first group's run, 15 in the second.

Lite (no rig, local DuckDB):

  • New CollectionLogPerServerResponseBudgetToolTests: default call on 200 seeded rows
    stays under budget.

  • McpToolsListBudgetTests, CollectionLogFleetFormToolTests, CollectionLogToolTests:
    all green.

  • Full Darling.Tests suite (targeted classes above were run individually. The full
    suite was not run in this lane due to context budget).

  • Full Lite.Tests suite (same reason).

Both builds are 0 Warning(s), 0 Error(s).

CHANGELOG entry

SECTION: Fixed
ENTRY:

Generated with Claude Code

https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ

erikdarlingdata and others added 3 commits September 25, 2026 04:12
Measures a default per-server call's UTF-8 bytes on both target kinds
against a seeded store: 90,514 bytes (SQL Server target), 89,593 bytes
(PostgreSQL target) at the old 200-row default, both well over the
32 KB McpResponseBudget.DefaultBytes target.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TszxYhJJbTEh4LrZ56NYo3
…age (#4198)

Sizes get_collection_log's one-server form (both products) so a
default call stays under the shared 32 KB MCP response budget:

- Lowers the per-server default row limit from 200 to
  McpResponseBudget.CollectionLogPerServerDefaultLimit (58), sized
  against the wider of the two target-kind row shapes (SQL Server
  targets add plan_fetch/text_fetch, PostgreSQL targets never do).
- Previews error_message to 500 characters by default
  (error_message_truncated marks a cut), with a new full_text
  opt-in — the same shape get_store_query_stats already uses.
- Web viewer's /api/read row for get_collection_log keeps today's
  behavior explicitly (limit 200, full_text: true), pinned by a
  no-rig source-text test.
- Adds FieldPreviewCutKeys to McpPayloadContractCensusTests, since
  no other merged PR had added it yet.

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

# Conflicts:
#	Darling/Darling.Tests/McpPayloadContractCensusTests.cs
#	Darling/Darling.Tests/McpToolsListBudgetTests.cs
#	Lite.Tests/McpToolsListBudgetTests.cs
@erikdarlingdata erikdarlingdata changed the title DO NOT MERGE (MCP budget): size get_collection_log's per-server default under the response budget (#4198) MCP budget: add get_collection_log per-server response budget and error_message preview (#4198) Sep 25, 2026
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 25, 2026 09:03
@erikdarlingdata
erikdarlingdata enabled auto-merge (squash) September 25, 2026 09:03
erikdarlingdata and others added 3 commits September 25, 2026 06:17
Darling: HEAD=172,347 (collection_log +127) + dev=172,367 -> 172,494
Lite: HEAD=90,387 (collection_log +116) + dev=90,418 -> 90,534
Census: keep error_message_truncated (HEAD) + add top_query_text_truncated (dev)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVjn4PBJN71NQXdFo6ZxNQ
@erikdarlingdata
erikdarlingdata merged commit 76c72bc into dev Sep 25, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4198-collection-log-default branch September 25, 2026 11:32
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>
erikdarlingdata added a commit that referenced this pull request Sep 25, 2026
…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
erikdarlingdata added a commit that referenced this pull request Sep 25, 2026
* Add the #4198 MCP read-tool budget pin (part of #4198)

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

* MCP budget pin: empty ExemptOffenders now every #4198 per-tool lane has 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

* MCP budget pin: get_collection_health is still over on this fixture

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

---------

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