Skip to content

fix: guard client pagination loops against misbehaving servers#3167

Merged
jlowin merged 2 commits intomainfrom
fix/client-pagination-guards
Feb 12, 2026
Merged

fix: guard client pagination loops against misbehaving servers#3167
jlowin merged 2 commits intomainfrom
fix/client-pagination-guards

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Feb 12, 2026

The auto-pagination loops in Client.list_tools(), list_resources(), list_resource_templates(), and list_prompts() had no protection against servers that return bogus nextCursor values. A server that always returns a non-null cursor (or cycles through cursors, or returns empty strings) would cause the client to loop forever — appearing to "hang" after connecting.

This adds two guards to every client list method and the server-side context proxy helper:

  1. Empty cursor normalizationif not result.nextCursor instead of is None, so empty strings and other falsy values are treated as end-of-pagination.
  2. Cycle detection — track seen cursors and break with a warning if the server returns one we've already visited.
# Before: loops forever if server always returns nextCursor
tools = await client.list_tools()

# After: terminates cleanly with a warning log
tools = await client.list_tools()  # returns whatever was fetched before the cycle

Fixes #3158

Treat empty/falsy nextCursor as end-of-pagination and detect cursor
cycles across all client list methods and the server context proxy
helper.
@jlowin jlowin added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. client Related to the FastMCP client SDK or client-side functionality. labels Feb 12, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 12, 2026

Walkthrough

This pull request adds pagination safety mechanisms across multiple list methods in both the client and server by introducing duplicate cursor detection to prevent infinite pagination loops. The changes introduce a seen_cursors set to track previously encountered nextCursor values, modify loop termination conditions to check for falsy cursor values instead of strict None comparisons, and log warnings when duplicate cursors are detected before breaking the pagination loop. Documentation files were also updated to reflect source code line number changes resulting from the added implementation.

Possibly related PRs

  • PR #2903: Introduces initial pagination functionality in MCP list methods that this PR enhances with duplicate-cursor detection and safer loop termination logic.
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding guards to client pagination loops against misbehaving servers.
Description check ✅ Passed The description covers the problem, solution approach with two specific guards, before/after behavior, and references the fixed issue, though the contributors checklist items are not explicitly marked.
Linked Issues check ✅ Passed The PR successfully addresses issue #3158 by implementing pagination guards (empty cursor normalization and cycle detection) across all client list methods to prevent infinite loops from malformed server responses.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing pagination loop issues: code changes add safety guards to four client list methods and server context helper, plus documentation anchor updates for SDK reference docs.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/client-pagination-guards

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/fastmcp/server/context.py (1)

426-436: Pagination guard logic looks correct but silently swallows cycle detection, unlike client mixins.

The client-side list_tools, list_resources, list_resource_templates, and list_prompts all emit a logger.warning(…) when a duplicate cursor is detected. This server-side helper breaks silently. Consider adding a warning for consistency and debuggability.

🔧 Suggested: add a warning on duplicate cursor
             if result.nextCursor in seen_cursors:
+                logger.warning(
+                    "Server returned duplicate pagination cursor"
+                    f" {result.nextCursor!r}; stopping pagination"
+                )
                 break

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f8b2d91de0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/fastmcp/client/mixins/tools.py
@jlowin jlowin merged commit 175479f into main Feb 12, 2026
16 checks passed
@jlowin jlowin deleted the fix/client-pagination-guards branch February 12, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. client Related to the FastMCP client SDK or client-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fastmcp client hangs after oauth authentication flow finish

1 participant