Skip to content

feat(pagination): expose page param on list-query tools#71

Merged
ysyneu merged 1 commit into
mainfrom
fix/list-tools-page-param
Jul 8, 2026
Merged

feat(pagination): expose page param on list-query tools#71
ysyneu merged 1 commit into
mainfrom
fix/list-tools-page-param

Conversation

@ysyneu

@ysyneu ysyneu commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Problem

The list-query MCP tools hit paginated Flashduty backends (ListOptions{Page, Limit}) but exposed only limit (max 100). Any result past the first page was unreachable — a query matching >100 items silently dropped the tail, with no recourse but narrowing the time window/filters. The truncated/hint machinery even flagged the shortfall while offering no way to page.

Fix

Add a 1-based page param to every list tool that queries a Page-capable endpoint and surfaces a total:

Tool Change
query_incidents + page
query_changes + page
query_incident_alerts + page (applied per incident)
query_channels + limit + page
query_members + limit + page
query_teams + limit + page

Dedicated by-ID lookups that return everything stay unpaged (incident_idslist-by-ids, person_idsperson/infos, team_idsteam/infos). channel_ids is a filter on the same paginated /change... /channel/list, so it pages like any listing.

Truncation-signal correctness

addTruncationHint compared total > count (this page's size) — correct only on page 1. On a final partial page it falsely reported truncated and sent the agent chasing an empty next page. New addPageHint accounts for the page offset (seen = (page-1)*limit + count) and names the exact next page. Full-set / by-ID responses keep addTruncationHint.

change_ids correctness

/change/list has no server-side id filter, so query_changes(change_ids=…) filters one page client-side. It now reports total = found count and skips the page hint (feeding the filtered count with the window's unfiltered total into addPageHint would mislead: "Showing 0 of 5000, request page:2").

Consistency

Shared optionalPaging helper centralizes the limit/page parse across the six handlers (also removes a stray hardcoded 20 in query_changes); PageDescription mirrors LimitDescription.

Out of scope

list_similar_incidents — backend /incident/past-list has no Page (top-N by design).

Tests

pagination_page_test.go: wire-level tests that page reaches the backend as p (and default omits it), the channel_ids/person_ids path split, the change_ids found-count/no-hint behavior, and a table-driven TestAddPageHint covering the last-page math.

go build, go vet, and go test ./pkg/... ./internal/... all pass. (make lint fails locally on a golangci-lint↔go toolchain version mismatch, unrelated to this change.)

The list-query MCP tools hit paginated backends (ListOptions{Page,Limit})
but exposed only `limit` (max 100) — any result past the first page was
unreachable, so a query matching >100 items silently dropped the tail with
no recourse but narrowing the window/filters.

Add a 1-based `page` param to every list tool that queries a Page-capable
endpoint and surfaces a `total`: query_incidents, query_changes,
query_incident_alerts, query_channels, query_members, query_teams. The
three that had no `limit` (channels/members/teams) gain both. Dedicated
by-ID lookups that return everything (incident_ids→list-by-ids,
person_ids→person/infos, team_ids→team/infos) stay unpaged; channel_ids is
a filter on the same paginated /channel/list, so it pages like any listing.

Fix the truncation signal for paged reads: `addTruncationHint` compared
`total > count` (this page's size), which was correct only on page 1 — on a
final partial page it falsely reported "truncated" and sent the agent
chasing an empty next page. New `addPageHint` accounts for the page offset
(seen = (page-1)*limit + count) and names the exact next page. Full-set /
by-ID responses keep `addTruncationHint`.

Shared `optionalPaging` helper centralizes the limit/page parse across the
six handlers; `PageDescription` mirrors `LimitDescription`. Wire-level tests
cover page reaching the backend as `p` (and default omitting it), the
channel_ids/person_ids path split, and the last-page truncation math.

Out of scope: list_similar_incidents (backend /incident/past-list has no
Page — top-N by design).
@ysyneu ysyneu merged commit 61e8dea into main Jul 8, 2026
13 checks passed
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