Drain all pages from MCP SDK paginated list methods — get every tool, resource, and prompt without cursor management
Project description
mcplisten
Drain all pages from MCP SDK paginated list methods — get every tool, resource, and prompt without cursor management.
Python developers using the MCP Python SDK's
Client.list_tools()only receive the first page of results when a server paginates its responses. mcplisten transparently drains every page so you get the complete inventory.
Quick Start
pip install git+https://github.com/prasad-a-abhishek/mcplisten.git
from mcplisten import list_all_tools
# Async usage (with MCP SDK Client)
from mcp import Client
async with Client(server_params) as client:
tools = await list_all_tools(client) # drains all pages
print(f"Got {len(tools)} tools")
# Sync usage (with SyncMCPClient from mcpsync)
from mcpsync import SyncMCPClient
from mcplisten import list_all_tools_sync
with SyncMCPClient(params) as client:
tools = list_all_tools_sync(client)
⚡ Performance & Benchmarks
mcplisten is a thin pagination drain helper — it adds zero computational overhead beyond the network I/O of fetching additional pages. The synchronous wrapper spawns a fresh event loop per call (thread-safe for single-shot use).
python3 benchmarks/run_benchmark.py
Benchmark environment: Python 3.11.15, Linux x86_64 (kernel 6.12.67), 4 vCPU.
Note: mcplisten has no direct competitor — the MCP Python SDK itself does not provide list_all_* helpers (see modelcontextprotocol/python-sdk#2556).
Test Status
The repository ships with a 131-test pytest suite covering every spec acceptance criterion (22/22), concurrent-call safety, unicode round-trip, dict-shaped and pydantic-shaped responses, CLI end-to-end against a fake paginating stdio server, and zero-dependency enforcement. Run pytest tests/ -q to reproduce (≈1 second).
Spec: see spec.md for the canonical 22-acceptance-criteria contract that drives the test suite.
Why mcplisten?
The MCP Python SDK's ClientSession.list_tools(cursor=...) accepts a cursor parameter but requires callers to manually loop across pages. MCP gateways, Claude Code, Cursor, and the Inspector CLI all shipped with this single-page limitation — silently losing tools when servers register more tools than fit in one page.
mcplisten is the fix: a zero-dependency, zero-overhead wrapper that calls list_tools(cursor=None) then follows nextCursor until the server returns null. No SDK changes required. No configuration. Drop in.
| Feature | mcplisten | SDK default |
|---|---|---|
| Multi-page drain | ✅ | ❌ single page only |
| Zero dependencies | ✅ | — |
| Sync + async | ✅ | async only |
Generic list_all() |
✅ | ❌ |
| CLI included | ✅ | ❌ |
Key Features
list_all_tools(client)— drain all pages fromlist_tools(), returnslist[dict]list_all_resources(client)— drain all pages fromlist_resources()list_all_prompts(client)— drain all pages fromlist_prompts()list_all_resource_templates(client)— drain all pages fromlist_resource_templates()list_all(client, method, items_key)— generic drain helper- Sync wrappers —
list_all_*_sync()variants forSyncMCPClient - CLI —
mcplisten list-tools -- <server-cmd>,list-resources,list-prompts - Zero dependencies — pure Python stdlib, no third-party packages
- Full type stubs — Python 3.11+ with complete type annotations
CLI Reference
# List all tools from a stdio server
mcplisten list-tools -- python -m my_mcp_server
# List all resources
mcplisten list-resources -- python -m my_mcp_server
# List all prompts
mcplisten list-prompts -- python -m my_mcp_server
# Verbose mode — includes per-server tool counts
mcplisten list-tools --verbose -- python -m my_mcp_server
# Help
mcplisten --help
mcplisten list-tools --help
API Reference
list_all_tools(client) — async
from mcplisten import list_all_tools
tools: list[dict[str, Any]] = await list_all_tools(client)
Drains all pages from client.list_tools() (works with Client, ClientSession, and ClientSessionGroup).
list_all_tools_sync(client) — sync
from mcplisten import list_all_tools_sync
tools: list[dict[str, Any]] = list_all_tools_sync(client)
Synchronous wrapper for use with SyncMCPClient (from the mcpsync extra).
list_all(client, method, items_key) — generic
from mcplisten import list_all
result: list[dict[str, Any]] = await list_all(client, "list_tools", "tools")
Generic drain helper for any paginated list method. items_key is the dict key holding the items list in each page response.
CLI
mcplisten [--help]
list-tools [--verbose] [--] <server-cmd>...
list-resources [--] <server-cmd>...
list-prompts [--] <server-cmd>...
list-resource-templates [--] <server-cmd>...
Exits 0 on success (print JSON to stdout), non-zero on error (print message to stderr).
Limitations
- Cursor timing: if a server adds a tool between page 1 and page 2 of a drain, the caller may see duplicates. This is consistent with the MCP SDK's at-most-once semantics.
- No streaming variant: memory-constrained streaming (async generator) is a separate future feature.
- SDK version sensitivity: if the MCP SDK changes its pagination API (method signature or cursor field location), this library will break. Tests pin against a known SDK version.
- No parallelization:
ClientSessionGroupdrains each session sequentially, not in parallel.
Non-Goals
- Changing the underlying MCP SDK's pagination mechanism
- Server-side pagination implementation
- Authentication (passes through to the underlying client)
- Tool/result caching
License
MIT License — © 2026 Prasad Abhishek
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcplisten-0.1.0.tar.gz.
File metadata
- Download URL: mcplisten-0.1.0.tar.gz
- Upload date:
- Size: 142.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57e2780b5c62a768e6e3860246b3450f881eb9b6ac65478a5ab6981d05b1b017
|
|
| MD5 |
c5128d26f63eefe500739a103c55ff92
|
|
| BLAKE2b-256 |
0a33e648f98f767368cfe5f751ff320b8236687e0a8047cc82d36bf797dcb130
|
File details
Details for the file mcplisten-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcplisten-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f82e1e4e20e68c0deb391271698220142b0f50f3b7da4fb4332822ed651ee5cd
|
|
| MD5 |
b41ef2cf1b97101d2785c67113712af7
|
|
| BLAKE2b-256 |
5a7eca22f37c6560005d85c9dacc6ef8118fb6f8b7ee59bb9dd2db1d05f74637
|