fastmcp 2.3.2__py3-none-any.whl → 2.3.4__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/client/__init__.py +2 -0
- fastmcp/client/client.py +84 -21
- fastmcp/client/transports.py +53 -28
- fastmcp/exceptions.py +2 -0
- fastmcp/prompts/prompt.py +12 -6
- fastmcp/resources/resource_manager.py +22 -1
- fastmcp/resources/template.py +21 -17
- fastmcp/resources/types.py +25 -27
- fastmcp/server/openapi.py +14 -1
- fastmcp/server/proxy.py +4 -4
- fastmcp/server/server.py +78 -56
- fastmcp/settings.py +55 -29
- fastmcp/tools/tool.py +45 -45
- fastmcp/tools/tool_manager.py +27 -2
- fastmcp/utilities/exceptions.py +49 -0
- fastmcp/utilities/json_schema.py +78 -17
- fastmcp/utilities/logging.py +11 -6
- fastmcp/utilities/openapi.py +122 -7
- fastmcp/utilities/tests.py +4 -2
- {fastmcp-2.3.2.dist-info → fastmcp-2.3.4.dist-info}/METADATA +2 -2
- {fastmcp-2.3.2.dist-info → fastmcp-2.3.4.dist-info}/RECORD +24 -23
- {fastmcp-2.3.2.dist-info → fastmcp-2.3.4.dist-info}/WHEEL +0 -0
- {fastmcp-2.3.2.dist-info → fastmcp-2.3.4.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.3.2.dist-info → fastmcp-2.3.4.dist-info}/licenses/LICENSE +0 -0
fastmcp/utilities/json_schema.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
|
-
from collections.abc import Mapping, Sequence
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
def _prune_param(schema: dict, param: str) -> dict:
|
|
@@ -14,6 +13,7 @@ def _prune_param(schema: dict, param: str) -> dict:
|
|
|
14
13
|
removed = props.pop(param, None)
|
|
15
14
|
if removed is None: # nothing to do
|
|
16
15
|
return schema
|
|
16
|
+
|
|
17
17
|
# Keep empty properties object rather than removing it entirely
|
|
18
18
|
schema["properties"] = props
|
|
19
19
|
if param in schema.get("required", []):
|
|
@@ -21,39 +21,100 @@ def _prune_param(schema: dict, param: str) -> dict:
|
|
|
21
21
|
if not schema["required"]:
|
|
22
22
|
schema.pop("required")
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
return schema
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _walk_and_prune(
|
|
28
|
+
schema: dict,
|
|
29
|
+
prune_defs: bool = False,
|
|
30
|
+
prune_titles: bool = False,
|
|
31
|
+
prune_additional_properties: bool = False,
|
|
32
|
+
) -> dict:
|
|
33
|
+
"""Walk the schema and optionally prune titles, unused definitions, and additionalProperties: false."""
|
|
34
|
+
|
|
35
|
+
# Will only be used if prune_defs is True
|
|
25
36
|
used_defs: set[str] = set()
|
|
26
37
|
|
|
27
|
-
def walk(node: object) -> None:
|
|
28
|
-
if isinstance(node,
|
|
29
|
-
|
|
30
|
-
if
|
|
31
|
-
|
|
38
|
+
def walk(node: object) -> None:
|
|
39
|
+
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
|
+
# Remove title if requested
|
|
47
|
+
if prune_titles and "title" in node:
|
|
48
|
+
node.pop("title")
|
|
49
|
+
|
|
50
|
+
# Remove additionalProperties: false at any level if requested
|
|
51
|
+
if (
|
|
52
|
+
prune_additional_properties
|
|
53
|
+
and node.get("additionalProperties", None) is False
|
|
54
|
+
):
|
|
55
|
+
node.pop("additionalProperties")
|
|
56
|
+
|
|
57
|
+
# Walk children
|
|
32
58
|
for v in node.values():
|
|
33
59
|
walk(v)
|
|
34
|
-
|
|
60
|
+
|
|
61
|
+
elif isinstance(node, list):
|
|
35
62
|
for v in node:
|
|
36
63
|
walk(v)
|
|
37
64
|
|
|
65
|
+
# Traverse the schema once
|
|
38
66
|
walk(schema)
|
|
39
67
|
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
+
return schema
|
|
78
|
+
|
|
47
79
|
|
|
80
|
+
def _prune_additional_properties(schema: dict) -> dict:
|
|
81
|
+
"""Remove additionalProperties from the schema if it is False."""
|
|
82
|
+
if schema.get("additionalProperties", None) is False:
|
|
83
|
+
schema.pop("additionalProperties")
|
|
48
84
|
return schema
|
|
49
85
|
|
|
50
86
|
|
|
51
|
-
def
|
|
87
|
+
def compress_schema(
|
|
88
|
+
schema: dict,
|
|
89
|
+
prune_params: list[str] | None = None,
|
|
90
|
+
prune_defs: bool = True,
|
|
91
|
+
prune_additional_properties: bool = True,
|
|
92
|
+
prune_titles: bool = False,
|
|
93
|
+
) -> dict:
|
|
52
94
|
"""
|
|
53
95
|
Remove the given parameters from the schema.
|
|
54
96
|
|
|
97
|
+
Args:
|
|
98
|
+
schema: The schema to compress
|
|
99
|
+
prune_params: List of parameter names to remove from properties
|
|
100
|
+
prune_defs: Whether to remove unused definitions
|
|
101
|
+
prune_additional_properties: Whether to remove additionalProperties: false
|
|
102
|
+
prune_titles: Whether to remove title fields from the schema
|
|
55
103
|
"""
|
|
104
|
+
# Make a copy so we don't modify the original
|
|
56
105
|
schema = copy.deepcopy(schema)
|
|
57
|
-
|
|
106
|
+
|
|
107
|
+
# Remove specific parameters if requested
|
|
108
|
+
for param in prune_params or []:
|
|
58
109
|
schema = _prune_param(schema, param=param)
|
|
110
|
+
|
|
111
|
+
# Do a single walk to handle pruning operations
|
|
112
|
+
if prune_defs or prune_titles or prune_additional_properties:
|
|
113
|
+
schema = _walk_and_prune(
|
|
114
|
+
schema,
|
|
115
|
+
prune_defs=prune_defs,
|
|
116
|
+
prune_titles=prune_titles,
|
|
117
|
+
prune_additional_properties=prune_additional_properties,
|
|
118
|
+
)
|
|
119
|
+
|
|
59
120
|
return schema
|
fastmcp/utilities/logging.py
CHANGED
|
@@ -21,22 +21,27 @@ def get_logger(name: str) -> logging.Logger:
|
|
|
21
21
|
|
|
22
22
|
def configure_logging(
|
|
23
23
|
level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | int = "INFO",
|
|
24
|
+
logger: logging.Logger | None = None,
|
|
24
25
|
) -> None:
|
|
25
|
-
"""
|
|
26
|
+
"""
|
|
27
|
+
Configure logging for FastMCP.
|
|
26
28
|
|
|
27
29
|
Args:
|
|
30
|
+
logger: the logger to configure
|
|
28
31
|
level: the log level to use
|
|
29
32
|
"""
|
|
33
|
+
if logger is None:
|
|
34
|
+
logger = logging.getLogger("FastMCP")
|
|
35
|
+
|
|
30
36
|
# Only configure the FastMCP logger namespace
|
|
31
37
|
handler = RichHandler(console=Console(stderr=True), rich_tracebacks=True)
|
|
32
38
|
formatter = logging.Formatter("%(message)s")
|
|
33
39
|
handler.setFormatter(formatter)
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
fastmcp_logger.setLevel(level)
|
|
41
|
+
logger.setLevel(level)
|
|
37
42
|
|
|
38
43
|
# Remove any existing handlers to avoid duplicates on reconfiguration
|
|
39
|
-
for hdlr in
|
|
40
|
-
|
|
44
|
+
for hdlr in logger.handlers[:]:
|
|
45
|
+
logger.removeHandler(hdlr)
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
logger.addHandler(handler)
|
fastmcp/utilities/openapi.py
CHANGED
|
@@ -84,6 +84,9 @@ class HTTPRoute(BaseModel):
|
|
|
84
84
|
responses: dict[str, ResponseInfo] = Field(
|
|
85
85
|
default_factory=dict
|
|
86
86
|
) # Key: status code str
|
|
87
|
+
schema_definitions: dict[str, JsonSchema] = Field(
|
|
88
|
+
default_factory=dict
|
|
89
|
+
) # Store component schemas
|
|
87
90
|
|
|
88
91
|
|
|
89
92
|
# Export public symbols
|
|
@@ -221,6 +224,27 @@ class OpenAPI31Parser(BaseOpenAPIParser):
|
|
|
221
224
|
logger.warning("OpenAPI schema has no paths defined.")
|
|
222
225
|
return []
|
|
223
226
|
|
|
227
|
+
# Extract component schemas to add to each route
|
|
228
|
+
schema_definitions = {}
|
|
229
|
+
if hasattr(self.openapi, "components") and self.openapi.components:
|
|
230
|
+
components = self.openapi.components
|
|
231
|
+
if hasattr(components, "schemas") and components.schemas:
|
|
232
|
+
for name, schema in components.schemas.items():
|
|
233
|
+
try:
|
|
234
|
+
if isinstance(schema, Reference):
|
|
235
|
+
resolved_schema = self._resolve_ref(schema)
|
|
236
|
+
schema_definitions[name] = self._extract_schema_as_dict(
|
|
237
|
+
resolved_schema
|
|
238
|
+
)
|
|
239
|
+
else:
|
|
240
|
+
schema_definitions[name] = self._extract_schema_as_dict(
|
|
241
|
+
schema
|
|
242
|
+
)
|
|
243
|
+
except Exception as e:
|
|
244
|
+
logger.warning(
|
|
245
|
+
f"Failed to extract schema definition '{name}': {e}"
|
|
246
|
+
)
|
|
247
|
+
|
|
224
248
|
for path_str, path_item_obj in self.openapi.paths.items():
|
|
225
249
|
if not isinstance(path_item_obj, PathItem):
|
|
226
250
|
logger.warning(
|
|
@@ -269,6 +293,7 @@ class OpenAPI31Parser(BaseOpenAPIParser):
|
|
|
269
293
|
parameters=parameters,
|
|
270
294
|
request_body=request_body_info,
|
|
271
295
|
responses=responses,
|
|
296
|
+
schema_definitions=schema_definitions,
|
|
272
297
|
)
|
|
273
298
|
routes.append(route)
|
|
274
299
|
logger.info(
|
|
@@ -386,16 +411,36 @@ class OpenAPI31Parser(BaseOpenAPIParser):
|
|
|
386
411
|
|
|
387
412
|
param_schema_dict = {}
|
|
388
413
|
if param_schema_obj: # Check if schema exists
|
|
414
|
+
# Resolve the schema if it's a reference
|
|
415
|
+
resolved_schema = self._resolve_ref(param_schema_obj)
|
|
389
416
|
param_schema_dict = self._extract_schema_as_dict(param_schema_obj)
|
|
417
|
+
|
|
418
|
+
# Ensure default value is preserved from resolved schema
|
|
419
|
+
if (
|
|
420
|
+
not isinstance(resolved_schema, Reference)
|
|
421
|
+
and hasattr(resolved_schema, "default")
|
|
422
|
+
and resolved_schema.default is not None
|
|
423
|
+
):
|
|
424
|
+
param_schema_dict["default"] = resolved_schema.default
|
|
390
425
|
elif parameter.content:
|
|
391
426
|
# Handle complex parameters with 'content'
|
|
392
427
|
first_media_type = next(iter(parameter.content.values()), None)
|
|
393
428
|
if (
|
|
394
429
|
first_media_type and first_media_type.media_type_schema
|
|
395
430
|
): # CORRECTED: Use 'media_type_schema'
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
)
|
|
431
|
+
# Resolve the schema if it's a reference
|
|
432
|
+
media_schema = first_media_type.media_type_schema
|
|
433
|
+
resolved_media_schema = self._resolve_ref(media_schema)
|
|
434
|
+
param_schema_dict = self._extract_schema_as_dict(media_schema)
|
|
435
|
+
|
|
436
|
+
# Ensure default value is preserved from resolved schema
|
|
437
|
+
if (
|
|
438
|
+
not isinstance(resolved_media_schema, Reference)
|
|
439
|
+
and hasattr(resolved_media_schema, "default")
|
|
440
|
+
and resolved_media_schema.default is not None
|
|
441
|
+
):
|
|
442
|
+
param_schema_dict["default"] = resolved_media_schema.default
|
|
443
|
+
|
|
399
444
|
logger.debug(
|
|
400
445
|
f"Parameter '{parameter.name}' using schema from 'content' field."
|
|
401
446
|
)
|
|
@@ -543,6 +588,27 @@ class OpenAPI30Parser(BaseOpenAPIParser):
|
|
|
543
588
|
logger.warning("OpenAPI schema has no paths defined.")
|
|
544
589
|
return []
|
|
545
590
|
|
|
591
|
+
# Extract component schemas to add to each route
|
|
592
|
+
schema_definitions = {}
|
|
593
|
+
if hasattr(self.openapi, "components") and self.openapi.components:
|
|
594
|
+
components = self.openapi.components
|
|
595
|
+
if hasattr(components, "schemas") and components.schemas:
|
|
596
|
+
for name, schema in components.schemas.items():
|
|
597
|
+
try:
|
|
598
|
+
if isinstance(schema, Reference_30):
|
|
599
|
+
resolved_schema = self._resolve_ref(schema)
|
|
600
|
+
schema_definitions[name] = self._extract_schema_as_dict(
|
|
601
|
+
resolved_schema
|
|
602
|
+
)
|
|
603
|
+
else:
|
|
604
|
+
schema_definitions[name] = self._extract_schema_as_dict(
|
|
605
|
+
schema
|
|
606
|
+
)
|
|
607
|
+
except Exception as e:
|
|
608
|
+
logger.warning(
|
|
609
|
+
f"Failed to extract schema definition '{name}': {e}"
|
|
610
|
+
)
|
|
611
|
+
|
|
546
612
|
for path_str, path_item_obj in self.openapi.paths.items():
|
|
547
613
|
if not isinstance(path_item_obj, PathItem_30):
|
|
548
614
|
logger.warning(
|
|
@@ -593,6 +659,7 @@ class OpenAPI30Parser(BaseOpenAPIParser):
|
|
|
593
659
|
parameters=parameters,
|
|
594
660
|
request_body=request_body_info,
|
|
595
661
|
responses=responses,
|
|
662
|
+
schema_definitions=schema_definitions,
|
|
596
663
|
)
|
|
597
664
|
routes.append(route)
|
|
598
665
|
logger.info(
|
|
@@ -711,14 +778,34 @@ class OpenAPI30Parser(BaseOpenAPIParser):
|
|
|
711
778
|
|
|
712
779
|
param_schema_dict = {}
|
|
713
780
|
if param_schema_obj: # Check if schema exists
|
|
781
|
+
# Resolve the schema if it's a reference
|
|
782
|
+
resolved_schema = self._resolve_ref(param_schema_obj)
|
|
714
783
|
param_schema_dict = self._extract_schema_as_dict(param_schema_obj)
|
|
784
|
+
|
|
785
|
+
# Ensure default value is preserved from resolved schema
|
|
786
|
+
if (
|
|
787
|
+
not isinstance(resolved_schema, Reference_30)
|
|
788
|
+
and hasattr(resolved_schema, "default")
|
|
789
|
+
and resolved_schema.default is not None
|
|
790
|
+
):
|
|
791
|
+
param_schema_dict["default"] = resolved_schema.default
|
|
715
792
|
elif parameter.content:
|
|
716
793
|
# Handle complex parameters with 'content'
|
|
717
794
|
first_media_type = next(iter(parameter.content.values()), None)
|
|
718
795
|
if first_media_type and first_media_type.media_type_schema:
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
)
|
|
796
|
+
# Resolve the schema if it's a reference
|
|
797
|
+
media_schema = first_media_type.media_type_schema
|
|
798
|
+
resolved_media_schema = self._resolve_ref(media_schema)
|
|
799
|
+
param_schema_dict = self._extract_schema_as_dict(media_schema)
|
|
800
|
+
|
|
801
|
+
# Ensure default value is preserved from resolved schema
|
|
802
|
+
if (
|
|
803
|
+
not isinstance(resolved_media_schema, Reference_30)
|
|
804
|
+
and hasattr(resolved_media_schema, "default")
|
|
805
|
+
and resolved_media_schema.default is not None
|
|
806
|
+
):
|
|
807
|
+
param_schema_dict["default"] = resolved_media_schema.default
|
|
808
|
+
|
|
722
809
|
logger.debug(
|
|
723
810
|
f"Parameter '{parameter.name}' using schema from 'content' field."
|
|
724
811
|
)
|
|
@@ -1173,6 +1260,23 @@ def _combine_schemas(route: openapi.HTTPRoute) -> dict[str, Any]:
|
|
|
1173
1260
|
# Copy the schema and add description if available
|
|
1174
1261
|
param_schema = param.schema_.copy() if isinstance(param.schema_, dict) else {}
|
|
1175
1262
|
|
|
1263
|
+
# Convert #/components/schemas references to #/$defs references
|
|
1264
|
+
if isinstance(param_schema, dict) and "$ref" in param_schema:
|
|
1265
|
+
ref_path = param_schema["$ref"]
|
|
1266
|
+
if ref_path.startswith("#/components/schemas/"):
|
|
1267
|
+
schema_name = ref_path.split("/")[-1]
|
|
1268
|
+
param_schema["$ref"] = f"#/$defs/{schema_name}"
|
|
1269
|
+
|
|
1270
|
+
# Also handle anyOf, allOf, oneOf references
|
|
1271
|
+
for section in ["anyOf", "allOf", "oneOf"]:
|
|
1272
|
+
if section in param_schema and isinstance(param_schema[section], list):
|
|
1273
|
+
for i, item in enumerate(param_schema[section]):
|
|
1274
|
+
if isinstance(item, dict) and "$ref" in item:
|
|
1275
|
+
ref_path = item["$ref"]
|
|
1276
|
+
if ref_path.startswith("#/components/schemas/"):
|
|
1277
|
+
schema_name = ref_path.split("/")[-1]
|
|
1278
|
+
param_schema[section][i]["$ref"] = f"#/$defs/{schema_name}"
|
|
1279
|
+
|
|
1176
1280
|
# Add parameter description to schema if available and not already present
|
|
1177
1281
|
if param.description and not param_schema.get("description"):
|
|
1178
1282
|
param_schema["description"] = param.description
|
|
@@ -1193,8 +1297,19 @@ def _combine_schemas(route: openapi.HTTPRoute) -> dict[str, Any]:
|
|
|
1193
1297
|
if route.request_body.required:
|
|
1194
1298
|
required.extend(body_schema.get("required", []))
|
|
1195
1299
|
|
|
1196
|
-
|
|
1300
|
+
result = {
|
|
1197
1301
|
"type": "object",
|
|
1198
1302
|
"properties": properties,
|
|
1199
1303
|
"required": required,
|
|
1200
1304
|
}
|
|
1305
|
+
|
|
1306
|
+
# Add schema definitions if available
|
|
1307
|
+
if route.schema_definitions:
|
|
1308
|
+
result["$defs"] = route.schema_definitions
|
|
1309
|
+
|
|
1310
|
+
# Use compress_schema to remove unused definitions
|
|
1311
|
+
from fastmcp.utilities.json_schema import compress_schema
|
|
1312
|
+
|
|
1313
|
+
result = compress_schema(result)
|
|
1314
|
+
|
|
1315
|
+
return result
|
fastmcp/utilities/tests.py
CHANGED
|
@@ -71,7 +71,7 @@ def _run_server(mcp_server: FastMCP, transport: Literal["sse"], port: int) -> No
|
|
|
71
71
|
|
|
72
72
|
@contextmanager
|
|
73
73
|
def run_server_in_process(
|
|
74
|
-
server_fn: Callable[[str, int], None],
|
|
74
|
+
server_fn: Callable[[str, int], None], *args
|
|
75
75
|
) -> Generator[str, None, None]:
|
|
76
76
|
"""
|
|
77
77
|
Context manager that runs a Starlette app in a separate process and returns the
|
|
@@ -88,7 +88,9 @@ def run_server_in_process(
|
|
|
88
88
|
s.bind((host, 0))
|
|
89
89
|
port = s.getsockname()[1]
|
|
90
90
|
|
|
91
|
-
proc = multiprocessing.Process(
|
|
91
|
+
proc = multiprocessing.Process(
|
|
92
|
+
target=server_fn, args=(host, port, *args), daemon=True
|
|
93
|
+
)
|
|
92
94
|
proc.start()
|
|
93
95
|
|
|
94
96
|
# Wait for server to be running
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmcp
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.4
|
|
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
|
|
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
|
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
20
|
Requires-Dist: exceptiongroup>=1.2.2
|
|
21
21
|
Requires-Dist: httpx>=0.28.1
|
|
22
|
-
Requires-Dist: mcp<2.0.0,>=1.8.
|
|
22
|
+
Requires-Dist: mcp<2.0.0,>=1.8.1
|
|
23
23
|
Requires-Dist: openapi-pydantic>=0.5.1
|
|
24
24
|
Requires-Dist: python-dotenv>=1.1.0
|
|
25
25
|
Requires-Dist: rich>=13.9.4
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
fastmcp/__init__.py,sha256=yTAqLZORsPqbr7AE0ayw6zIYBeMlxQlI-3HE2WqbvHk,435
|
|
2
|
-
fastmcp/exceptions.py,sha256=
|
|
2
|
+
fastmcp/exceptions.py,sha256=YvaKqOT3w0boXF9ylIoaSIzW9XiQ1qLFG1LZq6B60H8,680
|
|
3
3
|
fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
fastmcp/settings.py,sha256=
|
|
4
|
+
fastmcp/settings.py,sha256=Slo7sRSbXblgmTQcRSee6ns6CsW2yW-TvBY--kAhJqg,3856
|
|
5
5
|
fastmcp/cli/__init__.py,sha256=Ii284TNoG5lxTP40ETMGhHEq3lQZWxu9m9JuU57kUpQ,87
|
|
6
6
|
fastmcp/cli/claude.py,sha256=IAlcZ4qZKBBj09jZUMEx7EANZE_IR3vcu7zOBJmMOuU,4567
|
|
7
7
|
fastmcp/cli/cli.py,sha256=Tb-WiIXFZiq4nqlZ6LMXN2iYY30clC4Om_gP89HbJcE,15641
|
|
8
|
-
fastmcp/client/__init__.py,sha256=
|
|
8
|
+
fastmcp/client/__init__.py,sha256=Ri8GFHolIKOZnXaMzIc3VpkLcEqAmOoYGCKgmSk6NnE,550
|
|
9
9
|
fastmcp/client/base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
fastmcp/client/client.py,sha256=
|
|
10
|
+
fastmcp/client/client.py,sha256=EOS6_2zd9zWxhCN_cY6cAiqGmCSWMX1t3g6PxemjTtw,17982
|
|
11
11
|
fastmcp/client/logging.py,sha256=Q8jYcZj4KA15Yiz3RP8tBXj8sd9IxL3VThF_Y0O4Upc,356
|
|
12
12
|
fastmcp/client/roots.py,sha256=IxI_bHwHTmg6c2H-s1av1ZgrRnNDieHtYwdGFbzXT5c,2471
|
|
13
13
|
fastmcp/client/sampling.py,sha256=UlDHxnd6k_HoU8RA3ob0g8-e6haJBc9u27N_v291QoI,1698
|
|
14
|
-
fastmcp/client/transports.py,sha256=
|
|
14
|
+
fastmcp/client/transports.py,sha256=30SubI-fgrqVknyPlySVJ7sGkOMAjm8CP-Owrb8gu58,19704
|
|
15
15
|
fastmcp/contrib/README.md,sha256=rKknYSI1T192UvSszqwwDlQ2eYQpxywrNTLoj177SYU,878
|
|
16
16
|
fastmcp/contrib/bulk_tool_caller/README.md,sha256=5aUUY1TSFKtz1pvTLSDqkUCkGkuqMfMZNsLeaNqEgAc,1960
|
|
17
17
|
fastmcp/contrib/bulk_tool_caller/__init__.py,sha256=xvGSSaUXTQrc31erBoi1Gh7BikgOliETDiYVTP3rLxY,75
|
|
@@ -25,33 +25,34 @@ fastmcp/low_level/README.md,sha256=IRvElvOOc_RLLsqbUm7e6VOEwrKHPJeox0pV7JVKHWw,1
|
|
|
25
25
|
fastmcp/low_level/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
26
|
fastmcp/low_level/sse_server_transport.py,sha256=pUG3AL4Wjf9LgH9fj1l3emGEjFDFDhmKcDfgiiFJcuQ,4448
|
|
27
27
|
fastmcp/prompts/__init__.py,sha256=An8uMBUh9Hrb7qqcn_5_Hent7IOeSh7EA2IUVsIrtHc,179
|
|
28
|
-
fastmcp/prompts/prompt.py,sha256=
|
|
28
|
+
fastmcp/prompts/prompt.py,sha256=CGu11NbOvO0b79F3EDCG7YbajGslpoPu59VOEzanIp0,7968
|
|
29
29
|
fastmcp/prompts/prompt_manager.py,sha256=9VcioLE-AoUKe1e9SynNQME9SvWy0q1QAvO1ewIWVmI,3126
|
|
30
30
|
fastmcp/resources/__init__.py,sha256=t0x1j8lc74rjUKtXe9H5Gs4fpQt82K4NgBK6Y7A0xTg,467
|
|
31
31
|
fastmcp/resources/resource.py,sha256=Rx1My_fi1f-oqnQ9R_v7ejopAk4BJDfbB75-s4d31dM,2492
|
|
32
|
-
fastmcp/resources/resource_manager.py,sha256=
|
|
33
|
-
fastmcp/resources/template.py,sha256=
|
|
34
|
-
fastmcp/resources/types.py,sha256=
|
|
32
|
+
fastmcp/resources/resource_manager.py,sha256=aJFbn1-Rc-oMahp3SSWNJXJEu8Nxu-gc24i6lTVALQo,10316
|
|
33
|
+
fastmcp/resources/template.py,sha256=ex1s2kBQmGUU1zQ-b__egyJoNlNNKI42JALO0uxxAaE,7408
|
|
34
|
+
fastmcp/resources/types.py,sha256=5fUFvzRlekNjtfihtq8S-fT0alKoNfclzrugqeM5JRE,6366
|
|
35
35
|
fastmcp/server/__init__.py,sha256=bMD4aQD4yJqLz7-mudoNsyeV8UgQfRAg3PRwPvwTEds,119
|
|
36
36
|
fastmcp/server/context.py,sha256=ykitQygA7zT5prbFTLCuYlnAzuljf_9ErUT0FYBPv3E,8135
|
|
37
37
|
fastmcp/server/dependencies.py,sha256=1utkxFsV37HZcWBwI69JyngVN2ppGO_PEgxUlUHHy_Q,742
|
|
38
38
|
fastmcp/server/http.py,sha256=utl7vJkMvKUnKIflCptVWk1oqOi7_sJJHqUl22g4JC8,10473
|
|
39
|
-
fastmcp/server/openapi.py,sha256=
|
|
40
|
-
fastmcp/server/proxy.py,sha256=
|
|
41
|
-
fastmcp/server/server.py,sha256=
|
|
39
|
+
fastmcp/server/openapi.py,sha256=_7U0XtPk4wCkGOBfYx3J3ujA9iqQtnsc0scA4sCsIT0,24170
|
|
40
|
+
fastmcp/server/proxy.py,sha256=mt3eM6TQWfnZD5XehmTXisskZ4CBbsWyjRPjprlTjBY,9653
|
|
41
|
+
fastmcp/server/server.py,sha256=EM5BqwXRlG73sMZg6186yMVKfXYGn5gT4qqAxfNa8lU,45454
|
|
42
42
|
fastmcp/tools/__init__.py,sha256=ocw-SFTtN6vQ8fgnlF8iNAOflRmh79xS1xdO0Bc3QPE,96
|
|
43
|
-
fastmcp/tools/tool.py,sha256=
|
|
44
|
-
fastmcp/tools/tool_manager.py,sha256=
|
|
43
|
+
fastmcp/tools/tool.py,sha256=k7awnrPoId_1XJHFce7X3mAEgBsJyr2v5kuuxXrE5Ww,7602
|
|
44
|
+
fastmcp/tools/tool_manager.py,sha256=v4Ur-JXDPXUxHqHJxA52IIcZfSiCBOnoFFLOmmJR1A8,4157
|
|
45
45
|
fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
|
|
46
46
|
fastmcp/utilities/cache.py,sha256=aV3oZ-ZhMgLSM9iAotlUlEy5jFvGXrVo0Y5Bj4PBtqY,707
|
|
47
47
|
fastmcp/utilities/decorators.py,sha256=AjhjsetQZF4YOPV5MTZmIxO21iFp_4fDIS3O2_KNCEg,2990
|
|
48
|
-
fastmcp/utilities/
|
|
49
|
-
fastmcp/utilities/
|
|
50
|
-
fastmcp/utilities/
|
|
51
|
-
fastmcp/utilities/
|
|
48
|
+
fastmcp/utilities/exceptions.py,sha256=Aax9K0larjzrrgJBS6o_PQwoIrvBvVwck2suZvgafXE,1359
|
|
49
|
+
fastmcp/utilities/json_schema.py,sha256=m65XU9lPq7pCxJ9vvCeGRl0HOFr6ArezvYpMBR6-gAg,3777
|
|
50
|
+
fastmcp/utilities/logging.py,sha256=n4P7P-aFDCuUFz8O-ykzUOj2sXl789HtWI_pX3ynGaY,1234
|
|
51
|
+
fastmcp/utilities/openapi.py,sha256=V3hANT6KcD_Bloq9uHDVkVJRcGaZIq8GH5ZZ7bKVmXY,56943
|
|
52
|
+
fastmcp/utilities/tests.py,sha256=mAV2EjDeCbm9V9NsVIUjcmzf93MgDjfj8kMvHpf4vgo,3224
|
|
52
53
|
fastmcp/utilities/types.py,sha256=6CcqAQ1QqCO2HGSFlPS6FO5JRWnacjCcO2-EhyEnZV0,4400
|
|
53
|
-
fastmcp-2.3.
|
|
54
|
-
fastmcp-2.3.
|
|
55
|
-
fastmcp-2.3.
|
|
56
|
-
fastmcp-2.3.
|
|
57
|
-
fastmcp-2.3.
|
|
54
|
+
fastmcp-2.3.4.dist-info/METADATA,sha256=9uZJ9YUNRVnoD6oFmDatjuiaQn8GAWt9XKzqagsngyQ,15754
|
|
55
|
+
fastmcp-2.3.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
56
|
+
fastmcp-2.3.4.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
|
|
57
|
+
fastmcp-2.3.4.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
58
|
+
fastmcp-2.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|