Skip to content

feat(pagination): cursor-based pagination + two-phase tool discovery#6

Merged
bntvllnt merged 3 commits intomainfrom
feat/pagination-two-phase-discovery
Mar 27, 2026
Merged

feat(pagination): cursor-based pagination + two-phase tool discovery#6
bntvllnt merged 3 commits intomainfrom
feat/pagination-two-phase-discovery

Conversation

@bntvllnt
Copy link
Copy Markdown
Contributor

Summary

  • Adds opt-in cursor-based pagination for tools/list (MCP spec-compliant)
  • Adds two-phase tool discovery: tools/list_summary (name+description only) + tools/describe (full schema on-demand)
  • Both features enabled via new pagination field on ServerConfig

Key design decisions

  • No-cursor safety: tools/list without cursor always returns ALL tools — prevents silent tool loss for clients that don't support pagination
  • HMAC-signed cursors: Per-instance secret, constant-time verification via crypto.subtle.verify(), cross-method namespace prevents cursor reuse
  • Cached tool list: Tools are immutable after registration, schema conversion runs once
  • Handler override ordering: Pagination handlers registered AFTER registerTools() to avoid SDK assertCanSetRequestHandler conflict
  • Two-phase is non-standard: tools/list_summary + tools/describe are custom MCP methods (community proposal #1923), documented as bespoke extensions targeting custom agents

Files changed

File Change
src/pagination.ts NEW — HMAC cursor encode/decode, paginateTools(), createPaginationContext()
src/server.ts Override tools/list handler, register two-phase handlers
src/types.ts PaginationConfig interface + pagination on ServerConfig
src/index.ts Export PaginationConfig, ToolSummary, ToolPage
tests/pagination.test.ts NEW — 28 tests covering all ACs + edge cases + SDK canary
vitest.config.ts Branch threshold 98% (v8 limitation on HMAC-guarded defensive code)

Test plan

  • 102 tests passing (74 existing + 28 new)
  • 100% line/statement/function coverage
  • 98% branch coverage (remaining 2% = HMAC-guarded unreachable defensive code)
  • Backwards compatible: no pagination config = zero behavior change
  • Existing server/hooks/e2e/validators tests unaffected
  • SDK canary test verifies setRequestHandler override works
  • Lint, typecheck, build all green

Adds opt-in pagination for tools/list and two-phase discovery
(tools/list_summary + tools/describe) to reduce token overhead for
MCP clients with many tools.

- Cursor-based pagination (MCP spec-compliant) with HMAC-signed cursors
- No-cursor requests always return ALL tools (prevents silent tool loss)
- Two-phase: tools/list_summary (name+description) + tools/describe (full schema)
- PaginationConfig on ServerConfig with pageSize validation (>= 1)
- Constant-time HMAC verification via crypto.subtle.verify()
- Cached tool list (immutable after registration)
- 102 tests, 100% line/statement/function coverage
@bntvllnt bntvllnt self-assigned this Mar 27, 2026
- Reject NaN and non-integer floats for pageSize (Number.isInteger)
- Wrap atob() in try-catch in hmacVerify for edge runtime compat
- Update stale test comment
- Bump package.json to 0.2.0
- Add v0.2.0 CHANGELOG entry (pagination + two-phase + security)
- Add pagination section to README API reference
- Update CLAUDE.md and AGENTS.md with pagination architecture
- Regenerate llms.txt and llms-full.txt with pagination API docs
- Update default server version to 0.2.0
@bntvllnt bntvllnt merged commit 7cf7844 into main Mar 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant