UAT: MCPToolAdapter.discover_tools() does not handle cursor-based pagination in tools/list — silently misses tools from large MCP servers #2585

Open
opened 2026-04-03 19:01:02 +00:00 by freemo · 1 comment
Owner

Bug Report

Feature Area

Standards Alignment — MCP (Model Context Protocol) / Tool Discovery

What Was Tested

Code-level analysis of src/cleveragents/mcp/adapter.py — the discover_tools() method's tools/list call.

Expected Behavior (from spec)

The MCP specification defines cursor-based pagination for tools/list:

// Request:
{"method": "tools/list", "params": {"cursor": "optional-cursor-value"}}

// Response:
{
  "tools": [...],
  "nextCursor": "next-page-cursor"  // present if more tools exist
}

When nextCursor is present in the response, the client must make additional tools/list calls with {"cursor": nextCursor} until nextCursor is absent, to retrieve all available tools.

Actual Behavior (from code)

In src/cleveragents/mcp/adapter.py, discover_tools():

def discover_tools(self, tool_filter=None):
    with self._lock:
        ...
        result = self._transport.call("tools/list", {})  # ← No cursor support
        raw_tools = result.get("tools", [])              # ← Only first page
        ...

The method calls tools/list once with an empty params dict and only processes the first page of results. If the MCP server has more tools than fit on the first page, nextCursor in the response is silently ignored.

Impact

  • Silent tool loss: MCP servers with many tools (e.g., large GitHub MCP server, filesystem MCP server) will only expose the first page of tools to CleverAgents.
  • Non-deterministic behavior: The number of tools available depends on the server's page size, which varies by implementation.
  • Skill composition broken: Skills that reference MCP tools from the second page or beyond will fail to find those tools in the registry.

Code Location

  • src/cleveragents/mcp/adapter.pydiscover_tools() method (line ~429)

Steps to Reproduce

# Simulate an MCP server with paginated tools/list:
# First call returns 10 tools + nextCursor
# Second call returns 5 more tools (no nextCursor)
# Current code only gets 10 tools, misses 5

Fix Required

Implement cursor-based pagination in discover_tools():

def discover_tools(self, tool_filter=None):
    with self._lock:
        ...
        all_raw_tools = []
        cursor = None
        while True:
            params = {}
            if cursor:
                params["cursor"] = cursor
            result = self._transport.call("tools/list", params)
            all_raw_tools.extend(result.get("tools", []))
            cursor = result.get("nextCursor")
            if not cursor:
                break
        # Process all_raw_tools...

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester

## Bug Report ### Feature Area Standards Alignment — MCP (Model Context Protocol) / Tool Discovery ### What Was Tested Code-level analysis of `src/cleveragents/mcp/adapter.py` — the `discover_tools()` method's `tools/list` call. ### Expected Behavior (from spec) The MCP specification defines cursor-based pagination for `tools/list`: ```json // Request: {"method": "tools/list", "params": {"cursor": "optional-cursor-value"}} // Response: { "tools": [...], "nextCursor": "next-page-cursor" // present if more tools exist } ``` When `nextCursor` is present in the response, the client must make additional `tools/list` calls with `{"cursor": nextCursor}` until `nextCursor` is absent, to retrieve all available tools. ### Actual Behavior (from code) In `src/cleveragents/mcp/adapter.py`, `discover_tools()`: ```python def discover_tools(self, tool_filter=None): with self._lock: ... result = self._transport.call("tools/list", {}) # ← No cursor support raw_tools = result.get("tools", []) # ← Only first page ... ``` The method calls `tools/list` once with an empty params dict and only processes the first page of results. If the MCP server has more tools than fit on the first page, `nextCursor` in the response is silently ignored. ### Impact - **Silent tool loss**: MCP servers with many tools (e.g., large GitHub MCP server, filesystem MCP server) will only expose the first page of tools to CleverAgents. - **Non-deterministic behavior**: The number of tools available depends on the server's page size, which varies by implementation. - **Skill composition broken**: Skills that reference MCP tools from the second page or beyond will fail to find those tools in the registry. ### Code Location - `src/cleveragents/mcp/adapter.py` — `discover_tools()` method (line ~429) ### Steps to Reproduce ```python # Simulate an MCP server with paginated tools/list: # First call returns 10 tools + nextCursor # Second call returns 5 more tools (no nextCursor) # Current code only gets 10 tools, misses 5 ``` ### Fix Required Implement cursor-based pagination in `discover_tools()`: ```python def discover_tools(self, tool_filter=None): with self._lock: ... all_raw_tools = [] cursor = None while True: params = {} if cursor: params["cursor"] = cursor result = self._transport.call("tools/list", params) all_raw_tools.extend(result.get("tools", [])) cursor = result.get("nextCursor") if not cursor: break # Process all_raw_tools... ``` --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • MoSCoW: Should Have

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **MoSCoW**: Should Have --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
freemo added this to the v3.6.0 milestone 2026-04-05 04:53:36 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#2585
No description provided.