Pagination

Offset-based pagination with page and limit query params. Cursor pagination is on the roadmap.

Defaults

Override per resource

class UserResource(BaseResource):
    model = User
    limit = 50

Override per request

🤖 MCP — tools/call

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_user",
    "arguments": {"page": 3, "limit": 100}
  }
}

🌐 REST — Querystring

GET /users?page=3&limit=100

Invalid values are silently ignored (the defaults remain in effect).

Response shape

List responses come wrapped:

{
  "meta": {
    "page": 1,
    "limit": 25,
    "next": "/users?page=2&limit=25",
    "previous": "/users?page=0&limit=25"
  },
  "objects": [ ... ]
}

meta.previous only appears on page 2 and beyond.

Counting

?count=true returns {"count": N} instead of objects. The implementation rewrites the SELECT to count(DISTINCT id) to avoid Django's wrapping subquery — much faster on InnoDB.

Normalize

?normalize_list=true returns a dict keyed by id instead of a list:

{"42": {...}, "43": {...}}

Useful for client-side stores that index by id.

📌

Cursor pagination is planned — opt-in per resource, opaque token from last id/timestamp. It avoids skipping/duplicating rows when the list is changing under you.

0-mcp by Stamatios Stamou Jr — github.com/ssjunior/0-mcp