fastmcp 2.3.4__py3-none-any.whl → 2.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fastmcp/settings.py CHANGED
@@ -29,6 +29,7 @@ class Settings(BaseSettings):
29
29
 
30
30
  test_mode: bool = False
31
31
  log_level: LOG_LEVEL = "INFO"
32
+
32
33
  client_raise_first_exceptiongroup_error: Annotated[
33
34
  bool,
34
35
  Field(
@@ -44,6 +45,21 @@ class Settings(BaseSettings):
44
45
  ),
45
46
  ),
46
47
  ] = True
48
+
49
+ resource_prefix_format: Annotated[
50
+ Literal["protocol", "path"],
51
+ Field(
52
+ default="path",
53
+ description=inspect.cleandoc(
54
+ """
55
+ When perfixing a resource URI, either use path formatting (resource://prefix/path)
56
+ or protocol formatting (prefix+resource://path). Protocol formatting was the default in FastMCP < 2.4;
57
+ path formatting is current default.
58
+ """
59
+ ),
60
+ ),
61
+ ] = "path"
62
+
47
63
  tool_attempt_parse_json_args: Annotated[
48
64
  bool,
49
65
  Field(
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, Literal
4
+ from urllib.parse import urlparse
5
+
6
+ from pydantic import AnyUrl, BaseModel, Field
7
+
8
+ if TYPE_CHECKING:
9
+ from fastmcp.client.transports import (
10
+ SSETransport,
11
+ StdioTransport,
12
+ StreamableHttpTransport,
13
+ )
14
+
15
+
16
+ def infer_transport_type_from_url(
17
+ url: str | AnyUrl,
18
+ ) -> Literal["streamable-http", "sse"]:
19
+ """
20
+ Infer the appropriate transport type from the given URL.
21
+ """
22
+ url = str(url)
23
+ if not url.startswith("http"):
24
+ raise ValueError(f"Invalid URL: {url}")
25
+
26
+ parsed_url = urlparse(url)
27
+ path = parsed_url.path
28
+
29
+ if "/sse/" in path or path.rstrip("/").endswith("/sse"):
30
+ return "sse"
31
+ else:
32
+ return "streamable-http"
33
+
34
+
35
+ class LocalMCPServer(BaseModel):
36
+ command: str
37
+ args: list[str] = Field(default_factory=list)
38
+ env: dict[str, Any] = Field(default_factory=dict)
39
+ cwd: str | None = None
40
+
41
+ def to_transport(self) -> StdioTransport:
42
+ from fastmcp.client.transports import StdioTransport
43
+
44
+ return StdioTransport(
45
+ command=self.command,
46
+ args=self.args,
47
+ env=self.env,
48
+ cwd=self.cwd,
49
+ )
50
+
51
+
52
+ class RemoteMCPServer(BaseModel):
53
+ url: str
54
+ transport: Literal["streamable-http", "sse", "http"] | None = None
55
+ headers: dict[str, str] = Field(default_factory=dict)
56
+
57
+ def to_transport(self) -> StreamableHttpTransport | SSETransport:
58
+ from fastmcp.client.transports import SSETransport, StreamableHttpTransport
59
+
60
+ if self.transport is None:
61
+ transport = infer_transport_type_from_url(self.url)
62
+ else:
63
+ transport = self.transport
64
+
65
+ if transport == "sse":
66
+ return SSETransport(self.url, headers=self.headers)
67
+ else:
68
+ return StreamableHttpTransport(self.url, headers=self.headers)
69
+
70
+
71
+ class MCPConfig(BaseModel):
72
+ mcpServers: dict[str, LocalMCPServer | RemoteMCPServer]
73
+
74
+ @classmethod
75
+ def from_dict(cls, config: dict[str, Any]) -> MCPConfig:
76
+ return cls(mcpServers=config.get("mcpServers", config))