Skip to content

get_pg_extensions/get_pg_write_stats/get_pg_server_config(_changes) move reading guidance off tools/list (#3898) - #4078

Merged
erikdarlingdata merged 2 commits into
devfrom
feature/3898-content-pg-b
Sep 23, 2026
Merged

erikdarlingdata merged 2 commits into
devfrom
feature/3898-content-pg-b

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Refs #3898.

Why

Issue #3898: a client that loads Darling's whole MCP catalog pays about 330 KB of tools/list before its first
question. Four tools in DarlingMcpPgServerStateTools.cs carried 1,146 to 2,252 characters each. This PR moves
that guidance off tools/list and into get_tool_guide, which serves it on request. Nothing is deleted.

What changes

Converted, in this order: get_pg_extensions, get_pg_write_stats, get_pg_server_config, then
get_pg_server_config_changes. All four are Darling-only. Lite has no PostgreSQL target, so there is no twin to
convert (D6 does not apply).

Tool Before (served chars) After: head After: served (head + pointer)
get_pg_extensions 1,727 467 498
get_pg_write_stats 1,509 567 598
get_pg_server_config 2,252 581 612
get_pg_server_config_changes 1,146 537 568

Every original sentence moved to the tail unchanged. The tail is the tool's full original description, byte for
byte. The head is new, short text written to carry the guardrail facts. Confirmed with the dropcheck script:
missing=0 on all four.

D2 parameter caps

Two parameters were over the 200-character cap.

get_pg_server_config.include_defaults was 249 chars and is now 164 chars. Its dropped clause named one fact: a
pending_restart row is kept in that view whatever its source. That fact now sits in a new tail sentence:
A setting marked pending_restart is kept in the non-default view whatever its source, because it is the row that says the file and the server disagree.

get_pg_extensions.database_name was 803 chars and is now 196 chars. Its dropped clause named one number: a
sixteen-database host holds 1,632 rows. That number now sits in a new tail sentence:
A sixteen-database host's product is 1,632 rows against the 1,000-row maximum. database_name completes one database at a time instead, sixteen calls that each finish.

Head pins

New file: Darling/Darling.Tests/McpToolGuideHeads.PgB.cs (McpToolGuideHeadsPgBTests). It follows the PgA
pattern. It pins each tool's guardrail facts. It checks that the D2 overflow text landed in the tail. It checks
that the two trimmed parameters stayed at or under 200 characters.

Budget

Updated Darling/Darling.Tests/McpToolsListBudget/DarlingMcpPgServerStateTools.txt for all four tools and their
two changed parameters. This PR does not touch the total ceiling (McpToolsListBudgetTests.TotalCeilingBytes). It
only lowers the measured total.

No topic file entry

None of these four tools shares repeated prose with another. PerformanceMonitor.Common/Mcp/McpToolGuideTopics.PgB.cs
stays at its pre-created empty s_pgB = [].

Corrections

None. No original sentence was found to misstate tool behavior.

D4 removals

None. None of the four descriptions carried an issue reference, an anecdote, or a WIRE CHANGE notice.

Re-pointed pins

None needed re-pointing to a specific half. Three existing pins read the tool's full [Description] attribute
text, head and tail combined, rather than the served head alone. They kept passing once the full original text
landed in the tail.

  • McpLatestSnapshotStampTests.DarlingOnlyStampedTools_KeepTheStampedDialect requires get_pg_server_config to
    state captured_at and LATEST IS A TIME. Both phrases are also in the new head. The brief named them as
    guardrail facts a caller must see without a second call.
  • McpPageContractTests.PgServerConfig_NamesItsDenominators_InItsDescription requires truncated,
    THE PAGE IS BOUNDED BY limit, COUNTS ARE OF THE SNAPSHOT, NOT OF THE PAGE, non_default_count,
    non_default_returned, and settings_returned, plus matching text in the limit and include_defaults
    parameter descriptions. This test caught the one real defect in this PR. My first draft of the trimmed
    include_defaults description dropped the word pending_restart. This test requires it. I fixed it by
    rewording the trimmed parameter to keep the word.
  • PgServerConfigScopeRungTests.TheToolAttachesTheOverrideSection_AndLeavesTheServerWideCountsAlone requires
    PER-DATABASE AND PER-ROLE OVERRIDES ARE A SEPARATE SECTION and database_overrides.

D9: known traps for the misreading check

  1. Q: get_pg_extensions returns fewer rows than a 16-database host has. Does that mean only those databases
    have extensions?
    Correct: No. Rows are capped by limit. truncated withholds the state totals, and installed rows (for
    example plpgsql) are the first ones a cap removes.
    Prevents it: the head's Rows are databases x extension names, so a multi-database host overflows limit; truncated withholds state totals, and installed rows like plpgsql are cut first. Read install_census for the complete picture.
  2. Q: get_pg_extensions shows plpgsql as absent on a large host. Is it really not installed?
    Correct: No. It is the extension most likely to be cut by a row cap. It is not the extension most likely
    to be missing.
    Prevents it: the head's installed rows like plpgsql are cut first.
  3. Q: get_pg_write_stats returns several rows across a day. Can they be charted as a time series?
    Correct: No. One row describes the whole window. There is no series.
    Prevents it: the head's as ONE row, not a series.
  4. Q: get_pg_write_stats.buffers_backend is null on a PostgreSQL 17 server. Was nothing measured?
    Correct: No. PostgreSQL 17 removed the column. The fact now lives in pg_stat_io, read by
    get_pg_io_stats.
    Prevents it: the head's buffers_backend/buffers_backend_fsync are NULL on PostgreSQL 17+ (moved to pg_stat_io; see get_pg_io_stats), not unmeasured.
  5. Q: get_pg_write_stats's wal_bytes is null on an Aurora target. Does that mean no WAL was written?
    Correct: No. Aurora does not implement pg_stat_wal at all, so the column is always null there.
    Prevents it: the head's wal_* columns are NULL on Aurora (no pg_stat_wal); get_pg_top_queries has per-statement WAL.
  6. Q: get_pg_write_stats.checkpoints_requested is null right after a restart. Is that a data gap?
    Correct: No. A restart inside the window deliberately nulls that field. A shutdown checkpoint's own
    counters cannot be told apart from the workload's.
    Prevents it: the head's A restart inside the window nulls checkpoints_requested, its percent, both checkpoint time fields and buffers_written_checkpoint.
  7. Q: get_pg_server_config is called mid-incident. Does it show the setting's live value right now?
    Correct: No. It is the newest stored snapshot from an hourly collector, not the live server.
    Prevents it: the head's LATEST IS A TIME: the newest stored snapshot, not a window or the live server; captured_at is when it was taken (collector runs hourly).
  8. Q: get_pg_server_config's non_default_count says 40 but only 25 rows came back at limit=25. Does the
    server only have 25 non-default settings?
    Correct: No. non_default_count counts the whole snapshot. settings_returned (25) is only this page.
    Prevents it: the head's non_default_count is the snapshot's, not the page's.
  9. Q: get_pg_server_config's answer has no database_overrides key. Does that mean the check did not run?
    Correct: No. The key is present only when the cluster actually has an override.
    Prevents it: the head's database_overrides (present only if any exist) is what sessions actually run with.
  10. Q: get_pg_server_config_changes returns no rows right after an upgrade added new extension settings. Did
    nothing change?
    Correct: A setting's first appearance is deliberately not reported as a change. So "no rows" is expected
    even after a real upgrade.
    Prevents it: the head's A setting appearing for the FIRST time (an upgrade, a new extension) is NOT reported as a change.
  11. Q: get_pg_server_config_changes shows a row with old_value: null. Is that a collection error?
    Correct: No. That is a set change: an override appeared where none existed, so old_value is
    legitimately null.
    Prevents it: the head's carrying change_kind: changed, set (old_value null) or reset (new_value null).
  12. Q: get_pg_server_config_changes shows a change right after a monitoring tool reconnected. Is that a real
    configuration change?
    Correct: No. Session-scoped rows are excluded, so a reconnect never reads as one.
    Prevents it: the head's Session-scoped rows are excluded.

Test plan

  • dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Debug. Build succeeded, 0 Warning(s), 0
    Error(s).
  • Targeted test classes, all passed: McpToolsListBudgetTests, McpToolGuideHeadsPgBTests,
    McpLatestSnapshotStampTests, McpPageContractTests, PgServerConfigScopeRungTests,
    DarlingMcpToolsTests, and the shared McpToolGuide* / McpDescription* / McpZeroIsAMeasurement* /
    McpPayloadContractCensus* suites. Also every other class naming one of the four tools. One real failure
    turned up along the way and was fixed. See "Re-pointed pins" above.
  • Dropped-sentence check: python dropcheck.py origin/dev HEAD get_pg_extensions get_pg_write_stats get_pg_server_config get_pg_server_config_changes. Result: missing=0 on all four.
  • git merge origin/dev, which picked up three unrelated The MCP surface costs ~100k tokens of context before the first call: 157 tools, 336 KB of tools/list, 86 KB of instructions #3898 lanes' commits. Clean merge, no conflicts.
  • Full suite after the merge: Darling.Tests.exe. Total: 13,236, Errors: 0, Failed: 0, Skipped: 631. The
    skips are the live-PostgreSQL classes. This lane has no rig.
  • Plain-English checker run on this PR body, down to 0 real hits outside the allowed D9 labels and the
    attribution emoji.

Coordinator verification

  • The branch already had origin/dev merged (head 9ec95f1).
  • dropcheck: missing=0 for all four tools.
  • D9: a small model answered all 12 traps from the served text alone, with no misreads. It answered Q12 with "not stated" and pointed to the guide.
  • Full suites on 9ec95f1: Darling.Tests 13,236 total, 0 failed. Lite.Tests 5,234 total, 0 failed.

Handoff

get_pg_lock_stats and get_pg_buffer_usage, the other two tools on DarlingMcpPgServerStateTools.cs, are left
for a later lane, per this lane's brief.

🤖 Generated with Claude Code

https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF

erikdarlingdata and others added 2 commits September 23, 2026 17:04
…3898)

