Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,7 @@ import asyncio

from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client
from mcp.types import Resource
from mcp.types import PaginatedRequestParams, Resource


async def list_all_resources() -> None:
Expand All @@ -1857,7 +1857,7 @@ async def list_all_resources() -> None:

while True:
# Fetch a page of resources
result = await session.list_resources(cursor=cursor)
result = await session.list_resources(params=PaginatedRequestParams(cursor=cursor))
all_resources.extend(result.resources)

print(f"Fetched {len(result.resources)} resources")
Expand Down
4 changes: 2 additions & 2 deletions examples/snippets/clients/pagination_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client
from mcp.types import Resource
from mcp.types import PaginatedRequestParams, Resource


async def list_all_resources() -> None:
Expand All @@ -23,7 +23,7 @@ async def list_all_resources() -> None:

while True:
# Fetch a page of resources
result = await session.list_resources(cursor=cursor)
result = await session.list_resources(params=PaginatedRequestParams(cursor=cursor))
all_resources.extend(result.resources)

print(f"Fetched {len(result.resources)} resources")
Expand Down
165 changes: 136 additions & 29 deletions src/mcp/client/session.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import logging
from datetime import timedelta
from typing import Any, Protocol
from typing import Any, Protocol, overload

import anyio.lowlevel
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
from jsonschema import SchemaError, ValidationError, validate
from pydantic import AnyUrl, TypeAdapter
from typing_extensions import deprecated

import mcp.types as types
from mcp.shared.context import RequestContext
Expand Down Expand Up @@ -212,25 +213,79 @@ async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResul
types.EmptyResult,
)

async def list_resources(self, cursor: str | None = None) -> types.ListResourcesResult:
"""Send a resources/list request."""
@overload
@deprecated("Use list_resources(params=PaginatedRequestParams(...)) instead")
async def list_resources(self, cursor: str | None) -> types.ListResourcesResult: ...

@overload
async def list_resources(self, *, params: types.PaginatedRequestParams | None) -> types.ListResourcesResult: ...

@overload
async def list_resources(self) -> types.ListResourcesResult: ...

async def list_resources(
self,
cursor: str | None = None,
*,
params: types.PaginatedRequestParams | None = None,
) -> types.ListResourcesResult:
"""Send a resources/list request.

Args:
cursor: Simple cursor string for pagination (deprecated, use params instead)
params: Full pagination parameters including cursor and any future fields
"""
if params is not None and cursor is not None:
raise ValueError("Cannot specify both cursor and params")

if params is not None:
request_params = params
elif cursor is not None:
request_params = types.PaginatedRequestParams(cursor=cursor)
else:
request_params = None

return await self.send_request(
types.ClientRequest(
types.ListResourcesRequest(
params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None,
)
),
types.ClientRequest(types.ListResourcesRequest(params=request_params)),
types.ListResourcesResult,
)

async def list_resource_templates(self, cursor: str | None = None) -> types.ListResourceTemplatesResult:
"""Send a resources/templates/list request."""
@overload
@deprecated("Use list_resource_templates(params=PaginatedRequestParams(...)) instead")
async def list_resource_templates(self, cursor: str | None) -> types.ListResourceTemplatesResult: ...

@overload
async def list_resource_templates(
self, *, params: types.PaginatedRequestParams | None
) -> types.ListResourceTemplatesResult: ...

@overload
async def list_resource_templates(self) -> types.ListResourceTemplatesResult: ...

async def list_resource_templates(
self,
cursor: str | None = None,
*,
params: types.PaginatedRequestParams | None = None,
) -> types.ListResourceTemplatesResult:
"""Send a resources/templates/list request.

Args:
cursor: Simple cursor string for pagination (deprecated, use params instead)
params: Full pagination parameters including cursor and any future fields
"""
if params is not None and cursor is not None:
raise ValueError("Cannot specify both cursor and params")

if params is not None:
request_params = params
elif cursor is not None:
request_params = types.PaginatedRequestParams(cursor=cursor)
else:
request_params = None

return await self.send_request(
types.ClientRequest(
types.ListResourceTemplatesRequest(
params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None,
)
),
types.ClientRequest(types.ListResourceTemplatesRequest(params=request_params)),
types.ListResourceTemplatesResult,
)

Expand Down Expand Up @@ -317,14 +372,40 @@ async def _validate_tool_result(self, name: str, result: types.CallToolResult) -
except SchemaError as e:
raise RuntimeError(f"Invalid schema for tool {name}: {e}")

async def list_prompts(self, cursor: str | None = None) -> types.ListPromptsResult:
"""Send a prompts/list request."""
@overload
@deprecated("Use list_prompts(params=PaginatedRequestParams(...)) instead")
async def list_prompts(self, cursor: str | None) -> types.ListPromptsResult: ...

@overload
async def list_prompts(self, *, params: types.PaginatedRequestParams | None) -> types.ListPromptsResult: ...

@overload
async def list_prompts(self) -> types.ListPromptsResult: ...

async def list_prompts(
self,
cursor: str | None = None,
*,
params: types.PaginatedRequestParams | None = None,
) -> types.ListPromptsResult:
"""Send a prompts/list request.

Args:
cursor: Simple cursor string for pagination (deprecated, use params instead)
params: Full pagination parameters including cursor and any future fields
"""
if params is not None and cursor is not None:
raise ValueError("Cannot specify both cursor and params")

if params is not None:
request_params = params
elif cursor is not None:
request_params = types.PaginatedRequestParams(cursor=cursor)
else:
request_params = None

return await self.send_request(
types.ClientRequest(
types.ListPromptsRequest(
params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None,
)
),
types.ClientRequest(types.ListPromptsRequest(params=request_params)),
types.ListPromptsResult,
)

Expand Down Expand Up @@ -363,14 +444,40 @@ async def complete(
types.CompleteResult,
)

async def list_tools(self, cursor: str | None = None) -> types.ListToolsResult:
"""Send a tools/list request."""
@overload
@deprecated("Use list_tools(params=PaginatedRequestParams(...)) instead")
async def list_tools(self, cursor: str | None) -> types.ListToolsResult: ...

@overload
async def list_tools(self, *, params: types.PaginatedRequestParams | None) -> types.ListToolsResult: ...

@overload
async def list_tools(self) -> types.ListToolsResult: ...

async def list_tools(
self,
cursor: str | None = None,
*,
params: types.PaginatedRequestParams | None = None,
) -> types.ListToolsResult:
"""Send a tools/list request.

Args:
cursor: Simple cursor string for pagination (deprecated, use params instead)
params: Full pagination parameters including cursor and any future fields
"""
if params is not None and cursor is not None:
raise ValueError("Cannot specify both cursor and params")

if params is not None:
request_params = params
elif cursor is not None:
request_params = types.PaginatedRequestParams(cursor=cursor)
else:
request_params = None

result = await self.send_request(
types.ClientRequest(
types.ListToolsRequest(
params=types.PaginatedRequestParams(cursor=cursor) if cursor is not None else None,
)
),
types.ClientRequest(types.ListToolsRequest(params=request_params)),
types.ListToolsResult,
)

Expand Down
Loading
Loading