Skip to content

Sweep the corpus onto x-overslash-pagination, and bound the 17 list actions that declare nothing #577

Description

@angel-manuel

Why

The generic-pagination PR shipped the extension, the runtime, the /v1/search flag and the dashboard pill, but annotated exactly one shipped template (services/gmail.yaml). That was deliberate — twenty template judgements in one diff are impossible to argue with individually — and it leaves the actual damage unfixed. The Metabase case that started this is still live, and eventbrite.list_event_attendees is the same shape waiting.

Read docs/design/generic-pagination.md and the decision entry first; the vocabulary is settled and this issue is about applying it.

Part 1 — annotate what already pages

These declare paging parameters the gateway now knows how to read. Each is mechanical: add a pagination: block naming the parameters that already exist.

service operations page size continuation style
github list_installations, list_repos, list_issues per_page (default 30) RFC 8288 Link (not currently modelled — no page param either, so one must be added) link
stripe list_charges limit (default 10) none declared — needs starting_after cursor
notion search, query_database page_size (body, no default) start_cursor (body) cursor
google_drive list_files, list_permissions pageSize (no default) pageToken cursor
google_keep list_notes pageSize (no default) pageToken cursor
outlook list_messages, list_folders $top (no default) $skip offset
metabase search limit (default 50) offset offset
google_calendar list_events maxResults (no default) none declared — needs pageToken cursor
google_tasks list_tasklists, list_tasks maxResults (no default) none declared — needs pageToken cursor
email search limit (body, no default) none — response carries {results, total, truncated} n/a, page-size half only
slack (MCP) list_channels, read_channel_history limit (defaults 100 / 50) cursor cursor
hubspot (MCP) search_crm_objects, search_owners, get_campaign_contacts_by_type, get_content_analytics_report limit offset offset
whatsapp (MCP) seven list tools limit page (default 0) page

Two things to check as you go, because they are where the value is:

  • A page-size parameter with no default: bounds nothing. page_size.default seeds it. That is most of the table.
  • Several rows need a continuation parameter added to the template, not just annotated — the upstream supports it and we never declared it. Those are the ones that make an action genuinely pageable rather than merely bounded.

Note slack.search_messages spells page size count, which is a seventh spelling and needs no new vocabulary — page_size.param names whatever the parameter is called.

Part 2 — bound what declares nothing

Seventeen HTTP-runtime list operations declare no page size at all. Where the upstream supports one, add the parameter and the pagination: block. Where it does not (Metabase's list_cards is the canonical case — no pagination, no sorting, no field selection), say so in the action's description and point at the paged sibling, which is what metabase.yaml already does in prose.

  • metabase.list_databases, list_cards, popular_items, recents
  • eventbrite.list_my_orders, list_organizations, list_ticket_classes, list_event_attendees — the severe one: an unbounded collection of rich objects, the same shape as the Metabase failure
  • outlook.list_folders
  • stripe.list_customers (its sibling list_charges declares limit)
  • resend.list_domains
  • google_calendar.list_calendars
  • gmail.list_labels
  • MCP side: hubspot.get_crm_objects, query_crm_data, get_properties, search_properties, get_campaign_analytics, get_campaign_asset_metrics; deepwiki.read_wiki_contents

Part 3 — the gate that keeps it swept

Close with a corpus test shaped like registry::tests::shipped_mutating_actions_declare_disclose: every shipped action whose key looks like a list (or that returns a collection) either declares x-overslash-pagination or appears in an ALLOW_MISSING list with a comment saying why the upstream cannot page. Keep the allow-list honest — the existing one is empty and carries the instruction "add entries only with a comment explaining why".

Notes

  • NextStyle::Link is refused on MCP tools at compile: a tool result has no response headers.
  • The gateway does not clamp page_size.max; it bounds default at validation time and writes the dashboard tooltip.
  • Where a parameter already declares its own default:, that wins and page_size.default is inert — validation warns (pagination_default_shadowed). Prefer removing the duplicate over leaving both.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent to pick up

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions