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/cli/cli.py +30 -138
- fastmcp/cli/run.py +179 -0
- fastmcp/client/client.py +80 -20
- fastmcp/client/logging.py +20 -6
- fastmcp/client/progress.py +38 -0
- fastmcp/client/transports.py +153 -67
- fastmcp/server/context.py +6 -3
- fastmcp/server/http.py +70 -15
- fastmcp/server/openapi.py +113 -10
- fastmcp/server/server.py +414 -138
- fastmcp/settings.py +16 -0
- fastmcp/utilities/mcp_config.py +76 -0
- fastmcp/utilities/openapi.py +233 -602
- fastmcp/utilities/tests.py +8 -4
- {fastmcp-2.3.4.dist-info → fastmcp-2.4.0.dist-info}/METADATA +26 -3
- {fastmcp-2.3.4.dist-info → fastmcp-2.4.0.dist-info}/RECORD +19 -17
- fastmcp/low_level/sse_server_transport.py +0 -104
- {fastmcp-2.3.4.dist-info → fastmcp-2.4.0.dist-info}/WHEEL +0 -0
- {fastmcp-2.3.4.dist-info → fastmcp-2.4.0.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.3.4.dist-info → fastmcp-2.4.0.dist-info}/licenses/LICENSE +0 -0
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))
|