fastmcp 2.10.5__py3-none-any.whl → 2.10.6__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/__init__.py CHANGED
@@ -1,10 +1,15 @@
1
1
  """FastMCP - An ergonomic MCP interface."""
2
2
 
3
3
  import warnings
4
- from importlib.metadata import version
4
+ from importlib.metadata import version as _version
5
5
  from fastmcp.settings import Settings
6
+ from fastmcp.utilities.logging import configure_logging as _configure_logging
6
7
 
7
8
  settings = Settings()
9
+ _configure_logging(
10
+ level=settings.log_level,
11
+ enable_rich_tracebacks=settings.enable_rich_tracebacks,
12
+ )
8
13
 
9
14
  from fastmcp.server.server import FastMCP
10
15
  from fastmcp.server.context import Context
@@ -13,7 +18,7 @@ import fastmcp.server
13
18
  from fastmcp.client import Client
14
19
  from . import client
15
20
 
16
- __version__ = version("fastmcp")
21
+ __version__ = _version("fastmcp")
17
22
 
18
23
 
19
24
  # ensure deprecation warnings are displayed by default
@@ -5,7 +5,7 @@ import cyclopts
5
5
  from .claude_code import claude_code_command
6
6
  from .claude_desktop import claude_desktop_command
7
7
  from .cursor import cursor_command
8
- from .mcp_config import mcp_config_command
8
+ from .mcp_json import mcp_json_command
9
9
 
10
10
  # Create a cyclopts app for install subcommands
