fastmcp 2.12.1__py3-none-any.whl → 2.13.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.
Files changed (109) hide show
  1. fastmcp/__init__.py +2 -2
  2. fastmcp/cli/cli.py +56 -36
  3. fastmcp/cli/install/__init__.py +2 -0
  4. fastmcp/cli/install/claude_code.py +7 -16
  5. fastmcp/cli/install/claude_desktop.py +4 -12
  6. fastmcp/cli/install/cursor.py +20 -30
  7. fastmcp/cli/install/gemini_cli.py +241 -0
  8. fastmcp/cli/install/mcp_json.py +4 -12
  9. fastmcp/cli/run.py +15 -94
  10. fastmcp/client/__init__.py +9 -9
  11. fastmcp/client/auth/oauth.py +117 -206
  12. fastmcp/client/client.py +123 -47
  13. fastmcp/client/elicitation.py +6 -1
  14. fastmcp/client/logging.py +18 -14
  15. fastmcp/client/oauth_callback.py +85 -171
  16. fastmcp/client/sampling.py +1 -1
  17. fastmcp/client/transports.py +81 -26
  18. fastmcp/contrib/component_manager/__init__.py +1 -1
  19. fastmcp/contrib/component_manager/component_manager.py +2 -2
  20. fastmcp/contrib/component_manager/component_service.py +7 -7
  21. fastmcp/contrib/mcp_mixin/README.md +35 -4
  22. fastmcp/contrib/mcp_mixin/__init__.py +2 -2
  23. fastmcp/contrib/mcp_mixin/mcp_mixin.py +54 -7
  24. fastmcp/experimental/sampling/handlers/openai.py +2 -2
  25. fastmcp/experimental/server/openapi/__init__.py +5 -8
  26. fastmcp/experimental/server/openapi/components.py +11 -7
  27. fastmcp/experimental/server/openapi/routing.py +2 -2
  28. fastmcp/experimental/utilities/openapi/__init__.py +10 -15
  29. fastmcp/experimental/utilities/openapi/director.py +16 -10
  30. fastmcp/experimental/utilities/openapi/json_schema_converter.py +6 -2
  31. fastmcp/experimental/utilities/openapi/models.py +3 -3
  32. fastmcp/experimental/utilities/openapi/parser.py +37 -16
  33. fastmcp/experimental/utilities/openapi/schemas.py +33 -7
  34. fastmcp/mcp_config.py +3 -4
  35. fastmcp/prompts/__init__.py +1 -1
  36. fastmcp/prompts/prompt.py +32 -27
  37. fastmcp/prompts/prompt_manager.py +16 -101
  38. fastmcp/resources/__init__.py +5 -5
  39. fastmcp/resources/resource.py +28 -20
  40. fastmcp/resources/resource_manager.py +9 -168
  41. fastmcp/resources/template.py +119 -27
  42. fastmcp/resources/types.py +30 -24
  43. fastmcp/server/__init__.py +1 -1
  44. fastmcp/server/auth/__init__.py +9 -5
  45. fastmcp/server/auth/auth.py +80 -47
  46. fastmcp/server/auth/handlers/authorize.py +326 -0
  47. fastmcp/server/auth/jwt_issuer.py +236 -0
  48. fastmcp/server/auth/middleware.py +96 -0
  49. fastmcp/server/auth/oauth_proxy.py +1556 -265
  50. fastmcp/server/auth/oidc_proxy.py +412 -0
  51. fastmcp/server/auth/providers/auth0.py +193 -0
  52. fastmcp/server/auth/providers/aws.py +263 -0
  53. fastmcp/server/auth/providers/azure.py +314 -129
  54. fastmcp/server/auth/providers/bearer.py +1 -1
  55. fastmcp/server/auth/providers/debug.py +114 -0
  56. fastmcp/server/auth/providers/descope.py +229 -0
  57. fastmcp/server/auth/providers/discord.py +308 -0
  58. fastmcp/server/auth/providers/github.py +31 -6
  59. fastmcp/server/auth/providers/google.py +50 -7
  60. fastmcp/server/auth/providers/in_memory.py +27 -3
  61. fastmcp/server/auth/providers/introspection.py +281 -0
  62. fastmcp/server/auth/providers/jwt.py +48 -31
  63. fastmcp/server/auth/providers/oci.py +233 -0
  64. fastmcp/server/auth/providers/scalekit.py +238 -0
  65. fastmcp/server/auth/providers/supabase.py +188 -0
  66. fastmcp/server/auth/providers/workos.py +37 -15
  67. fastmcp/server/context.py +194 -67
  68. fastmcp/server/dependencies.py +56 -16
  69. fastmcp/server/elicitation.py +1 -1
  70. fastmcp/server/http.py +57 -18
  71. fastmcp/server/low_level.py +121 -2
  72. fastmcp/server/middleware/__init__.py +1 -1
  73. fastmcp/server/middleware/caching.py +476 -0
  74. fastmcp/server/middleware/error_handling.py +14 -10
  75. fastmcp/server/middleware/logging.py +158 -116
  76. fastmcp/server/middleware/middleware.py +30 -16
  77. fastmcp/server/middleware/rate_limiting.py +3 -3
  78. fastmcp/server/middleware/tool_injection.py +116 -0
  79. fastmcp/server/openapi.py +15 -7
  80. fastmcp/server/proxy.py +22 -11
  81. fastmcp/server/server.py +744 -254
  82. fastmcp/settings.py +65 -15
  83. fastmcp/tools/__init__.py +1 -1
  84. fastmcp/tools/tool.py +173 -108
  85. fastmcp/tools/tool_manager.py +30 -112
  86. fastmcp/tools/tool_transform.py +13 -11
  87. fastmcp/utilities/cli.py +67 -28
  88. fastmcp/utilities/components.py +7 -2
  89. fastmcp/utilities/inspect.py +79 -23
  90. fastmcp/utilities/json_schema.py +21 -4
  91. fastmcp/utilities/json_schema_type.py +4 -4
  92. fastmcp/utilities/logging.py +182 -10
  93. fastmcp/utilities/mcp_server_config/__init__.py +3 -3
  94. fastmcp/utilities/mcp_server_config/v1/environments/base.py +1 -2
  95. fastmcp/utilities/mcp_server_config/v1/environments/uv.py +10 -45
  96. fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +8 -7
  97. fastmcp/utilities/mcp_server_config/v1/schema.json +5 -1
  98. fastmcp/utilities/mcp_server_config/v1/sources/base.py +0 -1
  99. fastmcp/utilities/openapi.py +11 -11
  100. fastmcp/utilities/tests.py +93 -10
  101. fastmcp/utilities/types.py +87 -21
  102. fastmcp/utilities/ui.py +626 -0
  103. {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/METADATA +141 -60
  104. fastmcp-2.13.2.dist-info/RECORD +144 -0
  105. {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/WHEEL +1 -1
  106. fastmcp/cli/claude.py +0 -144
  107. fastmcp-2.12.1.dist-info/RECORD +0 -128
  108. {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/entry_points.txt +0 -0
  109. {fastmcp-2.12.1.dist-info → fastmcp-2.13.2.dist-info}/licenses/LICENSE +0 -0
fastmcp/server/proxy.py CHANGED
@@ -69,7 +69,7 @@ class ProxyManagerMixin:
69
69
  class ProxyToolManager(ToolManager, ProxyManagerMixin):
70
70
  """A ToolManager that sources its tools from a remote client in addition to local and mounted tools."""
71
71
 
72
- def __init__(self, client_factory: ClientFactoryT, **kwargs):
72
+ def __init__(self, client_factory: ClientFactoryT, **kwargs: Any):
73
73
  super().__init__(**kwargs)
74
74
  self.client_factory = client_factory
75
75
 
@@ -123,7 +123,7 @@ class ProxyToolManager(ToolManager, ProxyManagerMixin):
123
123
  class ProxyResourceManager(ResourceManager, ProxyManagerMixin):
124
124
  """A ResourceManager that sources its resources from a remote client in addition to local and mounted resources."""
125
125
 
126
- def __init__(self, client_factory: ClientFactoryT, **kwargs):
126
+ def __init__(self, client_factory: ClientFactoryT, **kwargs: Any):
127
127
  super().__init__(**kwargs)
128
128
  self.client_factory = client_factory
129
129
 
@@ -198,13 +198,15 @@ class ProxyResourceManager(ResourceManager, ProxyManagerMixin):
198
198
  elif isinstance(result[0], BlobResourceContents):
199
199
  return result[0].blob
200
200
  else:
201
- raise ResourceError(f"Unsupported content type: {type(result[0])}")
201
+ raise ResourceError(
202
+ f"Unsupported content type: {type(result[0])}"
203
+ ) from None
202
204
 
203
205
 
204
206
  class ProxyPromptManager(PromptManager, ProxyManagerMixin):
205
207
  """A PromptManager that sources its prompts from a remote client in addition to local and mounted prompts."""
206
208
 
207
- def __init__(self, client_factory: ClientFactoryT, **kwargs):
209
+ def __init__(self, client_factory: ClientFactoryT, **kwargs: Any):
208
210
  super().__init__(**kwargs)
209
211
  self.client_factory = client_factory
210
212
 
@@ -258,7 +260,7 @@ class ProxyTool(Tool, MirroredComponent):
258
260
  A Tool that represents and executes a tool on a remote server.
259
261
  """
260
262
 
261
- def __init__(self, client: Client, **kwargs):
263
+ def __init__(self, client: Client, **kwargs: Any):
262
264
  super().__init__(**kwargs)
263
265
  self._client = client
264
266
 
@@ -268,10 +270,12 @@ class ProxyTool(Tool, MirroredComponent):
268
270
  return cls(
269
271
  client=client,
270
272
  name=mcp_tool.name,
273
+ title=mcp_tool.title,
271
274
  description=mcp_tool.description,
272
275
  parameters=mcp_tool.inputSchema,
273
276
  annotations=mcp_tool.annotations,
274
277
  output_schema=mcp_tool.outputSchema,
278
+ icons=mcp_tool.icons,
275
279
  meta=mcp_tool.meta,
276
280
  tags=(mcp_tool.meta or {}).get("_fastmcp", {}).get("tags", []),
277
281
  _mirrored=True,
@@ -327,8 +331,10 @@ class ProxyResource(Resource, MirroredComponent):
327
331
  client=client,
328
332
  uri=mcp_resource.uri,
329
333
  name=mcp_resource.name,
334
+ title=mcp_resource.title,
330
335
  description=mcp_resource.description,
331
336
  mime_type=mcp_resource.mimeType or "text/plain",
337
+ icons=mcp_resource.icons,
332
338
  meta=mcp_resource.meta,
333
339
  tags=(mcp_resource.meta or {}).get("_fastmcp", {}).get("tags", []),
334
340
  _mirrored=True,
@@ -354,7 +360,7 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
354
360
  A ResourceTemplate that represents and creates resources from a remote server template.
355
361
  """
356
362
 
357
- def __init__(self, client: Client, **kwargs):
363
+ def __init__(self, client: Client, **kwargs: Any):
358
364
  super().__init__(**kwargs)
359
365
  self._client = client
360
366
 
@@ -367,8 +373,10 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
367
373
  client=client,
368
374
  uri_template=mcp_template.uriTemplate,
369
375
  name=mcp_template.name,
376
+ title=mcp_template.title,
370
377
  description=mcp_template.description,
371
378
  mime_type=mcp_template.mimeType or "text/plain",
379
+ icons=mcp_template.icons,
372
380
  parameters={}, # Remote templates don't have local parameters
373
381
  meta=mcp_template.meta,
374
382
  tags=(mcp_template.meta or {}).get("_fastmcp", {}).get("tags", []),
@@ -402,8 +410,10 @@ class ProxyTemplate(ResourceTemplate, MirroredComponent):
402
410
  client=self._client,
403
411
  uri=parameterized_uri,
404
412
  name=self.name,
413
+ title=self.title,
405
414
  description=self.description,
406
415
  mime_type=result[0].mimeType,
416
+ icons=self.icons,
407
417
  meta=self.meta,
408
418
  tags=(self.meta or {}).get("_fastmcp", {}).get("tags", []),
409
419
  _value=value,
@@ -437,8 +447,10 @@ class ProxyPrompt(Prompt, MirroredComponent):
437
447
  return cls(
438
448
  client=client,
439
449
  name=mcp_prompt.name,
450
+ title=mcp_prompt.title,
440
451
  description=mcp_prompt.description,
441
452
  arguments=arguments,
453
+ icons=mcp_prompt.icons,
442
454
  meta=mcp_prompt.meta,
443
455
  tags=(mcp_prompt.meta or {}).get("_fastmcp", {}).get("tags", []),
444
456
  _mirrored=True,
@@ -537,7 +549,7 @@ class ProxyClient(Client[ClientTransportT]):
537
549
  def __init__(
538
550
  self,
539
551
  transport: ClientTransportT
540
- | FastMCP
552
+ | FastMCP[Any]
541
553
  | FastMCP1Server
542
554
  | AnyUrl
543
555
  | Path
@@ -558,7 +570,7 @@ class ProxyClient(Client[ClientTransportT]):
558
570
  kwargs["log_handler"] = ProxyClient.default_log_handler
559
571
  if "progress_handler" not in kwargs:
560
572
  kwargs["progress_handler"] = ProxyClient.default_progress_handler
561
- super().__init__(**kwargs | dict(transport=transport))
573
+ super().__init__(**kwargs | {"transport": transport})
562
574
 
563
575
  @classmethod
564
576
  async def default_sampling_handler(
@@ -572,7 +584,7 @@ class ProxyClient(Client[ClientTransportT]):
572
584
  """
573
585
  ctx = get_context()
574
586
  content = await ctx.sample(
575
- [msg for msg in messages],
587
+ list(messages),
576
588
  system_prompt=params.systemPrompt,
577
589
  temperature=params.temperature,
578
590
  max_tokens=params.maxTokens,
@@ -640,7 +652,7 @@ class StatefulProxyClient(ProxyClient[ClientTransportT]):
640
652
  Note that it is essential to ensure that the proxy server itself is also stateful.
641
653
  """
642
654
 
643
- def __init__(self, *args, **kwargs):
655
+ def __init__(self, *args: Any, **kwargs: Any):
644
656
  super().__init__(*args, **kwargs)
645
657
  self._caches: dict[ServerSession, Client[ClientTransportT]] = {}
646
658
 
@@ -649,7 +661,6 @@ class StatefulProxyClient(ProxyClient[ClientTransportT]):
649
661
  The stateful proxy client will be forced disconnected when the session is exited.
650
662
  So we do nothing here.
651
663
  """
652
- pass
653
664
 
654
665
  async def clear(self):
655
666
  """