get_pg_extensions, get_pg_write_stats, get_pg_server_config and
get_pg_server_config_changes each served 1,146-2,252 characters of guidance
in tools/list. Each now serves a short head (498-612 chars) plus a pointer,
with the full original text moved to get_tool_guide's tail. Nothing was
deleted and no tool behavior changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 23, 2026 21:15
@erikdarlingdata
erikdarlingdata enabled auto-merge (squash) September 23, 2026 21:15
@erikdarlingdata
erikdarlingdata merged commit 20de87f into dev Sep 23, 2026
17 of 18 checks passed
@erikdarlingdata
erikdarlingdata deleted the feature/3898-content-pg-b branch September 23, 2026 21:20
erikdarlingdata added a commit that referenced this pull request Sep 23, 2026
…ntries in their sections (#4080)

Adds 42 entries and 42 link refs (#3992, #3995, #3996, #3998, #4001, #4002, #4003, #4007, #4010, #4011, #4013, #4015, #4020, #4022, #4025, #4029, #4030, #4031, #4036, #4038, #4039, #4040, #4044, #4047, #4048, #4049, #4050, #4051, #4055, #4061, #4063, #4064, #4065, #4066, #4067, #4068, #4069, #4070, #4071, #4073, #4074, #4078). Each PR's entry was buffered, and this lands every entry whose PR was merged on origin/dev when it ran.

#3989 left 26 entries under bare 'Changed' and 'Fixed' lines above '### Added'. They move into '### Changed' and '### Fixed', below the new entries, and one blank line stays under [Unreleased].


Claude-Session: https://claude.ai/code/session_01Ua31ugERL5DmhFVRtf6keQ

Co-authored-by: Claude Opus 5.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