Pagination
The MCP Ruby SDK supports pagination for list operations that may return large result sets. Pagination uses string cursor tokens carrying a zero-based offset, treated as opaque by clients: the server decides page size, and the client follows nextCursor until the server omits it.
Pagination applies to tools/list, prompts/list, resources/list, and resources/templates/list, including lists produced by a custom resources_list_handler.
Enabling Pagination
Pass page_size: to MCP::Server.new to split list responses into pages. When page_size is omitted (the default), list responses contain all items in a single response, preserving the pre-pagination behavior.
server = MCP::Server.new(
name: "my_server",
tools: tools,
page_size: 50,
)
When page_size is set, list responses include a nextCursor field whenever more pages are available:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{ "name": "example_tool" }
],
"nextCursor": "50"
}
}
Invalid cursors (e.g. non-numeric, negative, or out-of-range) are rejected with JSON-RPC error code -32602 (Invalid params) per the MCP specification.
List Result Caching
Per SEP-2549, list and read results can carry cache hints telling clients how long a result stays fresh (ttlMs, max-age semantics in milliseconds; 0 means do not cache) and whether shared intermediaries may cache it (cacheScope: "public" or "private").
Emission is opt-in: pass ttl_ms: and/or cache_scope: to MCP::Server.new and both fields are added to tools/list, prompts/list, resources/list, resources/templates/list, and resources/read results (a missing field is filled with the defaults ttlMs: 0 / cacheScope: "private", the scope that keeps a potentially user-dependent result out of shared caches). When neither is set, responses are serialized exactly as before. The 2026-07-28 revision makes both hints required on these results, so on requests carrying the modern _meta envelope the server always emits them, filling unset values with the same defaults; legacy protocol versions keep the opt-in behavior.
server = MCP::Server.new(
name: "my_server",
tools: tools,
ttl_ms: 60_000, # results stay fresh for one minute
cache_scope: "private", # only the requesting client may cache them
)
A resources_read_handler can override the hints per result by returning a full result hash instead of bare contents:
server.resources_read_handler do |params|
{ contents: [{ uri: params[:uri], mimeType: "text/plain", text: "..." }], ttlMs: 5_000 }
end
Client Side
Iterating pages, fetching whole collections with the max_pages guard, and reading the cache hints on the result structs are documented on the client Pagination page.