fastmcp 2.14.4__py3-none-any.whl → 3.0.0b1__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.
Files changed (175) hide show
  1. fastmcp/_vendor/__init__.py +1 -0
  2. fastmcp/_vendor/docket_di/README.md +7 -0
  3. fastmcp/_vendor/docket_di/__init__.py +163 -0
  4. fastmcp/cli/cli.py +112 -28
  5. fastmcp/cli/install/claude_code.py +1 -5
  6. fastmcp/cli/install/claude_desktop.py +1 -5
  7. fastmcp/cli/install/cursor.py +1 -5
  8. fastmcp/cli/install/gemini_cli.py +1 -5
  9. fastmcp/cli/install/mcp_json.py +1 -6
  10. fastmcp/cli/run.py +146 -5
  11. fastmcp/client/__init__.py +7 -9
  12. fastmcp/client/auth/oauth.py +18 -17
  13. fastmcp/client/client.py +100 -870
  14. fastmcp/client/elicitation.py +1 -1
  15. fastmcp/client/mixins/__init__.py +13 -0
  16. fastmcp/client/mixins/prompts.py +295 -0
  17. fastmcp/client/mixins/resources.py +325 -0
  18. fastmcp/client/mixins/task_management.py +157 -0
  19. fastmcp/client/mixins/tools.py +397 -0
  20. fastmcp/client/sampling/handlers/anthropic.py +2 -2
  21. fastmcp/client/sampling/handlers/openai.py +1 -1
  22. fastmcp/client/tasks.py +3 -3
  23. fastmcp/client/telemetry.py +47 -0
  24. fastmcp/client/transports/__init__.py +38 -0
  25. fastmcp/client/transports/base.py +82 -0
  26. fastmcp/client/transports/config.py +170 -0
  27. fastmcp/client/transports/http.py +145 -0
  28. fastmcp/client/transports/inference.py +154 -0
  29. fastmcp/client/transports/memory.py +90 -0
  30. fastmcp/client/transports/sse.py +89 -0
  31. fastmcp/client/transports/stdio.py +543 -0
  32. fastmcp/contrib/component_manager/README.md +4 -10
  33. fastmcp/contrib/component_manager/__init__.py +1 -2
  34. fastmcp/contrib/component_manager/component_manager.py +95 -160
  35. fastmcp/contrib/component_manager/example.py +1 -1
  36. fastmcp/contrib/mcp_mixin/example.py +4 -4
  37. fastmcp/contrib/mcp_mixin/mcp_mixin.py +11 -4
  38. fastmcp/decorators.py +41 -0
  39. fastmcp/dependencies.py +12 -1
  40. fastmcp/exceptions.py +4 -0
  41. fastmcp/experimental/server/openapi/__init__.py +18 -15
  42. fastmcp/mcp_config.py +13 -4
  43. fastmcp/prompts/__init__.py +6 -3
  44. fastmcp/prompts/function_prompt.py +465 -0
  45. fastmcp/prompts/prompt.py +321 -271
  46. fastmcp/resources/__init__.py +5 -3
  47. fastmcp/resources/function_resource.py +335 -0
  48. fastmcp/resources/resource.py +325 -115
  49. fastmcp/resources/template.py +215 -43
  50. fastmcp/resources/types.py +27 -12
  51. fastmcp/server/__init__.py +2 -2
  52. fastmcp/server/auth/__init__.py +14 -0
  53. fastmcp/server/auth/auth.py +30 -10
  54. fastmcp/server/auth/authorization.py +190 -0
  55. fastmcp/server/auth/oauth_proxy/__init__.py +14 -0
  56. fastmcp/server/auth/oauth_proxy/consent.py +361 -0
  57. fastmcp/server/auth/oauth_proxy/models.py +178 -0
  58. fastmcp/server/auth/{oauth_proxy.py → oauth_proxy/proxy.py} +24 -778
  59. fastmcp/server/auth/oauth_proxy/ui.py +277 -0
  60. fastmcp/server/auth/oidc_proxy.py +2 -2
  61. fastmcp/server/auth/providers/auth0.py +24 -94
  62. fastmcp/server/auth/providers/aws.py +26 -95
  63. fastmcp/server/auth/providers/azure.py +41 -129
  64. fastmcp/server/auth/providers/descope.py +18 -49
  65. fastmcp/server/auth/providers/discord.py +25 -86
  66. fastmcp/server/auth/providers/github.py +23 -87
  67. fastmcp/server/auth/providers/google.py +24 -87
  68. fastmcp/server/auth/providers/introspection.py +60 -79
  69. fastmcp/server/auth/providers/jwt.py +30 -67
  70. fastmcp/server/auth/providers/oci.py +47 -110
  71. fastmcp/server/auth/providers/scalekit.py +23 -61
  72. fastmcp/server/auth/providers/supabase.py +18 -47
  73. fastmcp/server/auth/providers/workos.py +34 -127
  74. fastmcp/server/context.py +372 -419
  75. fastmcp/server/dependencies.py +541 -251
  76. fastmcp/server/elicitation.py +20 -18
  77. fastmcp/server/event_store.py +3 -3
  78. fastmcp/server/http.py +16 -6
  79. fastmcp/server/lifespan.py +198 -0
  80. fastmcp/server/low_level.py +92 -2
  81. fastmcp/server/middleware/__init__.py +5 -1
  82. fastmcp/server/middleware/authorization.py +312 -0
  83. fastmcp/server/middleware/caching.py +101 -54
  84. fastmcp/server/middleware/middleware.py +6 -9
  85. fastmcp/server/middleware/ping.py +70 -0
  86. fastmcp/server/middleware/tool_injection.py +2 -2
  87. fastmcp/server/mixins/__init__.py +7 -0
  88. fastmcp/server/mixins/lifespan.py +217 -0
  89. fastmcp/server/mixins/mcp_operations.py +392 -0
  90. fastmcp/server/mixins/transport.py +342 -0
  91. fastmcp/server/openapi/__init__.py +41 -21
  92. fastmcp/server/openapi/components.py +16 -339
  93. fastmcp/server/openapi/routing.py +34 -118
  94. fastmcp/server/openapi/server.py +67 -392
  95. fastmcp/server/providers/__init__.py +71 -0
  96. fastmcp/server/providers/aggregate.py +261 -0
  97. fastmcp/server/providers/base.py +578 -0
  98. fastmcp/server/providers/fastmcp_provider.py +674 -0
  99. fastmcp/server/providers/filesystem.py +226 -0
  100. fastmcp/server/providers/filesystem_discovery.py +327 -0
  101. fastmcp/server/providers/local_provider/__init__.py +11 -0
  102. fastmcp/server/providers/local_provider/decorators/__init__.py +15 -0
  103. fastmcp/server/providers/local_provider/decorators/prompts.py +256 -0
  104. fastmcp/server/providers/local_provider/decorators/resources.py +240 -0
  105. fastmcp/server/providers/local_provider/decorators/tools.py +315 -0
  106. fastmcp/server/providers/local_provider/local_provider.py +465 -0
  107. fastmcp/server/providers/openapi/__init__.py +39 -0
  108. fastmcp/server/providers/openapi/components.py +332 -0
  109. fastmcp/server/providers/openapi/provider.py +405 -0
  110. fastmcp/server/providers/openapi/routing.py +109 -0
  111. fastmcp/server/providers/proxy.py +867 -0
  112. fastmcp/server/providers/skills/__init__.py +59 -0
  113. fastmcp/server/providers/skills/_common.py +101 -0
  114. fastmcp/server/providers/skills/claude_provider.py +44 -0
  115. fastmcp/server/providers/skills/directory_provider.py +153 -0
  116. fastmcp/server/providers/skills/skill_provider.py +432 -0
  117. fastmcp/server/providers/skills/vendor_providers.py +142 -0
  118. fastmcp/server/providers/wrapped_provider.py +140 -0
  119. fastmcp/server/proxy.py +34 -700
  120. fastmcp/server/sampling/run.py +341 -2
  121. fastmcp/server/sampling/sampling_tool.py +4 -3
  122. fastmcp/server/server.py +1214 -2171
  123. fastmcp/server/tasks/__init__.py +2 -1
  124. fastmcp/server/tasks/capabilities.py +13 -1
  125. fastmcp/server/tasks/config.py +66 -3
  126. fastmcp/server/tasks/handlers.py +65 -273
  127. fastmcp/server/tasks/keys.py +4 -6
  128. fastmcp/server/tasks/requests.py +474 -0
  129. fastmcp/server/tasks/routing.py +76 -0
  130. fastmcp/server/tasks/subscriptions.py +20 -11
  131. fastmcp/server/telemetry.py +131 -0
  132. fastmcp/server/transforms/__init__.py +244 -0
  133. fastmcp/server/transforms/namespace.py +193 -0
  134. fastmcp/server/transforms/prompts_as_tools.py +175 -0
  135. fastmcp/server/transforms/resources_as_tools.py +190 -0
  136. fastmcp/server/transforms/tool_transform.py +96 -0
  137. fastmcp/server/transforms/version_filter.py +124 -0
  138. fastmcp/server/transforms/visibility.py +526 -0
  139. fastmcp/settings.py +34 -96
  140. fastmcp/telemetry.py +122 -0
  141. fastmcp/tools/__init__.py +10 -3
  142. fastmcp/tools/function_parsing.py +201 -0
  143. fastmcp/tools/function_tool.py +467 -0
  144. fastmcp/tools/tool.py +215 -362
  145. fastmcp/tools/tool_transform.py +38 -21
  146. fastmcp/utilities/async_utils.py +69 -0
  147. fastmcp/utilities/components.py +152 -91
  148. fastmcp/utilities/inspect.py +8 -20
  149. fastmcp/utilities/json_schema.py +12 -5
  150. fastmcp/utilities/json_schema_type.py +17 -15
  151. fastmcp/utilities/lifespan.py +56 -0
  152. fastmcp/utilities/logging.py +12 -4
  153. fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +3 -3
  154. fastmcp/utilities/openapi/parser.py +3 -3
  155. fastmcp/utilities/pagination.py +80 -0
  156. fastmcp/utilities/skills.py +253 -0
  157. fastmcp/utilities/tests.py +0 -16
  158. fastmcp/utilities/timeout.py +47 -0
  159. fastmcp/utilities/types.py +1 -1
  160. fastmcp/utilities/versions.py +285 -0
  161. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/METADATA +8 -5
  162. fastmcp-3.0.0b1.dist-info/RECORD +228 -0
  163. fastmcp/client/transports.py +0 -1170
  164. fastmcp/contrib/component_manager/component_service.py +0 -209
  165. fastmcp/prompts/prompt_manager.py +0 -117
  166. fastmcp/resources/resource_manager.py +0 -338
  167. fastmcp/server/tasks/converters.py +0 -206
  168. fastmcp/server/tasks/protocol.py +0 -359
  169. fastmcp/tools/tool_manager.py +0 -170
  170. fastmcp/utilities/mcp_config.py +0 -56
  171. fastmcp-2.14.4.dist-info/RECORD +0 -161
  172. /fastmcp/server/{openapi → providers/openapi}/README.md +0 -0
  173. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/WHEEL +0 -0
  174. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/entry_points.txt +0 -0
  175. {fastmcp-2.14.4.dist-info → fastmcp-3.0.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,5 @@
1
- from .resource import FunctionResource, Resource
1
+ from .function_resource import FunctionResource, resource
2
+ from .resource import Resource, ResourceContent, ResourceResult
2
3
  from .template import ResourceTemplate
3
4
  from .types import (
4
5
  BinaryResource,
@@ -7,7 +8,6 @@ from .types import (
7
8
  HttpResource,
8
9
  TextResource,
9
10
  )
10
- from .resource_manager import ResourceManager
11
11
 
12
12
  __all__ = [
13
13
  "BinaryResource",
@@ -16,7 +16,9 @@ __all__ = [
16
16
  "FunctionResource",
17
17
  "HttpResource",
18
18
  "Resource",
19
- "ResourceManager",
19
+ "ResourceContent",
20
+ "ResourceResult",
20
21
  "ResourceTemplate",
21
22
  "TextResource",
23
+ "resource",
22
24
  ]
@@ -0,0 +1,335 @@
1
+ """Standalone @resource decorator for FastMCP."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import inspect
6
+ import warnings
7
+ from collections.abc import Callable
8
+ from dataclasses import dataclass, field
9
+ from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeVar, runtime_checkable
10
+
11
+ from mcp.types import Annotations, Icon
12
+ from pydantic import AnyUrl
13
+
14
+ import fastmcp
15
+ from fastmcp.decorators import resolve_task_config
16
+ from fastmcp.resources.resource import Resource, ResourceResult
17
+ from fastmcp.server.dependencies import (
18
+ transform_context_annotations,
19
+ without_injected_parameters,
20
+ )
21
+ from fastmcp.server.tasks.config import TaskConfig
22
+ from fastmcp.tools.tool import AuthCheckCallable
23
+ from fastmcp.utilities.async_utils import call_sync_fn_in_threadpool
24
+
25
+ if TYPE_CHECKING:
26
+ from docket import Docket
27
+
28
+ from fastmcp.resources.template import ResourceTemplate
29
+
30
+ F = TypeVar("F", bound=Callable[..., Any])
31
+
32
+
33
+ @runtime_checkable
34
+ class DecoratedResource(Protocol):
35
+ """Protocol for functions decorated with @resource."""
36
+
37
+ __fastmcp__: ResourceMeta
38
+
39
+ def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
40
+
41
+
42
+ @dataclass(frozen=True, kw_only=True)
43
+ class ResourceMeta:
44
+ """Metadata attached to functions by the @resource decorator."""
45
+
46
+ type: Literal["resource"] = field(default="resource", init=False)
47
+ uri: str
48
+ name: str | None = None
49
+ version: str | int | None = None
50
+ title: str | None = None
51
+ description: str | None = None
52
+ icons: list[Icon] | None = None
53
+ tags: set[str] | None = None
54
+ mime_type: str | None = None
55
+ annotations: Annotations | None = None
56
+ meta: dict[str, Any] | None = None
57
+ task: bool | TaskConfig | None = None
58
+ auth: AuthCheckCallable | list[AuthCheckCallable] | None = None
59
+ enabled: bool = True
60
+
61
+
62
+ class FunctionResource(Resource):
63
+ """A resource that defers data loading by wrapping a function.
64
+
65
+ The function is only called when the resource is read, allowing for lazy loading
66
+ of potentially expensive data. This is particularly useful when listing resources,
67
+ as the function won't be called until the resource is actually accessed.
68
+
69
+ The function can return:
70
+ - str for text content (default)
71
+ - bytes for binary content
72
+ - other types will be converted to JSON
73
+ """
74
+
75
+ fn: Callable[..., Any]
76
+
77
+ @classmethod
78
+ def from_function(
79
+ cls,
80
+ fn: Callable[..., Any],
81
+ uri: str | AnyUrl | None = None,
82
+ *,
83
+ metadata: ResourceMeta | None = None,
84
+ # Keep individual params for backwards compat
85
+ name: str | None = None,
86
+ version: str | int | None = None,
87
+ title: str | None = None,
88
+ description: str | None = None,
89
+ icons: list[Icon] | None = None,
90
+ mime_type: str | None = None,
91
+ tags: set[str] | None = None,
92
+ annotations: Annotations | None = None,
93
+ meta: dict[str, Any] | None = None,
94
+ task: bool | TaskConfig | None = None,
95
+ auth: AuthCheckCallable | list[AuthCheckCallable] | None = None,
96
+ ) -> FunctionResource:
97
+ """Create a FunctionResource from a function.
98
+
99
+ Args:
100
+ fn: The function to wrap
101
+ uri: The URI for the resource (required if metadata not provided)
102
+ metadata: ResourceMeta object with all configuration. If provided,
103
+ individual parameters must not be passed.
104
+ name, title, etc.: Individual parameters for backwards compatibility.
105
+ Cannot be used together with metadata parameter.
106
+ """
107
+ # Check mutual exclusion
108
+ individual_params_provided = (
109
+ any(
110
+ x is not None
111
+ for x in [
112
+ name,
113
+ version,
114
+ title,
115
+ description,
116
+ icons,
117
+ mime_type,
118
+ tags,
119
+ annotations,
120
+ meta,
121
+ task,
122
+ auth,
123
+ ]
124
+ )
125
+ or uri is not None
126
+ )
127
+
128
+ if metadata is not None and individual_params_provided:
129
+ raise TypeError(
130
+ "Cannot pass both 'metadata' and individual parameters to from_function(). "
131
+ "Use metadata alone or individual parameters alone."
132
+ )
133
+
134
+ # Build metadata from kwargs if not provided
135
+ if metadata is None:
136
+ if uri is None:
137
+ raise TypeError("uri is required when metadata is not provided")
138
+ metadata = ResourceMeta(
139
+ uri=str(uri),
140
+ name=name,
141
+ version=version,
142
+ title=title,
143
+ description=description,
144
+ icons=icons,
145
+ tags=tags,
146
+ mime_type=mime_type,
147
+ annotations=annotations,
148
+ meta=meta,
149
+ task=task,
150
+ auth=auth,
151
+ )
152
+
153
+ uri_obj = AnyUrl(metadata.uri)
154
+
155
+ # Get function name - use class name for callable objects
156
+ func_name = (
157
+ metadata.name or getattr(fn, "__name__", None) or fn.__class__.__name__
158
+ )
159
+
160
+ # Normalize task to TaskConfig and validate
161
+ task_value = metadata.task
162
+ if task_value is None:
163
+ task_config = TaskConfig(mode="forbidden")
164
+ elif isinstance(task_value, bool):
165
+ task_config = TaskConfig.from_bool(task_value)
166
+ else:
167
+ task_config = task_value
168
+ task_config.validate_function(fn, func_name)
169
+
170
+ # if the fn is a callable class, we need to get the __call__ method from here out
171
+ if not inspect.isroutine(fn):
172
+ fn = fn.__call__
173
+ # if the fn is a staticmethod, we need to work with the underlying function
174
+ if isinstance(fn, staticmethod):
175
+ fn = fn.__func__
176
+
177
+ # Transform Context type annotations to Depends() for unified DI
178
+ fn = transform_context_annotations(fn)
179
+
180
+ # Wrap fn to handle dependency resolution internally
181
+ wrapped_fn = without_injected_parameters(fn)
182
+
183
+ return cls(
184
+ fn=wrapped_fn,
185
+ uri=uri_obj,
186
+ name=func_name,
187
+ version=str(metadata.version) if metadata.version is not None else None,
188
+ title=metadata.title,
189
+ description=metadata.description or inspect.getdoc(fn),
190
+ icons=metadata.icons,
191
+ mime_type=metadata.mime_type or "text/plain",
192
+ tags=metadata.tags or set(),
193
+ annotations=metadata.annotations,
194
+ meta=metadata.meta,
195
+ task_config=task_config,
196
+ auth=metadata.auth,
197
+ )
198
+
199
+ async def read(
200
+ self,
201
+ ) -> str | bytes | ResourceResult:
202
+ """Read the resource by calling the wrapped function."""
203
+ # self.fn is wrapped by without_injected_parameters which handles
204
+ # dependency resolution internally
205
+ if inspect.iscoroutinefunction(self.fn):
206
+ result = await self.fn()
207
+ else:
208
+ # Run sync functions in threadpool to avoid blocking the event loop
209
+ result = await call_sync_fn_in_threadpool(self.fn)
210
+ # Handle sync wrappers that return awaitables (e.g., partial(async_fn))
211
+ if inspect.isawaitable(result):
212
+ result = await result
213
+
214
+ # If user returned another Resource, read it recursively
215
+ if isinstance(result, Resource):
216
+ return await result.read()
217
+
218
+ return result
219
+
220
+ def register_with_docket(self, docket: Docket) -> None:
221
+ """Register this resource with docket for background execution.
222
+
223
+ FunctionResource registers the underlying function, which has the user's
224
+ Depends parameters for docket to resolve.
225
+ """
226
+ if not self.task_config.supports_tasks():
227
+ return
228
+ docket.register(self.fn, names=[self.key])
229
+
230
+
231
+ def resource(
232
+ uri: str,
233
+ *,
234
+ name: str | None = None,
235
+ version: str | int | None = None,
236
+ title: str | None = None,
237
+ description: str | None = None,
238
+ icons: list[Icon] | None = None,
239
+ mime_type: str | None = None,
240
+ tags: set[str] | None = None,
241
+ annotations: Annotations | dict[str, Any] | None = None,
242
+ meta: dict[str, Any] | None = None,
243
+ task: bool | TaskConfig | None = None,
244
+ auth: AuthCheckCallable | list[AuthCheckCallable] | None = None,
245
+ ) -> Callable[[F], F]:
246
+ """Standalone decorator to mark a function as an MCP resource.
247
+
248
+ Returns the original function with metadata attached. Register with a server
249
+ using mcp.add_resource().
250
+ """
251
+ if isinstance(annotations, dict):
252
+ annotations = Annotations(**annotations)
253
+
254
+ if inspect.isroutine(uri):
255
+ raise TypeError(
256
+ "The @resource decorator requires a URI. "
257
+ "Use @resource('uri') instead of @resource"
258
+ )
259
+
260
+ def create_resource(fn: Callable[..., Any]) -> FunctionResource | ResourceTemplate:
261
+ from fastmcp.resources.template import ResourceTemplate
262
+ from fastmcp.server.dependencies import without_injected_parameters
263
+
264
+ resolved = resolve_task_config(task)
265
+ has_uri_params = "{" in uri and "}" in uri
266
+ wrapper_fn = without_injected_parameters(fn)
267
+ has_func_params = bool(inspect.signature(wrapper_fn).parameters)
268
+
269
+ # Create metadata first
270
+ resource_meta = ResourceMeta(
271
+ uri=uri,
272
+ name=name,
273
+ version=version,
274
+ title=title,
275
+ description=description,
276
+ icons=icons,
277
+ tags=tags,
278
+ mime_type=mime_type,
279
+ annotations=annotations,
280
+ meta=meta,
281
+ task=resolved,
282
+ auth=auth,
283
+ )
284
+
285
+ if has_uri_params or has_func_params:
286
+ # ResourceTemplate doesn't have metadata support yet, so pass individual params
287
+ return ResourceTemplate.from_function(
288
+ fn=fn,
289
+ uri_template=uri,
290
+ name=name,
291
+ version=version,
292
+ title=title,
293
+ description=description,
294
+ icons=icons,
295
+ mime_type=mime_type,
296
+ tags=tags,
297
+ annotations=annotations,
298
+ meta=meta,
299
+ task=resolved,
300
+ auth=auth,
301
+ )
302
+ else:
303
+ return FunctionResource.from_function(fn, metadata=resource_meta)
304
+
305
+ def attach_metadata(fn: F) -> F:
306
+ metadata = ResourceMeta(
307
+ uri=uri,
308
+ name=name,
309
+ version=version,
310
+ title=title,
311
+ description=description,
312
+ icons=icons,
313
+ tags=tags,
314
+ mime_type=mime_type,
315
+ annotations=annotations,
316
+ meta=meta,
317
+ task=task,
318
+ auth=auth,
319
+ )
320
+ target = fn.__func__ if hasattr(fn, "__func__") else fn
321
+ target.__fastmcp__ = metadata
322
+ return fn
323
+
324
+ def decorator(fn: F) -> F:
325
+ if fastmcp.settings.decorator_mode == "object":
326
+ warnings.warn(
327
+ "decorator_mode='object' is deprecated and will be removed in a future version. "
328
+ "Decorators now return the original function with metadata attached.",
329
+ DeprecationWarning,
330
+ stacklevel=3,
331
+ )
332
+ return create_resource(fn) # type: ignore[return-value]
333
+ return attach_metadata(fn)
334
+
335
+ return decorator