From a392f78d0760f57aab00d6b1e27e539081018deb Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 27 May 2025 08:43:31 -0400 Subject: [PATCH 1/3] Add global setting --- src/fastmcp/client/client.py | 49 ++++++++++++++++++------------------ src/fastmcp/settings.py | 8 ++++++ 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/fastmcp/client/client.py b/src/fastmcp/client/client.py index 7e8c106e8..b177b950a 100644 --- a/src/fastmcp/client/client.py +++ b/src/fastmcp/client/client.py @@ -9,6 +9,7 @@ from exceptiongroup import catch from mcp import ClientSession from pydantic import AnyUrl +import fastmcp from fastmcp.client.logging import ( LogHandler, MessageHandler, @@ -45,8 +46,8 @@ class Client: MCP client that delegates connection management to a Transport instance. The Client class is responsible for MCP protocol logic, while the Transport - handles connection establishment and management. Client provides methods - for working with resources, prompts, tools and other MCP capabilities. + handles connection establishment and management. Client provides methods for + working with resources, prompts, tools and other MCP capabilities. Args: transport: Connection source specification, which can be: @@ -57,25 +58,23 @@ class Client: - MCPConfig: MCP server configuration - dict: Transport configuration roots: Optional RootsList or RootsHandler for filesystem access - sampling_handler: Optional handler for sampling requests - log_handler: Optional handler for log messages - message_handler: Optional handler for protocol messages - progress_handler: Optional handler for progress notifications - timeout: Optional timeout for requests (seconds or timedelta) - init_timeout: Optional timeout for initial connection (seconds or - timedelta) + sampling_handler: Optional handler for sampling requests log_handler: + Optional handler for log messages message_handler: Optional handler for + protocol messages progress_handler: Optional handler for progress + notifications timeout: Optional timeout for requests (seconds or + timedelta) init_timeout: Optional timeout for initial connection + (seconds or timedelta). Set to 0 to disable. If None, uses the value + in the FastMCP global settings. Examples: - ```python - # Connect to FastMCP server - client = Client("http://localhost:8080") + ```python # Connect to FastMCP server client = + Client("http://localhost:8080") async with client: - # List available resources - resources = await client.list_resources() + # List available resources resources = await client.list_resources() - # Call a tool - result = await client.call_tool("my_tool", {"param": "value"}) + # Call a tool result = await client.call_tool("my_tool", {"param": + "value"}) ``` """ @@ -95,7 +94,7 @@ class Client: message_handler: MessageHandler | None = None, progress_handler: ProgressHandler | None = None, timeout: datetime.timedelta | float | int | None = None, - init_timeout: datetime.timedelta | float | int = 1, + init_timeout: datetime.timedelta | float | int | None = None, ): self.transport = infer_transport(transport) self._session: ClientSession | None = None @@ -114,14 +113,16 @@ class Client: if isinstance(timeout, int | float): timeout = datetime.timedelta(seconds=timeout) - if isinstance(init_timeout, int): - self._init_timeout = float(init_timeout) - elif isinstance(init_timeout, datetime.timedelta): - self._init_timeout = float(init_timeout.total_seconds()) - elif isinstance(init_timeout, float): - self._init_timeout = init_timeout + # handle init handshake timeout + if init_timeout is None: + init_timeout = fastmcp.settings.settings.client_init_timeout + if isinstance(init_timeout, datetime.timedelta): + init_timeout = init_timeout.total_seconds() + elif not init_timeout: + init_timeout = None else: - raise ValueError("init_timeout must be int, float or datetime.timedelta") + init_timeout = float(init_timeout) + self._init_timeout = init_timeout self._session_kwargs: SessionKwargs = { "sampling_callback": None, diff --git a/src/fastmcp/settings.py b/src/fastmcp/settings.py index 662b0db6f..30b7a7461 100644 --- a/src/fastmcp/settings.py +++ b/src/fastmcp/settings.py @@ -87,6 +87,14 @@ class Settings(BaseSettings): ), ] = False + client_init_timeout: Annotated[ + float | None, + Field( + default=1, + description="The timeout for the client's initialization handshake, in seconds. Set to None or 0 to disable.", + ), + ] = None + @model_validator(mode="after") def setup_logging(self) -> Self: """Finalize the settings.""" From 8236b4a1fe8aa7dc9420c72fff092523b30c4a32 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 27 May 2025 08:46:24 -0400 Subject: [PATCH 2/3] Update settings.py --- src/fastmcp/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fastmcp/settings.py b/src/fastmcp/settings.py index 30b7a7461..c872ecb2a 100644 --- a/src/fastmcp/settings.py +++ b/src/fastmcp/settings.py @@ -90,7 +90,6 @@ class Settings(BaseSettings): client_init_timeout: Annotated[ float | None, Field( - default=1, description="The timeout for the client's initialization handshake, in seconds. Set to None or 0 to disable.", ), ] = None From bf68db2df002bb2dda309bf676c792925de8f56a Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 27 May 2025 08:47:04 -0400 Subject: [PATCH 3/3] Fix docstring --- src/fastmcp/client/client.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/fastmcp/client/client.py b/src/fastmcp/client/client.py index b177b950a..853f68c79 100644 --- a/src/fastmcp/client/client.py +++ b/src/fastmcp/client/client.py @@ -58,13 +58,13 @@ class Client: - MCPConfig: MCP server configuration - dict: Transport configuration roots: Optional RootsList or RootsHandler for filesystem access - sampling_handler: Optional handler for sampling requests log_handler: - Optional handler for log messages message_handler: Optional handler for - protocol messages progress_handler: Optional handler for progress - notifications timeout: Optional timeout for requests (seconds or - timedelta) init_timeout: Optional timeout for initial connection - (seconds or timedelta). Set to 0 to disable. If None, uses the value - in the FastMCP global settings. + sampling_handler: Optional handler for sampling requests + log_handler: Optional handler for log messages + message_handler: Optional handler for protocol messages + progress_handler: Optional handler for progress notifications + timeout: Optional timeout for requests (seconds or timedelta) + init_timeout: Optional timeout for initial connection (seconds or timedelta). + Set to 0 to disable. If None, uses the value in the FastMCP global settings. Examples: ```python # Connect to FastMCP server client =