Back to Documentation

Pagination and Streaming

Efficient data retrieval patterns for large datasets and real-time feeds. Let agents control how data flows.

Pagination Strategies

Cursor-Based Pagination

Most reliable for changing datasets. Uses opaque cursor for position tracking.

{
  "tool": "list_orders",
  "arguments": {
    "limit": 50,
    "cursor": "eyJpZCI6MTIzfQ==",
    "direction": "forward"
  }
}

// Response includes next cursor
{
  "items": [...],
  "next_cursor": "eyJpZCI6MTczfQ==",
  "has_more": true
}

Offset-Based Pagination

Simple but less stable. Good for static datasets.

{
  "tool": "search_products",
  "arguments": {
    "page": 3,
    "per_page": 20,
    "sort": "created_at"
  }
}

// Response with page metadata
{
  "items": [...],
  "page": 3,
  "per_page": 20,
  "total_pages": 15,
  "total_items": 287
}

Keyset Pagination

Uses actual data values for positioning. Efficient for large datasets.

{
  "tool": "list_events",
  "arguments": {
    "limit": 100,
    "after_id": "evt_8291",
    "after_timestamp": "2025-08-25T10:00:00Z"
  }
}

Server-Sent Events (SSE)

Stream real-time updates and partial results as they become available:

SSE Stream Example

// Agent initiates stream
{
  "tool": "stream_logs",
  "arguments": {
    "filter": "level:error",
    "follow": true
  }
}

// Server sends events
data: {"id":"log_1","level":"error","message":"Connection failed"}

data: {"id":"log_2","level":"error","message":"Retry attempted"}

event: done
data: {"total_events": 2, "session_id": "stream_abc123"}

Event Types

  • • data - Regular data event
  • • progress - Progress update
  • • error - Error notification
  • • done - Stream complete

Stream Controls

  • • Pause/resume capability
  • • Backpressure handling
  • • Automatic reconnection
  • • Event buffering

Iteration Patterns

Progressive Loading

Load data incrementally as needed:

1. Load first page (10 items)
2. Process and check if more needed
3. Load next page if criteria met
4. Continue until done or limit reached

Parallel Pagination

Fetch multiple pages concurrently:

// After getting total pages
Promise.all([
  fetchPage(1),
  fetchPage(2),
  fetchPage(3)
])

Windowed Iteration

Process data in sliding windows:

Window 1: Items 0-99
Window 2: Items 50-149 (50% overlap)
Window 3: Items 100-199 (50% overlap)

Advanced Features

Resumable Pagination

Save and restore pagination state:

{
  "pagination_state": {
    "cursor": "abc123",
    "processed": 450,
    "total": 1200
  }
}

Adaptive Page Size

Adjust page size based on performance:

if (latency > 500ms) {
  page_size = Math.max(10, page_size / 2)
} else if (latency < 100ms) {
  page_size = Math.min(200, page_size * 2)
}

Configuration Example

{
  "pagination": {
    "default_strategy": "cursor",
    "default_page_size": 50,
    "max_page_size": 500,
    "endpoints": {
      "/api/orders": {
        "strategy": "cursor",
        "page_size": 100,
        "sort_required": true
      },
      "/api/search": {
        "strategy": "offset",
        "max_results": 1000,
        "deep_pagination_limit": 10000
      },
      "/api/events": {
        "strategy": "keyset",
        "key_fields": ["timestamp", "id"],
        "supports_streaming": true
      }
    }
  },
  "streaming": {
    "enabled": true,
    "protocols": ["sse", "websocket"],
    "heartbeat_interval": 30,
    "reconnect_attempts": 3,
    "buffer_size": 1000
  }
}

Best Practices

Use stable sort orders

Always include a unique field in sort to ensure consistent pagination

Implement page size limits

Protect your API from excessive page size requests

Provide total counts carefully

COUNT(*) can be expensive; consider estimates for large datasets

Stream for real-time data

Use SSE or WebSockets for live updates instead of polling

Efficient data retrieval at scale

MCPify handles pagination complexity so agents can focus on the data.