mcp-pagination
Skill2 starsChanged 3 months agoMITView on GitHub
Internal guardrail invoked by mcp-builder only — audits MCP tool schemas with list_*, search_*, find_*, get_all_* or SQL-executing operations for missing pagination (limit, offset, cursor) and unbounded results. Not for general MCP questions, single-item getters, or mutation-only tools.
In this repository46 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .cursor/rules/commit-conventions.mdcCursor rule
- .cursor/rules/cross-platform-handoff.mdcCursor rule
- .cursor/rules/dev-files-workspace.mdcCursor rule
- .cursor/rules/documentation-standards.mdcCursor rule
- .cursor/rules/gh-cli-preference.mdcCursor rule
- .cursor/rules/github-repository-policy.mdcCursor rule
- .cursor/rules/git-worktree-agent-workflow.mdcCursor rule
- .cursor/rules/hooks-guide.mdcCursor rule
- .cursor/rules/plugin-structure.mdcCursor rule
- .cursor/rules/plugin-version-bump.mdcCursor rule
- .cursor/rules/skill-frontmatter.mdcCursor rule
- .cursor/rules/skill-quality-standards.mdcCursor rule
- .cursor/rules/skills-guide.mdcCursor rule
- .cursor/rules/user-facing-script-standards.mdcCursor rule
- run-tamirs-superpowersSkill
- field-notebook-uiSkill
- diagnose-refusalSkill
- targeted-debugSkill
- decisionSkill
- deliver-devSkill
- diagnose-objectiveSkill
- orchestrate-devSkill
- plan-devSkill
- pr-devSkill
- start-devSkill
- switch-devSkill
- worker-devSkill
- changelog-reviewSkill
- dark-terminal-docSkill
- docs-reviewSkill
- platform-syncSkill
- mcp-builderSkill
- cleanupSkill
- github-policySkill
- multi-agent-repoSkill
- repo-scaffoldSkill
- repo-standardsSkill
- capture-configSkill
- find-skillSkill
- notify-setupSkill
- retroSkill
- session-reportSkill
- skill-creatorSkill
- usage-captureSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 4 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 57
If mcp-builder passes planned tool names or API pagination params, use them as input for Steps 1–3 below.
- Distinctive: line 91
Use these defaults unless the tool's documentation specifies lower maximums:
- Distinctive: line 104
If a tool has no pagination parameter, narrow scope with filters before fetching:
- Distinctive: line 134
Do NOT pre-fetch all pages and merge results — this defeats the guardrail entirely.
- Distinctive: line 212
Before approving any MCP server design that includes list or search tools, verify:
- Very specific: line 224
When invoked from mcp-builder Phase 4.1, report pass/fail per item.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
MCP Pagination Guardrails (Internal)
Why this skill exists
MCP tools that return lists or search results have no built-in safety net against unbounded responses. Calling list_issues, search_code, or any similar tool without a limit parameter can return hundreds or thousands of items, consuming 10-100x more tokens than needed, slowing responses, and inflating API costs. Naive implementations skip pagination because the tool "works" without it — this guardrail enforces limits before that mistake reaches production.
This skill is invoked by mcp-builder via Skill("mcp-pagination") when list/search operations appear in an MCP server design. It is not user-facing — users should run mcp-builder instead.
When mcp-builder invokes this skill
| mcp-builder phase | Why |
| Phase 1.3 — after cataloging collection endpoints | Set pagination strategy before any tool schemas |
Phase 3.0 — before each list_* / search_* / SQL tool | Apply limits and cursor mapping per tool |
| Phase 4.1 — after Inspector testing | Run quick-reference checklist against implemented tools |
| Phase 5 — eval design | Confirm evals use caller-driven pagination, not full scans |
If mcp-builder passes planned tool names or API pagination params, use them as input for Steps 1–3 below.
Workflow
Step 1 — Identify list/search operations in the MCP server design.
Any tool whose name matches these patterns needs a limit strategy:
list_*— always paginatedsearch_*— always paginatedget_*that returns an array at the top level — treat as paginated (name prefix alone does not exempt a tool; return type is what matters)- SQL-executing tools — require
LIMITclause enforcement
Exempt from guardrails (do not flag these):
- Single-item getters:
get_issue(id),get_user(id)— return one object, not an array - Mutations:
create_*,update_*,delete_*— not collection operations - Streaming/generative tools: LLM completion streams, SSE feeds, WebSocket subscriptions — these push generated data, not paginated lists
For API-specific pagination parameter names (GitHub REST per_page, GraphQL first/after, Slack cursor, Notion page_size, etc.), load references/pagination-patterns.md.
Step 2 — Verify each operation has a limiting mechanism.
For each identified operation, confirm one of the following is present:
| Mechanism | When to use | Example parameter |
limit / max_results / per_page | Primary list endpoints (REST) | limit=20 |
page + per_page | Offset pagination | page=1, per_page=10 |
cursor / page_token | Token-based continuation (REST) | cursor="<token>" |
first + after | GraphQL Relay cursor pagination | first=20, after="<endCursor>" |
SQL LIMIT clause | Any tool that executes raw SQL | SELECT ... LIMIT 50 |
| Date/time filter | When no explicit limit param exists | since="2024-06-01T00:00:00Z" |
Step 3 — Set safe starting limits.
Use these defaults unless the tool's documentation specifies lower maximums:
| Operation type | Safe starting limit | Rationale |
| Code search | 5-10 | Results are large; 10 is usually enough to find the target |
| Issue / PR search | 10-20 | Each item has metadata; 20 fits comfortably in context |
| Channel / message list | 50-100 | Lightweight items; higher limit reduces round-trips |
| SQL queries | 50-100 | Depends on row width — prefer lower for wide schemas |
| GraphQL list | 20 | Use first=20; avoid last unless reverse pagination needed |
| Generic list | 20 | Safe default when no guidance exists |
Step 4 — Add alternative filters when no limit param exists.
If a tool has no pagination parameter, narrow scope with filters before fetching:
# Date filtering — prefer ISO 8601 with timezone
since="2024-06-01T00:00:00Z"
before="2024-07-01T00:00:00Z"
# State filtering — exclude irrelevant items
state="open" # or "closed", "merged"
status="active" # or "inactive", "archived"
# Owner/author filtering
author="username"
assignee="username"
# Path/extension filtering (code search)
path="src/api"
extension="ts"Step 5 — Enforce incremental fetching.
The server design must not auto-paginate through all results. The correct pattern:
1. Fetch first page with safe limit
2. Return results to caller
3. Only fetch next page if caller explicitly requests moreDo NOT pre-fetch all pages and merge results — this defeats the guardrail entirely.
Hard Rules
- Never generate or approve a list/search MCP tool that has no limiting strategy — every such tool must expose at least one of:
limit,max_results,per_page,cursor,first, or a date filter parameter. - Never set a default limit above 100 — even if the tool supports higher values; the caller can increase it explicitly.
- Never auto-paginate — fetching page 2+ without an explicit caller request is forbidden; it silently multiplies token consumption.
- Always start at the low end of the safe range — prefer 10 over 50 when context size is unknown.
- SQL-executing tools must reject queries without a
LIMITclause — validate the SQL string server-side before executing. - Do not exempt a tool from guardrails based on name prefix alone — a
get_*tool that returns an array needs limits just likelist_*. - Do not apply guardrails to streaming/generative tools — LLM completions, SSE, and WebSocket tools are not collection-listing operations.
- Do not hardcode absolute paths or employer-specific tool names in server designs — keep examples generic (
owner="my-org", not a real org name).
Anti-patterns
Missing limit entirely:
# BAD — no limit; can return thousands of items
list_issues(repo="my-repo", state="open")
# GOOD
list_issues(repo="my-repo", state="open", limit=20)Auto-paginating all results:
# BAD — fetches every page and returns merged array
results = []
page = 1
while True:
batch = list_issues(repo="my-repo", page=page, per_page=100)
if not batch: break
results.extend(batch)
page += 1
return results
# GOOD — return page 1 and expose a cursor for the caller to continue
return list_issues(repo="my-repo", page=1, per_page=20, cursor=None)Unbounded SQL:
-- BAD
SELECT * FROM events WHERE user_id = $1
-- GOOD
SELECT * FROM events WHERE user_id = $1 ORDER BY created_at DESC LIMIT 50Overly broad search without filters:
# BAD — searches entire GitHub with no scope
search_code(query="auth")
# GOOD
search_code(query="auth", repo="my-org/my-repo", path="src/auth", limit=10)GraphQL auto-cursor-following:
# BAD — follows all cursors before returning
cursor = None
all_items = []
while True:
page = client.issues(first=100, after=cursor)
all_items.extend(page.nodes)
if not page.pageInfo.hasNextPage:
break
cursor = page.pageInfo.endCursor
return all_items
# GOOD — return first page with cursor for caller to continue
page = client.issues(first=20, after=after_cursor)
return {"items": page.nodes, "endCursor": page.pageInfo.endCursor, "hasNextPage": page.pageInfo.hasNextPage}Quick-reference checklist
Before approving any MCP server design that includes list or search tools, verify:
- Every
list_*tool haslimitorper_page(REST) orfirst(GraphQL) with a documented default <= 100 - Every
search_*tool haslimitormax_resultswith a documented default <= 20 - GraphQL list tools expose
first+afterand returnpageInfo.endCursor+pageInfo.hasNextPage - SQL-executing tools validate for a
LIMITclause before running - No tool auto-paginates; pagination is always caller-driven
- Streaming/generative tools (LLM completions, SSE, WebSocket) are correctly exempted
get_*tools that return arrays are treated as list operations (not exempted by name prefix)- Date/state/author filters are available as fallback when no limit param exists
- Default limits are at the conservative end of the safe range for the operation type
When invoked from mcp-builder Phase 4.1, report pass/fail per item. Return control to mcp-builder only after all items pass or you list concrete fixes for each failure.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

