mcp/client: add list_all_* helpers with pagination safety guards
The Python SDK lacks auto-pagination helpers for the four list verbs (tools/list, resources/list, resources/templates/list, prompts/list). Callers must write their own cursor-draining loops, and those loops have no protection against infinite pagination or cursor cycles.
The TypeScript SDK already provides this via _listAllPages with a listMaxPages cap and cursor cycle detection (see typescript-sdk#2336). The Go SDK is getting the same guards in go-sdk#1110. This PR brings the Python SDK to parity.
What changed
Four new methods on the high-level Client:
await client.list_all_tools() -> ListToolsResult
await client.list_all_resources() -> ListResourcesResult
await client.list_all_resource_templates() -> ListResourceTemplatesResult
await client.list_all_prompts() -> ListPromptsResult
Each drains all pages into a single aggregated result via a shared
_drain_all_pages helper with two safety guards:
-
Page cap:
Client.list_max_pages(default 64, matching the TS
SDK'sDEFAULT_LIST_MAX_PAGES). Exceeding the cap raises
PaginationExceededError. Setting to 0 or a negative value
disables the cap (unlimited). -
Cursor cycle detection: a
seenset tracks all cursors
returned by the server. A repeated cursor raises
CursorCycleError, preventing infinite loops from buggy servers.
Both exception types are exported from mcp.client.
Configuration
# Default: 64 pages
client = Client(server)
# Custom cap
client = Client(server, list_max_pages=100)
# Unlimited
client = Client(server, list_max_pages=0)
How Has This Been Tested
9 new tests in tests/client/test_list_all_pagination.py:
- Normal multi-item drain for all 4 verbs
- Empty server returns empty lists
PaginationExceededErrorwhen cap exceededCursorCycleErroron repeated cursor- Unlimited mode (
list_max_pages=0) - Terminal cursor stripping (
next_cursor is None)
All 709 existing client tests continue to pass. Lint (ruff check)
and type check (pyright) are clean.
Types of changes
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to change)
- Documentation update
Checklist
- I have read the MCP Documentation
- My code follows the repository's style guidelines
- New and existing tests pass locally
- I have added appropriate error handling
- I have added or updated documentation as needed