Bound automatic pagination in the MCP client - #505
Open
koic wants to merge 1 commit into
Open
Conversation
## Motivation and Context `MCP::Client#tools`, `#resources`, `#resource_templates`, and `#prompts` follow `nextCursor` until the server stops offering one. The `seen` set in `fetch_all_pages` catches a server that repeats or cycles cursors, but a fresh cursor on every response walks past that guard, and the client keeps requesting and retaining pages for as long as the server keeps producing them. The transports' per-message limits do not help here, since each individual page can be small. `MCP::Client.new` now takes `max_pages:`, defaulting to `MAX_PAGES` (1000). Reaching it raises `PaginationLimitError` rather than truncating the collection silently, since a short array would be indistinguishable from a server that genuinely ran out of items. The single-page `list_*` methods are unchanged, so callers who need their own policy still have one. ## How Has This Been Tested? New tests in `test/mcp/client_test.rb` cover a server that returns a distinct cursor per page, the boundary where a server stops exactly at `max_pages`, and the argument validation. The existing repeat-cursor and cycling-cursor tests are unaffected. `bundle exec rake` (tests, RuboCop, and conformance baseline) passes. ## Breaking Changes An all-pages call against a server offering more than 1000 pages now raises `MCP::Client::PaginationLimitError` instead of continuing. Pass a larger `max_pages:` to `MCP::Client.new` if that is expected.
koic
force-pushed
the
bound_client_automatic_pagination
branch
from
August 10, 2026 19:42
bf772b2 to
3ff7075
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
MCP::Client#tools,#resources,#resource_templates, and#promptsfollownextCursoruntil the server stops offering one. Theseenset infetch_all_pagescatches a server that repeats or cycles cursors, but a fresh cursor on every response walks past that guard, and the client keeps requesting and retaining pages for as long as the server keeps producing them. The transports' per-message limits do not help here, since each individual page can be small.MCP::Client.newnow takesmax_pages:, defaulting toMAX_PAGES(1000). Reaching it raisesPaginationLimitErrorrather than truncating the collection silently, since a short array would be indistinguishable from a server that genuinely ran out of items. The single-pagelist_*methods are unchanged, so callers who need their own policy still have one.How Has This Been Tested?
New tests in
test/mcp/client_test.rbcover a server that returns a distinct cursor per page, the boundary where a server stops exactly atmax_pages, and the argument validation. The existing repeat-cursor and cycling-cursor tests are unaffected.bundle exec rake(tests, RuboCop, and conformance baseline) passes.Breaking Changes
An all-pages call against a server offering more than 1000 pages now raises
MCP::Client::PaginationLimitErrorinstead of continuing. Pass a largermax_pages:toMCP::Client.newif that is expected.Types of changes
Checklist