fastmcp 2.8.1__py3-none-any.whl → 2.9.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 +99 -1
- fastmcp/cli/run.py +1 -3
- fastmcp/client/auth/oauth.py +1 -2
- fastmcp/client/client.py +21 -5
- fastmcp/client/transports.py +17 -2
- fastmcp/contrib/mcp_mixin/README.md +79 -2
- fastmcp/contrib/mcp_mixin/mcp_mixin.py +14 -0
- fastmcp/prompts/prompt.py +91 -11
- fastmcp/prompts/prompt_manager.py +119 -43
- fastmcp/resources/resource.py +11 -1
- fastmcp/resources/resource_manager.py +249 -76
- fastmcp/resources/template.py +27 -1
- fastmcp/server/auth/providers/bearer.py +32 -10
- fastmcp/server/context.py +41 -2
- fastmcp/server/http.py +8 -0
- fastmcp/server/middleware/__init__.py +6 -0
- fastmcp/server/middleware/error_handling.py +206 -0
- fastmcp/server/middleware/logging.py +165 -0
- fastmcp/server/middleware/middleware.py +236 -0
- fastmcp/server/middleware/rate_limiting.py +231 -0
- fastmcp/server/middleware/timing.py +156 -0
- fastmcp/server/proxy.py +250 -140
- fastmcp/server/server.py +320 -242
- fastmcp/settings.py +2 -2
- fastmcp/tools/tool.py +6 -2
- fastmcp/tools/tool_manager.py +114 -45
- fastmcp/utilities/components.py +22 -2
- fastmcp/utilities/inspect.py +326 -0
- fastmcp/utilities/json_schema.py +67 -23
- fastmcp/utilities/mcp_config.py +13 -7
- fastmcp/utilities/openapi.py +5 -3
- fastmcp/utilities/tests.py +1 -1
- fastmcp/utilities/types.py +90 -1
- {fastmcp-2.8.1.dist-info → fastmcp-2.9.0.dist-info}/METADATA +2 -2
- {fastmcp-2.8.1.dist-info → fastmcp-2.9.0.dist-info}/RECORD +38 -31
- {fastmcp-2.8.1.dist-info → fastmcp-2.9.0.dist-info}/WHEEL +0 -0
- {fastmcp-2.8.1.dist-info → fastmcp-2.9.0.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.8.1.dist-info → fastmcp-2.9.0.dist-info}/licenses/LICENSE +0 -0
fastmcp/utilities/json_schema.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
|
+
from collections import defaultdict
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
def _prune_param(schema: dict, param: str) -> dict:
|
|
@@ -24,25 +25,77 @@ def _prune_param(schema: dict, param: str) -> dict:
|
|
|
24
25
|
return schema
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
def _prune_unused_defs(schema: dict) -> dict:
|
|
29
|
+
"""Walk the schema and prune unused defs."""
|
|
30
|
+
|
|
31
|
+
root_defs: set[str] = set()
|
|
32
|
+
referenced_by: defaultdict[str, list] = defaultdict(list)
|
|
33
|
+
|
|
34
|
+
defs = schema.get("$defs")
|
|
35
|
+
if defs is None:
|
|
36
|
+
return schema
|
|
37
|
+
|
|
38
|
+
def walk(
|
|
39
|
+
node: object, current_def: str | None = None, skip_defs: bool = False
|
|
40
|
+
) -> None:
|
|
41
|
+
if isinstance(node, dict):
|
|
42
|
+
# Process $ref for definition tracking
|
|
43
|
+
ref = node.get("$ref")
|
|
44
|
+
if isinstance(ref, str) and ref.startswith("#/$defs/"):
|
|
45
|
+
def_name = ref.split("/")[-1]
|
|
46
|
+
if current_def:
|
|
47
|
+
referenced_by[def_name].append(current_def)
|
|
48
|
+
else:
|
|
49
|
+
root_defs.add(def_name)
|
|
50
|
+
|
|
51
|
+
# Walk children
|
|
52
|
+
for k, v in node.items():
|
|
53
|
+
if skip_defs and k == "$defs":
|
|
54
|
+
continue
|
|
55
|
+
|
|
56
|
+
walk(v, current_def=current_def)
|
|
57
|
+
|
|
58
|
+
elif isinstance(node, list):
|
|
59
|
+
for v in node:
|
|
60
|
+
walk(v)
|
|
61
|
+
|
|
62
|
+
# Traverse the schema once, skipping the $defs
|
|
63
|
+
walk(schema, skip_defs=True)
|
|
64
|
+
|
|
65
|
+
# Now figure out what defs reference other defs
|
|
66
|
+
for def_name, value in defs.items():
|
|
67
|
+
walk(value, current_def=def_name)
|
|
68
|
+
|
|
69
|
+
# Figure out what defs were referenced directly or recursively
|
|
70
|
+
def def_is_referenced(def_name):
|
|
71
|
+
if def_name in root_defs:
|
|
72
|
+
return True
|
|
73
|
+
references = referenced_by.get(def_name)
|
|
74
|
+
if references:
|
|
75
|
+
for reference in references:
|
|
76
|
+
if def_is_referenced(reference):
|
|
77
|
+
return True
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
# Remove orphaned definitions if requested
|
|
81
|
+
for def_name in list(defs):
|
|
82
|
+
if not def_is_referenced(def_name):
|
|
83
|
+
defs.pop(def_name)
|
|
84
|
+
if not defs:
|
|
85
|
+
schema.pop("$defs", None)
|
|
86
|
+
|
|
87
|
+
return schema
|
|
88
|
+
|
|
89
|
+
|
|
27
90
|
def _walk_and_prune(
|
|
28
91
|
schema: dict,
|
|
29
|
-
prune_defs: bool = False,
|
|
30
92
|
prune_titles: bool = False,
|
|
31
93
|
prune_additional_properties: bool = False,
|
|
32
94
|
) -> dict:
|
|
33
|
-
"""Walk the schema and optionally prune titles
|
|
34
|
-
|
|
35
|
-
# Will only be used if prune_defs is True
|
|
36
|
-
used_defs: set[str] = set()
|
|
95
|
+
"""Walk the schema and optionally prune titles and additionalProperties: false."""
|
|
37
96
|
|
|
38
97
|
def walk(node: object) -> None:
|
|
39
98
|
if isinstance(node, dict):
|
|
40
|
-
# Process $ref for definition tracking
|
|
41
|
-
if prune_defs:
|
|
42
|
-
ref = node.get("$ref")
|
|
43
|
-
if isinstance(ref, str) and ref.startswith("#/$defs/"):
|
|
44
|
-
used_defs.add(ref.split("/")[-1])
|
|
45
|
-
|
|
46
99
|
# Remove title if requested
|
|
47
100
|
if prune_titles and "title" in node:
|
|
48
101
|
node.pop("title")
|
|
@@ -62,18 +115,8 @@ def _walk_and_prune(
|
|
|
62
115
|
for v in node:
|
|
63
116
|
walk(v)
|
|
64
117
|
|
|
65
|
-
# Traverse the schema once
|
|
66
118
|
walk(schema)
|
|
67
119
|
|
|
68
|
-
# Remove orphaned definitions if requested
|
|
69
|
-
if prune_defs:
|
|
70
|
-
defs = schema.get("$defs", {})
|
|
71
|
-
for def_name in list(defs):
|
|
72
|
-
if def_name not in used_defs:
|
|
73
|
-
defs.pop(def_name)
|
|
74
|
-
if not defs:
|
|
75
|
-
schema.pop("$defs", None)
|
|
76
|
-
|
|
77
120
|
return schema
|
|
78
121
|
|
|
79
122
|
|
|
@@ -109,12 +152,13 @@ def compress_schema(
|
|
|
109
152
|
schema = _prune_param(schema, param=param)
|
|
110
153
|
|
|
111
154
|
# Do a single walk to handle pruning operations
|
|
112
|
-
if
|
|
155
|
+
if prune_titles or prune_additional_properties:
|
|
113
156
|
schema = _walk_and_prune(
|
|
114
157
|
schema,
|
|
115
|
-
prune_defs=prune_defs,
|
|
116
158
|
prune_titles=prune_titles,
|
|
117
159
|
prune_additional_properties=prune_additional_properties,
|
|
118
160
|
)
|
|
161
|
+
if prune_defs:
|
|
162
|
+
schema = _prune_unused_defs(schema)
|
|
119
163
|
|
|
120
164
|
return schema
|
fastmcp/utilities/mcp_config.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
from typing import TYPE_CHECKING, Annotated, Any, Literal
|
|
4
5
|
from urllib.parse import urlparse
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
import httpx
|
|
8
|
+
from pydantic import AnyUrl, ConfigDict, Field
|
|
7
9
|
|
|
8
10
|
from fastmcp.utilities.types import FastMCPBaseModel
|
|
9
11
|
|
|
@@ -17,7 +19,7 @@ if TYPE_CHECKING:
|
|
|
17
19
|
|
|
18
20
|
def infer_transport_type_from_url(
|
|
19
21
|
url: str | AnyUrl,
|
|
20
|
-
) -> Literal["
|
|
22
|
+
) -> Literal["http", "sse"]:
|
|
21
23
|
"""
|
|
22
24
|
Infer the appropriate transport type from the given URL.
|
|
23
25
|
"""
|
|
@@ -28,10 +30,11 @@ def infer_transport_type_from_url(
|
|
|
28
30
|
parsed_url = urlparse(url)
|
|
29
31
|
path = parsed_url.path
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
# Match /sse followed by /, ?, &, or end of string
|
|
34
|
+
if re.search(r"/sse(/|\?|&|$)", path):
|
|
32
35
|
return "sse"
|
|
33
36
|
else:
|
|
34
|
-
return "
|
|
37
|
+
return "http"
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
class StdioMCPServer(FastMCPBaseModel):
|
|
@@ -55,14 +58,16 @@ class StdioMCPServer(FastMCPBaseModel):
|
|
|
55
58
|
class RemoteMCPServer(FastMCPBaseModel):
|
|
56
59
|
url: str
|
|
57
60
|
headers: dict[str, str] = Field(default_factory=dict)
|
|
58
|
-
transport: Literal["streamable-http", "sse"] | None = None
|
|
61
|
+
transport: Literal["http", "streamable-http", "sse"] | None = None
|
|
59
62
|
auth: Annotated[
|
|
60
|
-
str | Literal["oauth"] | None,
|
|
63
|
+
str | Literal["oauth"] | httpx.Auth | None,
|
|
61
64
|
Field(
|
|
62
|
-
description='Either a string representing a Bearer token
|
|
65
|
+
description='Either a string representing a Bearer token, the literal "oauth" to use OAuth authentication, or an httpx.Auth instance for custom authentication.',
|
|
63
66
|
),
|
|
64
67
|
] = None
|
|
65
68
|
|
|
69
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
70
|
+
|
|
66
71
|
def to_transport(self) -> StreamableHttpTransport | SSETransport:
|
|
67
72
|
from fastmcp.client.transports import SSETransport, StreamableHttpTransport
|
|
68
73
|
|
|
@@ -74,6 +79,7 @@ class RemoteMCPServer(FastMCPBaseModel):
|
|
|
74
79
|
if transport == "sse":
|
|
75
80
|
return SSETransport(self.url, headers=self.headers, auth=self.auth)
|
|
76
81
|
else:
|
|
82
|
+
# Both "http" and "streamable-http" map to StreamableHttpTransport
|
|
77
83
|
return StreamableHttpTransport(
|
|
78
84
|
self.url, headers=self.headers, auth=self.auth
|
|
79
85
|
)
|
fastmcp/utilities/openapi.py
CHANGED
|
@@ -262,16 +262,18 @@ class OpenAPIParser(
|
|
|
262
262
|
|
|
263
263
|
if isinstance(resolved_schema, (self.schema_cls)):
|
|
264
264
|
# Convert schema to dictionary
|
|
265
|
-
|
|
265
|
+
result = resolved_schema.model_dump(
|
|
266
266
|
mode="json", by_alias=True, exclude_none=True
|
|
267
267
|
)
|
|
268
268
|
elif isinstance(resolved_schema, dict):
|
|
269
|
-
|
|
269
|
+
result = resolved_schema
|
|
270
270
|
else:
|
|
271
271
|
logger.warning(
|
|
272
272
|
f"Expected Schema after resolving, got {type(resolved_schema)}. Returning empty dict."
|
|
273
273
|
)
|
|
274
|
-
|
|
274
|
+
result = {}
|
|
275
|
+
|
|
276
|
+
return _replace_ref_with_defs(result)
|
|
275
277
|
except Exception as e:
|
|
276
278
|
logger.error(f"Failed to extract schema as dict: {e}", exc_info=False)
|
|
277
279
|
return {}
|
fastmcp/utilities/tests.py
CHANGED
|
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
|
|
20
20
|
@contextmanager
|
|
21
21
|
def temporary_settings(**kwargs: Any):
|
|
22
22
|
"""
|
|
23
|
-
Temporarily override
|
|
23
|
+
Temporarily override FastMCP setting values.
|
|
24
24
|
|
|
25
25
|
Args:
|
|
26
26
|
**kwargs: The settings to override, including nested settings.
|
fastmcp/utilities/types.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import base64
|
|
4
4
|
import inspect
|
|
5
|
+
import mimetypes
|
|
5
6
|
from collections.abc import Callable
|
|
6
7
|
from functools import lru_cache
|
|
7
8
|
from pathlib import Path
|
|
@@ -11,11 +12,13 @@ from typing import Annotated, TypeAlias, TypeVar, Union, get_args, get_origin
|
|
|
11
12
|
from mcp.types import (
|
|
12
13
|
Annotations,
|
|
13
14
|
AudioContent,
|
|
15
|
+
BlobResourceContents,
|
|
14
16
|
EmbeddedResource,
|
|
15
17
|
ImageContent,
|
|
16
18
|
TextContent,
|
|
19
|
+
TextResourceContents, # Added import
|
|
17
20
|
)
|
|
18
|
-
from pydantic import BaseModel, ConfigDict, TypeAdapter
|
|
21
|
+
from pydantic import AnyUrl, BaseModel, ConfigDict, TypeAdapter, UrlConstraints
|
|
19
22
|
|
|
20
23
|
T = TypeVar("T")
|
|
21
24
|
|
|
@@ -203,3 +206,89 @@ class Audio:
|
|
|
203
206
|
mimeType=mime_type or self._mime_type,
|
|
204
207
|
annotations=annotations or self.annotations,
|
|
205
208
|
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class File:
|
|
212
|
+
"""Helper class for returning audio from tools."""
|
|
213
|
+
|
|
214
|
+
def __init__(
|
|
215
|
+
self,
|
|
216
|
+
path: str | Path | None = None,
|
|
217
|
+
data: bytes | None = None,
|
|
218
|
+
format: str | None = None,
|
|
219
|
+
name: str | None = None,
|
|
220
|
+
annotations: Annotations | None = None,
|
|
221
|
+
):
|
|
222
|
+
if path is None and data is None:
|
|
223
|
+
raise ValueError("Either path or data must be provided")
|
|
224
|
+
if path is not None and data is not None:
|
|
225
|
+
raise ValueError("Only one of path or data can be provided")
|
|
226
|
+
|
|
227
|
+
self.path = Path(path) if path else None
|
|
228
|
+
self.data = data
|
|
229
|
+
self._format = format
|
|
230
|
+
self._mime_type = self._get_mime_type()
|
|
231
|
+
self._name = name
|
|
232
|
+
self.annotations = annotations
|
|
233
|
+
|
|
234
|
+
def _get_mime_type(self) -> str:
|
|
235
|
+
"""Get MIME type from format or guess from file extension."""
|
|
236
|
+
if self._format:
|
|
237
|
+
fmt = self._format.lower()
|
|
238
|
+
# Map common text formats to text/plain
|
|
239
|
+
if fmt in {"plain", "txt", "text"}:
|
|
240
|
+
return "text/plain"
|
|
241
|
+
return f"application/{fmt}"
|
|
242
|
+
|
|
243
|
+
if self.path:
|
|
244
|
+
mime_type, _ = mimetypes.guess_type(self.path)
|
|
245
|
+
if mime_type:
|
|
246
|
+
return mime_type
|
|
247
|
+
|
|
248
|
+
return "application/octet-stream"
|
|
249
|
+
|
|
250
|
+
def to_resource_content(
|
|
251
|
+
self,
|
|
252
|
+
mime_type: str | None = None,
|
|
253
|
+
annotations: Annotations | None = None,
|
|
254
|
+
) -> EmbeddedResource:
|
|
255
|
+
if self.path:
|
|
256
|
+
with open(self.path, "rb") as f:
|
|
257
|
+
raw_data = f.read()
|
|
258
|
+
uri_str = self.path.resolve().as_uri()
|
|
259
|
+
elif self.data is not None:
|
|
260
|
+
raw_data = self.data
|
|
261
|
+
if self._name:
|
|
262
|
+
uri_str = f"file:///{self._name}.{self._mime_type.split('/')[1]}"
|
|
263
|
+
else:
|
|
264
|
+
uri_str = f"file:///resource.{self._mime_type.split('/')[1]}"
|
|
265
|
+
else:
|
|
266
|
+
raise ValueError("No resource data available")
|
|
267
|
+
|
|
268
|
+
mime = mime_type or self._mime_type
|
|
269
|
+
UriType = Annotated[AnyUrl, UrlConstraints(host_required=False)]
|
|
270
|
+
uri = TypeAdapter(UriType).validate_python(uri_str)
|
|
271
|
+
|
|
272
|
+
if mime.startswith("text/"):
|
|
273
|
+
try:
|
|
274
|
+
text = raw_data.decode("utf-8")
|
|
275
|
+
except UnicodeDecodeError:
|
|
276
|
+
text = raw_data.decode("latin-1")
|
|
277
|
+
resource = TextResourceContents(
|
|
278
|
+
text=text,
|
|
279
|
+
mimeType=mime,
|
|
280
|
+
uri=uri,
|
|
281
|
+
)
|
|
282
|
+
else:
|
|
283
|
+
data = base64.b64encode(raw_data).decode()
|
|
284
|
+
resource = BlobResourceContents(
|
|
285
|
+
blob=data,
|
|
286
|
+
mimeType=mime,
|
|
287
|
+
uri=uri,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
return EmbeddedResource(
|
|
291
|
+
type="resource",
|
|
292
|
+
resource=resource,
|
|
293
|
+
annotations=annotations or self.annotations,
|
|
294
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmcp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
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
|
|
@@ -380,7 +380,7 @@ mcp.run(transport="stdio") # Default, so transport argument is optional
|
|
|
380
380
|
**Streamable HTTP**: Recommended for web deployments.
|
|
381
381
|
|
|
382
382
|
```python
|
|
383
|
-
mcp.run(transport="
|
|
383
|
+
mcp.run(transport="http", host="127.0.0.1", port=8000, path="/mcp")
|
|
384
384
|
```
|
|
385
385
|
|
|
386
386
|
**SSE**: For compatibility with existing SSE clients.
|
|
@@ -1,69 +1,76 @@
|
|
|
1
1
|
fastmcp/__init__.py,sha256=5ChT4kg3srdFl0-9dZekGqpzCESlpc6ohrfPbWf1aTo,1300
|
|
2
2
|
fastmcp/exceptions.py,sha256=-krEavxwddQau6T7MESCR4VjKNLfP9KHJrU1p3y72FU,744
|
|
3
3
|
fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
fastmcp/settings.py,sha256=
|
|
4
|
+
fastmcp/settings.py,sha256=2IgZ2cOiwr_bVWkFgY4BZxDKFnayZpCN4q3iT_FEfyE,9011
|
|
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=
|
|
8
|
-
fastmcp/cli/run.py,sha256=
|
|
7
|
+
fastmcp/cli/cli.py,sha256=598s1S-KdqIB85mwqvXJaBVen6xYY65ek4v-q3lmY4k,15933
|
|
8
|
+
fastmcp/cli/run.py,sha256=Pw3vH5wKRHfbmHRn0saIbC4l450KPOzeQbzPFqG4AbY,6208
|
|
9
9
|
fastmcp/client/__init__.py,sha256=kd2hhSuD8rZuF87c9zlPJP_icJ-Rx3exyNoK0EzfOtE,617
|
|
10
|
-
fastmcp/client/client.py,sha256=
|
|
10
|
+
fastmcp/client/client.py,sha256=aVeR2S8WeGs2aZDcG1lIdX1gdRPGml2jnfHkLPJNQ-c,25598
|
|
11
11
|
fastmcp/client/logging.py,sha256=hOPRailZUp89RUck6V4HPaWVZinVrNY8HD4hD0dd-fE,822
|
|
12
12
|
fastmcp/client/oauth_callback.py,sha256=ODAnVX-ettL82RuI5KpfkKf8iDtYMDue3Tnab5sjQtM,10071
|
|
13
13
|
fastmcp/client/progress.py,sha256=WjLLDbUKMsx8DK-fqO7AGsXb83ak-6BMrLvzzznGmcI,1043
|
|
14
14
|
fastmcp/client/roots.py,sha256=IxI_bHwHTmg6c2H-s1av1ZgrRnNDieHtYwdGFbzXT5c,2471
|
|
15
15
|
fastmcp/client/sampling.py,sha256=Q8PzYCERa1W3xGGI9I9QOhhDM-M4i3P5lESb0cp2iI8,1595
|
|
16
|
-
fastmcp/client/transports.py,sha256=
|
|
16
|
+
fastmcp/client/transports.py,sha256=K_5hBTGuJ7iuseQ4Hkjl1ypgdJwZ-Sdt0xgxxEy1W7w,33472
|
|
17
17
|
fastmcp/client/auth/__init__.py,sha256=4DNsfp4iaQeBcpds0JDdMn6Mmfud44stWLsret0sVKY,91
|
|
18
18
|
fastmcp/client/auth/bearer.py,sha256=MFEFqcH6u_V86msYiOsEFKN5ks1V9BnBNiPsPLHUTqo,399
|
|
19
|
-
fastmcp/client/auth/oauth.py,sha256=
|
|
19
|
+
fastmcp/client/auth/oauth.py,sha256=Gu0P4M6875dinVNqjczcJsJJIJNrkoA7UqrSx5NuuwE,14692
|
|
20
20
|
fastmcp/contrib/README.md,sha256=rKknYSI1T192UvSszqwwDlQ2eYQpxywrNTLoj177SYU,878
|
|
21
21
|
fastmcp/contrib/bulk_tool_caller/README.md,sha256=5aUUY1TSFKtz1pvTLSDqkUCkGkuqMfMZNsLeaNqEgAc,1960
|
|
22
22
|
fastmcp/contrib/bulk_tool_caller/__init__.py,sha256=xvGSSaUXTQrc31erBoi1Gh7BikgOliETDiYVTP3rLxY,75
|
|
23
23
|
fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py,sha256=2NcrGS59qvHo1lfbRaT8NSWfCxN66knciLxFvnGwCLY,4165
|
|
24
24
|
fastmcp/contrib/bulk_tool_caller/example.py,sha256=6og_8pCJN_CabworC5R82zPAwwwM-W7HNJLQQSnS3lU,319
|
|
25
|
-
fastmcp/contrib/mcp_mixin/README.md,sha256=
|
|
25
|
+
fastmcp/contrib/mcp_mixin/README.md,sha256=X6rzt_4vC_rmq9jbHmrVPqYLGVVlw9b4TVL4H_0SMmQ,4277
|
|
26
26
|
fastmcp/contrib/mcp_mixin/__init__.py,sha256=aw9IQ1ssNjCgws4ZNt8bkdpossAAGVAwwjBpMp9O5ZQ,153
|
|
27
27
|
fastmcp/contrib/mcp_mixin/example.py,sha256=GnunkXmtG5hLLTUsM8aW5ZURU52Z8vI4tNLl-fK7Dg0,1228
|
|
28
|
-
fastmcp/contrib/mcp_mixin/mcp_mixin.py,sha256=
|
|
28
|
+
fastmcp/contrib/mcp_mixin/mcp_mixin.py,sha256=sUSJ2o0sTsb061MyPN2xuYP0oI4W6YVQXupY3nnjD50,8687
|
|
29
29
|
fastmcp/prompts/__init__.py,sha256=An8uMBUh9Hrb7qqcn_5_Hent7IOeSh7EA2IUVsIrtHc,179
|
|
30
|
-
fastmcp/prompts/prompt.py,sha256=
|
|
31
|
-
fastmcp/prompts/prompt_manager.py,sha256=
|
|
30
|
+
fastmcp/prompts/prompt.py,sha256=A1IE5kadPEZ8s0wzsAvuwaAY0iMJjyJhzT9MMoecASs,13227
|
|
31
|
+
fastmcp/prompts/prompt_manager.py,sha256=nnQyzAG-k-bAlUA7ftG1djoGnsPLAG_OlCwLRP72oHM,7687
|
|
32
32
|
fastmcp/resources/__init__.py,sha256=y1iAuqx-GIrS1NqIYzKezIDiYyjNEzzHD35epHpMnXE,463
|
|
33
|
-
fastmcp/resources/resource.py,sha256=
|
|
34
|
-
fastmcp/resources/resource_manager.py,sha256=
|
|
35
|
-
fastmcp/resources/template.py,sha256=
|
|
33
|
+
fastmcp/resources/resource.py,sha256=l88biP6r5_OWZfWNp9ugIdHyySgI7r6wvVGyEv-EcM4,5384
|
|
34
|
+
fastmcp/resources/resource_manager.py,sha256=pUKHWLjGw21jvHSzBzBPlput7nEa7dEDGR1gt3mF4bI,19797
|
|
35
|
+
fastmcp/resources/template.py,sha256=c8Y_sc4fCnhElE-B5n0J3W5vt-B7oK96_WGce4rav6g,9680
|
|
36
36
|
fastmcp/resources/types.py,sha256=SiYNLnpXT-mHgNUrzqKUvXYUsY-V3gwJIrYdJfFwDDo,4868
|
|
37
37
|
fastmcp/server/__init__.py,sha256=bMD4aQD4yJqLz7-mudoNsyeV8UgQfRAg3PRwPvwTEds,119
|
|
38
|
-
fastmcp/server/context.py,sha256=
|
|
38
|
+
fastmcp/server/context.py,sha256=wChVb8MxdZNxveWfjGbOrLgiYpUzNjyyQuWOkbburdY,11749
|
|
39
39
|
fastmcp/server/dependencies.py,sha256=iKJdz1XsVJcrfHo_reXj9ZSldw-HeAwsp9S6lAgfGA8,2358
|
|
40
|
-
fastmcp/server/http.py,sha256=
|
|
40
|
+
fastmcp/server/http.py,sha256=gwovXTVKd7UR_mrbMP3WI3eaxFKvZcxwjm3RwKxL6wU,12055
|
|
41
41
|
fastmcp/server/openapi.py,sha256=rF8umkOQGLejDVH7Ef36QdMmjv6zwPB5tmkgmQscM7A,39539
|
|
42
|
-
fastmcp/server/proxy.py,sha256=
|
|
43
|
-
fastmcp/server/server.py,sha256=
|
|
42
|
+
fastmcp/server/proxy.py,sha256=nz8DSDMd3LWDgtI2a3l3-EYn2i45wvgxx7zdLMs8C84,14944
|
|
43
|
+
fastmcp/server/server.py,sha256=VNtVQx0nBpcGF5kDPS-I_3EfMScL2Lr5dxAQ1WAPFBU,76428
|
|
44
44
|
fastmcp/server/auth/__init__.py,sha256=doHCLwOIElvH1NrTdpeP9JKfnNf3MDYPSpQfdsQ-uI0,84
|
|
45
45
|
fastmcp/server/auth/auth.py,sha256=kz02HGwXYU0N0clURZDjFNWdKSpTYmgmCnGJN-jSG3Y,1640
|
|
46
46
|
fastmcp/server/auth/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
|
-
fastmcp/server/auth/providers/bearer.py,sha256=
|
|
47
|
+
fastmcp/server/auth/providers/bearer.py,sha256=RxYPvZiUNhACeSaoFV2rmtY-094jwWdR3ytLL1xjtnE,13961
|
|
48
48
|
fastmcp/server/auth/providers/bearer_env.py,sha256=zHbJmzT6RhEW9tGG-_aRACQ_t0GwXCvKEAnKQLCO9mY,1892
|
|
49
49
|
fastmcp/server/auth/providers/in_memory.py,sha256=_8hRo6KZEVqsSSMNxpseJH48LZEywF4uZ687XuOmqYw,13772
|
|
50
|
+
fastmcp/server/middleware/__init__.py,sha256=sKrgbpTlaVdzg_bL8ZI5SGf7EceVqqFUcUr9rvt1r08,112
|
|
51
|
+
fastmcp/server/middleware/error_handling.py,sha256=SoDatr9i3T2qSIUbSEGWrOnu4WPPyMDymnsF5GR_BiE,7572
|
|
52
|
+
fastmcp/server/middleware/logging.py,sha256=igGYQiQ7zvkbhN35kU9LWT7-0cSpH7V-31m6yg6ddSc,5732
|
|
53
|
+
fastmcp/server/middleware/middleware.py,sha256=v6nKcphMhCxwDvbtffPYHHl-WYr9V09czaBRNi-ebqI,6882
|
|
54
|
+
fastmcp/server/middleware/rate_limiting.py,sha256=VTrCoQFmWCm0BxwOrNfG21CBFDDOKJT7IiSEjpJgmPA,7921
|
|
55
|
+
fastmcp/server/middleware/timing.py,sha256=lL_xc-ErLD5lplfvd5-HIyWEbZhgNBYkcQ74KFXAMkA,5591
|
|
50
56
|
fastmcp/tools/__init__.py,sha256=vzqb-Y7Kf0d5T0aOsld-O-FA8kD7-4uFExChewFHEzY,201
|
|
51
|
-
fastmcp/tools/tool.py,sha256=
|
|
52
|
-
fastmcp/tools/tool_manager.py,sha256=
|
|
57
|
+
fastmcp/tools/tool.py,sha256=I_johIZKUY3Vi--wxuYFBDDc0YDxKiT4CARFHMOxes8,11230
|
|
58
|
+
fastmcp/tools/tool_manager.py,sha256=F3J8IHl-fJ8ocoTEhNrzxgwsgGdX_K5gwXCHz2gfGp0,7790
|
|
53
59
|
fastmcp/tools/tool_transform.py,sha256=pBRLu6qoXsdg1fwkV219PyJQy_Rp6fFCNOqFFbI4VOc,27612
|
|
54
60
|
fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
|
|
55
61
|
fastmcp/utilities/cache.py,sha256=aV3oZ-ZhMgLSM9iAotlUlEy5jFvGXrVo0Y5Bj4PBtqY,707
|
|
56
|
-
fastmcp/utilities/components.py,sha256=
|
|
62
|
+
fastmcp/utilities/components.py,sha256=JhXTFWQ2lUe5h2eDVKQLVWnVfvQ77iCbBxE4CYQEuTs,2382
|
|
57
63
|
fastmcp/utilities/exceptions.py,sha256=7Z9j5IzM5rT27BC1Mcn8tkS-bjqCYqMKwb2MMTaxJYU,1350
|
|
58
64
|
fastmcp/utilities/http.py,sha256=1ns1ymBS-WSxbZjGP6JYjSO52Wa_ls4j4WbnXiupoa4,245
|
|
59
|
-
fastmcp/utilities/
|
|
65
|
+
fastmcp/utilities/inspect.py,sha256=XNA0dfYM5G-FVbJaVJO8loSUUCNypyLA-QjqTOneJyU,10833
|
|
66
|
+
fastmcp/utilities/json_schema.py,sha256=K0QH5UazBD_tweBi-TguWYjUu5Lgp9wcM-wT42Fet5w,5022
|
|
60
67
|
fastmcp/utilities/logging.py,sha256=B1WNO-ZWFjd9wiFSh13YtW1hAKaNmbpscDZleIAhr-g,1317
|
|
61
|
-
fastmcp/utilities/mcp_config.py,sha256=
|
|
62
|
-
fastmcp/utilities/openapi.py,sha256=
|
|
63
|
-
fastmcp/utilities/tests.py,sha256=
|
|
64
|
-
fastmcp/utilities/types.py,sha256=
|
|
65
|
-
fastmcp-2.
|
|
66
|
-
fastmcp-2.
|
|
67
|
-
fastmcp-2.
|
|
68
|
-
fastmcp-2.
|
|
69
|
-
fastmcp-2.
|
|
68
|
+
fastmcp/utilities/mcp_config.py,sha256=ryjAfJUPquDSoKdSymPH4M2B0WvuM3pWUGI3cOgAX80,2782
|
|
69
|
+
fastmcp/utilities/openapi.py,sha256=54rABuCPw067sDkbqPVDuqxeelWqRAdDX8oC_YUx4m4,39049
|
|
70
|
+
fastmcp/utilities/tests.py,sha256=O9hRSjnyaYQqu1RJ-CFBw1cIjezlwSQtS-Ea_iqO4sY,3899
|
|
71
|
+
fastmcp/utilities/types.py,sha256=XfTwZU1MhBfMCPU5SDNu3z8-D_yaLbw_PfoXCZOm530,9589
|
|
72
|
+
fastmcp-2.9.0.dist-info/METADATA,sha256=DfZzyvO8K8CmlttO9qA4LiHF3v6Aq06XH9jN15nZgng,17762
|
|
73
|
+
fastmcp-2.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
74
|
+
fastmcp-2.9.0.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
|
|
75
|
+
fastmcp-2.9.0.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
76
|
+
fastmcp-2.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|