fastmcp 2.1.2__py3-none-any.whl → 2.2.1__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 +32 -0
- fastmcp/client/client.py +16 -15
- fastmcp/client/transports.py +28 -7
- fastmcp/exceptions.py +8 -0
- fastmcp/prompts/prompt.py +20 -1
- fastmcp/prompts/prompt_manager.py +37 -47
- fastmcp/resources/resource.py +20 -1
- fastmcp/resources/resource_manager.py +83 -116
- fastmcp/resources/template.py +81 -8
- fastmcp/server/openapi.py +10 -16
- fastmcp/server/proxy.py +102 -76
- fastmcp/server/server.py +321 -256
- fastmcp/settings.py +8 -11
- fastmcp/tools/tool.py +67 -7
- fastmcp/tools/tool_manager.py +46 -47
- {fastmcp-2.1.2.dist-info → fastmcp-2.2.1.dist-info}/METADATA +14 -6
- {fastmcp-2.1.2.dist-info → fastmcp-2.2.1.dist-info}/RECORD +20 -20
- {fastmcp-2.1.2.dist-info → fastmcp-2.2.1.dist-info}/WHEEL +0 -0
- {fastmcp-2.1.2.dist-info → fastmcp-2.2.1.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.1.2.dist-info → fastmcp-2.2.1.dist-info}/licenses/LICENSE +0 -0
fastmcp/settings.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations as _annotations
|
|
2
2
|
|
|
3
|
-
from enum import Enum
|
|
4
3
|
from typing import TYPE_CHECKING, Literal
|
|
5
4
|
|
|
6
5
|
from pydantic import Field
|
|
@@ -11,12 +10,7 @@ if TYPE_CHECKING:
|
|
|
11
10
|
|
|
12
11
|
LOG_LEVEL = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
class DuplicateBehavior(Enum):
|
|
16
|
-
WARN = "warn"
|
|
17
|
-
ERROR = "error"
|
|
18
|
-
REPLACE = "replace"
|
|
19
|
-
IGNORE = "ignore"
|
|
13
|
+
DuplicateBehavior = Literal["warn", "error", "replace", "ignore"]
|
|
20
14
|
|
|
21
15
|
|
|
22
16
|
class Settings(BaseSettings):
|
|
@@ -48,26 +42,29 @@ class ServerSettings(BaseSettings):
|
|
|
48
42
|
log_level: LOG_LEVEL = Field(default_factory=lambda: Settings().log_level)
|
|
49
43
|
|
|
50
44
|
# HTTP settings
|
|
51
|
-
host: str = "
|
|
45
|
+
host: str = "127.0.0.1"
|
|
52
46
|
port: int = 8000
|
|
53
47
|
sse_path: str = "/sse"
|
|
54
48
|
message_path: str = "/messages/"
|
|
55
49
|
debug: bool = False
|
|
56
50
|
|
|
57
51
|
# resource settings
|
|
58
|
-
on_duplicate_resources: DuplicateBehavior =
|
|
52
|
+
on_duplicate_resources: DuplicateBehavior = "warn"
|
|
59
53
|
|
|
60
54
|
# tool settings
|
|
61
|
-
on_duplicate_tools: DuplicateBehavior =
|
|
55
|
+
on_duplicate_tools: DuplicateBehavior = "warn"
|
|
62
56
|
|
|
63
57
|
# prompt settings
|
|
64
|
-
on_duplicate_prompts: DuplicateBehavior =
|
|
58
|
+
on_duplicate_prompts: DuplicateBehavior = "warn"
|
|
65
59
|
|
|
66
60
|
dependencies: list[str] = Field(
|
|
67
61
|
default_factory=list,
|
|
68
62
|
description="List of dependencies to install in the server environment",
|
|
69
63
|
)
|
|
70
64
|
|
|
65
|
+
# cache settings (for checking mounted servers)
|
|
66
|
+
cache_expiration_seconds: float = 0
|
|
67
|
+
|
|
71
68
|
|
|
72
69
|
class ClientSettings(BaseSettings):
|
|
73
70
|
"""FastMCP client settings."""
|
fastmcp/tools/tool.py
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
1
|
+
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
+
import json
|
|
4
5
|
from collections.abc import Callable
|
|
5
6
|
from typing import TYPE_CHECKING, Annotated, Any
|
|
6
7
|
|
|
8
|
+
import pydantic_core
|
|
9
|
+
from mcp.types import EmbeddedResource, ImageContent, TextContent
|
|
10
|
+
from mcp.types import Tool as MCPTool
|
|
7
11
|
from pydantic import BaseModel, BeforeValidator, Field
|
|
8
12
|
|
|
9
13
|
from fastmcp.exceptions import ToolError
|
|
10
14
|
from fastmcp.utilities.func_metadata import FuncMetadata, func_metadata
|
|
11
|
-
from fastmcp.utilities.types import _convert_set_defaults
|
|
15
|
+
from fastmcp.utilities.types import Image, _convert_set_defaults
|
|
12
16
|
|
|
13
17
|
if TYPE_CHECKING:
|
|
14
18
|
from mcp.server.session import ServerSessionT
|
|
@@ -57,7 +61,7 @@ class Tool(BaseModel):
|
|
|
57
61
|
is_async = inspect.iscoroutinefunction(fn)
|
|
58
62
|
|
|
59
63
|
if context_kwarg is None:
|
|
60
|
-
if
|
|
64
|
+
if inspect.ismethod(fn) and hasattr(fn, "__func__"):
|
|
61
65
|
sig = inspect.signature(fn.__func__)
|
|
62
66
|
else:
|
|
63
67
|
sig = inspect.signature(fn)
|
|
@@ -66,14 +70,16 @@ class Tool(BaseModel):
|
|
|
66
70
|
context_kwarg = param_name
|
|
67
71
|
break
|
|
68
72
|
|
|
73
|
+
# Use callable typing to ensure fn is treated as a callable despite being a classmethod
|
|
74
|
+
fn_callable: Callable[..., Any] = fn
|
|
69
75
|
func_arg_metadata = func_metadata(
|
|
70
|
-
|
|
76
|
+
fn_callable,
|
|
71
77
|
skip_names=[context_kwarg] if context_kwarg is not None else [],
|
|
72
78
|
)
|
|
73
79
|
parameters = func_arg_metadata.arg_model.model_json_schema()
|
|
74
80
|
|
|
75
81
|
return cls(
|
|
76
|
-
fn=
|
|
82
|
+
fn=fn_callable,
|
|
77
83
|
name=func_name,
|
|
78
84
|
description=func_doc,
|
|
79
85
|
parameters=parameters,
|
|
@@ -87,10 +93,10 @@ class Tool(BaseModel):
|
|
|
87
93
|
self,
|
|
88
94
|
arguments: dict[str, Any],
|
|
89
95
|
context: Context[ServerSessionT, LifespanContextT] | None = None,
|
|
90
|
-
) ->
|
|
96
|
+
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
|
91
97
|
"""Run the tool with arguments."""
|
|
92
98
|
try:
|
|
93
|
-
|
|
99
|
+
result = await self.fn_metadata.call_fn_with_arg_validation(
|
|
94
100
|
self.fn,
|
|
95
101
|
self.is_async,
|
|
96
102
|
arguments,
|
|
@@ -98,10 +104,64 @@ class Tool(BaseModel):
|
|
|
98
104
|
if self.context_kwarg is not None
|
|
99
105
|
else None,
|
|
100
106
|
)
|
|
107
|
+
return _convert_to_content(result)
|
|
101
108
|
except Exception as e:
|
|
102
109
|
raise ToolError(f"Error executing tool {self.name}: {e}") from e
|
|
103
110
|
|
|
111
|
+
def to_mcp_tool(self, **overrides: Any) -> MCPTool:
|
|
112
|
+
kwargs = {
|
|
113
|
+
"name": self.name,
|
|
114
|
+
"description": self.description,
|
|
115
|
+
"inputSchema": self.parameters,
|
|
116
|
+
}
|
|
117
|
+
return MCPTool(**kwargs | overrides)
|
|
118
|
+
|
|
104
119
|
def __eq__(self, other: object) -> bool:
|
|
105
120
|
if not isinstance(other, Tool):
|
|
106
121
|
return False
|
|
107
122
|
return self.model_dump() == other.model_dump()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _convert_to_content(
|
|
126
|
+
result: Any,
|
|
127
|
+
_process_as_single_item: bool = False,
|
|
128
|
+
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
|
129
|
+
"""Convert a result to a sequence of content objects."""
|
|
130
|
+
if result is None:
|
|
131
|
+
return []
|
|
132
|
+
|
|
133
|
+
if isinstance(result, TextContent | ImageContent | EmbeddedResource):
|
|
134
|
+
return [result]
|
|
135
|
+
|
|
136
|
+
if isinstance(result, Image):
|
|
137
|
+
return [result.to_image_content()]
|
|
138
|
+
|
|
139
|
+
if isinstance(result, list | tuple) and not _process_as_single_item:
|
|
140
|
+
# if the result is a list, then it could either be a list of MCP types,
|
|
141
|
+
# or a "regular" list that the tool is returning, or a mix of both.
|
|
142
|
+
#
|
|
143
|
+
# so we extract all the MCP types / images and convert them as individual content elements,
|
|
144
|
+
# and aggregate the rest as a single content element
|
|
145
|
+
|
|
146
|
+
mcp_types = []
|
|
147
|
+
other_content = []
|
|
148
|
+
|
|
149
|
+
for item in result:
|
|
150
|
+
if isinstance(item, TextContent | ImageContent | EmbeddedResource | Image):
|
|
151
|
+
mcp_types.append(_convert_to_content(item)[0])
|
|
152
|
+
else:
|
|
153
|
+
other_content.append(item)
|
|
154
|
+
if other_content:
|
|
155
|
+
other_content = _convert_to_content(
|
|
156
|
+
other_content, _process_as_single_item=True
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return other_content + mcp_types
|
|
160
|
+
|
|
161
|
+
if not isinstance(result, str):
|
|
162
|
+
try:
|
|
163
|
+
result = json.dumps(pydantic_core.to_jsonable_python(result))
|
|
164
|
+
except Exception:
|
|
165
|
+
result = str(result)
|
|
166
|
+
|
|
167
|
+
return [TextContent(type="text", text=result)]
|
fastmcp/tools/tool_manager.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations as _annotations
|
|
2
2
|
|
|
3
|
-
import copy
|
|
4
3
|
from collections.abc import Callable
|
|
5
4
|
from typing import TYPE_CHECKING, Any
|
|
6
5
|
|
|
7
6
|
from mcp.shared.context import LifespanContextT
|
|
7
|
+
from mcp.types import EmbeddedResource, ImageContent, TextContent
|
|
8
8
|
|
|
9
|
-
from fastmcp.exceptions import
|
|
9
|
+
from fastmcp.exceptions import NotFoundError
|
|
10
10
|
from fastmcp.settings import DuplicateBehavior
|
|
11
11
|
from fastmcp.tools.tool import Tool
|
|
12
12
|
from fastmcp.utilities.logging import get_logger
|
|
@@ -22,17 +22,38 @@ logger = get_logger(__name__)
|
|
|
22
22
|
class ToolManager:
|
|
23
23
|
"""Manages FastMCP tools."""
|
|
24
24
|
|
|
25
|
-
def __init__(self, duplicate_behavior: DuplicateBehavior =
|
|
25
|
+
def __init__(self, duplicate_behavior: DuplicateBehavior | None = None):
|
|
26
26
|
self._tools: dict[str, Tool] = {}
|
|
27
|
+
|
|
28
|
+
# Default to "warn" if None is provided
|
|
29
|
+
if duplicate_behavior is None:
|
|
30
|
+
duplicate_behavior = "warn"
|
|
31
|
+
|
|
32
|
+
if duplicate_behavior not in DuplicateBehavior.__args__:
|
|
33
|
+
raise ValueError(
|
|
34
|
+
f"Invalid duplicate_behavior: {duplicate_behavior}. "
|
|
35
|
+
f"Must be one of: {', '.join(DuplicateBehavior.__args__)}"
|
|
36
|
+
)
|
|
37
|
+
|
|
27
38
|
self.duplicate_behavior = duplicate_behavior
|
|
28
39
|
|
|
29
|
-
def
|
|
30
|
-
"""
|
|
31
|
-
return self._tools
|
|
40
|
+
def has_tool(self, key: str) -> bool:
|
|
41
|
+
"""Check if a tool exists."""
|
|
42
|
+
return key in self._tools
|
|
43
|
+
|
|
44
|
+
def get_tool(self, key: str) -> Tool:
|
|
45
|
+
"""Get tool by key."""
|
|
46
|
+
if key in self._tools:
|
|
47
|
+
return self._tools[key]
|
|
48
|
+
raise NotFoundError(f"Unknown tool: {key}")
|
|
49
|
+
|
|
50
|
+
def get_tools(self) -> dict[str, Tool]:
|
|
51
|
+
"""Get all registered tools, indexed by registered key."""
|
|
52
|
+
return self._tools
|
|
32
53
|
|
|
33
54
|
def list_tools(self) -> list[Tool]:
|
|
34
55
|
"""List all registered tools."""
|
|
35
|
-
return list(self.
|
|
56
|
+
return list(self.get_tools().values())
|
|
36
57
|
|
|
37
58
|
def add_tool_from_fn(
|
|
38
59
|
self,
|
|
@@ -45,55 +66,33 @@ class ToolManager:
|
|
|
45
66
|
tool = Tool.from_function(fn, name=name, description=description, tags=tags)
|
|
46
67
|
return self.add_tool(tool)
|
|
47
68
|
|
|
48
|
-
def add_tool(self, tool: Tool) -> Tool:
|
|
69
|
+
def add_tool(self, tool: Tool, key: str | None = None) -> Tool:
|
|
49
70
|
"""Register a tool with the server."""
|
|
50
|
-
|
|
71
|
+
key = key or tool.name
|
|
72
|
+
existing = self._tools.get(key)
|
|
51
73
|
if existing:
|
|
52
|
-
if self.duplicate_behavior ==
|
|
53
|
-
logger.warning(f"Tool already exists: {
|
|
54
|
-
self._tools[
|
|
55
|
-
elif self.duplicate_behavior ==
|
|
56
|
-
self._tools[
|
|
57
|
-
elif self.duplicate_behavior ==
|
|
58
|
-
raise ValueError(f"Tool already exists: {
|
|
59
|
-
elif self.duplicate_behavior ==
|
|
60
|
-
|
|
61
|
-
|
|
74
|
+
if self.duplicate_behavior == "warn":
|
|
75
|
+
logger.warning(f"Tool already exists: {key}")
|
|
76
|
+
self._tools[key] = tool
|
|
77
|
+
elif self.duplicate_behavior == "replace":
|
|
78
|
+
self._tools[key] = tool
|
|
79
|
+
elif self.duplicate_behavior == "error":
|
|
80
|
+
raise ValueError(f"Tool already exists: {key}")
|
|
81
|
+
elif self.duplicate_behavior == "ignore":
|
|
82
|
+
return existing
|
|
83
|
+
else:
|
|
84
|
+
self._tools[key] = tool
|
|
62
85
|
return tool
|
|
63
86
|
|
|
64
87
|
async def call_tool(
|
|
65
88
|
self,
|
|
66
|
-
|
|
89
|
+
key: str,
|
|
67
90
|
arguments: dict[str, Any],
|
|
68
91
|
context: Context[ServerSessionT, LifespanContextT] | None = None,
|
|
69
|
-
) ->
|
|
92
|
+
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
|
70
93
|
"""Call a tool by name with arguments."""
|
|
71
|
-
tool = self.get_tool(
|
|
94
|
+
tool = self.get_tool(key)
|
|
72
95
|
if not tool:
|
|
73
|
-
raise
|
|
96
|
+
raise NotFoundError(f"Unknown tool: {key}")
|
|
74
97
|
|
|
75
98
|
return await tool.run(arguments, context=context)
|
|
76
|
-
|
|
77
|
-
def import_tools(
|
|
78
|
-
self, tool_manager: ToolManager, prefix: str | None = None
|
|
79
|
-
) -> None:
|
|
80
|
-
"""
|
|
81
|
-
Import all tools from another ToolManager with prefixed names.
|
|
82
|
-
|
|
83
|
-
Args:
|
|
84
|
-
tool_manager: Another ToolManager instance to import tools from
|
|
85
|
-
prefix: Prefix to add to tool names, including the delimiter.
|
|
86
|
-
The resulting tool name will be in the format "{prefix}{original_name}"
|
|
87
|
-
if prefix is provided, otherwise the original name is used.
|
|
88
|
-
For example, with prefix "weather/" and tool "forecast",
|
|
89
|
-
the imported tool would be available as "weather/forecast"
|
|
90
|
-
"""
|
|
91
|
-
for name, tool in tool_manager._tools.items():
|
|
92
|
-
prefixed_name = f"{prefix}{name}" if prefix else name
|
|
93
|
-
|
|
94
|
-
new_tool = copy.copy(tool)
|
|
95
|
-
new_tool.name = prefixed_name
|
|
96
|
-
|
|
97
|
-
# Store the copied tool
|
|
98
|
-
self.add_tool(new_tool)
|
|
99
|
-
logger.debug(f'Imported tool "{name}" as "{prefixed_name}"')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmcp
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: The fast, Pythonic way to build MCP servers.
|
|
5
5
|
Project-URL: Homepage, https://gofastmcp.com
|
|
6
6
|
Project-URL: Repository, https://github.com/jlowin/fastmcp
|
|
@@ -17,10 +17,11 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: exceptiongroup>=1.2.2
|
|
21
|
+
Requires-Dist: httpx>=0.28.1
|
|
22
22
|
Requires-Dist: mcp<2.0.0,>=1.6.0
|
|
23
23
|
Requires-Dist: openapi-pydantic>=0.5.1
|
|
24
|
+
Requires-Dist: python-dotenv>=1.1.0
|
|
24
25
|
Requires-Dist: rich>=13.9.4
|
|
25
26
|
Requires-Dist: typer>=0.15.2
|
|
26
27
|
Requires-Dist: websockets>=15.0.1
|
|
@@ -94,6 +95,7 @@ FastMCP handles the complex protocol details and server management, letting you
|
|
|
94
95
|
- [Proxy Servers](#proxy-servers)
|
|
95
96
|
- [Composing MCP Servers](#composing-mcp-servers)
|
|
96
97
|
- [OpenAPI \& FastAPI Generation](#openapi--fastapi-generation)
|
|
98
|
+
- [Handling `stderr`](#handling-stderr)
|
|
97
99
|
- [Running Your Server](#running-your-server)
|
|
98
100
|
- [Development Mode (Recommended for Building \& Testing)](#development-mode-recommended-for-building--testing)
|
|
99
101
|
- [Claude Desktop Integration (For Regular Use)](#claude-desktop-integration-for-regular-use)
|
|
@@ -121,7 +123,7 @@ FastMCP provides a high-level, Pythonic interface for building and interacting w
|
|
|
121
123
|
|
|
122
124
|
## Why FastMCP?
|
|
123
125
|
|
|
124
|
-
The MCP protocol is powerful but implementing it involves a lot of boilerplate - server setup, protocol handlers, content types, error management. FastMCP handles all the complex protocol details and server management, so you can focus on building great tools. It
|
|
126
|
+
The MCP protocol is powerful but implementing it involves a lot of boilerplate - server setup, protocol handlers, content types, error management. FastMCP handles all the complex protocol details and server management, so you can focus on building great tools. It's designed to be high-level and Pythonic; in most cases, decorating a function is all you need.
|
|
125
127
|
|
|
126
128
|
FastMCP aims to be:
|
|
127
129
|
|
|
@@ -580,13 +582,13 @@ proxy_client = Client(
|
|
|
580
582
|
)
|
|
581
583
|
|
|
582
584
|
# Create a proxy server that connects to the client and exposes its capabilities
|
|
583
|
-
proxy = FastMCP.
|
|
585
|
+
proxy = FastMCP.from_client(proxy_client, name="Stdio-to-SSE Proxy")
|
|
584
586
|
|
|
585
587
|
if __name__ == "__main__":
|
|
586
588
|
proxy.run(transport='sse')
|
|
587
589
|
```
|
|
588
590
|
|
|
589
|
-
`FastMCP.
|
|
591
|
+
`FastMCP.from_client` is a class method that connects to the target, discovers its capabilities, and dynamically builds the proxy server instance.
|
|
590
592
|
|
|
591
593
|
|
|
592
594
|
|
|
@@ -694,6 +696,12 @@ mcp_server = FastMCP.from_openapi(openapi_spec, client=http_client)
|
|
|
694
696
|
if __name__ == "__main__":
|
|
695
697
|
mcp_server.run()
|
|
696
698
|
```
|
|
699
|
+
|
|
700
|
+
### Handling `stderr`
|
|
701
|
+
The MCP spec allows for the server to write anything it wants to `stderr`, and it
|
|
702
|
+
doesn't specify the format in any way. FastMCP will forward the server's `stderr`
|
|
703
|
+
to the client's `stderr`.
|
|
704
|
+
|
|
697
705
|
## Running Your Server
|
|
698
706
|
|
|
699
707
|
Choose the method that best suits your needs:
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
fastmcp/__init__.py,sha256=2bwhjiyLJisyobp1O9tVYMjriHZAx_f4bIKJYOL-Rpk,399
|
|
2
|
-
fastmcp/exceptions.py,sha256=
|
|
2
|
+
fastmcp/exceptions.py,sha256=QKVHbftoZp4YZQ2NxA-t1SjztqspFdX95YTFOAmr5EE,640
|
|
3
3
|
fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
fastmcp/settings.py,sha256=
|
|
4
|
+
fastmcp/settings.py,sha256=VCjc-3011pKRYjt2h9rZ68XhVEekbpyLyVUREVBTSrg,1955
|
|
5
5
|
fastmcp/cli/__init__.py,sha256=Ii284TNoG5lxTP40ETMGhHEq3lQZWxu9m9JuU57kUpQ,87
|
|
6
6
|
fastmcp/cli/claude.py,sha256=IAlcZ4qZKBBj09jZUMEx7EANZE_IR3vcu7zOBJmMOuU,4567
|
|
7
|
-
fastmcp/cli/cli.py,sha256=
|
|
7
|
+
fastmcp/cli/cli.py,sha256=vdnJi_zz4ZYoPxp9xlJbh6RlGogaFY3icaOPzO_xsLE,14874
|
|
8
8
|
fastmcp/client/__init__.py,sha256=BXO9NUhntZ5GnUACfaRCzDJ5IzxqFJs8qKG-CRMSco4,490
|
|
9
9
|
fastmcp/client/base.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
10
|
-
fastmcp/client/client.py,sha256=
|
|
10
|
+
fastmcp/client/client.py,sha256=1WxEaBqyAvYGhS6y_Xzei173Ufjd4rZ_REfbNFNWJnE,8033
|
|
11
11
|
fastmcp/client/roots.py,sha256=IxI_bHwHTmg6c2H-s1av1ZgrRnNDieHtYwdGFbzXT5c,2471
|
|
12
12
|
fastmcp/client/sampling.py,sha256=WdRhIZbWv54rXYI8lWHv0thXmGCloZYPFpwJK9El_sQ,1613
|
|
13
|
-
fastmcp/client/transports.py,sha256=
|
|
13
|
+
fastmcp/client/transports.py,sha256=lEE1PbqbntbFFKlVbrJtOpWzZa6N0_d1UXwixLgcpg0,15474
|
|
14
14
|
fastmcp/prompts/__init__.py,sha256=LtPAv2JKIu54AwUd3iwv-HUd4DPcwgEqy6itEd3BH_E,194
|
|
15
|
-
fastmcp/prompts/prompt.py,sha256=
|
|
16
|
-
fastmcp/prompts/prompt_manager.py,sha256=
|
|
15
|
+
fastmcp/prompts/prompt.py,sha256=mQ6iRnt7J8oKBUhlgPDYXnIzwwDNWCk4heTqCmv1sco,6622
|
|
16
|
+
fastmcp/prompts/prompt_manager.py,sha256=tMob9a-igjuzf6oTPLPGidFpJdg5JaPJVlYgyNkiCbE,2901
|
|
17
17
|
fastmcp/resources/__init__.py,sha256=t0x1j8lc74rjUKtXe9H5Gs4fpQt82K4NgBK6Y7A0xTg,467
|
|
18
|
-
fastmcp/resources/resource.py,sha256=
|
|
19
|
-
fastmcp/resources/resource_manager.py,sha256=
|
|
20
|
-
fastmcp/resources/template.py,sha256=
|
|
18
|
+
fastmcp/resources/resource.py,sha256=5FN2a7dpNwf7FSEYTNvQvkTxtodu1OPxSlJL-U-8yrM,2413
|
|
19
|
+
fastmcp/resources/resource_manager.py,sha256=_0itubfjYvfkA_wXKa4DQN5YpE7ejXhsE1hdt7m8XwU,9072
|
|
20
|
+
fastmcp/resources/template.py,sha256=Xed7mmCNHUPG2lR9YOZ2MJ1jLiHP_Cp8Osms0b69ExM,5761
|
|
21
21
|
fastmcp/resources/types.py,sha256=tigil7z-SUJMakGXzDLIGSqTepPrAsRpwqwtBA4yoUY,6168
|
|
22
22
|
fastmcp/server/__init__.py,sha256=pdkghG11VLMZiluQ-4_rl2JK1LMWmV003m9dDRUN8W4,92
|
|
23
23
|
fastmcp/server/context.py,sha256=s1885AZRipKB3VltfaO3VEtMxGefKs8fdZByj-4tbNI,7120
|
|
24
|
-
fastmcp/server/openapi.py,sha256=
|
|
25
|
-
fastmcp/server/proxy.py,sha256=
|
|
26
|
-
fastmcp/server/server.py,sha256=
|
|
24
|
+
fastmcp/server/openapi.py,sha256=DVdUfs-rbBF_CIlxrI6HJ5aYbzuyDqGLAhT1TeyxwFc,22424
|
|
25
|
+
fastmcp/server/proxy.py,sha256=in-ZGwd7I8h7fITKMyHXaJRqODudn7MXsG0hVv9M0rA,8580
|
|
26
|
+
fastmcp/server/server.py,sha256=PFhnwa24diSKCz8KO39q43yuSHSbqYrzgnSspc-SPfg,31721
|
|
27
27
|
fastmcp/tools/__init__.py,sha256=ocw-SFTtN6vQ8fgnlF8iNAOflRmh79xS1xdO0Bc3QPE,96
|
|
28
|
-
fastmcp/tools/tool.py,sha256=
|
|
29
|
-
fastmcp/tools/tool_manager.py,sha256=
|
|
28
|
+
fastmcp/tools/tool.py,sha256=FGihp_hzKLj4hK7EdHNUwe8o3NMzCngw4ftMmL_X4XI,5797
|
|
29
|
+
fastmcp/tools/tool_manager.py,sha256=hClv7fwj0cQSSwW0i-Swt7xiVqR4T9LVmr1Tp704nW4,3283
|
|
30
30
|
fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
|
|
31
31
|
fastmcp/utilities/decorators.py,sha256=AjhjsetQZF4YOPV5MTZmIxO21iFp_4fDIS3O2_KNCEg,2990
|
|
32
32
|
fastmcp/utilities/func_metadata.py,sha256=uh-u3gAjLD4kCcGf0ZkZZwBTTl-84JuANZTnDqP5ztI,7841
|
|
33
33
|
fastmcp/utilities/logging.py,sha256=zav8pnFxG_fvGJHUV2XpobmT9WVrmv1mlQBSCz-CPx4,1159
|
|
34
34
|
fastmcp/utilities/openapi.py,sha256=PrH3usbTblaVC6jIH1UGiPEfgB2sSCLj33zA5dH7o_s,45193
|
|
35
35
|
fastmcp/utilities/types.py,sha256=m2rPYMzO-ZFvvZ46N-1-Xqyw693K7yq9Z2xR4pVELyk,2091
|
|
36
|
-
fastmcp-2.1.
|
|
37
|
-
fastmcp-2.1.
|
|
38
|
-
fastmcp-2.1.
|
|
39
|
-
fastmcp-2.1.
|
|
40
|
-
fastmcp-2.1.
|
|
36
|
+
fastmcp-2.2.1.dist-info/METADATA,sha256=DSlO410ImcFq2nxjE-BfQaqzXLkkThKE9yLe-pTKA1k,27760
|
|
37
|
+
fastmcp-2.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
38
|
+
fastmcp-2.2.1.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
|
|
39
|
+
fastmcp-2.2.1.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
40
|
+
fastmcp-2.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|