fastmcp 2.11.1__py3-none-any.whl → 2.11.2__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 CHANGED
@@ -138,7 +138,7 @@ def version(
138
138
 
139
139
 
140
140
  @app.command
141
- def dev(
141
+ async def dev(
142
142
  server_spec: str,
143
143
  *,
144
144
  with_editable: Annotated[
@@ -220,7 +220,7 @@ def dev(
220
220
 
221
221
  try:
222
222
  # Import server to get dependencies
223
- server: FastMCP = run_module.import_server(file, server_object)
223
+ server: FastMCP = await run_module.import_server(file, server_object)
224
224
  if server.dependencies is not None:
225
225
  with_packages = list(set(with_packages + server.dependencies))
226
226
 
@@ -283,7 +283,7 @@ def dev(
283
283
 
284
284
 
285
285
  @app.command
286
- def run(
286
+ async def run(
287
287
  server_spec: str,
288
288
  *server_args: str,
289
289
  transport: Annotated[
@@ -414,7 +414,7 @@ def run(
414
414
  else:
415
415
  # Use direct import for backwards compatibility
416
416
  try:
417
- run_module.run_command(
417
+ await run_module.run_command(
418
418
  server_spec=server_spec,
419
419
  transport=transport,
420
420
  host=host,
@@ -476,7 +476,7 @@ async def inspect(
476
476
 
477
477
  try:
478
478
  # Import the server
479
- server = run_module.import_server(file, server_object)
479
+ server = await run_module.import_server(file, server_object)
480
480
 
481
481
  # Get server information - using native async support
482
482
  info = await inspect_fastmcp(server)
@@ -167,7 +167,7 @@ def install_claude_code(
167
167
  return False
168
168
 
169
169
 
170
- def claude_code_command(
170
+ async def claude_code_command(
171
171
  server_spec: str,
172
172
  *,
173
173
  server_name: Annotated[
@@ -234,7 +234,7 @@ def claude_code_command(
234
234
  Args:
235
235
  server_spec: Python file to install, optionally with :object suffix
236
236
  """
237
- file, server_object, name, packages, env_dict = process_common_args(
237
+ file, server_object, name, packages, env_dict = await process_common_args(
238
238
  server_spec, server_name, with_packages, env_vars, env_file
239
239
  )
240
240
 
@@ -140,7 +140,7 @@ def install_claude_desktop(
140
140
  return False
141
141
 
142
142
 
143
- def claude_desktop_command(
143
+ async def claude_desktop_command(
144
144
  server_spec: str,
145
145
  *,
146
146
  server_name: Annotated[
@@ -207,7 +207,7 @@ def claude_desktop_command(
207
207
  Args:
208
208
  server_spec: Python file to install, optionally with :object suffix
209
209
  """
210
- file, server_object, name, with_packages, env_dict = process_common_args(
210
+ file, server_object, name, with_packages, env_dict = await process_common_args(
211
211
  server_spec, server_name, with_packages, env_vars, env_file
212
212
  )
213
213
 
@@ -150,7 +150,7 @@ def install_cursor(
150
150
  return False
151
151
 
152
152
 
153
- def cursor_command(
153
+ async def cursor_command(
154
154
  server_spec: str,
155
155
  *,
156
156
  server_name: Annotated[
@@ -217,7 +217,7 @@ def cursor_command(
217
217
  Args:
218
218
  server_spec: Python file to install, optionally with :object suffix
219
219
  """
220
- file, server_object, name, with_packages, env_dict = process_common_args(
220
+ file, server_object, name, with_packages, env_dict = await process_common_args(
221
221
  server_spec, server_name, with_packages, env_vars, env_file
222
222
  )
223
223
 
@@ -113,7 +113,7 @@ def install_mcp_json(
113
113
  return False
114
114
 
115
115
 
116
- def mcp_json_command(
116
+ async def mcp_json_command(
117
117
  server_spec: str,
118
118
  *,
119
119
  server_name: Annotated[
@@ -188,7 +188,7 @@ def mcp_json_command(
188
188
  Args:
189
189
  server_spec: Python file to install, optionally with :object suffix
190
190
  """
191
- file, server_object, name, packages, env_dict = process_common_args(
191
+ file, server_object, name, packages, env_dict = await process_common_args(
192
192
  server_spec, server_name, with_packages, env_vars, env_file
193
193
  )
194
194
 
@@ -23,7 +23,7 @@ def parse_env_var(env_var: str) -> tuple[str, str]:
23
23
  return key.strip(), value.strip()
24
24
 
25
25
 
26
- def process_common_args(
26
+ async def process_common_args(
27
27
  server_spec: str,
28
28
  server_name: str | None,
29
29
  with_packages: list[str],
@@ -49,7 +49,7 @@ def process_common_args(
49
49
  server = None
50
50
  if not name:
51
51
  try:
52
- server = import_server(file, server_object)
52
+ server = await import_server(file, server_object)
53
53
  name = server.name
54
54
  except (ImportError, ModuleNotFoundError) as e:
55
55
  logger.debug(
fastmcp/cli/run.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """FastMCP run command implementation with enhanced type hints."""
2
2
 
3
3
  import importlib.util
4
+ import inspect
4
5
  import json
5
6
  import re
6
7
  import subprocess
@@ -58,15 +59,15 @@ def parse_file_path(server_spec: str) -> tuple[Path, str | None]:
58
59
  return file_path, server_object
59
60
 
60
61
 
61
- def import_server(file: Path, server_object: str | None = None) -> Any:
62
+ async def import_server(file: Path, server_or_factory: str | None = None) -> Any:
62
63
  """Import a MCP server from a file.
63
64
 
64
65
  Args:
65
66
  file: Path to the file
66
- server_object: Optional object name in format "module:object" or just "object"
67
+ server_or_factory: Optional object name in format "module:object" or just "object"
67
68
 
68
69
  Returns:
69
- The server object
70
+ The server object (or result of calling a factory function)
70
71
  """
71
72
  # Add parent directory to Python path so imports can be resolved
72
73
  file_dir = str(file.parent)
@@ -86,11 +87,12 @@ def import_server(file: Path, server_object: str | None = None) -> Any:
86
87
  spec.loader.exec_module(module)
87
88
 
88
89
  # If no object specified, try common server names
89
- if not server_object:
90
- # Look for the most common server object names
90
+ if not server_or_factory:
91
+ # Look for common server instance names
91
92
  for name in ["mcp", "server", "app"]:
92
93
  if hasattr(module, name):
93
- return getattr(module, name)
94
+ obj = getattr(module, name)
95
+ return await _resolve_server_or_factory(obj, file, name)
94
96
 
95
97
  logger.error(
96
98
  f"No server object found in {file}. Please either:\n"
@@ -100,14 +102,14 @@ def import_server(file: Path, server_object: str | None = None) -> Any:
100
102
  )
101
103
  sys.exit(1)
102
104
 
103
- assert server_object is not None
105
+ assert server_or_factory is not None
104
106
 
105
107
  # Handle module:object syntax
106
- if ":" in server_object:
107
- module_name, object_name = server_object.split(":", 1)
108
+ if ":" in server_or_factory:
109
+ module_name, object_name = server_or_factory.split(":", 1)
108
110
  try:
109
111
  server_module = importlib.import_module(module_name)
110
- server = getattr(server_module, object_name, None)
112
+ obj = getattr(server_module, object_name, None)
111
113
  except ImportError:
112
114
  logger.error(
113
115
  f"Could not import module '{module_name}'",
@@ -116,16 +118,62 @@ def import_server(file: Path, server_object: str | None = None) -> Any:
116
118
  sys.exit(1)
117
119
  else:
118
120
  # Just object name
119
- server = getattr(module, server_object, None)
121
+ obj = getattr(module, server_or_factory, None)
120
122
 
121
- if server is None:
123
+ if obj is None:
122
124
  logger.error(
123
- f"Server object '{server_object}' not found",
125
+ f"Server object '{server_or_factory}' not found",
124
126
  extra={"file": str(file)},
125
127
  )
126
128
  sys.exit(1)
127
129
 
128
- return server
130
+ return await _resolve_server_or_factory(obj, file, server_or_factory)
131
+
132
+
133
+ async def _resolve_server_or_factory(obj: Any, file: Path, name: str) -> Any:
134
+ """Resolve a server object or factory function to a server instance.
135
+
136
+ Args:
137
+ obj: The object that might be a server or factory function
138
+ file: Path to the file for error messages
139
+ name: Name of the object for error messages
140
+
141
+ Returns:
142
+ A server instance
143
+ """
144
+ # Check if it's a function or coroutine function
145
+ if inspect.isfunction(obj) or inspect.iscoroutinefunction(obj):
146
+ logger.debug(f"Found factory function '{name}' in {file}")
147
+
148
+ try:
149
+ if inspect.iscoroutinefunction(obj):
150
+ # Async factory function
151
+ server = await obj()
152
+ else:
153
+ # Sync factory function
154
+ server = obj()
155
+
156
+ # Validate the result is a FastMCP server
157
+ if not isinstance(server, FastMCP | FastMCP1x):
158
+ logger.error(
159
+ f"Factory function '{name}' must return a FastMCP server instance, "
160
+ f"got {type(server).__name__}",
161
+ extra={"file": str(file)},
162
+ )
163
+ sys.exit(1)
164
+
165
+ logger.debug(f"Factory function '{name}' created server: {server.name}")
166
+ return server
167
+
168
+ except Exception as e:
169
+ logger.error(
170
+ f"Failed to call factory function '{name}': {e}",
171
+ extra={"file": str(file)},
172
+ )
173
+ sys.exit(1)
174
+
175
+ # Not a function, return as-is (should be a server instance)
176
+ return obj
129
177
 
130
178
 
131
179
  def run_with_uv(
@@ -219,7 +267,7 @@ def create_client_server(url: str) -> Any:
219
267
  import fastmcp
220
268
 
221
269
  client = fastmcp.Client(url)
222
- server = fastmcp.FastMCP.from_client(client)
270
+ server = fastmcp.FastMCP.as_proxy(client)
223
271
  return server
224
272
  except Exception as e:
225
273
  logger.error(f"Failed to create client for URL {url}: {e}")
@@ -237,14 +285,16 @@ def create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]:
237
285
  return server
238
286
 
239
287
 
240
- def import_server_with_args(
241
- file: Path, server_object: str | None = None, server_args: list[str] | None = None
288
+ async def import_server_with_args(
289
+ file: Path,
290
+ server_or_factory: str | None = None,
291
+ server_args: list[str] | None = None,
242
292
  ) -> Any:
243
293
  """Import a server with optional command line arguments.
244
294
 
245
295
  Args:
246
296
  file: Path to the server file
247
- server_object: Optional server object name
297
+ server_or_factory: Optional server object or factory function name
248
298
  server_args: Optional command line arguments to inject
249
299
 
250
300
  Returns:
@@ -254,14 +304,14 @@ def import_server_with_args(
254
304
  original_argv = sys.argv[:]
255
305
  try:
256
306
  sys.argv = [str(file)] + server_args
257
- return import_server(file, server_object)
307
+ return await import_server(file, server_or_factory)
258
308
  finally:
259
309
  sys.argv = original_argv
260
310
  else:
261
- return import_server(file, server_object)
311
+ return await import_server(file, server_or_factory)
262
312
 
263
313
 
264
- def run_command(
314
+ async def run_command(
265
315
  server_spec: str,
266
316
  transport: TransportType | None = None,
267
317
  host: str | None = None,
@@ -293,8 +343,8 @@ def run_command(
293
343
  server = create_mcp_config_server(Path(server_spec))
294
344
  else:
295
345
  # Handle file case
296
- file, server_object = parse_file_path(server_spec)
297
- server = import_server_with_args(file, server_object, server_args)
346
+ file, server_or_factory = parse_file_path(server_spec)
347
+ server = await import_server_with_args(file, server_or_factory, server_args)
298
348
  logger.debug(f'Found server "{server.name}" in {file}')
299
349
 
300
350
  # Run the server
@@ -320,7 +370,7 @@ def run_command(
320
370
  kwargs["show_banner"] = False
321
371
 
322
372
  try:
323
- server.run(**kwargs)
373
+ await server.run_async(**kwargs)
324
374
  except Exception as e:
325
375
  logger.error(f"Failed to run server: {e}")
326
376
  sys.exit(1)
fastmcp/server/proxy.py CHANGED
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import inspect
3
4
  import warnings
4
- from collections.abc import Callable
5
+ from collections.abc import Awaitable, Callable
5
6
  from pathlib import Path
6
7
  from typing import TYPE_CHECKING, Any, cast
7
8
  from urllib.parse import quote
@@ -48,11 +49,27 @@ if TYPE_CHECKING:
48
49
 
49
50
  logger = get_logger(__name__)
50
51
 
52
+ # Type alias for client factory functions
53
+ ClientFactoryT = Callable[[], Client] | Callable[[], Awaitable[Client]]
51
54
 
52
- class ProxyToolManager(ToolManager):
55
+
56
+ class ProxyManagerMixin:
57
+ """A mixin for proxy managers to provide a unified client retrieval method."""
58
+
59
+ client_factory: ClientFactoryT
60
+
61
+ async def _get_client(self) -> Client:
62
+ """Gets a client instance by calling the sync or async factory."""
63
+ client = self.client_factory()
64
+ if inspect.isawaitable(client):
65
+ client = await client
66
+ return client
67
+
68
+
69
+ class ProxyToolManager(ToolManager, ProxyManagerMixin):
53
70
  """A ToolManager that sources its tools from a remote client in addition to local and mounted tools."""
54
71
 
55
- def __init__(self, client_factory: Callable[[], Client], **kwargs):
72
+ def __init__(self, client_factory: ClientFactoryT, **kwargs):
56
73
  super().__init__(**kwargs)
57
74
  self.client_factory = client_factory
58
75
 
@@ -63,7 +80,7 @@ class ProxyToolManager(ToolManager):
63
80
 
64
81
  # Then add proxy tools, but don't overwrite existing ones
65
82
  try:
66
- client = self.client_factory()
83
+ client = await self._get_client()
67
84
  async with client:
68
85
  client_tools = await client.list_tools()
69
86
  for tool in client_tools:
@@ -94,7 +111,7 @@ class ProxyToolManager(ToolManager):
94
111
  return await super().call_tool(key, arguments)
95
112
  except NotFoundError:
96
113
  # If not found locally, try proxy
97
- client = self.client_factory()
114
+ client = await self._get_client()
98
115
  async with client:
99
116
  result = await client.call_tool(key, arguments)
100
117
  return ToolResult(
@@ -103,10 +120,10 @@ class ProxyToolManager(ToolManager):
103
120
  )
104
121
 
105
122
 
106
- class ProxyResourceManager(ResourceManager):
123
+ class ProxyResourceManager(ResourceManager, ProxyManagerMixin):
107
124
  """A ResourceManager that sources its resources from a remote client in addition to local and mounted resources."""
108
125
 
109
- def __init__(self, client_factory: Callable[[], Client], **kwargs):
126
+ def __init__(self, client_factory: ClientFactoryT, **kwargs):
110
127
  super().__init__(**kwargs)
111
128
  self.client_factory = client_factory
112
129
 
@@ -117,7 +134,7 @@ class ProxyResourceManager(ResourceManager):
117
134
 
118
135
  # Then add proxy resources, but don't overwrite existing ones
119
136
  try:
120
- client = self.client_factory()
137
+ client = await self._get_client()
121
138
  async with client:
122
139
  client_resources = await client.list_resources()
123
140
  for resource in client_resources:
@@ -140,7 +157,7 @@ class ProxyResourceManager(ResourceManager):
140
157
 
141
158
  # Then add proxy templates, but don't overwrite existing ones
142
159
  try:
143
- client = self.client_factory()
160
+ client = await self._get_client()
144
161
  async with client:
145
162
  client_templates = await client.list_resource_templates()
146
163
  for template in client_templates:
@@ -173,7 +190,7 @@ class ProxyResourceManager(ResourceManager):
173
190
  return await super().read_resource(uri)
174
191
  except NotFoundError:
175
192
  # If not found locally, try proxy
176
- client = self.client_factory()
193
+ client = await self._get_client()
177
194
  async with client:
178
195
  result = await client.read_resource(uri)
179
196
  if isinstance(result[0], TextResourceContents):
@@ -184,10 +201,10 @@ class ProxyResourceManager(ResourceManager):
184
201
  raise ResourceError(f"Unsupported content type: {type(result[0])}")
185
202
 
186
203
 
187
- class ProxyPromptManager(PromptManager):
204
+ class ProxyPromptManager(PromptManager, ProxyManagerMixin):
188
205
  """A PromptManager that sources its prompts from a remote client in addition to local and mounted prompts."""
189
206
 
190
- def __init__(self, client_factory: Callable[[], Client], **kwargs):
207
+ def __init__(self, client_factory: ClientFactoryT, **kwargs):
191
208
  super().__init__(**kwargs)
192
209
  self.client_factory = client_factory
193
210
 
@@ -198,7 +215,7 @@ class ProxyPromptManager(PromptManager):
198
215
 
199
216
  # Then add proxy prompts, but don't overwrite existing ones
200
217
  try:
201
- client = self.client_factory()
218
+ client = await self._get_client()
202
219
  async with client:
203
220
  client_prompts = await client.list_prompts()
204
221
  for prompt in client_prompts:
@@ -230,7 +247,7 @@ class ProxyPromptManager(PromptManager):
230
247
  return await super().render_prompt(name, arguments)
231
248
  except NotFoundError:
232
249
  # If not found locally, try proxy
233
- client = self.client_factory()
250
+ client = await self._get_client()
234
251
  async with client:
235
252
  result = await client.get_prompt(name, arguments)
236
253
  return result
@@ -444,7 +461,7 @@ class FastMCPProxy(FastMCP):
444
461
  self,
445
462
  client: Client | None = None,
446
463
  *,
447
- client_factory: Callable[[], Client] | None = None,
464
+ client_factory: ClientFactoryT | None = None,
448
465
  **kwargs,
449
466
  ):
450
467
  """
@@ -459,6 +476,7 @@ class FastMCPProxy(FastMCP):
459
476
  created that provides session isolation for backwards compatibility.
460
477
  client_factory: A callable that returns a Client instance when called.
461
478
  This gives you full control over session creation and reuse.
479
+ Can be either a synchronous or asynchronous function.
462
480
  **kwargs: Additional settings for the FastMCP server.
463
481
  """
464
482
 
fastmcp/server/server.py CHANGED
@@ -140,19 +140,18 @@ class FastMCP(Generic[LifespanResultT]):
140
140
  ]
141
141
  | None
142
142
  ) = None,
143
- tool_serializer: Callable[[Any], str] | None = None,
144
- cache_expiration_seconds: float | None = None,
145
- on_duplicate_tools: DuplicateBehavior | None = None,
146
- on_duplicate_resources: DuplicateBehavior | None = None,
147
- on_duplicate_prompts: DuplicateBehavior | None = None,
143
+ dependencies: list[str] | None = None,
148
144
  resource_prefix_format: Literal["protocol", "path"] | None = None,
149
145
  mask_error_details: bool | None = None,
150
146
  tools: list[Tool | Callable[..., Any]] | None = None,
151
147
  tool_transformations: dict[str, ToolTransformConfig] | None = None,
152
- dependencies: list[str] | None = None,
148
+ tool_serializer: Callable[[Any], str] | None = None,
153
149
  include_tags: set[str] | None = None,
154
150
  exclude_tags: set[str] | None = None,
155
151
  include_fastmcp_meta: bool | None = None,
152
+ on_duplicate_tools: DuplicateBehavior | None = None,
153
+ on_duplicate_resources: DuplicateBehavior | None = None,
154
+ on_duplicate_prompts: DuplicateBehavior | None = None,
156
155
  # ---
157
156
  # ---
158
157
  # --- The following arguments are DEPRECATED ---
@@ -304,6 +303,10 @@ class FastMCP(Generic[LifespanResultT]):
304
303
  def instructions(self) -> str | None:
305
304
  return self._mcp_server.instructions
306
305
 
306
+ @property
307
+ def version(self) -> str | None:
308
+ return self._mcp_server.version
309
+
307
310
  async def run_async(
308
311
  self,
309
312
  transport: Transport | None = None,
fastmcp/settings.py CHANGED
@@ -244,13 +244,10 @@ class Settings(BaseSettings):
244
244
  ),
245
245
  ] = False
246
246
 
247
- server_dependencies: Annotated[
248
- list[str],
249
- Field(
250
- default_factory=list,
251
- description="List of dependencies to install in the server environment",
252
- ),
253
- ] = []
247
+ server_dependencies: list[str] = Field(
248
+ default_factory=list,
249
+ description="List of dependencies to install in the server environment",
250
+ )
254
251
 
255
252
  # StreamableHTTP settings
256
253
  json_response: bool = False
@@ -9,6 +9,7 @@ from typing import Any
9
9
  from mcp.server.fastmcp import FastMCP as FastMCP1x
10
10
 
11
11
  import fastmcp
12
+ from fastmcp import Client
12
13
  from fastmcp.server.server import FastMCP
13
14
 
14
15
 
@@ -71,7 +72,7 @@ class FastMCPInfo:
71
72
  instructions: str | None
72
73
  fastmcp_version: str
73
74
  mcp_version: str
74
- server_version: str
75
+ server_version: str | None
75
76
  tools: list[ToolInfo]
76
77
  prompts: list[PromptInfo]
77
78
  resources: list[ResourceInfo]
@@ -170,7 +171,9 @@ async def inspect_fastmcp_v2(mcp: FastMCP[Any]) -> FastMCPInfo:
170
171
  instructions=mcp.instructions,
171
172
  fastmcp_version=fastmcp.__version__,
172
173
  mcp_version=importlib.metadata.version("mcp"),
173
- server_version=fastmcp.__version__, # v2.x uses FastMCP version
174
+ server_version=(
175
+ mcp.version if hasattr(mcp, "version") else mcp._mcp_server.version
176
+ ),
174
177
  tools=tool_infos,
175
178
  prompts=prompt_infos,
176
179
  resources=resource_infos,
@@ -179,7 +182,7 @@ async def inspect_fastmcp_v2(mcp: FastMCP[Any]) -> FastMCPInfo:
179
182
  )
180
183
 
181
184
 
182
- async def inspect_fastmcp_v1(mcp: Any) -> FastMCPInfo:
185
+ async def inspect_fastmcp_v1(mcp: FastMCP1x) -> FastMCPInfo:
183
186
  """Extract information from a FastMCP v1.x instance using a Client.
184
187
 
185
188
  Args:
@@ -188,7 +191,6 @@ async def inspect_fastmcp_v1(mcp: Any) -> FastMCPInfo:
188
191
  Returns:
189
192
  FastMCPInfo dataclass containing the extracted information
190
193
  """
191
- from fastmcp import Client
192
194
 
193
195
  # Use a client to interact with the FastMCP1x server
194
196
  async with Client(mcp) as client:
@@ -288,11 +290,11 @@ async def inspect_fastmcp_v1(mcp: Any) -> FastMCPInfo:
288
290
  }
289
291
 
290
292
  return FastMCPInfo(
291
- name=mcp.name,
292
- instructions=getattr(mcp, "instructions", None),
293
- fastmcp_version=fastmcp.__version__, # Report current fastmcp version
293
+ name=mcp._mcp_server.name,
294
+ instructions=mcp._mcp_server.instructions,
295
+ fastmcp_version=importlib.metadata.version("mcp"),
294
296
  mcp_version=importlib.metadata.version("mcp"),
295
- server_version="1.0", # FastMCP 1.x version
297
+ server_version=mcp._mcp_server.version,
296
298
  tools=tool_infos,
297
299
  prompts=prompt_infos,
298
300
  resources=resource_infos,
@@ -301,14 +303,7 @@ async def inspect_fastmcp_v1(mcp: Any) -> FastMCPInfo:
301
303
  )
302
304
 
303
305
 
304
- def _is_fastmcp_v1(mcp: Any) -> bool:
305
- """Check if the given instance is a FastMCP v1.x instance."""
306
-
307
- # Check if it's an instance of FastMCP1x and not FastMCP2
308
- return isinstance(mcp, FastMCP1x) and not isinstance(mcp, FastMCP)
309
-
310
-
311
- async def inspect_fastmcp(mcp: FastMCP[Any] | Any) -> FastMCPInfo:
306
+ async def inspect_fastmcp(mcp: FastMCP[Any] | FastMCP1x) -> FastMCPInfo:
312
307
  """Extract information from a FastMCP instance into a dataclass.
313
308
 
314
309
  This function automatically detects whether the instance is FastMCP v1.x or v2.x
@@ -320,7 +315,7 @@ async def inspect_fastmcp(mcp: FastMCP[Any] | Any) -> FastMCPInfo:
320
315
  Returns:
321
316
  FastMCPInfo dataclass containing the extracted information
322
317
  """
323
- if _is_fastmcp_v1(mcp):
318
+ if isinstance(mcp, FastMCP1x):
324
319
  return await inspect_fastmcp_v1(mcp)
325
320
  else:
326
321
  return await inspect_fastmcp_v2(mcp)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.11.1
3
+ Version: 2.11.2
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
@@ -2,17 +2,17 @@ fastmcp/__init__.py,sha256=B_FAqsxbTJmwvJKyIDMOZWpUUdmO806bKo8RR32oZL0,1503
2
2
  fastmcp/exceptions.py,sha256=-krEavxwddQau6T7MESCR4VjKNLfP9KHJrU1p3y72FU,744
3
3
  fastmcp/mcp_config.py,sha256=jf6VyGHli3GcZNg4spdV1L_lPOeNCKTJh-nGIBaMgn4,10324
4
4
  fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- fastmcp/settings.py,sha256=70cxWrYktvHSOHCgj2rKLJ09HU-pHnfs0jCxxv2Rf80,11131
5
+ fastmcp/settings.py,sha256=LxSDlUmWX2SJLZRjX5ih07jAVIHaFZFRK7RCQPPKAGI,11081
6
6
  fastmcp/cli/__init__.py,sha256=Ii284TNoG5lxTP40ETMGhHEq3lQZWxu9m9JuU57kUpQ,87
7
7
  fastmcp/cli/claude.py,sha256=IAlcZ4qZKBBj09jZUMEx7EANZE_IR3vcu7zOBJmMOuU,4567
8
- fastmcp/cli/cli.py,sha256=ovUWG-E3lAfIfKegn2zfYM9oiB0yyPkLViQZd12mYKw,15669
9
- fastmcp/cli/run.py,sha256=OOdau2sNQsgan4NXucY-3LWOWn6cKjmdALfzht2RXQ0,10508
8
+ fastmcp/cli/cli.py,sha256=32OKZ49JKq3INqIlHXnZfFNTxQ2XYE1UkW3x5iTvtlI,15699
9
+ fastmcp/cli/run.py,sha256=12I_JP4NSbmNqfQT2u14wvl4Uq2Rr_RvlK1z6bgAfOQ,12383
10
10
  fastmcp/cli/install/__init__.py,sha256=cDEc0hhuf_xwGpI6ghpqlvlMdBMJUGHq_rs-tgmOJZ8,695
11
- fastmcp/cli/install/claude_code.py,sha256=ayTZtudjNWHE8MIGeJfb_TmJI3F5K_DHD1X3qEjxEWg,7712
12
- fastmcp/cli/install/claude_desktop.py,sha256=y8ha2OKM8IuvQbmGNq842q-m-vs_ts2P9cMxAhbBvs4,6872
13
- fastmcp/cli/install/cursor.py,sha256=q5jXBzpxvoWrgP9pItwNlyl13XpYbtIlZS_dRBkBSdc,6837
14
- fastmcp/cli/install/mcp_json.py,sha256=uxCN8fsIjJStWtL0J7kfQ9haIJU0SYF8CXYT-crl_o0,5923
15
- fastmcp/cli/install/shared.py,sha256=Y0YZei1YemVCkg0ieUgfRse-lqSlIn5Ho8t6pB9nDa4,2683
11
+ fastmcp/cli/install/claude_code.py,sha256=1aSO02cJGGWAVl_iVY_dWpShz9Df5ndrAGA_qEj5rbc,7724
12
+ fastmcp/cli/install/claude_desktop.py,sha256=4ErROs-wxdLWr-bCMvL3r9-UIYMETfAghzHTNzhLx5E,6884
13
+ fastmcp/cli/install/cursor.py,sha256=KkRzIBiqaJhmT1wfl3IzprgTnIiAIioTcveq-oDHELE,6849
14
+ fastmcp/cli/install/mcp_json.py,sha256=RUlg7rQiwBysgTOoJfjvVwgz9MFXT-u7aleBDzK1eVQ,5935
15
+ fastmcp/cli/install/shared.py,sha256=T-0R3-WMlmq5uRHYMEVbdItvm6zThzFET4AlI_foG7s,2695
16
16
  fastmcp/client/__init__.py,sha256=J-RcLU2WcnYnstXWoW01itGtAg7DEjvCsWyqQKQljoo,663
17
17
  fastmcp/client/client.py,sha256=GniETS28L8B-ahzztU2ZLI_XSCcEib-miGzE2ZnG4Xc,34054
18
18
  fastmcp/client/elicitation.py,sha256=Jf9yqna8R7r1hqedXAyh9a2-QNVzbCSKUDZhkFHqHqg,2403
@@ -68,8 +68,8 @@ fastmcp/server/elicitation.py,sha256=jZIHjV4NjhYbT-w8pBArwd0vNzP8OYwzmsnWDdk6Bd0
68
68
  fastmcp/server/http.py,sha256=idZGs4kRm_eLMscMrlEBIBpX21aiuTlvon9Fizmjswo,11648
69
69
  fastmcp/server/low_level.py,sha256=LNmc_nU_wx-fRG8OEHdLPKopZpovcrWlyAxJzKss3TA,1239
70
70
  fastmcp/server/openapi.py,sha256=-7-pKwQ1hT-UV9OnLlWrjbbXXRfZld8YJqa4Duybhtw,42102
71
- fastmcp/server/proxy.py,sha256=4eHW2Vgwe7zvd0g-ozsvYRyIoengyGyhlyMcSPhcaIU,24975
72
- fastmcp/server/server.py,sha256=hmNiwYFnWhERY-WhxAvS9jIvXOx8_g8ylX-Ju91Y4qk,87597
71
+ fastmcp/server/proxy.py,sha256=soKobVa-c-1Vex7IYnz-jAT526Do2Z4Rs1FaT5ruLro,25651
72
+ fastmcp/server/server.py,sha256=PBDHMx2N2Zr6qVeEs7XEcZrCNObnsAoIrPbK9DlArGk,87634
73
73
  fastmcp/server/auth/__init__.py,sha256=ldv13Dsxr2r-VdUV6af6P5qa3wMPQ-MP_yKxsWdlb-4,550
74
74
  fastmcp/server/auth/auth.py,sha256=FMkCcht4BMEqKx-SwvfzVC5l7X2moiIzS_ZevaHBq08,10536
75
75
  fastmcp/server/auth/registry.py,sha256=4ftVbbuyAi-8zBiJL9-dYIKLU_EOpxY-pFdzHMrmjV8,1306
@@ -93,7 +93,7 @@ fastmcp/utilities/cli.py,sha256=TXuSyALFAGJwi7tWEBwBmaGhYZBdF1aG6dLgl3zjM1w,3272
93
93
  fastmcp/utilities/components.py,sha256=wmo1XZBqf_tcOMMN1a-r8d1pT7g--Zmf75f5-vXx5FA,5333
94
94
  fastmcp/utilities/exceptions.py,sha256=7Z9j5IzM5rT27BC1Mcn8tkS-bjqCYqMKwb2MMTaxJYU,1350
95
95
  fastmcp/utilities/http.py,sha256=1ns1ymBS-WSxbZjGP6JYjSO52Wa_ls4j4WbnXiupoa4,245
96
- fastmcp/utilities/inspect.py,sha256=XNA0dfYM5G-FVbJaVJO8loSUUCNypyLA-QjqTOneJyU,10833
96
+ fastmcp/utilities/inspect.py,sha256=VLCrh8oMnIg49uuwVO899rUcHhxszPJ1nU0RZ8q2HX8,10639
97
97
  fastmcp/utilities/json_schema.py,sha256=Nk6qQKtp0-MlMbRQmx8ps8SJ7SW9CpuWhSes1VASFPQ,8141
98
98
  fastmcp/utilities/json_schema_type.py,sha256=fSG-af3OPGgOhuhY_xb0-JsTu5tqi275zXlUw4ItjNo,22287
99
99
  fastmcp/utilities/logging.py,sha256=1y7oNmy8WrR0NsfNVw1LPoKu92OFdmzIO65syOKi_BI,1388
@@ -101,8 +101,8 @@ fastmcp/utilities/mcp_config.py,sha256=zzs4VWHqG0eWEnEUwVve7mef_JFThwfvqBYt7nx3j
101
101
  fastmcp/utilities/openapi.py,sha256=Jcxu0s9VdA8RSkx1iyoTQwvsny4YCusuuJahyy-TvE8,63300
102
102
  fastmcp/utilities/tests.py,sha256=9FVLmGYfUjqfn0pPH33awlTgvg-JCNbnZnraJHNSYTg,6156
103
103
  fastmcp/utilities/types.py,sha256=zrF8Oc_L_BdzGj0pqU5ZalM02BisC0_D-d8kcRGccS0,13984
104
- fastmcp-2.11.1.dist-info/METADATA,sha256=7kstQeYl88_tx9oEhjN98bGmGWskG478FOFlvfCuMiA,17839
105
- fastmcp-2.11.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
106
- fastmcp-2.11.1.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
107
- fastmcp-2.11.1.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
108
- fastmcp-2.11.1.dist-info/RECORD,,
104
+ fastmcp-2.11.2.dist-info/METADATA,sha256=6OE28R9_gx-82MA3st0SR6dCxsfoH4oftu0jhSjbL10,17839
105
+ fastmcp-2.11.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
106
+ fastmcp-2.11.2.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
107
+ fastmcp-2.11.2.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
108
+ fastmcp-2.11.2.dist-info/RECORD,,