Skip to main content

MCP Pagination Module

The MCP Server V2 implements pagination for tools/list, resources/list, and prompts/list endpoints per the MCP 2025-11-25 specification.

Overview

Pagination uses opaque cursors (base64url encoded) that the server generates. Clients cannot determine page size - the server decides based on its configuration. Key Features:
  • Default page size: 50 items
  • Maximum page size: 100 items
  • Opaque cursor encoding (base64url)
  • Invalid cursor validation with JSON-RPC errors

Code Usage

Basic Pagination

from praisonai.mcp_server.registry import MCPToolRegistry

# Create registry and register tools
registry = MCPToolRegistry()
for i in range(100):
    registry.register(
        name=f"tool_{i}",
        handler=lambda: f"Tool {i}",
        description=f"Tool number {i}"
    )

# Get first page (default 50 items)
tools, next_cursor = registry.list_paginated()
print(f"Got {len(tools)} tools")
print(f"Next cursor: {next_cursor}")

# Get next page using cursor
if next_cursor:
    more_tools, next_cursor = registry.list_paginated(cursor=next_cursor)
    print(f"Got {len(more_tools)} more tools")

Custom Page Size

# Request smaller pages
tools, next_cursor = registry.list_paginated(page_size=10)
print(f"Got {len(tools)} tools")  # 10 tools

# Page size is clamped to MAX_PAGE_SIZE (100)
tools, _ = registry.list_paginated(page_size=200)
print(f"Got {len(tools)} tools")  # Max 100 tools

Cursor Utilities

from praisonai.mcp_server.registry import encode_cursor, decode_cursor

# Encode a cursor with offset
cursor = encode_cursor(50)
print(f"Cursor: {cursor}")  # e.g., "NTA"

# Decode cursor
offset, snapshot = decode_cursor(cursor)
print(f"Offset: {offset}")  # 50

# Encode with snapshot hash (for consistency checking)
cursor = encode_cursor(100, "abc123hash")
offset, snapshot = decode_cursor(cursor)
print(f"Offset: {offset}, Snapshot: {snapshot}")

Resource and Prompt Pagination

from praisonai.mcp_server.registry import MCPResourceRegistry, MCPPromptRegistry

# Resource pagination
resource_registry = MCPResourceRegistry()
resources, next_cursor = resource_registry.list_paginated(page_size=20)

# Prompt pagination
prompt_registry = MCPPromptRegistry()
prompts, next_cursor = prompt_registry.list_paginated(page_size=20)

Server Handler Integration

The MCP server automatically handles pagination in the protocol handlers:
from praisonai.mcp_server.server import MCPServer
import asyncio

server = MCPServer(name="my-server")

# The server handles pagination automatically
# Client sends: {"method": "tools/list", "params": {"cursor": "NTA"}}
# Server responds with paginated results and nextCursor

Error Handling

Invalid cursors raise ValueError:
try:
    tools, _ = registry.list_paginated(cursor="invalid!!!")
except ValueError as e:
    print(f"Invalid cursor: {e}")
The server converts this to a JSON-RPC error with code -32602 (Invalid params).

MCP Protocol Compliance

This implementation follows MCP 2025-11-25 specification:
RequirementImplementation
Opaque cursorsBase64url encoded offset
Server-determined page sizeDefault 50, max 100
nextCursor in responseIncluded when more results exist
Invalid cursor handlingJSON-RPC error -32602

Constants

from praisonai.mcp_server.registry import DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE

print(f"Default page size: {DEFAULT_PAGE_SIZE}")  # 50
print(f"Maximum page size: {MAX_PAGE_SIZE}")      # 100

See Also