Expand description
MCP pagination helpers.
ClickUp’s paginated endpoints come in four flavours:
- page-based (v2):
?page=N, response carrieslast_page: bool. - cursor-based (v3):
?cursor=X, response carriesnext_cursor: stringor null. - start-id-based (v2 comments):
?start=<unix_ms>&start_id=<id>pair, response is a bare array, termination inferred from page-size hint. - body-based (v3 audit-log): pagination state lives inside the POST
body as
pagination: { pageRows, pageTimestamp, pageDirection }.
This module hides the loop logic and response-shape glue so each MCP tool dispatch can be a one-liner.
§Contract
Schema. Every paginated tool’s inputSchema gains one of:
- page style:
page(int ≥0),limit(int ≥1),all(bool); or - cursor style:
cursor(opaque string),limit(int ≥1),all(bool); or - start-id style:
start(int ms),start_id(string),limit(int ≥1),all(bool); or - body style:
page_rows,page_timestamp(int ms),page_direction("NEXT"/"PREVIOUS"),limit,all.
Output. The contract is opt-in:
-
If the caller passes NO pagination arg, the response is unchanged from pre-pagination: a bare compact array. Back-compat for existing clients.
-
If the caller passes ANY pagination arg, the response becomes an envelope:
{ "items": [...], "pagination": { "style": "page" | "cursor" | "start_id" | "body", "page": 0, // page style only "last_page": false, // page style only "next_cursor": "...", // cursor style only, omitted when exhausted "next_start": 1700000000, // start_id style only, omitted when exhausted "next_start_id": "...", // start_id style only, omitted when exhausted "next_page_timestamp": 1700000, // body style only, omitted when exhausted "page_direction": "NEXT", // body style only, echoes caller input "has_more": true, "returned": 42, "all": false } }
Calling code uses PageArgs::from_args / CursorArgs::from_args /
StartIdArgs::from_args / BodyPaginationArgs::from_args to parse
pagination input, then page_dispatch / cursor_dispatch /
start_id_dispatch / body_pagination_dispatch to run the fetch loop.
Structs§
- Body
Pagination Args - Parsed body-pagination input. ClickUp’s v3 audit-log endpoint
(
POST /v3/workspaces/{ws}/auditlogs) puts pagination state inside the request body aspagination: { pageRows, pageTimestamp, pageDirection }, not in query params.pageDirectionis"NEXT"or"PREVIOUS"—--allwalks in whatever direction the caller passes, defaulting to"NEXT"(newer events) if unspecified. - Cursor
Args - Parsed cursor-based pagination input.
- Page
Args - Parsed page-based pagination input.
- Start
IdArgs - Parsed start-id-based pagination input. ClickUp’s v2 comment endpoints
(
/v2/task/{id}/comment,/v2/list/{id}/comment,/v2/view/{id}/comment,/v2/comment/{id}/reply) use this style: pass?start=<unix_ms>&start_id=<id>to retrieve items older than that boundary. Both params are required as a pair when paginating; omitting them returns the first page (newest first). The response is a bare{ "comments": [...] }array — no pagination metadata — so termination is inferred when the returned array is shorter than the endpoint’s page size (25 for ClickUp’s comment endpoints).
Functions§
- body_
pagination_ dispatch - Run a body-pagination POST loop for endpoints like the v3 audit-log query.
Pagination state lives inside the request body as
pagination: { pageRows, pageTimestamp, pageDirection }. - cursor_
dispatch - Run a cursor-based pagination loop.
build_path(cursor)should return a path including any?cursor=...query whencursoris Some, or no cursor query when None.items_keysis the list of candidate response keys to extract the array from; first match wins. Typical:&["data", "<legacy>"]where<legacy>is the pre-v3 key ("channels","replies", etc.) for back-compat with any older envelope shape. - page_
dispatch - Run a page-based pagination loop and return either a bare compact array
(no pagination args) or a
{items, pagination}envelope (any pagination arg).build_path(page)should return a path including any?page=Nquery, e.g./v2/list/123/task?page=2.items_keyis the response field holding the array (e.g."tasks"). - start_
id_ dispatch - Run a start-id-based pagination loop.
build_path(start, start_id)should return a path including the?start=...&start_id=...query when both are Some, or no pagination query when both are None. (ClickUp requires the params as a pair — passing only one is a caller bug.)items_keyis the response array’s field name ("comments"for both comment endpoints).