python-sdk icon indicating copy to clipboard operation
python-sdk copied to clipboard

Enhancement in list_tools for both client and servce side

Open xlb0479 opened this issue 5 months ago • 2 comments

Description

https://github.com/modelcontextprotocol/python-sdk/blob/6566c08446ad37b66f1457532c7f5a14f243ae10/src/mcp/client/session.py#L384-L394

Why can't we expose the params parameter of tools/list to the client, so that the server can use this params to enhance the tools/list functionality — for example, enabling context-aware tool filtering?

xlb0479 avatar Jul 16 '25 01:07 xlb0479

Hi @xlb0479 - I don't understand your requirement - by definition the PaginatedRequestParams are being used by the client for pagination, so they are available for the client to update its request for pagination.

Could you provide some more details on what you're trying to achieve?

felixweinberger avatar Oct 06 '25 18:10 felixweinberger

Linking this to the ongoing protocol work around discovery/filtering (e.g. https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1300 and related scope/versioning SEPs).

From a host/client perspective, once tools/list (and friends) gain richer filtering in the spec – especially things like:

  • filter.groups / filter.tags (as in SEP-1300),
  • and potentially filter.names / filter.excludeNames for explicit allow/deny lists –

the Python SDK will need a way to surface those fields ergonomically, otherwise host apps are forced to:

  • either drop down to raw JSON RPC calls, or
  • accept that some protocol features (like name-based whitelists) aren’t available from the high-level client.

Concretely, it would be very helpful if list_tools (and similar methods) exposed either:

  1. A typed filter argument that tracks the spec, e.g.:
class ToolsFilter(TypedDict, total=False):
    names: list[str]
    exclude_names: list[str]
    groups: list[str]
    tags: list[str]
    # future fields as SEPs land

async def list_tools(
    self,
    *,
    cursor: str | None = None,
    filter: ToolsFilter | None = None,
) -> ListToolsResult:
    ...

or, if you prefer to keep the surface area stable while SEPs evolve:

  1. A params escape hatch that can pass through arbitrary filter fields from the spec, while still keeping cursor explicit, e.g.:
async def list_tools(
    self,
    *,
    cursor: str | None = None,
    params: dict[str, Any] | None = None,
) -> ListToolsResult:
    ...

Personally I’d lean toward the typed filter once the protocol side is more settled, but even a generic params argument would unblock early adopters who want to:

  • implement tool whitelists on the server side (to avoid large responses that get filtered on the client),
  • align Python hosts with SEP-1300 and future discovery SEPs,
  • and avoid having to bypass the SDK for common discovery operations.

Happy to adjust the suggestion once the exact filter shape is finalized in the spec – the main ask is to make sure the SDK has a clear path to expose those protocol-level filters without requiring users to reimplement the client.

dgenio avatar Nov 27 '25 17:11 dgenio

I'm going to close this issue as ClientSession has recently been refactored to allow passing in the full params object, rather than just the cursor: https://github.com/modelcontextprotocol/python-sdk/blob/89ff338174cec2b28f23deaec6136a4f3b11e875/src/mcp/client/session.py#L495

Further discussions around tool filtering should happen in SEP discussion threads rather than in in the Python SDK repo.

maxisbey avatar Dec 08 '25 10:12 maxisbey