Summary
When an MCP server paginates its tools/list response, Droid registers only the first page of tools and never follows nextCursor. Tools beyond page 1 are absent from the session's tool registry for the entire session: loading one by exact name fails as "unavailable in this session", and invoking it fails with InputValidationError.
tools/list pagination is explicitly part of the MCP spec, with page size determined by the server — so any server whose tool count exceeds one page silently loses tools in Droid.
Environment
droid 0.186.0, Windows 11 (10.0.26200), Windows PowerShell 5.1
- MCP server: Laravel MCP (
laravel/mcp package), streamable HTTP transport, 101 registered tools, default page size 50, max page size 100
Reproduction
- Configure an HTTP MCP server exposing more tools than one page (ours: 101 tools at 50/page) in
~/.factory/mcp.json.
- Start a session and inspect the server's registered tools: exactly 50, matching page 1 of
tools/list in registration order.
- Attempt to load a page-2 tool by exact name: fails as "unavailable in this session".
Manual protocol walk against the same server (initialize → tools/list, following cursors):
tools/list -> 50 tools, nextCursor eyJvZmZzZXQiOjUwfQ== (base64 {"offset":50})
tools/list (cursor) -> 50 tools, nextCursor eyJvZmZzZXQiOjEwMH0= (base64 {"offset":100})
tools/list (cursor) -> 1 tool, no nextCursor
total: 101 tools
Single-variable control: setting the server's page size to 1 and reconnecting makes exactly 1 tool register (the first in registration order). Page size and tool count are irrelevant — the client never requests page 2, whatever a page contains.
Expected
Per the MCP spec (2026-07-28, https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/pagination):
tools/list is a paginated operation, and "page size is determined by the server, and clients MUST NOT assume a fixed page size".
- The pagination flow has the client repeat the request with the cursor until a response omits
nextCursor; clients "SHOULD treat a missing nextCursor as the end of results" and "support both paginated and non-paginated flows".
Droid should follow nextCursor until the list is exhausted (or request a larger page where the server supports it) and register all tools.
Actual
Only page 1 registers. Which tools are available depends on server-side registration order, and any server with more tools than one page silently loses the rest. Because Droid never sends a follow-up request, it also never reaches the only spec-sanctioned end-of-results signal (a response without nextCursor).
Notes
Summary
When an MCP server paginates its
tools/listresponse, Droid registers only the first page of tools and never followsnextCursor. Tools beyond page 1 are absent from the session's tool registry for the entire session: loading one by exact name fails as "unavailable in this session", and invoking it fails withInputValidationError.tools/listpagination is explicitly part of the MCP spec, with page size determined by the server — so any server whose tool count exceeds one page silently loses tools in Droid.Environment
droid0.186.0, Windows 11 (10.0.26200), Windows PowerShell 5.1laravel/mcppackage), streamable HTTP transport, 101 registered tools, default page size 50, max page size 100Reproduction
~/.factory/mcp.json.tools/listin registration order.Manual protocol walk against the same server (
initialize→tools/list, following cursors):Single-variable control: setting the server's page size to 1 and reconnecting makes exactly 1 tool register (the first in registration order). Page size and tool count are irrelevant — the client never requests page 2, whatever a page contains.
Expected
Per the MCP spec (2026-07-28, https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/pagination):
tools/listis a paginated operation, and "page size is determined by the server, and clients MUST NOT assume a fixed page size".nextCursor; clients "SHOULD treat a missingnextCursoras the end of results" and "support both paginated and non-paginated flows".Droid should follow
nextCursoruntil the list is exhausted (or request a larger page where the server supports it) and register all tools.Actual
Only page 1 registers. Which tools are available depends on server-side registration order, and any server with more tools than one page silently loses the rest. Because Droid never sends a follow-up request, it also never reaches the only spec-sanctioned end-of-results signal (a response without
nextCursor).Notes
cursorparameter is honored, and invalid cursors are handled gracefully — the manual walk above retrieved all 101 tools.tools/listpagination vianextCursoropenai/codex#28858). LibreChat's fix PR shows the cursor-following implementation: 🪢 fix: Paginate MCPtools/listto Load All Tools danny-avila/LibreChat#13840