fastmcp 2.10.0__py3-none-any.whl → 2.10.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.
@@ -53,6 +53,11 @@ def create_elicitation_callback(
53
53
  if not isinstance(result, ElicitResult):
54
54
  result = ElicitResult(action="accept", content=result)
55
55
  content = to_jsonable_python(result.content)
56
+ if not isinstance(content, dict | None):
57
+ raise ValueError(
58
+ "Elicitation responses must be serializable as a JSON object (dict). Received: "
59
+ f"{result.content!r}"
60
+ )
56
61
  return MCPElicitResult(**result.model_dump() | {"content": content})
57
62
  except Exception as e:
58
63
  return mcp.types.ErrorData(
@@ -773,8 +773,6 @@ class MCPConfigTransport(ClientTransport):
773
773
  """
774
774
 
775
775
  def __init__(self, config: MCPConfig | dict):
776
- from fastmcp.client.client import Client
777
-
778
776
  if isinstance(config, dict):
779
777
  config = MCPConfig.from_dict(config)
780
778
  self.config = config
@@ -792,9 +790,9 @@ class MCPConfigTransport(ClientTransport):
792
790
  composite_server = FastMCP()
793
791
 
794
792
  for name, server in self.config.mcpServers.items():
795
- server_client = Client(transport=server.to_transport())
796
793
  composite_server.mount(
797
- prefix=name, server=FastMCP.as_proxy(server_client)
794
+ prefix=name,
795
+ server=FastMCP.as_proxy(backend=server.to_transport()),
798
796
  )
799
797
 
800
798
  self.transport = FastMCPTransport(mcp=composite_server)
@@ -399,12 +399,21 @@ class BearerAuthProvider(OAuthProvider):
399
399
  return None
400
400
 
401
401
  def _extract_scopes(self, claims: dict[str, Any]) -> list[str]:
402
- """Extract scopes from JWT claims."""
403
- scope_claim = claims.get("scope", "")
404
- if isinstance(scope_claim, str):
405
- return scope_claim.split()
406
- elif isinstance(scope_claim, list):
407
- return scope_claim
402
+ """
403
+ Extract scopes from JWT claims. Supports both 'scope' and 'scp'
404
+ claims.
405
+
406
+ Checks the `scope` claim first (standard OAuth2 claim), then the `scp`
407
+ claim (used by some Identity Providers).
408
+ """
409
+
410
+ for claim in ["scope", "scp"]:
411
+ if claim in claims:
412
+ if isinstance(claims[claim], str):
413
+ return claims[claim].split()
414
+ elif isinstance(claims[claim], list):
415
+ return claims[claim]
416
+
408
417
  return []
409
418
 
410
419
  async def verify_token(self, token: str) -> AccessToken | None:
fastmcp/server/proxy.py CHANGED
@@ -1,9 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pathlib import Path
3
4
  from typing import TYPE_CHECKING, Any, cast
4
5
  from urllib.parse import quote
5
6
 
6
7
  import mcp.types
8
+ from mcp.client.session import ClientSession
9
+ from mcp.shared.context import LifespanContextT, RequestContext
7
10
  from mcp.shared.exceptions import McpError
8
11
  from mcp.types import (
9
12
  METHOD_NOT_FOUND,
@@ -14,6 +17,10 @@ from mcp.types import (
14
17
  from pydantic.networks import AnyUrl
15
18
 
16
19
  from fastmcp.client import Client
20
+ from fastmcp.client.elicitation import ElicitResult
21
+ from fastmcp.client.logging import LogMessage
22
+ from fastmcp.client.roots import RootsList
23
+ from fastmcp.client.transports import ClientTransportT
17
24
  from fastmcp.exceptions import NotFoundError, ResourceError, ToolError
18
25
  from fastmcp.prompts import Prompt, PromptMessage
19
26
  from fastmcp.prompts.prompt import PromptArgument
@@ -21,10 +28,12 @@ from fastmcp.prompts.prompt_manager import PromptManager
21
28
  from fastmcp.resources import Resource, ResourceTemplate
22
29
  from fastmcp.resources.resource_manager import ResourceManager
23
30
  from fastmcp.server.context import Context
31
+ from fastmcp.server.dependencies import get_context
24
32
  from fastmcp.server.server import FastMCP
25
33
  from fastmcp.tools.tool import Tool, ToolResult
26
34
  from fastmcp.tools.tool_manager import ToolManager
27
35
  from fastmcp.utilities.logging import get_logger
36
+ from fastmcp.utilities.mcp_config import MCPConfig
28
37
 
29
38
  if TYPE_CHECKING:
30
39
  from fastmcp.server import Context
@@ -406,3 +415,110 @@ class FastMCPProxy(FastMCP):
406
415
  self._tool_manager = ProxyToolManager(client=self.client)
407
416
  self._resource_manager = ProxyResourceManager(client=self.client)
408
417
  self._prompt_manager = ProxyPromptManager(client=self.client)
418
+
419
+
420
+ async def default_proxy_roots_handler(
421
+ context: RequestContext[ClientSession, LifespanContextT],
422
+ ) -> RootsList:
423
+ """
424
+ A handler that forwards the list roots request from the remote server to the proxy's connected clients and relays the response back to the remote server.
425
+ """
426
+ ctx = get_context()
427
+ return await ctx.list_roots()
428
+
429
+
430
+ class ProxyClient(Client[ClientTransportT]):
431
+ """
432
+ A proxy client that forwards advanced interactions between a remote MCP server and the proxy's connected clients.
433
+ Supports forwarding roots, sampling, elicitation, logging, and progress.
434
+ """
435
+
436
+ def __init__(
437
+ self,
438
+ transport: (
439
+ ClientTransportT
440
+ | FastMCP
441
+ | AnyUrl
442
+ | Path
443
+ | MCPConfig
444
+ | dict[str, Any]
445
+ | str
446
+ ),
447
+ **kwargs,
448
+ ):
449
+ if "roots" not in kwargs:
450
+ kwargs["roots"] = default_proxy_roots_handler
451
+ if "sampling_handler" not in kwargs:
452
+ kwargs["sampling_handler"] = ProxyClient.default_sampling_handler
453
+ if "elicitation_handler" not in kwargs:
454
+ kwargs["elicitation_handler"] = ProxyClient.default_elicitation_handler
455
+ if "log_handler" not in kwargs:
456
+ kwargs["log_handler"] = ProxyClient.default_log_handler
457
+ if "progress_handler" not in kwargs:
458
+ kwargs["progress_handler"] = ProxyClient.default_progress_handler
459
+ super().__init__(transport, **kwargs)
460
+
461
+ @classmethod
462
+ async def default_sampling_handler(
463
+ cls,
464
+ messages: list[mcp.types.SamplingMessage],
465
+ params: mcp.types.CreateMessageRequestParams,
466
+ context: RequestContext[ClientSession, LifespanContextT],
467
+ ) -> mcp.types.CreateMessageResult:
468
+ """
469
+ A handler that forwards the sampling request from the remote server to the proxy's connected clients and relays the response back to the remote server.
470
+ """
471
+ ctx = get_context()
472
+ content = await ctx.sample(
473
+ [msg for msg in messages],
474
+ system_prompt=params.systemPrompt,
475
+ temperature=params.temperature,
476
+ max_tokens=params.maxTokens,
477
+ model_preferences=params.modelPreferences,
478
+ )
479
+ if isinstance(content, mcp.types.ResourceLink | mcp.types.EmbeddedResource):
480
+ raise RuntimeError("Content is not supported")
481
+ return mcp.types.CreateMessageResult(
482
+ role="assistant",
483
+ model="fastmcp-client",
484
+ content=content,
485
+ )
486
+
487
+ @classmethod
488
+ async def default_elicitation_handler(
489
+ cls,
490
+ message: str,
491
+ response_type: type,
492
+ params: mcp.types.ElicitRequestParams,
493
+ context: RequestContext[ClientSession, LifespanContextT],
494
+ ) -> ElicitResult:
495
+ """
496
+ A handler that forwards the elicitation request from the remote server to the proxy's connected clients and relays the response back to the remote server.
497
+ """
498
+ ctx = get_context()
499
+ result = await ctx.elicit(message, response_type)
500
+ if result.action == "accept":
501
+ return result.data
502
+ else:
503
+ return ElicitResult(action=result.action)
504
+
505
+ @classmethod
506
+ async def default_log_handler(cls, message: LogMessage) -> None:
507
+ """
508
+ A handler that forwards the log notification from the remote server to the proxy's connected clients.
509
+ """
510
+ ctx = get_context()
511
+ await ctx.log(message.data, level=message.level, logger_name=message.logger)
512
+
513
+ @classmethod
514
+ async def default_progress_handler(
515
+ cls,
516
+ progress: float,
517
+ total: float | None,
518
+ message: str | None,
519
+ ) -> None:
520
+ """
521
+ A handler that forwards the progress notification from the remote server to the proxy's connected clients.
522
+ """
523
+ ctx = get_context()
524
+ await ctx.report_progress(progress, total, message)
fastmcp/server/server.py CHANGED
@@ -60,7 +60,7 @@ from fastmcp.settings import Settings
60
60
  from fastmcp.tools import ToolManager
61
61
  from fastmcp.tools.tool import FunctionTool, Tool, ToolResult
62
62
  from fastmcp.utilities.cache import TimedCache
63
- from fastmcp.utilities.cli import print_server_banner
63
+ from fastmcp.utilities.cli import log_server_banner
64
64
  from fastmcp.utilities.components import FastMCPComponent
65
65
  from fastmcp.utilities.logging import get_logger
66
66
  from fastmcp.utilities.mcp_config import MCPConfig
@@ -1343,7 +1343,7 @@ class FastMCP(Generic[LifespanResultT]):
1343
1343
 
1344
1344
  # Display server banner
1345
1345
  if show_banner:
1346
- print_server_banner(
1346
+ log_server_banner(
1347
1347
  server=self,
1348
1348
  transport="stdio",
1349
1349
  )
@@ -1368,6 +1368,7 @@ class FastMCP(Generic[LifespanResultT]):
1368
1368
  path: str | None = None,
1369
1369
  uvicorn_config: dict[str, Any] | None = None,
1370
1370
  middleware: list[ASGIMiddleware] | None = None,
1371
+ stateless_http: bool | None = None,
1371
1372
  ) -> None:
1372
1373
  """Run the server using HTTP transport.
1373
1374
 
@@ -1378,6 +1379,8 @@ class FastMCP(Generic[LifespanResultT]):
1378
1379
  log_level: Log level for the server (defaults to settings.log_level)
1379
1380
  path: Path for the endpoint (defaults to settings.streamable_http_path or settings.sse_path)
1380
1381
  uvicorn_config: Additional configuration for the Uvicorn server
1382
+ middleware: A list of middleware to apply to the app
1383
+ stateless_http: Whether to use stateless HTTP (defaults to settings.stateless_http)
1381
1384
  """
1382
1385
 
1383
1386
  host = host or self._deprecated_settings.host
@@ -1386,7 +1389,12 @@ class FastMCP(Generic[LifespanResultT]):
1386
1389
  log_level or self._deprecated_settings.log_level
1387
1390
  ).lower()
1388
1391
 
1389
- app = self.http_app(path=path, transport=transport, middleware=middleware)
1392
+ app = self.http_app(
1393
+ path=path,
1394
+ transport=transport,
1395
+ middleware=middleware,
1396
+ stateless_http=stateless_http,
1397
+ )
1390
1398
 
1391
1399
  # Get the path for the server URL
1392
1400
  server_path = (
@@ -1397,14 +1405,13 @@ class FastMCP(Generic[LifespanResultT]):
1397
1405
 
1398
1406
  # Display server banner
1399
1407
  if show_banner:
1400
- print_server_banner(
1408
+ log_server_banner(
1401
1409
  server=self,
1402
1410
  transport=transport,
1403
1411
  host=host,
1404
1412
  port=port,
1405
1413
  path=server_path,
1406
1414
  )
1407
-
1408
1415
  _uvicorn_config_from_user = uvicorn_config or {}
1409
1416
 
1410
1417
  config_kwargs: dict[str, Any] = {
@@ -1636,9 +1643,8 @@ class FastMCP(Generic[LifespanResultT]):
1636
1643
  resource_separator: Deprecated. Separator character for resource URIs.
1637
1644
  prompt_separator: Deprecated. Separator character for prompt names.
1638
1645
  """
1639
- from fastmcp import Client
1640
1646
  from fastmcp.client.transports import FastMCPTransport
1641
- from fastmcp.server.proxy import FastMCPProxy
1647
+ from fastmcp.server.proxy import FastMCPProxy, ProxyClient
1642
1648
 
1643
1649
  # Deprecated since 2.9.0
1644
1650
  # Prior to 2.9.0, the first positional argument was the prefix and the
@@ -1690,7 +1696,7 @@ class FastMCP(Generic[LifespanResultT]):
1690
1696
  as_proxy = server._has_lifespan
1691
1697
 
1692
1698
  if as_proxy and not isinstance(server, FastMCPProxy):
1693
- server = FastMCPProxy(Client(transport=FastMCPTransport(server)))
1699
+ server = FastMCPProxy(ProxyClient(transport=FastMCPTransport(server)))
1694
1700
 
1695
1701
  # Delegate mounting to all three managers
1696
1702
  mounted_server = MountedServer(
@@ -1901,14 +1907,16 @@ class FastMCP(Generic[LifespanResultT]):
1901
1907
  @classmethod
1902
1908
  def as_proxy(
1903
1909
  cls,
1904
- backend: Client[ClientTransportT]
1905
- | ClientTransport
1906
- | FastMCP[Any]
1907
- | AnyUrl
1908
- | Path
1909
- | MCPConfig
1910
- | dict[str, Any]
1911
- | str,
1910
+ backend: (
1911
+ Client[ClientTransportT]
1912
+ | ClientTransport
1913
+ | FastMCP[Any]
1914
+ | AnyUrl
1915
+ | Path
1916
+ | MCPConfig
1917
+ | dict[str, Any]
1918
+ | str
1919
+ ),
1912
1920
  **settings: Any,
1913
1921
  ) -> FastMCPProxy:
1914
1922
  """Create a FastMCP proxy server for the given backend.
@@ -1919,12 +1927,12 @@ class FastMCP(Generic[LifespanResultT]):
1919
1927
  `fastmcp.client.Client` constructor.
1920
1928
  """
1921
1929
  from fastmcp.client.client import Client
1922
- from fastmcp.server.proxy import FastMCPProxy
1930
+ from fastmcp.server.proxy import FastMCPProxy, ProxyClient
1923
1931
 
1924
1932
  if isinstance(backend, Client):
1925
1933
  client = backend
1926
1934
  else:
1927
- client = Client(backend)
1935
+ client = ProxyClient(backend)
1928
1936
 
1929
1937
  return FastMCPProxy(client=client, **settings)
1930
1938
 
fastmcp/settings.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations as _annotations
2
2
 
3
3
  import inspect
4
+ import warnings
4
5
  from pathlib import Path
5
6
  from typing import Annotated, Any, Literal
6
7
 
@@ -258,4 +259,21 @@ class Settings(BaseSettings):
258
259
  ] = None
259
260
 
260
261
 
261
- settings = Settings()
262
+ def __getattr__(name: str):
263
+ """
264
+ Used to deprecate the module-level Image class; can be removed once it is no longer imported to root.
265
+ """
266
+ if name == "settings":
267
+ import fastmcp
268
+
269
+ settings = fastmcp.settings
270
+ # Deprecated in 2.10.2
271
+ if settings.deprecation_warnings:
272
+ warnings.warn(
273
+ "`from fastmcp.settings import settings` is deprecated. use `fasmtpc.settings` instead.",
274
+ DeprecationWarning,
275
+ stacklevel=2,
276
+ )
277
+ return settings
278
+
279
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
fastmcp/utilities/cli.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from importlib.metadata import version
4
- from typing import TYPE_CHECKING, Any
4
+ from typing import TYPE_CHECKING, Any, Literal
5
5
 
6
6
  from rich.console import Console, Group
7
7
  from rich.panel import Panel
@@ -11,8 +11,6 @@ from rich.text import Text
11
11
  import fastmcp
12
12
 
13
13
  if TYPE_CHECKING:
14
- from typing import Literal
15
-
16
14
  from fastmcp import FastMCP
17
15
 
18
16
  LOGO_ASCII = r"""
@@ -25,7 +23,7 @@ _ __ ___ /_/ \__,_/____/\__/_/ /_/\____/_/ /_____(_)____/
25
23
  """.lstrip("\n")
26
24
 
27
25
 
28
- def print_server_banner(
26
+ def log_server_banner(
29
27
  server: FastMCP[Any],
30
28
  transport: Literal["stdio", "http", "sse", "streamable-http"],
31
29
  *,
@@ -33,7 +31,7 @@ def print_server_banner(
33
31
  port: int | None = None,
34
32
  path: str | None = None,
35
33
  ) -> None:
36
- """Print a formatted banner with server information and logo.
34
+ """Creates and logs a formatted banner with server information and logo.
37
35
 
38
36
  Args:
39
37
  transport: The transport protocol being used
@@ -43,15 +41,14 @@ def print_server_banner(
43
41
  path: Server path (for HTTP transports)
44
42
  """
45
43
 
46
- console = Console()
47
-
48
44
  # Create the logo text
49
45
  logo_text = Text(LOGO_ASCII, style="bold green")
50
46
 
51
47
  # Create the information table
52
48
  info_table = Table.grid(padding=(0, 1))
53
- info_table.add_column(style="bold cyan", justify="left")
54
- info_table.add_column(style="white", justify="left")
49
+ info_table.add_column(style="bold", justify="center") # Emoji column
50
+ info_table.add_column(style="bold cyan", justify="left") # Label column
51
+ info_table.add_column(style="white", justify="left") # Value column
55
52
 
56
53
  match transport:
57
54
  case "http" | "streamable-http":
@@ -61,7 +58,8 @@ def print_server_banner(
61
58
  case "stdio":
62
59
  display_transport = "STDIO"
63
60
 
64
- info_table.add_row("Transport:", display_transport)
61
+ info_table.add_row("🖥️", "Server name:", server.name)
62
+ info_table.add_row("📦", "Transport:", display_transport)
65
63
 
66
64
  # Show connection info based on transport
67
65
  if transport in ("http", "streamable-http", "sse"):
@@ -69,38 +67,36 @@ def print_server_banner(
69
67
  server_url = f"http://{host}:{port}"
70
68
  if path:
71
69
  server_url += f"/{path.lstrip('/')}"
72
- info_table.add_row("Server URL:", server_url)
70
+ info_table.add_row("🔗", "Server URL:", server_url)
73
71
 
74
72
  # Add documentation link
75
- info_table.add_row()
76
- info_table.add_row("Docs:", "https://gofastmcp.com")
77
- info_table.add_row("Hosting:", "https://fastmcp.cloud")
73
+ info_table.add_row("", "", "")
74
+ info_table.add_row("📚", "Docs:", "https://gofastmcp.com")
75
+ info_table.add_row("🚀", "Deploy:", "https://fastmcp.cloud")
78
76
 
79
77
  # Add version information with explicit style overrides
80
- info_table.add_row()
78
+ info_table.add_row("", "", "")
81
79
  info_table.add_row(
80
+ "🏎️",
82
81
  "FastMCP version:",
83
82
  Text(fastmcp.__version__, style="dim white", no_wrap=True),
84
83
  )
85
84
  info_table.add_row(
85
+ "🤝",
86
86
  "MCP version:",
87
87
  Text(version("mcp"), style="dim white", no_wrap=True),
88
88
  )
89
89
  # Create panel with logo and information using Group
90
90
  panel_content = Group(logo_text, "", info_table)
91
91
 
92
- # Use server name in title if provided
93
- title = "FastMCP 2.0"
94
- if server.name != "FastMCP":
95
- title += f" - {server.name}"
96
-
97
92
  panel = Panel(
98
93
  panel_content,
99
- title=title,
94
+ title="FastMCP 2.0",
100
95
  title_align="left",
101
96
  border_style="dim",
102
- padding=(2, 10),
97
+ padding=(2, 5),
103
98
  expand=False,
104
99
  )
105
100
 
106
- console.print(panel)
101
+ console = Console(stderr=True)
102
+ console.print(Group("\n", panel, "\n"))
@@ -50,3 +50,6 @@ def configure_logging(
50
50
  logger.removeHandler(hdlr)
51
51
 
52
52
  logger.addHandler(handler)
53
+
54
+ # Don't propagate to the root logger
55
+ logger.propagate = False
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import datetime
3
4
  import re
4
5
  from typing import TYPE_CHECKING, Annotated, Any, Literal
5
6
  from urllib.parse import urlparse
@@ -65,6 +66,7 @@ class RemoteMCPServer(FastMCPBaseModel):
65
66
  description='Either a string representing a Bearer token, the literal "oauth" to use OAuth authentication, or an httpx.Auth instance for custom authentication.',
66
67
  ),
67
68
  ] = None
69
+ sse_read_timeout: datetime.timedelta | int | float | None = None
68
70
 
69
71
  model_config = ConfigDict(arbitrary_types_allowed=True)
70
72
 
@@ -77,11 +79,19 @@ class RemoteMCPServer(FastMCPBaseModel):
77
79
  transport = self.transport
78
80
 
79
81
  if transport == "sse":
80
- return SSETransport(self.url, headers=self.headers, auth=self.auth)
82
+ return SSETransport(
83
+ self.url,
84
+ headers=self.headers,
85
+ auth=self.auth,
86
+ sse_read_timeout=self.sse_read_timeout,
87
+ )
81
88
  else:
82
89
  # Both "http" and "streamable-http" map to StreamableHttpTransport
83
90
  return StreamableHttpTransport(
84
- self.url, headers=self.headers, auth=self.auth
91
+ self.url,
92
+ headers=self.headers,
93
+ auth=self.auth,
94
+ sse_read_timeout=self.sse_read_timeout,
85
95
  )
86
96
 
87
97
 
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import copy
4
+ import logging
4
5
  import multiprocessing
5
6
  import socket
6
7
  import time
@@ -129,3 +130,15 @@ def run_server_in_process(
129
130
  proc.join(timeout=2)
130
131
  if proc.is_alive():
131
132
  raise RuntimeError("Server process failed to terminate even after kill")
133
+
134
+
135
+ @contextmanager
136
+ def caplog_for_fastmcp(caplog):
137
+ """Context manager to capture logs from FastMCP loggers even when propagation is disabled."""
138
+ caplog.clear()
139
+ logger = logging.getLogger("FastMCP")
140
+ logger.addHandler(caplog.handler)
141
+ try:
142
+ yield
143
+ finally:
144
+ logger.removeHandler(caplog.handler)
@@ -3,6 +3,7 @@
3
3
  import base64
4
4
  import inspect
5
5
  import mimetypes
6
+ import os
6
7
  from collections.abc import Callable
7
8
  from functools import lru_cache
8
9
  from pathlib import Path
@@ -101,7 +102,7 @@ class Image:
101
102
  if path is not None and data is not None:
102
103
  raise ValueError("Only one of path or data can be provided")
103
104
 
104
- self.path = Path(path) if path else None
105
+ self.path = Path(os.path.expandvars(str(path))).expanduser() if path else None
105
106
  self.data = data
106
107
  self._format = format
107
108
  self._mime_type = self._get_mime_type()
@@ -160,7 +161,7 @@ class Audio:
160
161
  if path is not None and data is not None:
161
162
  raise ValueError("Only one of path or data can be provided")
162
163
 
163
- self.path = Path(path) if path else None
164
+ self.path = Path(os.path.expandvars(str(path))).expanduser() if path else None
164
165
  self.data = data
165
166
  self._format = format
166
167
  self._mime_type = self._get_mime_type()
@@ -219,7 +220,7 @@ class File:
219
220
  if path is not None and data is not None:
220
221
  raise ValueError("Only one of path or data can be provided")
221
222
 
222
- self.path = Path(path) if path else None
223
+ self.path = Path(os.path.expandvars(str(path))).expanduser() if path else None
223
224
  self.data = data
224
225
  self._format = format
225
226
  self._mime_type = self._get_mime_type()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.10.0
3
+ Version: 2.10.2
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
@@ -1,21 +1,21 @@
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=yC3f0ITEWYeit37-wnF0G12klTw_hjrWjCr6oZtUT8o,8329
4
+ fastmcp/settings.py,sha256=Ta0TKA75xda9sNkIOpPVIEEk4W9jf_2gwcmO26uDQpg,8946
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=uJqUvFuyN7uslaCe5FHKp-EKdIRY5mRr-81f0c1r4PA,16257
8
8
  fastmcp/cli/run.py,sha256=JKBcy935Jy59WInwEaKt1gZkRDIESB7CRw_Oj987PVw,6301
9
9
  fastmcp/client/__init__.py,sha256=kd2hhSuD8rZuF87c9zlPJP_icJ-Rx3exyNoK0EzfOtE,617
10
10
  fastmcp/client/client.py,sha256=8Sx7NxnnF5IMv9E-J0MXjTI_TfhlM3j0mD1Rh-LXQJI,29213
11
- fastmcp/client/elicitation.py,sha256=8eWZpXbRFctZGgulyJ_GGI4GYXqAFf5Zp47vYTRD4fc,2155
11
+ fastmcp/client/elicitation.py,sha256=Jf9yqna8R7r1hqedXAyh9a2-QNVzbCSKUDZhkFHqHqg,2403
12
12
  fastmcp/client/logging.py,sha256=7GJ-BLFW16_IOJPlGTNEWPP0P-yqqRpmsLdiKrlVsw8,757
13
13
  fastmcp/client/messages.py,sha256=NIPjt-5js_DkI5BD4OVdTf6pz-nGjc2dtbgt-vAY234,4329
14
14
  fastmcp/client/oauth_callback.py,sha256=ODAnVX-ettL82RuI5KpfkKf8iDtYMDue3Tnab5sjQtM,10071
15
15
  fastmcp/client/progress.py,sha256=WjLLDbUKMsx8DK-fqO7AGsXb83ak-6BMrLvzzznGmcI,1043
16
16
  fastmcp/client/roots.py,sha256=IxI_bHwHTmg6c2H-s1av1ZgrRnNDieHtYwdGFbzXT5c,2471
17
17
  fastmcp/client/sampling.py,sha256=Q8PzYCERa1W3xGGI9I9QOhhDM-M4i3P5lESb0cp2iI8,1595
18
- fastmcp/client/transports.py,sha256=liHLuOcgKotdlhTJBOiSn73WX0v7mnFa853hJBdu-2E,33898
18
+ fastmcp/client/transports.py,sha256=DNzvZGbe5q_rvk1C0bifejk7Gh561h-QTGGlyqwiSxM,33813
19
19
  fastmcp/client/auth/__init__.py,sha256=4DNsfp4iaQeBcpds0JDdMn6Mmfud44stWLsret0sVKY,91
20
20
  fastmcp/client/auth/bearer.py,sha256=MFEFqcH6u_V86msYiOsEFKN5ks1V9BnBNiPsPLHUTqo,399
21
21
  fastmcp/client/auth/oauth.py,sha256=pSyuI0FlRK1qkBA6mvq-bxKzl2B-pMCvPPzIByTJBEo,11745
@@ -48,12 +48,12 @@ fastmcp/server/elicitation.py,sha256=jZIHjV4NjhYbT-w8pBArwd0vNzP8OYwzmsnWDdk6Bd0
48
48
  fastmcp/server/http.py,sha256=d0Jij4HVTaAohluRXArSniXLb1HcHP3ytbe-mMHg6nE,11678
49
49
  fastmcp/server/low_level.py,sha256=LNmc_nU_wx-fRG8OEHdLPKopZpovcrWlyAxJzKss3TA,1239
50
50
  fastmcp/server/openapi.py,sha256=ALIbl0r2T1cvbSeFwz6HpIzut2akdngAtKDdWGyIWHs,36221
51
- fastmcp/server/proxy.py,sha256=Ofx7P5rU7mKVPDjvvIKjQS7_C1w4-1UiKc78x7AdjN8,15211
52
- fastmcp/server/server.py,sha256=gfC3xvX6tnT57uRClvY2L0q1DndKoOlJZJRRQ372Cis,80812
51
+ fastmcp/server/proxy.py,sha256=NNyxtbOCJeKM-zRoaPCkVk26c7LHViHXNFfy95aXnAM,19591
52
+ fastmcp/server/server.py,sha256=KM1-dfwIoRiTYSLI5IvZ1Zy1imAkS3ILZ1QeRCgLNvY,81153
53
53
  fastmcp/server/auth/__init__.py,sha256=doHCLwOIElvH1NrTdpeP9JKfnNf3MDYPSpQfdsQ-uI0,84
54
54
  fastmcp/server/auth/auth.py,sha256=A00OKxglEMrGMMIiMbc6UmpGc2VoWDkEVU5g2pIzDIg,2119
55
55
  fastmcp/server/auth/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- fastmcp/server/auth/providers/bearer.py,sha256=iRExt5hRKmrwr7MjsUN-UdQDe-iCSjH7sNCURaK7HBs,16456
56
+ fastmcp/server/auth/providers/bearer.py,sha256=rjwuKFgCm4fLsAQzUaIaE8OD6bml3sBaO7NYq3Wgs24,16718
57
57
  fastmcp/server/auth/providers/bearer_env.py,sha256=NYPCW363Q8u8BdiPPz1FdB3_kwmbCaWT5yKdAO-ZgwA,2081
58
58
  fastmcp/server/auth/providers/in_memory.py,sha256=Sb3GOtLL2bWbm8z-T8cEsMz1qcQUSHpPEEgYRvTOQi4,14251
59
59
  fastmcp/server/middleware/__init__.py,sha256=m1QJFQ7JW_2JHpJp1FurBNYaxbBUa_HyDn1Bw9mtyvc,367
@@ -68,20 +68,20 @@ fastmcp/tools/tool_manager.py,sha256=Sm_tOO-SY0m7tEN_dofP-tvBnC2HroPRKLU6sp8gnUw
68
68
  fastmcp/tools/tool_transform.py,sha256=YY2DZdJZ6fEGtgEP1Djrc49F8rAEyx6fgRGEyIGaxPE,32601
69
69
  fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
70
70
  fastmcp/utilities/cache.py,sha256=aV3oZ-ZhMgLSM9iAotlUlEy5jFvGXrVo0Y5Bj4PBtqY,707
71
- fastmcp/utilities/cli.py,sha256=xLB7GSLpO7m7PZJCSFRvYg7aoe5FcqG1AxOizKTU-dY,3150
71
+ fastmcp/utilities/cli.py,sha256=n3HA8IXg7hKaizuM3SRCW65UMXlqjUDf5USRSuscTdY,3287
72
72
  fastmcp/utilities/components.py,sha256=WIxNVZ7YxCLpdIm_pbTYeP0lAxikvgptVYhIL0LVmCc,2535
73
73
  fastmcp/utilities/exceptions.py,sha256=7Z9j5IzM5rT27BC1Mcn8tkS-bjqCYqMKwb2MMTaxJYU,1350
74
74
  fastmcp/utilities/http.py,sha256=1ns1ymBS-WSxbZjGP6JYjSO52Wa_ls4j4WbnXiupoa4,245
75
75
  fastmcp/utilities/inspect.py,sha256=XNA0dfYM5G-FVbJaVJO8loSUUCNypyLA-QjqTOneJyU,10833
76
76
  fastmcp/utilities/json_schema.py,sha256=K0QH5UazBD_tweBi-TguWYjUu5Lgp9wcM-wT42Fet5w,5022
77
77
  fastmcp/utilities/json_schema_type.py,sha256=Sml03nJGOnUfxCGrHWRMwZMultV0X5JThMepUnHIUiA,22377
78
- fastmcp/utilities/logging.py,sha256=B1WNO-ZWFjd9wiFSh13YtW1hAKaNmbpscDZleIAhr-g,1317
79
- fastmcp/utilities/mcp_config.py,sha256=ryjAfJUPquDSoKdSymPH4M2B0WvuM3pWUGI3cOgAX80,2782
78
+ fastmcp/utilities/logging.py,sha256=1y7oNmy8WrR0NsfNVw1LPoKu92OFdmzIO65syOKi_BI,1388
79
+ fastmcp/utilities/mcp_config.py,sha256=uGmkepcNpS_7HEuaK3465OcwcmebHGyvUddOjLfw1jY,3075
80
80
  fastmcp/utilities/openapi.py,sha256=neeaXwwn1OWdUp0Gawhx4SJHLfV78gXU5OMMTFGeD24,45235
81
- fastmcp/utilities/tests.py,sha256=O9hRSjnyaYQqu1RJ-CFBw1cIjezlwSQtS-Ea_iqO4sY,3899
82
- fastmcp/utilities/types.py,sha256=SWtzKpIr9TMeOE6TyPgqSi-SBXpWBPUnA5QPiP4nDzw,10512
83
- fastmcp-2.10.0.dist-info/METADATA,sha256=KFUQ_3rSB_OfFyRM5neIk1NQVFtgSeIwsm7m67hfG-0,17796
84
- fastmcp-2.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
85
- fastmcp-2.10.0.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
86
- fastmcp-2.10.0.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
87
- fastmcp-2.10.0.dist-info/RECORD,,
81
+ fastmcp/utilities/tests.py,sha256=kZH8HQAC702a5vNJb4K0tO1ll9CZADWQ_P-5ERWSvSA,4242
82
+ fastmcp/utilities/types.py,sha256=c6HPvHCpkq8EXh0hWjaUlj9aCZklmxzAQHCXZy7llNo,10636
83
+ fastmcp-2.10.2.dist-info/METADATA,sha256=zvfV88PXJiHci0YJfQIrgPsaOvDaVsMVHUIHB6mtgCU,17796
84
+ fastmcp-2.10.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
85
+ fastmcp-2.10.2.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
86
+ fastmcp-2.10.2.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
87
+ fastmcp-2.10.2.dist-info/RECORD,,