Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

Hellobaka
Copy link

Replace while (cursor is not null) with while (!string.IsNullOrEmpty(cursor)) to prevent potential infinite loops if the cursor is an empty string.

Motivation and Context

When integrating with Alibaba Bailian's MCP service, I encountered an issue where the pagination API returns an empty string ("") instead of null for NextCursor when there is no more data. The previous loop condition failed to terminate in this case, resulting in infinite requests. This PR updates the loop condition to improve SDK compatibility with this scenario.

image

How Has This Been Tested?

Yes, I verified the change by testing the compiled code and confirmed that the modified logic works as expected and resolves the infinite request issue.

Breaking Changes

No.

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

Additional context

This change ensures more robust pagination handling and prevents potential infinite loops caused by empty cursor values.

cursor = toolResults.NextCursor;
}
while (cursor is not null);
while (!string.IsNullOrEmpty(cursor));
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to add an integration test that recreates the conditions of the infinite loop?

Copy link
Author

Choose a reason for hiding this comment

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

I'm not very familiar with xUnit or the project's test structure, so I'm not able to write a new integration test at this time.
If you'd like to reproduce the issue, you can do so by performing a paginated operation for tools, and on the last page, set the NextCursor property to an empty string ("") instead of null. This should help simulate the scenario in question.

@mikekistler
Copy link
Contributor

mikekistler commented Sep 16, 2025

What happens (or what should happen) when a subsequent request is made with cusror set to an empty string? Shouldn't that fail? If it did, then there would be no infinite loop.

@alvin-su
Copy link

When should this pull request be merged?

@halter73
Copy link
Contributor

If we do make this change, we should probably copy the pattern for prompts, resources and templated resources, and add tests.

What happens (or what should happen) when a subsequent request is made with cusror set to an empty string? Shouldn't that fail? If it did, then there would be no infinite loop.

Looking at the screenshot, Alibaba Bailian's MCP service continues to return the same tool listing with an empty cursor whether or not it should. I think that stopping iteration given an empty string as a nextCursor makes more sense than using it. We could also treat an empty nextCursor as an error, but I don't think that's helpful.

Looking at the TypeScript and Python SDK, neither automatically enumerates cursors the way we do. I cannot even find a sample in the TypeScript SDK repo that iterates over paginated results. Here's the list tools sample code:

https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/examples/client/simpleStreamableHttp.ts#L530-L539

The Python SDK repo has a sample of iterating over paginated resources that checks if result.nextCursor: where the empty string evaluates as false, so it would stop iterating in this case.

https://github.com/modelcontextprotocol/python-sdk/blob/71889d7387f070cd872cab7c9aa3d1ff1fa5a5d2/examples/snippets/clients/pagination_client.py#L31-L35

In the meantime, people can use the lower level await client.SendRequestAsync(RequestMethods.ToolsList, ... method to get the raw ListToolsResult and deal with the NextCursor themselves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants