Description
The MCP client never follows tools/list pagination. The MCP spec paginates tools/list with a top-level nextCursor: a client must re-issue the request with { "cursor": "<nextCursor>" } until the field is absent. Both JSON-RPC clients in src/connectors/mcp-client.ts call it exactly once with empty params:
// src/connectors/mcp-client.ts:462 (StdioJsonRpcClient) and :608 (HttpJsonRpcClient)
listTools(): Promise<unknown> {
return this.request("tools/list", {});
}
extractToolValues (:365) then reads only result.tools from that single page, so every tool after the first page is silently dropped from discovery.
That is not just a display gap: callMcpConnectorTool hard-rejects any tool name missing from the discovered set (src/connectors/mcp-runtime.ts:88-92):
MCP tool <name> was not returned by tools/list for <connector>. Run openwiki_list_mcp_tools first and use an exact discovered name.
So on any MCP server that paginates, valid read-only tools become permanently uncallable, and the error message points the user at openwiki_list_mcp_tools — which is itself truncated to page 1, so the advice can never resolve it.
Both transports are affected (stdio and HTTP).
Steps to Reproduce
- Configure an MCP connector against a server whose
tools/list paginates — page 1 returns some tools plus a nextCursor, page 2 returns the rest. (Hosted servers with large tool sets, e.g. Notion, do this.)
- Run
openwiki_list_mcp_tools for that connector.
- Note that only the page-1 tools are listed.
- Call
openwiki_call_mcp_tool with the exact name of a read-only tool that lives on page 2.
Minimal reproduction of the underlying behavior — a stub server that returns:
{"tools": [{"name": "page-one-tool"}], "nextCursor": "cursor-2"}
then, for a request carrying {"cursor": "cursor-2"}:
{"tools": [{"name": "page-two-tool"}]}
Expected Behavior
listMcpTools discovers the complete tool set across all pages, so page-two-tool is listed and can be called.
Actual Behavior
Only page-one-tool is discovered. The second request is never sent — tools/list is issued once with {} and nextCursor is ignored. Calling page-two-tool throws MCP tool page-two-tool was not returned by tools/list, even though the tool is valid and read-only.
Environment
- OS: Windows 11
- Node.js version: v24.18.1
- OpenWiki version:
main @ 398ebad
Additional Context
The sibling stdio/HTTP clients both expose an identical private request(method, params), so a single shared pagination helper can fix both without duplicating the loop. Any fix should bound the loop (stop on a repeated cursor and cap total pages) so a misbehaving server that always returns a cursor cannot spin forever.
I have a fix ready and will open a PR referencing this issue.
Description
The MCP client never follows
tools/listpagination. The MCP spec paginatestools/listwith a top-levelnextCursor: a client must re-issue the request with{ "cursor": "<nextCursor>" }until the field is absent. Both JSON-RPC clients insrc/connectors/mcp-client.tscall it exactly once with empty params:extractToolValues(:365) then reads onlyresult.toolsfrom that single page, so every tool after the first page is silently dropped from discovery.That is not just a display gap:
callMcpConnectorToolhard-rejects any tool name missing from the discovered set (src/connectors/mcp-runtime.ts:88-92):So on any MCP server that paginates, valid read-only tools become permanently uncallable, and the error message points the user at
openwiki_list_mcp_tools— which is itself truncated to page 1, so the advice can never resolve it.Both transports are affected (stdio and HTTP).
Steps to Reproduce
tools/listpaginates — page 1 returns some tools plus anextCursor, page 2 returns the rest. (Hosted servers with large tool sets, e.g. Notion, do this.)openwiki_list_mcp_toolsfor that connector.openwiki_call_mcp_toolwith the exact name of a read-only tool that lives on page 2.Minimal reproduction of the underlying behavior — a stub server that returns:
{"tools": [{"name": "page-one-tool"}], "nextCursor": "cursor-2"}then, for a request carrying
{"cursor": "cursor-2"}:{"tools": [{"name": "page-two-tool"}]}Expected Behavior
listMcpToolsdiscovers the complete tool set across all pages, sopage-two-toolis listed and can be called.Actual Behavior
Only
page-one-toolis discovered. The second request is never sent —tools/listis issued once with{}andnextCursoris ignored. Callingpage-two-toolthrowsMCP tool page-two-tool was not returned by tools/list, even though the tool is valid and read-only.Environment
main@ 398ebadAdditional Context
The sibling stdio/HTTP clients both expose an identical private
request(method, params), so a single shared pagination helper can fix both without duplicating the loop. Any fix should bound the loop (stop on a repeated cursor and cap total pages) so a misbehaving server that always returns a cursor cannot spin forever.I have a fix ready and will open a PR referencing this issue.