From ac8cc4eb331584def405019f87029ae5ec35567d Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Sat, 13 Dec 2025 20:22:43 -0500 Subject: [PATCH] Remove legacy _task_capable_initialize() workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function set experimental={"tasks": {}} but per the MCP spec: 1. Tasks belong in capabilities.tasks, not capabilities.experimental 2. Clients only need to declare task capabilities if receiving task-augmented requests from the server (bi-directional support) For client→server task requests (tools/call with task=True), only the server needs to declare task capabilities. The SDK's native session.initialize() handles this correctly. --- src/fastmcp/client/client.py | 6 +--- src/fastmcp/client/tasks.py | 63 ------------------------------------ 2 files changed, 1 insertion(+), 68 deletions(-) diff --git a/src/fastmcp/client/client.py b/src/fastmcp/client/client.py index c498039e9a..c9ee6c2fe3 100644 --- a/src/fastmcp/client/client.py +++ b/src/fastmcp/client/client.py @@ -56,7 +56,6 @@ ResourceTask, TaskNotificationHandler, ToolTask, - _task_capable_initialize, ) from fastmcp.exceptions import ToolError from fastmcp.mcp_config import MCPConfig @@ -458,10 +457,7 @@ async def initialize( try: with anyio.fail_after(timeout): - self._session_state.initialize_result = await _task_capable_initialize( - self.session - ) - + self._session_state.initialize_result = await self.session.initialize() return self._session_state.initialize_result except TimeoutError as e: raise RuntimeError("Failed to initialize server session") from e diff --git a/src/fastmcp/client/tasks.py b/src/fastmcp/client/tasks.py index e685153da0..54a397dad8 100644 --- a/src/fastmcp/client/tasks.py +++ b/src/fastmcp/client/tasks.py @@ -12,13 +12,6 @@ from typing import TYPE_CHECKING, Generic, TypeVar import mcp.types -from mcp import ClientSession -from mcp.client.session import ( - SUPPORTED_PROTOCOL_VERSIONS, - _default_elicitation_callback, - _default_list_roots_callback, - _default_sampling_callback, -) from mcp.types import GetTaskResult, TaskStatusNotification from fastmcp.client.messages import Message, MessageHandler @@ -30,62 +23,6 @@ from fastmcp.client.client import CallToolResult, Client -# TODO(SEP-1686): Remove this function when the MCP SDK adds an -# `experimental_capabilities` parameter to ClientSession (the server side -# already has this via `create_initialization_options(experimental_capabilities={})`). -# The SDK currently hardcodes `experimental=None` in ClientSession.initialize(). -async def _task_capable_initialize( - session: ClientSession, -) -> mcp.types.InitializeResult: - """Initialize a session with task capabilities declared.""" - sampling = ( - mcp.types.SamplingCapability() - if session._sampling_callback != _default_sampling_callback - else None - ) - elicitation = ( - mcp.types.ElicitationCapability() - if session._elicitation_callback != _default_elicitation_callback - else None - ) - roots = ( - mcp.types.RootsCapability(listChanged=True) - if session._list_roots_callback != _default_list_roots_callback - else None - ) - - result = await session.send_request( - mcp.types.ClientRequest( - mcp.types.InitializeRequest( - params=mcp.types.InitializeRequestParams( - protocolVersion=mcp.types.LATEST_PROTOCOL_VERSION, - capabilities=mcp.types.ClientCapabilities( - sampling=sampling, - elicitation=elicitation, - experimental={"tasks": {}}, - roots=roots, - ), - clientInfo=session._client_info, - ), - ) - ), - mcp.types.InitializeResult, - ) - - if result.protocolVersion not in SUPPORTED_PROTOCOL_VERSIONS: - raise RuntimeError( - f"Unsupported protocol version from the server: {result.protocolVersion}" - ) - - session._server_capabilities = result.capabilities - - await session.send_notification( - mcp.types.ClientNotification(mcp.types.InitializedNotification()) - ) - - return result - - class TaskNotificationHandler(MessageHandler): """MessageHandler that routes task status notifications to Task objects."""