Add global setting

This commit is contained in:
Jeremiah Lowin 2025-05-27 08:43:31 -04:00
commit a392f78d07
2 changed files with 33 additions and 24 deletions

View file

@ -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,

View file

@ -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."""