different-ai/openwork · error · ExternalMcpDiagnosticError
MCP_CATALOG_PAGE_LIMIT
MCP_CATALOG_PAGE_LIMIT
Error message
MCP_CATALOG_PAGE_LIMIT
What it means
Thrown after the loop when the provider requires more than pageLimit (default EXTERNAL_MCP_TOOL_PAGE_LIMIT = 20) tools/list pages to return its full catalog. This is a hard cap on pagination round-trips, distinct from the tool-item and byte limits.
Source
Thrown at ee/apps/den-api/src/capability-sources/external-mcp-client.ts:744
tracker: input.diagnostic,
code: "MCP_CATALOG_BYTE_LIMIT",
operatorAction: `Reduce the complete serialized tool catalog below ${EXTERNAL_MCP_CATALOG_LIMIT_BYTES} bytes.`,
})
}
catalogBytes += cursorMeasurement.bytes
if (seenCursors.has(result.nextCursor)) {
throw catalogDiagnosticError({
tracker: input.diagnostic,
code: "MCP_CATALOG_CURSOR_LOOP",
operatorAction: "Fix the provider's tools/list pagination so each nextCursor advances.",
})
}
seenCursors.add(result.nextCursor)
cursor = result.nextCursor
}
throw catalogDiagnosticError({
tracker: input.diagnostic,
code: "MCP_CATALOG_PAGE_LIMIT",
operatorAction: `Reduce the provider catalog to at most ${pageLimit} pages or use a scoped MCP server.`,
})
}
export type ExternalMcpConnectResult =
| { status: "connected" }
| { status: "needs_auth"; authorizeUrl: string }
/**
* Attempts to connect. For authType "none"/"apikey" this either succeeds or
* throws. For "oauth", if there's no valid token yet, the SDK's transport
* drives discovery (+ dynamic client registration if needed) and returns the
* authorize URL to send the admin's browser to — no token exchange happens
* yet, that's connect/callback's job. `signedState` (our own signed token
* identifying which connection this is for) is passed through as the
* standard OAuth `state` param, since that's the only param guaranteed to
* round-trip back to connect/callback on any spec-compliant server.
*/View on GitHub (pinned to 2b7df46e8a)
Solutions
- Reduce the provider catalog to at most 20 pages worth of tools
- Use a scoped MCP server exposing only the needed tools
- Increase the server's page size so the catalog fits in fewer pages
- Split the provider into multiple smaller servers
Example fix
// before: server pageSize=10 with 500 tools -> 50 pages // after: server pageSize=100 -> 5 pages (under the 20-page limit)
Defensive patterns
Strategy: validation
Validate before calling
const pages = Math.ceil(totalTools / pageSize)
if (pages > 20) throw new Error(`${pages} pages exceeds the 20-page catalog limit`) Try / catch
try {
await connectExternalMcp(...)
} catch (err) {
if (err instanceof Error && err.message.includes("MCP_CATALOG_PAGE_LIMIT")) {
console.error("Provider needs >20 tools/list pages; increase page size or reduce catalog")
} else throw err
} Prevention
- Honor the client's requested page size and use a large page size (e.g. 100+)
- Keep catalogs small enough to fit in 20 pages
- Prefer scoped servers for large internal registries
- Monitor page growth as your tool set expands
When it happens
Trigger: The while (cursor !== undefined) loop in collectExternalMcpToolPages exits without the diagnostic 'catalog_ready' pass because the iteration count reached pageLimit pages and nextCursor is still defined.
Common situations: Providers with tiny page sizes (e.g. 10 tools/page) and large catalogs (thousands of tools); servers that ignore the client's requested page size; very broad aggregator servers.
Related errors
- pagination_unsupported
- MCP_TOOL_DISCOVERY
- MCP_CATALOG_CURSOR_SIZE_LIMIT
- MCP_CATALOG_CURSOR_LOOP
- invalid_mcp_token_payload
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/cc5d8580b6d9b1f9.
Report an issue: GitHub.