Skip to content

MCP reads window only backwards from now, so no caller can ask about a past incident #2495

Closed

Description

@erikdarlingdata

Split out of #2494 rather than grown into it.

What

get_collection_log's reader is bounded on both sides — it takes a window start and a window end — and the viewer's Collection Log tab uses that to honour a custom From/To range. The MCP tool exposes only hours_back, always anchored to end = now.

So the capability exists in the read and is unreachable through the tool. An agent asked "what were the collectors doing during the incident last Tuesday?" can only say "the last N hours" and widen until Tuesday falls inside — dragging along everything since.

I claimed the past-incident case worked in #2494's description. It does not, and this is the correction.

Scope, because it is not one tool

get_collection_log is where it was noticed, not where it starts. The same hours_back-from-now shape is the norm across the read surface — get_wait_stats, get_query_store_top, get_blocking, get_alert_history and others all anchor to now. Any read whose stored data outlives its default window has the same gap.

That makes this a surface-wide parameter convention question, not a bug in one tool:

  1. Add optional from/to to reads that already window, keeping hours_back as the default path. Backward compatible; the widest change.
  2. Add an as_of anchor — keep hours_back as the span and let a caller move the endpoint off "now". Smaller and covers the incident case, which is nearly always "N hours around a known time".
  3. Leave it. Callers widen and filter client-side. Cheapest, and gets worse the more history the store keeps — which is the direction it is going.

Option 2 is the smaller change and covers the actual use case, but this wants deciding once for the surface rather than per tool, which is why it is an issue and not a patch.

Not a workaround

Widening hours_back until the window reaches back far enough is not equivalent: it changes what a top-N returns, what an average is taken over, and how much a capped read truncates. For an aggregate read, a wider window is a different answer, not the same answer with more rows.

Activity

  1. erikdarlingdata commented on Aug 22, 2026

    @erikdarlingdata
    OwnerAuthor

    Done in #2504. as_of — an optional ISO-8601 UTC anchor that moves the window's END off "now" while hours_back stays its LENGTH. Applied to 57 Darling / 50 Lite reads with identical name, semantics and description on both, plus all 57 web catalog descriptors and dispatch lambdas, so it is reachable from /api/read/* and not only from MCP.

    Option 2 was right, and for a better reason than this issue gave. hours_back was never a window — it was half a window plus an implicit end = now. as_of does not add a knob so much as make the existing one honest. Option 1 would have given ~100 reads three time parameters with a validity rule between them, including a state (from + to + hours_back all set) with no defensible answer.

    Left unanchored, deliberately

    Both exclusions are named in the instructions and pinned by a test that lists them, so the set cannot quietly grow.

    Two findings worth more than the feature

    Eight tools advertised as_of, validated it, refused bad input correctly — and then queried DateTime.UtcNow anyway. All eight came from resolving a rebase in dev's favour. All compiled and passed a green 5,600-test suite. One was worse than a dropped anchor: it passed already-UTC instants into server-local slots, shifting the window by the monitored server's offset even when unanchored. A tool that validates an anchor and then ignores it is worse than one that never offered it, because the caller is told the window moved.

    The pin written to catch that was itself vacuous at first. Reintroducing one of the bugs left it green, because the body still contained windowEnd from its own out var. It is now an absolute — an anchored tool may not name DateTime.UtcNow at all — verified by reintroducing one bug of each form and watching both fail. It also asserts it examined at least 40 tools, so a broken scan fails instead of passing for free, and derives its list of anchorable service methods from shipped source rather than a transcribed list.

    Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions