Remove legacy _task_capable_initialize() workaround (#2612)

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.
This commit is contained in:
Jeremiah Lowin 2025-12-13 20:29:06 -05:00 committed by GitHub
commit ff4e3bb131
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 1 additions and 68 deletions

View file

@ -56,7 +56,6 @@ from fastmcp.client.tasks import (
ResourceTask,
TaskNotificationHandler,
ToolTask,
_task_capable_initialize,
)
from fastmcp.exceptions import ToolError
from fastmcp.mcp_config import MCPConfig
@ -458,10 +457,7 @@ class Client(Generic[ClientTransportT]):
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

View file

@ -12,13 +12,6 @@ from datetime import datetime, timezone
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 @@ if TYPE_CHECKING:
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."""