11
11
  install_app = cyclopts.App(
@@ -17,4 +17,4 @@ install_app = cyclopts.App(
17
17
  install_app.command(claude_code_command, name="claude-code")
18
18
  install_app.command(claude_desktop_command, name="claude-desktop")
19
19
  install_app.command(cursor_command, name="cursor")
20
- install_app.command(mcp_config_command, name="mcp-json")
20
+ install_app.command(mcp_json_command, name="mcp-json")
@@ -16,7 +16,7 @@ from .shared import process_common_args
16
16
  logger = get_logger(__name__)
17
17
 
18
18
 
19
- def install_mcp_config(
19
+ def install_mcp_json(
20
20
  file: Path,
21
21
  server_object: str | None,
22
22
  name: str,
@@ -65,15 +65,18 @@ def install_mcp_config(
65
65
  # Add fastmcp run command
66
66
  args.extend(["fastmcp", "run", server_spec])
67
67
 
68
- # Build MCP server configuration (just the server object, not the wrapper)
69
- config = {
68
+ # Build MCP server configuration
69
+ server_config = {
70
70
  "command": "uv",
71
71
  "args": args,
72
72
  }
73
73
 
74
74
  # Add environment variables if provided
75
75
  if env_vars:
76
- config["env"] = env_vars
76
+ server_config["env"] = env_vars
77
+
78
+ # Wrap with server name as root key
79
+ config = {name: server_config}
77
80
 
78
81
  # Convert to JSON
79
82
  json_output = json.dumps(config, indent=2)
@@ -93,13 +96,13 @@ def install_mcp_config(
93
96
  return False
94
97
 
95
98
 
96
- def mcp_config_command(
99
+ def mcp_json_command(
97
100
  server_spec: str,
98
101
  *,
99
102
  server_name: Annotated[
100
103
  str | None,
101
104
  cyclopts.Parameter(
102
- name=["--server-name", "-n"],
105
+ name=["--name", "-n"],
103
106
  help="Custom name for the server in MCP config",
104
107
  ),
105
108
  ] = None,
@@ -151,7 +154,7 @@ def mcp_config_command(
151
154
  server_spec, server_name, with_packages, env_vars, env_file
152
155
  )
153
156
 
154
- success = install_mcp_config(
157
+ success = install_mcp_json(
155
158
  file=file,
156
159
  server_object=server_object,
157
160
  name=name,
@@ -78,7 +78,7 @@ class PromptManager:
78
78
  except Exception as e:
79
79
  # Skip failed mounts silently, matches existing behavior
80
80
  logger.warning(
81
- f"Failed to get prompts from mounted server '{mounted.prefix}': {e}"
81
+ f"Failed to get prompts from server: {mounted.server.name!r}, mounted at: {mounted.prefix!r}: {e}"
82
82
  )
83
83
  continue
84
84
 
@@ -109,7 +109,7 @@ class ResourceManager:
109
109
  except Exception as e:
110
110
  # Skip failed mounts silently, matches existing behavior
111
111
  logger.warning(
112
- f"Failed to get resources from mounted server '{mounted.prefix}': {e}"
112
+ f"Failed to get resources from server: {mounted.server.name!r}, mounted at: {mounted.prefix!r}: {e}"
113
113
  )
114
114
  continue
115
115
 
@@ -157,7 +157,7 @@ class ResourceManager:
157
157
  except Exception as e:
158
158
  # Skip failed mounts silently, matches existing behavior
159
159
  logger.warning(
160
- f"Failed to get templates from mounted server '{mounted.prefix}': {e}"
160
+ f"Failed to get templates from server: {mounted.server.name!r}, mounted at: {mounted.prefix!r}: {e}"
161
161
  )
162
162
  continue
163
163
 
fastmcp/server/context.py CHANGED
@@ -16,6 +16,7 @@ from mcp.shared.context import RequestContext
16
16
  from mcp.types import (
17
17
  ContentBlock,
18
18
  CreateMessageResult,
19
+ IncludeContext,
19
20
  ModelHint,
20
21
  ModelPreferences,
21
22
  Root,
@@ -272,6 +273,7 @@ class Context:
272
273
  self,
273
274
  messages: str | list[str | SamplingMessage],
274
275
  system_prompt: str | None = None,
276
+ include_context: IncludeContext | None = None,
275
277
  temperature: float | None = None,
276
278
  max_tokens: int | None = None,
277
279
  model_preferences: ModelPreferences | str | list[str] | None = None,
@@ -304,6 +306,7 @@ class Context:
304
306
  result: CreateMessageResult = await self.session.create_message(
305
307
  messages=sampling_messages,
306
308
  system_prompt=system_prompt,
309
+ include_context=include_context,
307
310
  temperature=temperature,
308
311
  max_tokens=max_tokens,
309
312
  model_preferences=self._parse_model_preferences(model_preferences),
fastmcp/server/openapi.py CHANGED
@@ -344,18 +344,28 @@ class OpenAPITool(Tool):
344
344
  suffixed_name = f"{p.name}__{p.location}"
345
345
  param_value = None
346
346
 
347
+ suffixed_value = arguments.get(suffixed_name)
347
348
  if (
348
349
  suffixed_name in arguments
349
- and arguments.get(suffixed_name) is not None
350
- and arguments.get(suffixed_name) != ""
350
+ and suffixed_value is not None
351
+ and suffixed_value != ""
352
+ and not (
353
+ isinstance(suffixed_value, list | dict)
354
+ and len(suffixed_value) == 0
355
+ )
351
356
  ):
352
357
  param_value = arguments[suffixed_name]
353
- elif (
354
- p.name in arguments
355
- and arguments.get(p.name) is not None
356
- and arguments.get(p.name) != ""
357
- ):
358
- param_value = arguments[p.name]
358
+ else:
359
+ name_value = arguments.get(p.name)
360
+ if (
361
+ p.name in arguments
362
+ and name_value is not None
363
+ and name_value != ""
364
+ and not (
365
+ isinstance(name_value, list | dict) and len(name_value) == 0
366
+ )
367
+ ):
368
+ param_value = arguments[p.name]
359
369
 
360
370
  if param_value is not None:
361
371
  # Handle different parameter styles and types
@@ -367,7 +377,11 @@ class OpenAPITool(Tool):
367
377
  ) # Default explode for query is True
368
378
 
369
379
  # Handle deepObject style for object parameters
370
- if param_style == "deepObject" and isinstance(param_value, dict):
380
+ if (
381
+ param_style == "deepObject"
382
+ and isinstance(param_value, dict)
383
+ and len(param_value) > 0
384
+ ):
371
385
  if param_explode:
372
386
  # deepObject with explode=true: object properties become separate parameters
373
387
  # e.g., target[id]=123&target[type]=user
@@ -386,6 +400,7 @@ class OpenAPITool(Tool):
386
400
  elif (
387
401
  isinstance(param_value, list)
388
402
  and p.schema_.get("type") == "array"
403
+ and len(param_value) > 0
389
404
  ):
390
405
  if param_explode:
391
406
  # When explode=True, we pass the array directly, which HTTPX will serialize
@@ -444,9 +459,7 @@ class OpenAPITool(Tool):
444
459
  params_to_exclude.add(p.name)
445
460
 
446
461
  body_params = {
447
- k: v
448
- for k, v in arguments.items()
449
- if k not in params_to_exclude and k != "context"
462
+ k: v for k, v in arguments.items() if k not in params_to_exclude
450
463
  }
451
464
 
452
465
  if body_params:
fastmcp/server/proxy.py CHANGED
@@ -580,3 +580,45 @@ class ProxyClient(Client[ClientTransportT]):
580
580
  """
581
581
  ctx = get_context()
582
582
  await ctx.report_progress(progress, total, message)
583
+
584
+
585
+ class StatefulProxyClient(ProxyClient[ClientTransportT]):
586
+ """
587
+ A proxy client that provides a stateful client factory for the proxy server.
588
+
589
+ The stateful proxy client bound its copy to the server session.
590
+ And it will be disconnected when the session is exited.
591
+
592
+ This is useful to proxy a stateful mcp server such as the Playwright MCP server.
593
+ Note that it is essential to ensure that the proxy server itself is also stateful.
594
+ """
595
+
596
+ async def __aexit__(self, exc_type, exc_value, traceback) -> None:
597
+ """
598
+ The stateful proxy client will be forced disconnected when the session is exited.
599
+ So we do nothing here.
600
+ """
601
+ pass
602
+
603
+ def new_stateful(self) -> Client[ClientTransportT]:
604
+ """
605
+ Create a new stateful proxy client instance with the same configuration.
606
+
607
+ Use this method as the client factory for stateful proxy server.
608
+ """
609
+ session = get_context().session
610
+ proxy_client = session.__dict__.get("_proxy_client", None)
611
+
612
+ if proxy_client is None:
613
+ proxy_client = self.new()
614
+ logger.debug(f"{proxy_client} created for {session}")
615
+ session.__dict__["_proxy_client"] = proxy_client
616
+
617
+ async def _on_session_exit():
618
+ proxy_client: Client = session.__dict__.pop("_proxy_client")
619
+ logger.debug(f"{proxy_client} will be disconnect")
620
+ await proxy_client._disconnect(force=True)
621
+
622
+ session._exit_stack.push_async_callback(_on_session_exit)
623
+
624
+ return proxy_client
fastmcp/server/server.py CHANGED
@@ -1662,8 +1662,7 @@ class FastMCP(Generic[LifespanResultT]):
1662
1662
  resource_separator: Deprecated. Separator character for resource URIs.
1663
1663
  prompt_separator: Deprecated. Separator character for prompt names.
1664
1664
  """
1665
- from fastmcp.client.transports import FastMCPTransport
1666
- from fastmcp.server.proxy import FastMCPProxy, ProxyClient
1665
+ from fastmcp.server.proxy import FastMCPProxy
1667
1666
 
1668
1667
  # Deprecated since 2.9.0
1669
1668
  # Prior to 2.9.0, the first positional argument was the prefix and the
@@ -1715,7 +1714,7 @@ class FastMCP(Generic[LifespanResultT]):
1715
1714
  as_proxy = server._has_lifespan
1716
1715
 
1717
1716
  if as_proxy and not isinstance(server, FastMCPProxy):
1718
- server = FastMCPProxy(ProxyClient(transport=FastMCPTransport(server)))
1717
+ server = FastMCP.as_proxy(server)
1719
1718
 
1720
1719
  # Delegate mounting to all three managers
1721
1720
  mounted_server = MountedServer(
fastmcp/settings.py CHANGED
@@ -5,7 +5,7 @@ import warnings
5
5
  from pathlib import Path
6
6
  from typing import Annotated, Any, Literal
7
7
 
8
- from pydantic import Field, model_validator
8
+ from pydantic import Field, field_validator
9
9
  from pydantic.fields import FieldInfo
10
10
  from pydantic_settings import (
11
11
  BaseSettings,
@@ -99,7 +99,16 @@ class Settings(BaseSettings):
99
99
  home: Path = Path.home() / ".fastmcp"
100
100
 
101
101
  test_mode: bool = False
102
+
102
103
  log_level: LOG_LEVEL = "INFO"
104
+
105
+ @field_validator("log_level", mode="before")
106
+ @classmethod
107
+ def normalize_log_level(cls, v):
108
+ if isinstance(v, str):
109
+ return v.upper()
110
+ return v
111
+
103
112
  enable_rich_tracebacks: Annotated[
104
113
  bool,
105
114
  Field(
@@ -162,17 +171,6 @@ class Settings(BaseSettings):
162
171
  ),
163
172
  ] = None
164
173
 
165
- @model_validator(mode="after")
166
- def setup_logging(self) -> Self:
167
- """Finalize the settings."""
168
- from fastmcp.utilities.logging import configure_logging
169
-
170
- configure_logging(
171
- self.log_level, enable_rich_tracebacks=self.enable_rich_tracebacks
172
- )
173
-
174
- return self
175
-
176
174
  # HTTP settings
177
175
  host: str = "127.0.0.1"
178
176
  port: int = 8000
fastmcp/tools/tool.py CHANGED
@@ -185,8 +185,9 @@ class Tool(FastMCPComponent):
185
185
  tool: Tool,
186
186
  transform_fn: Callable[..., Any] | None = None,
187
187
  name: str | None = None,
188
+ title: str | None | NotSetT = NotSet,
188
189
  transform_args: dict[str, ArgTransform] | None = None,
189
- description: str | None = None,
190
+ description: str | None | NotSetT = NotSet,
190
191
  tags: set[str] | None = None,
191
192
  annotations: ToolAnnotations | None = None,
192
193
  output_schema: dict[str, Any] | None | Literal[False] = None,
@@ -199,6 +200,7 @@ class Tool(FastMCPComponent):
199
200
  tool=tool,
200
201
  transform_fn=transform_fn,
201
202
  name=name,
203
+ title=title,
202
204
  transform_args=transform_args,
203
205
  description=description,
204
206
  tags=tags,
@@ -397,7 +399,7 @@ class ParsedFunction:
397
399
 
398
400
  try:
399
401
  type_adapter = get_cached_typeadapter(clean_output_type)
400
- base_schema = type_adapter.json_schema()
402
+ base_schema = type_adapter.json_schema(mode="serialization")
401
403
 
402
404
  # Generate schema for wrapped type if it's non-object
403
405
  # because MCP requires that output schemas are objects
@@ -408,7 +410,7 @@ class ParsedFunction:
408
410
  # Use the wrapped result schema directly
409
411
  wrapped_type = _WrappedResult[clean_output_type]
410
412
  wrapped_adapter = get_cached_typeadapter(wrapped_type)
411
- output_schema = wrapped_adapter.json_schema()
413
+ output_schema = wrapped_adapter.json_schema(mode="serialization")
412
414
  output_schema["x-fastmcp-wrap-result"] = True
413
415
  else:
414
416
  output_schema = base_schema
@@ -76,7 +76,7 @@ class ToolManager:
76
76
  except Exception as e:
77
77
  # Skip failed mounts silently, matches existing behavior
78
78
  logger.warning(
79
- f"Failed to get tools from mounted server '{mounted.prefix}': {e}"
79
+ f"Failed to get tools from server: {mounted.server.name!r}, mounted at: {mounted.prefix!r}: {e}"
80
80
  )
81
81
  continue
82
82
 
@@ -325,7 +325,8 @@ class TransformedTool(Tool):
325
325
  cls,
326
326
  tool: Tool,
327
327
  name: str | None = None,
328
- description: str | None = None,
328
+ title: str | None | NotSetT = NotSet,
329
+ description: str | None | NotSetT = NotSet,
329
330
  tags: set[str] | None = None,
330
331
  transform_fn: Callable[..., Any] | None = None,
331
332
  transform_args: dict[str, ArgTransform] | None = None,
@@ -342,6 +343,7 @@ class TransformedTool(Tool):
342
343
  to call the parent tool. Functions with **kwargs receive transformed
343
344
  argument names.
344
345
  name: New name for the tool. Defaults to parent tool's name.
346
+ title: New title for the tool. Defaults to parent tool's title.
345
347
  transform_args: Optional transformations for parent tool arguments.
346
348
  Only specified arguments are transformed, others pass through unchanged:
347
349
  - Simple rename (str)
@@ -506,13 +508,18 @@ class TransformedTool(Tool):
506
508
  f"{', '.join(sorted(duplicates))}"
507
509
  )
508
510
 
509
- final_description = description if description is not None else tool.description
511
+ final_name = name or tool.name
512
+ final_description = (
513
+ description if not isinstance(description, NotSetT) else tool.description
514
+ )
515
+ final_title = title if not isinstance(title, NotSetT) else tool.title
510
516
 
511
517
  transformed_tool = cls(
512
518
  fn=final_fn,
513
519
  forwarding_fn=forwarding_fn,
514
520
  parent_tool=tool,
515
- name=name or tool.name,
521
+ name=final_name,
522
+ title=final_title,
516
523
  description=final_description,
517
524
  parameters=final_schema,
518
525
  output_schema=final_output_schema,
@@ -1068,15 +1068,16 @@ def _replace_ref_with_defs(
1068
1068
  """
1069
1069
  schema = info.copy()
1070
1070
  if ref_path := schema.get("$ref"):
1071
- if ref_path.startswith("#/components/schemas/"):
1072
- schema_name = ref_path.split("/")[-1]
1073
- schema["$ref"] = f"#/$defs/{schema_name}"
1074
- elif not ref_path.startswith("#/"):
1075
- raise ValueError(
1076
- f"External or non-local reference not supported: {ref_path}. "
1077
- f"FastMCP only supports local schema references starting with '#/'. "
1078
- f"Please include all schema definitions within the OpenAPI document."
1079
- )
1071
+ if isinstance(ref_path, str):
1072
+ if ref_path.startswith("#/components/schemas/"):
1073
+ schema_name = ref_path.split("/")[-1]
1074
+ schema["$ref"] = f"#/$defs/{schema_name}"
1075
+ elif not ref_path.startswith("#/"):
1076
+ raise ValueError(
1077
+ f"External or non-local reference not supported: {ref_path}. "
1078
+ f"FastMCP only supports local schema references starting with '#/'. "
1079
+ f"Please include all schema definitions within the OpenAPI document."
1080
+ )
1080
1081
  elif properties := schema.get("properties"):
1081
1082
  if "$ref" in properties:
1082
1083
  schema["properties"] = _replace_ref_with_defs(properties)
@@ -1095,6 +1096,81 @@ def _replace_ref_with_defs(
1095
1096
  return schema
1096
1097
 
1097
1098
 
1099
+ def _make_optional_parameter_nullable(schema: dict[str, Any]) -> dict[str, Any]:
1100
+ """
1101
+ Make an optional parameter schema nullable to allow None values.
1102
+
1103
+ For optional parameters, we need to allow null values in addition to the
1104
+ specified type to handle cases where None is passed for optional parameters.
1105
+ """
1106
+ # If schema already has multiple types or is already nullable, don't modify
1107
+ if "anyOf" in schema or "oneOf" in schema or "allOf" in schema:
1108
+ return schema
1109
+
1110
+ # If it's already nullable (type includes null), don't modify
1111
+ if isinstance(schema.get("type"), list) and "null" in schema["type"]:
1112
+ return schema
1113
+
1114
+ # Create a new schema that allows null in addition to the original type
1115
+ if "type" in schema:
1116
+ original_type = schema["type"]
1117
+
1118
+ if isinstance(original_type, str):
1119
+ # Single type - make it a union with null
1120
+ nullable_schema = schema.copy()
1121
+
1122
+ nested_non_nullable_schema = {
1123
+ "type": original_type,
1124
+ }
1125
+
1126
+ # If the original type is an array, move the array-specific properties into the now-nested schema
1127
+ # https://json-schema.org/understanding-json-schema/reference/array
1128
+ if original_type == "array":
1129
+ for array_property in [
1130
+ "items",
1131
+ "prefixItems",
1132
+ "unevaluatedItems",
1133
+ "contains",
1134
+ "minContains",
1135
+ "maxContains",
1136
+ "minItems",
1137
+ "maxItems",
1138
+ "uniqueItems",
1139
+ ]:
1140
+ if array_property in nullable_schema:
1141
+ nested_non_nullable_schema[array_property] = nullable_schema[
1142
+ array_property
1143
+ ]
1144
+ del nullable_schema[array_property]
1145
+
1146
+ # If the original type is an object, move the object-specific properties into the now-nested schema
1147
+ # https://json-schema.org/understanding-json-schema/reference/object
1148
+ elif original_type == "object":
1149
+ for object_property in [
1150
+ "properties",
1151
+ "patternProperties",
1152
+ "additionalProperties",
1153
+ "unevaluatedProperties",
1154
+ "required",
1155
+ "propertyNames",
1156
+ "minProperties",
1157
+ "maxProperties",
1158
+ ]:
1159
+ if object_property in nullable_schema:
1160
+ nested_non_nullable_schema[object_property] = nullable_schema[
1161
+ object_property
1162
+ ]
1163
+ del nullable_schema[object_property]
1164
+
1165
+ nullable_schema["anyOf"] = [nested_non_nullable_schema, {"type": "null"}]
1166
+
1167
+ # Remove the original type since we're using anyOf
1168
+ del nullable_schema["type"]
1169
+ return nullable_schema
1170
+
1171
+ return schema
1172
+
1173
+
1098
1174
  def _combine_schemas(route: HTTPRoute) -> dict[str, Any]:
1099
1175
  """
1100
1176
  Combines parameter and request body schemas into a single schema.
@@ -1156,15 +1232,25 @@ def _combine_schemas(route: HTTPRoute) -> dict[str, Any]:
1156
1232
  else:
1157
1233
  param_schema["description"] = location_desc
1158
1234
 
1235
+ # Make optional parameters nullable to allow None values
1236
+ if not param.required:
1237
+ param_schema = _make_optional_parameter_nullable(param_schema)
1238
+
1159
1239
  properties[suffixed_name] = param_schema
1160
1240
  else:
1161
1241
  # No collision, use original name
1162
1242
  if param.required:
1163
1243
  required.append(param.name)
1164
- properties[param.name] = _replace_ref_with_defs(
1244
+ param_schema = _replace_ref_with_defs(
1165
1245
  param.schema_.copy(), param.description
1166
1246
  )
1167
1247
 
1248
+ # Make optional parameters nullable to allow None values
1249
+ if not param.required:
1250
+ param_schema = _make_optional_parameter_nullable(param_schema)
1251
+
1252
+ properties[param.name] = param_schema
1253
+
1168
1254
  # Add request body properties (no suffixes for body parameters)
1169
1255
  if route.request_body and route.request_body.content_schema:
1170
1256
  for prop_name, prop_schema in body_props.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.10.5
3
+ Version: 2.10.6
4
4
  Summary: The fast, Pythonic way to build MCP servers and clients.
5
5
  Project-URL: Homepage, https://gofastmcp.com
6
6
  Project-URL: Repository, https://github.com/jlowin/fastmcp
@@ -38,7 +38,7 @@ Description-Content-Type: text/markdown
38
38
 
39
39
  <strong>The fast, Pythonic way to build MCP servers and clients.</strong>
40
40
 
41
- *FastMCP is made with 💙 by [Prefect](https://www.prefect.io/)*
41
+ *FastMCP is made with ☕️ by [Prefect](https://www.prefect.io/)*
42
42
 
43
43
  [![Docs](https://img.shields.io/badge/docs-gofastmcp.com-blue)](https://gofastmcp.com)
44
44
  [![PyPI - Version](https://img.shields.io/pypi/v/fastmcp.svg)](https://pypi.org/project/fastmcp)
@@ -1,17 +1,17 @@
1
- fastmcp/__init__.py,sha256=5ChT4kg3srdFl0-9dZekGqpzCESlpc6ohrfPbWf1aTo,1300
1
+ fastmcp/__init__.py,sha256=B_FAqsxbTJmwvJKyIDMOZWpUUdmO806bKo8RR32oZL0,1503
2
2
  fastmcp/exceptions.py,sha256=-krEavxwddQau6T7MESCR4VjKNLfP9KHJrU1p3y72FU,744
3
3
  fastmcp/mcp_config.py,sha256=hOF_NO7F9LbrbmRTj99TVSqHIul4sExNpf1T1HRLpzo,9606
4
4
  fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- fastmcp/settings.py,sha256=Ta0TKA75xda9sNkIOpPVIEEk4W9jf_2gwcmO26uDQpg,8946
5
+ fastmcp/settings.py,sha256=nGbuVgqpZbMHI4PjMzRoU3gJcC2rdiPhP2kWmsptWNU,8817
6
6
  fastmcp/cli/__init__.py,sha256=Ii284TNoG5lxTP40ETMGhHEq3lQZWxu9m9JuU57kUpQ,87
7
7
  fastmcp/cli/claude.py,sha256=IAlcZ4qZKBBj09jZUMEx7EANZE_IR3vcu7zOBJmMOuU,4567
8
8
  fastmcp/cli/cli.py,sha256=Q4HDVDSty1Gx6qN_M4FDx8RYat34vhWT25338X-quNs,12672
9
9
  fastmcp/cli/run.py,sha256=V268Lf7LXdeMZ4_D4fKdFST7cOs8pGgLXZTxtcEJRWg,6715
10
- fastmcp/cli/install/__init__.py,sha256=afaNANIhivfKi4QhJdYUP56Q2XZ4da4dUbDq9HAMJqo,701
10
+ fastmcp/cli/install/__init__.py,sha256=cDEc0hhuf_xwGpI6ghpqlvlMdBMJUGHq_rs-tgmOJZ8,695
11
11
  fastmcp/cli/install/claude_code.py,sha256=VlFVGKKRppkmp42io6VPTQrQHgNww4H2ppa6mAWM-Ao,6430
12
12
  fastmcp/cli/install/claude_desktop.py,sha256=o3p3KiW0QzsrzOEa3OU_gkvzTuFSkabDwEqwwgp1mYU,5590
13
13
  fastmcp/cli/install/cursor.py,sha256=296a22T3fdaC8deCwh3TreVFoJ0QpjLxRF1gNsp3Wjg,5555
14
- fastmcp/cli/install/mcp_config.py,sha256=D1vkZj13ofNFbFhdn8eAuEx-CHTr3nGiVkjSZTdnetY,4559
14
+ fastmcp/cli/install/mcp_json.py,sha256=FfLm6OdinHunrau0GbZY6P1LUWTKYZvHvaEoyvAqguc,4602
15
15
  fastmcp/cli/install/shared.py,sha256=Y0YZei1YemVCkg0ieUgfRse-lqSlIn5Ho8t6pB9nDa4,2683
16
16
  fastmcp/client/__init__.py,sha256=kd2hhSuD8rZuF87c9zlPJP_icJ-Rx3exyNoK0EzfOtE,617
17
17
  fastmcp/client/client.py,sha256=GniETS28L8B-ahzztU2ZLI_XSCcEib-miGzE2ZnG4Xc,34054
@@ -42,21 +42,21 @@ fastmcp/contrib/mcp_mixin/example.py,sha256=GnunkXmtG5hLLTUsM8aW5ZURU52Z8vI4tNLl
42
42
  fastmcp/contrib/mcp_mixin/mcp_mixin.py,sha256=sUSJ2o0sTsb061MyPN2xuYP0oI4W6YVQXupY3nnjD50,8687
43
43
  fastmcp/prompts/__init__.py,sha256=An8uMBUh9Hrb7qqcn_5_Hent7IOeSh7EA2IUVsIrtHc,179
44
44
  fastmcp/prompts/prompt.py,sha256=Ux_FT8GTnejvjDWEgf5nSAIwbhV-9otgCJm-EqnzxvY,13861
45
- fastmcp/prompts/prompt_manager.py,sha256=Pt9cg_c9FR2EA0ITIHJT5Utihkd383JzhqhT-y2VnKo,7677
45
+ fastmcp/prompts/prompt_manager.py,sha256=lErodAnqVHRu_1FttfHTh-arWf9rkCOCGTxZzZP_3SE,7707
46
46
  fastmcp/resources/__init__.py,sha256=y1iAuqx-GIrS1NqIYzKezIDiYyjNEzzHD35epHpMnXE,463
47
47
  fastmcp/resources/resource.py,sha256=GGCUHUQe4ALrVJc-Ng1uz8-mtQSg_vuVA71H_qJkko0,6031
48
- fastmcp/resources/resource_manager.py,sha256=zjhso9ZP0EK_beTpUz_amqJ7XSABqU8mqPSk-JturOE,19777
48
+ fastmcp/resources/resource_manager.py,sha256=jmnKAkA7jevvKeccAVDsAAeXvI0IkrQeIXHCC36tf_0,19837
49
49
  fastmcp/resources/template.py,sha256=mYsw3xPWRq1AgOVFkG_A1otY3NXYw5oUJnVzMC1Qy80,10346
50
50
  fastmcp/resources/types.py,sha256=SiYNLnpXT-mHgNUrzqKUvXYUsY-V3gwJIrYdJfFwDDo,4868
51
51
  fastmcp/server/__init__.py,sha256=bMD4aQD4yJqLz7-mudoNsyeV8UgQfRAg3PRwPvwTEds,119
52
- fastmcp/server/context.py,sha256=OFkdgT53NkN_VYwwHjdR2C_28CWtPsFln36X0QLM23g,20258
52
+ fastmcp/server/context.py,sha256=hYDoc0O72SnyOloQvGRuYELOSkdAqQkSOBczVehokX0,20378
53
53
  fastmcp/server/dependencies.py,sha256=iKJdz1XsVJcrfHo_reXj9ZSldw-HeAwsp9S6lAgfGA8,2358
54
54
  fastmcp/server/elicitation.py,sha256=jZIHjV4NjhYbT-w8pBArwd0vNzP8OYwzmsnWDdk6Bd0,6136
55
55
  fastmcp/server/http.py,sha256=d0Jij4HVTaAohluRXArSniXLb1HcHP3ytbe-mMHg6nE,11678
56
56
  fastmcp/server/low_level.py,sha256=LNmc_nU_wx-fRG8OEHdLPKopZpovcrWlyAxJzKss3TA,1239
57
- fastmcp/server/openapi.py,sha256=LWT5rI8TN90MCppuo-LWkYM_ZVnxT6xtS-7Ny8sJIFI,41531
58
- fastmcp/server/proxy.py,sha256=3cABSJyOalxnqmHGaS8kb6jyaJEAXshQcOh8XihY7Kk,21936
59
- fastmcp/server/server.py,sha256=8ah5ZYgKLFT2sHzPRT3NUKBrQWi4nny_LPx6cN8EhQs,82816
57
+ fastmcp/server/openapi.py,sha256=L6lZy3kXknc1vzm3rJi3fe2Q-aMRluktp1EFBJq8Cs0,42079
58
+ fastmcp/server/proxy.py,sha256=7d92XLWCGgiTTIW0LWgdqacNc9JtHGj4BIP72aKrHwI,23513
59
+ fastmcp/server/server.py,sha256=2RfMq7W4jeenSsz54wjN6Yl0-HWTl9HkBBHMUV6rejg,82703
60
60
  fastmcp/server/auth/__init__.py,sha256=doHCLwOIElvH1NrTdpeP9JKfnNf3MDYPSpQfdsQ-uI0,84
61
61
  fastmcp/server/auth/auth.py,sha256=A00OKxglEMrGMMIiMbc6UmpGc2VoWDkEVU5g2pIzDIg,2119
62
62
  fastmcp/server/auth/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -70,9 +70,9 @@ fastmcp/server/middleware/middleware.py,sha256=jFy7NmLHvGmrGkKViS1PvR_7oGM1EklxN
70
70
  fastmcp/server/middleware/rate_limiting.py,sha256=VTrCoQFmWCm0BxwOrNfG21CBFDDOKJT7IiSEjpJgmPA,7921
71
71
  fastmcp/server/middleware/timing.py,sha256=lL_xc-ErLD5lplfvd5-HIyWEbZhgNBYkcQ74KFXAMkA,5591
72
72
  fastmcp/tools/__init__.py,sha256=vzqb-Y7Kf0d5T0aOsld-O-FA8kD7-4uFExChewFHEzY,201
73
- fastmcp/tools/tool.py,sha256=fW-xZQCLN2qSZrlAo2eQ1aEFa-VN5jYEHx5H936-_50,17466
74
- fastmcp/tools/tool_manager.py,sha256=Sm_tOO-SY0m7tEN_dofP-tvBnC2HroPRKLU6sp8gnUw,7739
75
- fastmcp/tools/tool_transform.py,sha256=nGvxxKsyfp3gYl_nkYFHlnb8Fc4Jtw6t7WL291S4Vh4,32558
73
+ fastmcp/tools/tool.py,sha256=-Cia4f7iMmWJJkUAze5AggGu61wGAtipMJno8CoOjko,17589
74
+ fastmcp/tools/tool_manager.py,sha256=xksy5A81YL1mGIJ9m6aBwTnFoiuNieI50tpmZ5ONChE,7769
75
+ fastmcp/tools/tool_transform.py,sha256=Fgf_hKXUVC2_UKa551GGyrS5JiChCvK8j0msh-iupA4,32870
76
76
  fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
77
77
  fastmcp/utilities/cache.py,sha256=aV3oZ-ZhMgLSM9iAotlUlEy5jFvGXrVo0Y5Bj4PBtqY,707
78
78
  fastmcp/utilities/cli.py,sha256=TXuSyALFAGJwi7tWEBwBmaGhYZBdF1aG6dLgl3zjM1w,3272
@@ -83,11 +83,11 @@ fastmcp/utilities/inspect.py,sha256=XNA0dfYM5G-FVbJaVJO8loSUUCNypyLA-QjqTOneJyU,
83
83
  fastmcp/utilities/json_schema.py,sha256=8qyb3qOvk1gc3p63uP6LGyKdOANkNdD9YA32OiBxyNw,5495
84
84
  fastmcp/utilities/json_schema_type.py,sha256=Sml03nJGOnUfxCGrHWRMwZMultV0X5JThMepUnHIUiA,22377
85
85
  fastmcp/utilities/logging.py,sha256=1y7oNmy8WrR0NsfNVw1LPoKu92OFdmzIO65syOKi_BI,1388
86
- fastmcp/utilities/openapi.py,sha256=Fvn6M_deDdm3qHGMLXClpIi5ZBp9bM31lvZ9XSnQkH4,52047
86
+ fastmcp/utilities/openapi.py,sha256=h9eB85w0lWiTx0NAS5WxwzKpNBdxHMAQ1zPv0lrjxvo,55566
87
87
  fastmcp/utilities/tests.py,sha256=kZH8HQAC702a5vNJb4K0tO1ll9CZADWQ_P-5ERWSvSA,4242
88
88
  fastmcp/utilities/types.py,sha256=c6HPvHCpkq8EXh0hWjaUlj9aCZklmxzAQHCXZy7llNo,10636
89
- fastmcp-2.10.5.dist-info/METADATA,sha256=T3PxSdKmyz51Fpby151d0mvdIQX-HZK0ns0aXlyIql0,17842
90
- fastmcp-2.10.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
91
- fastmcp-2.10.5.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
92
- fastmcp-2.10.5.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
93
- fastmcp-2.10.5.dist-info/RECORD,,
89
+ fastmcp-2.10.6.dist-info/METADATA,sha256=lQDaHuao4LS0HuJBYOv0nvhHs2ACFNUmNqWknT6Zmxk,17844
90
+ fastmcp-2.10.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
91
+ fastmcp-2.10.6.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
92
+ fastmcp-2.10.6.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
93
+ fastmcp-2.10.6.dist-info/RECORD,,