fastmcp 2.2.1__tar.gz → 2.2.3__tar.gz

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 (145) hide show
  1. {fastmcp-2.2.1 → fastmcp-2.2.3}/PKG-INFO +19 -19
  2. {fastmcp-2.2.1 → fastmcp-2.2.3}/README.md +18 -18
  3. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/clients/client.mdx +9 -0
  4. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/clients/transports.mdx +4 -0
  5. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/docs.json +2 -1
  6. fastmcp-2.2.3/docs/patterns/contrib.mdx +45 -0
  7. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/proxy.mdx +11 -9
  8. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/fastmcp.mdx +6 -0
  9. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/prompts.mdx +4 -0
  10. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/resources.mdx +65 -3
  11. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/tools.mdx +10 -3
  12. fastmcp-2.2.3/docs/snippets/version-badge.mdx +13 -0
  13. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/style.css +15 -18
  14. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/cli/cli.py +1 -1
  15. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/client.py +14 -21
  16. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/transports.py +2 -1
  17. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/README.md +11 -1
  18. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/bulk_tool_caller.py +5 -1
  19. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/example.py +1 -1
  20. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/README.md +1 -1
  21. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/example.py +2 -2
  22. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/template.py +5 -2
  23. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/proxy.py +34 -4
  24. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/tools/tool.py +6 -1
  25. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/test_client.py +30 -0
  26. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/contrib/test_bulk_tool_caller.py +2 -2
  27. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/contrib/test_mcp_mixin.py +3 -3
  28. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_resource_template.py +69 -2
  29. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/tools/test_tool_manager.py +14 -20
  30. fastmcp-2.2.1/docs/snippets/version-badge.mdx +0 -8
  31. {fastmcp-2.2.1 → fastmcp-2.2.3}/.cursor/rules/core-mcp-objects.mdc +0 -0
  32. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  33. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  34. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
  35. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/release.yml +0 -0
  36. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/workflows/publish.yml +0 -0
  37. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/workflows/run-static.yml +0 -0
  38. {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/workflows/run-tests.yml +0 -0
  39. {fastmcp-2.2.1 → fastmcp-2.2.3}/.gitignore +0 -0
  40. {fastmcp-2.2.1 → fastmcp-2.2.3}/.pre-commit-config.yaml +0 -0
  41. {fastmcp-2.2.1 → fastmcp-2.2.3}/LICENSE +0 -0
  42. {fastmcp-2.2.1 → fastmcp-2.2.3}/Windows_Notes.md +0 -0
  43. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/assets/demo-inspector.png +0 -0
  44. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/getting-started/installation.mdx +0 -0
  45. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/getting-started/quickstart.mdx +0 -0
  46. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/getting-started/welcome.mdx +0 -0
  47. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/composition.mdx +0 -0
  48. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/decorating-methods.mdx +0 -0
  49. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/fastapi.mdx +0 -0
  50. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/openapi.mdx +0 -0
  51. {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/context.mdx +0 -0
  52. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/complex_inputs.py +0 -0
  53. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/desktop.py +0 -0
  54. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/echo.py +0 -0
  55. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/memory.py +0 -0
  56. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/mount_example.py +0 -0
  57. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/readme-quickstart.py +0 -0
  58. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/sampling.py +0 -0
  59. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/screenshot.py +0 -0
  60. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/simple_echo.py +0 -0
  61. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/README.md +0 -0
  62. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/pyproject.toml +0 -0
  63. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/__init__.py +0 -0
  64. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/__main__.py +0 -0
  65. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/hub.py +0 -0
  66. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
  67. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
  68. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/lights/server.py +0 -0
  69. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/py.typed +0 -0
  70. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/settings.py +0 -0
  71. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/uv.lock +0 -0
  72. {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/text_me.py +0 -0
  73. {fastmcp-2.2.1 → fastmcp-2.2.3}/justfile +0 -0
  74. {fastmcp-2.2.1 → fastmcp-2.2.3}/pyproject.toml +0 -0
  75. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/__init__.py +0 -0
  76. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/cli/__init__.py +0 -0
  77. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/cli/claude.py +0 -0
  78. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/__init__.py +0 -0
  79. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/base.py +0 -0
  80. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/roots.py +0 -0
  81. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/sampling.py +0 -0
  82. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/README.md +0 -0
  83. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/__init__.py +0 -0
  84. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/__init__.py +0 -0
  85. {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/mcp_mixin.py +0 -0
  86. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/exceptions.py +0 -0
  87. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/prompts/__init__.py +0 -0
  88. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/prompts/prompt.py +0 -0
  89. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/prompts/prompt_manager.py +0 -0
  90. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/py.typed +0 -0
  91. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/__init__.py +0 -0
  92. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/resource.py +0 -0
  93. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/resource_manager.py +0 -0
  94. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/types.py +0 -0
  95. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/__init__.py +0 -0
  96. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/context.py +0 -0
  97. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/openapi.py +0 -0
  98. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/server.py +0 -0
  99. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/settings.py +0 -0
  100. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/tools/__init__.py +0 -0
  101. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/tools/tool_manager.py +0 -0
  102. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/__init__.py +0 -0
  103. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/decorators.py +0 -0
  104. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/func_metadata.py +0 -0
  105. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/logging.py +0 -0
  106. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/openapi.py +0 -0
  107. {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/types.py +0 -0
  108. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/__init__.py +0 -0
  109. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/cli/test_run.py +0 -0
  110. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/__init__.py +0 -0
  111. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/test_roots.py +0 -0
  112. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/test_sampling.py +0 -0
  113. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/conftest.py +0 -0
  114. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/contrib/__init__.py +0 -0
  115. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/prompts/__init__.py +0 -0
  116. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/prompts/test_base.py +0 -0
  117. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/prompts/test_prompt_manager.py +0 -0
  118. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/__init__.py +0 -0
  119. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_file_resources.py +0 -0
  120. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_function_resources.py +0 -0
  121. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_resource_manager.py +0 -0
  122. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_resources.py +0 -0
  123. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/__init__.py +0 -0
  124. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_file_server.py +0 -0
  125. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_import_server.py +0 -0
  126. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_lifespan.py +0 -0
  127. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_mount.py +0 -0
  128. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_openapi.py +0 -0
  129. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_proxy.py +0 -0
  130. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_run_server.py +0 -0
  131. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_server.py +0 -0
  132. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/test_servers/fastmcp_server.py +0 -0
  133. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/test_servers/sse.py +0 -0
  134. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/test_servers/stdio.py +0 -0
  135. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/tools/__init__.py +0 -0
  136. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/__init__.py +0 -0
  137. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/__init__.py +0 -0
  138. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/conftest.py +0 -0
  139. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/test_openapi.py +0 -0
  140. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
  141. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
  142. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/test_decorated_function.py +0 -0
  143. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/test_func_metadata.py +0 -0
  144. {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/test_logging.py +0 -0
  145. {fastmcp-2.2.1 → fastmcp-2.2.3}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.2.1
3
+ Version: 2.2.3
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
@@ -361,32 +361,32 @@ The `Context` object provides:
361
361
 
362
362
  ### Images
363
363
 
364
- Easily handle image input and output using the `fastmcp.Image` helper class.
364
+ Easily handle image outputs using the `fastmcp.Image` helper class.
365
+
366
+ <Tip>
367
+ The below code requires the `pillow` library to be installed.
368
+ </Tip>
365
369
 
366
370
  ```python
367
- from fastmcp import FastMCP, Image
368
- from PIL import Image as PILImage
369
- import io
371
+ from mcp.server.fastmcp import FastMCP, Image
372
+ from io import BytesIO
373
+ try:
374
+ from PIL import Image as PILImage
375
+ except ImportError:
376
+ raise ImportError("Please install the `pillow` library to run this example.")
370
377
 
371
- mcp = FastMCP("Image Demo")
378
+ mcp = FastMCP("My App")
372
379
 
373
380
  @mcp.tool()
374
- def create_thumbnail(image_data: Image) -> Image:
375
- """Creates a 100x100 thumbnail from the provided image."""
376
- img = PILImage.open(io.BytesIO(image_data.data)) # Assumes image_data received as Image with bytes
377
- img.thumbnail((100, 100))
378
- buffer = io.BytesIO()
381
+ def create_thumbnail(image_path: str) -> Image:
382
+ """Create a thumbnail from an image"""
383
+ img = PILImage.open(image_path)
384
+ img.thumbnail((100, 100))
385
+ buffer = BytesIO()
379
386
  img.save(buffer, format="PNG")
380
- # Return a new Image object with the thumbnail data
381
387
  return Image(data=buffer.getvalue(), format="png")
382
-
383
- @mcp.tool()
384
- def load_image_from_disk(path: str) -> Image:
385
- """Loads an image from the specified path."""
386
- # Handles reading file and detecting format based on extension
387
- return Image(path=path)
388
388
  ```
389
- FastMCP handles the conversion to/from the base64-encoded format required by the MCP protocol.
389
+ Return the `Image` helper class from your tool to send an image to the client. The `Image` helper class handles the conversion to/from the base64-encoded format required by the MCP protocol. It works with either a path to an image file, or a bytes object.
390
390
 
391
391
 
392
392
  ### MCP Clients
@@ -332,32 +332,32 @@ The `Context` object provides:
332
332
 
333
333
  ### Images
334
334
 
335
- Easily handle image input and output using the `fastmcp.Image` helper class.
335
+ Easily handle image outputs using the `fastmcp.Image` helper class.
336
+
337
+ <Tip>
338
+ The below code requires the `pillow` library to be installed.
339
+ </Tip>
336
340
 
337
341
  ```python
338
- from fastmcp import FastMCP, Image
339
- from PIL import Image as PILImage
340
- import io
342
+ from mcp.server.fastmcp import FastMCP, Image
343
+ from io import BytesIO
344
+ try:
345
+ from PIL import Image as PILImage
346
+ except ImportError:
347
+ raise ImportError("Please install the `pillow` library to run this example.")
341
348
 
342
- mcp = FastMCP("Image Demo")
349
+ mcp = FastMCP("My App")
343
350
 
344
351
  @mcp.tool()
345
- def create_thumbnail(image_data: Image) -> Image:
346
- """Creates a 100x100 thumbnail from the provided image."""
347
- img = PILImage.open(io.BytesIO(image_data.data)) # Assumes image_data received as Image with bytes
348
- img.thumbnail((100, 100))
349
- buffer = io.BytesIO()
352
+ def create_thumbnail(image_path: str) -> Image:
353
+ """Create a thumbnail from an image"""
354
+ img = PILImage.open(image_path)
355
+ img.thumbnail((100, 100))
356
+ buffer = BytesIO()
350
357
  img.save(buffer, format="PNG")
351
- # Return a new Image object with the thumbnail data
352
358
  return Image(data=buffer.getvalue(), format="png")
353
-
354
- @mcp.tool()
355
- def load_image_from_disk(path: str) -> Image:
356
- """Loads an image from the specified path."""
357
- # Handles reading file and detecting format based on extension
358
- return Image(path=path)
359
359
  ```
360
- FastMCP handles the conversion to/from the base64-encoded format required by the MCP protocol.
360
+ Return the `Image` helper class from your tool to send an image to the client. The `Image` helper class handles the conversion to/from the base64-encoded format required by the MCP protocol. It works with either a path to an image file, or a bytes object.
361
361
 
362
362
 
363
363
  ### MCP Clients
@@ -226,6 +226,15 @@ MCP allows servers to make requests *back* to the client for certain capabilitie
226
226
  )
227
227
  ```
228
228
 
229
+ ### Utility Methods
230
+
231
+ * **`ping()`**: Sends a ping request to the server to verify connectivity.
232
+ ```python
233
+ async def check_connection():
234
+ async with client:
235
+ await client.ping()
236
+ print("Server is reachable")
237
+ ```
229
238
 
230
239
  ### Error Handling
231
240
 
@@ -5,6 +5,10 @@ description: Understand the different ways FastMCP Clients can connect to server
5
5
  icon: link
6
6
  ---
7
7
 
8
+ import { VersionBadge } from "/snippets/version-badge.mdx"
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
8
12
  The FastMCP `Client` relies on a `ClientTransport` object to handle the specifics of connecting to and communicating with an MCP server. FastMCP provides several built-in transport implementations for common connection methods.
9
13
 
10
14
  While the `Client` often infers the correct transport automatically (see [Client Overview](/clients/client#transport-inference)), you can also instantiate transports explicitly for more control.
@@ -61,7 +61,8 @@
61
61
  "patterns/composition",
62
62
  "patterns/decorating-methods",
63
63
  "patterns/openapi",
64
- "patterns/fastapi"
64
+ "patterns/fastapi",
65
+ "patterns/contrib"
65
66
  ]
66
67
  },
67
68
  {
@@ -0,0 +1,45 @@
1
+ ---
2
+ title: "Contrib Modules"
3
+ description: "Community-contributed modules extending FastMCP"
4
+ icon: "cubes"
5
+ ---
6
+
7
+ import { VersionBadge } from "/snippets/version-badge.mdx"
8
+
9
+ <VersionBadge version="2.2.1" />
10
+
11
+ FastMCP includes a `contrib` package that holds community-contributed modules. These modules extend FastMCP's functionality but aren't officially maintained by the core team.
12
+
13
+ Contrib modules provide additional features, integrations, or patterns that complement the core FastMCP library. They offer a way for the community to share useful extensions while keeping the core library focused and maintainable.
14
+
15
+ The available modules can be viewed in the [contrib directory](https://github.com/jlowin/fastmcp/tree/main/src/contrib).
16
+
17
+ ## Usage
18
+
19
+ To use a contrib module, import it from the `fastmcp.contrib` package:
20
+
21
+ ```python
22
+ from fastmcp.contrib import my_module
23
+ ```
24
+
25
+ ## Important Considerations
26
+
27
+ - **Stability**: Modules in `contrib` may have different testing requirements or stability guarantees compared to the core library.
28
+ - **Compatibility**: Changes to core FastMCP might break modules in `contrib` without explicit warnings in the main changelog.
29
+ - **Dependencies**: Contrib modules may have additional dependencies not required by the core library. These dependencies are typically documented in the module's README or separate requirements files.
30
+
31
+ ## Contributing
32
+
33
+ We welcome contributions to the `contrib` package! If you have a module that extends FastMCP in a useful way, consider contributing it:
34
+
35
+ 1. Create a new directory in `src/fastmcp/contrib/` for your module
36
+ 3. Add proper tests for your module in `tests/contrib/`
37
+ 2. Include comprehensive documentation in a README.md file, including usage and examples, as well as any additional dependencies or installation instructions
38
+ 5. Submit a pull request
39
+
40
+ The ideal contrib module:
41
+ - Solves a specific use case or integration need
42
+ - Follows FastMCP coding standards
43
+ - Includes thorough documentation and examples
44
+ - Has comprehensive tests
45
+ - Specifies any additional dependencies
@@ -14,18 +14,20 @@ FastMCP provides a powerful proxying capability that allows one FastMCP server i
14
14
 
15
15
  Proxying means setting up a FastMCP server that doesn't implement its own tools or resources directly. Instead, when it receives a request (like `tools/call` or `resources/read`), it forwards that request to a *backend* MCP server, receives the response, and then relays that response back to the original client.
16
16
 
17
+
17
18
  ```mermaid
18
19
  sequenceDiagram
19
- participant Client
20
- participant ProxyServer as FastMCP Proxy Server
21
- participant BackendServer as Backend MCP Server
22
-
23
- Client->>ProxyServer: Request (e.g., stdio)
24
- ProxyServer->>BackendServer: Request (e.g., sse)
25
- BackendServer-->>ProxyServer: Response (e.g., sse)
26
- ProxyServer-->>Client: Response (e.g., stdio)
20
+ participant ClientApp as Your Client (e.g., Claude Desktop)
21
+ participant FastMCPProxy as FastMCP Proxy Server
22
+ participant BackendServer as Backend MCP Server (e.g., remote SSE)
23
+
24
+ ClientApp->>FastMCPProxy: MCP Request (e.g. stdio)
25
+ Note over FastMCPProxy, BackendServer: Proxy forwards the request
26
+ FastMCPProxy->>BackendServer: MCP Request (e.g. sse)
27
+ BackendServer-->>FastMCPProxy: MCP Response (e.g. sse)
28
+ Note over ClientApp, FastMCPProxy: Proxy relays the response
29
+ FastMCPProxy-->>ClientApp: MCP Response (e.g. stdio)
27
30
  ```
28
-
29
31
  ### Use Cases
30
32
 
31
33
  - **Transport Bridging**: Expose a server running on one transport (e.g., a remote SSE server) via a different transport (e.g., local Stdio for Claude Desktop).
@@ -5,6 +5,8 @@ description: Learn about the core FastMCP server class and how to run it.
5
5
  icon: server
6
6
  ---
7
7
 
8
+ import { VersionBadge } from "/snippets/version-badge.mdx"
9
+
8
10
  The central piece of a FastMCP application is the `FastMCP` server class. This class acts as the main container for your application's tools, resources, and prompts, and manages communication with MCP clients.
9
11
 
10
12
  ## Creating a Server
@@ -225,6 +227,8 @@ The CLI can dynamically find and run FastMCP server objects in your files, but i
225
227
 
226
228
  ## Composing Servers
227
229
 
230
+ <VersionBadge version="2.2.0" />
231
+
228
232
  FastMCP supports composing multiple servers together using `import_server` (static copy) and `mount` (live link). This allows you to organize large applications into modular components or reuse existing servers.
229
233
 
230
234
  See the [Server Composition](/patterns/composition) guide for full details, best practices, and examples.
@@ -246,6 +250,8 @@ main.mount("sub", sub)
246
250
 
247
251
  ## Proxying Servers
248
252
 
253
+ <VersionBadge version="2.0.0" />
254
+
249
255
  FastMCP can act as a proxy for any MCP server (local or remote) using `FastMCP.from_client`, letting you bridge transports or add a frontend to existing servers. For example, you can expose a remote SSE server locally via stdio, or vice versa.
250
256
 
251
257
  See the [Proxying Servers](/patterns/proxy) guide for details and advanced usage.
@@ -5,6 +5,8 @@ description: Create reusable, parameterized prompt templates for MCP clients.
5
5
  icon: message-lines
6
6
  ---
7
7
 
8
+ import { VersionBadge } from "/snippets/version-badge.mdx"
9
+
8
10
  Prompts are reusable message templates that help LLMs generate structured, purposeful responses. FastMCP simplifies defining these templates, primarily using the `@mcp.prompt` decorator.
9
11
 
10
12
  ## What Are Prompts?
@@ -201,6 +203,8 @@ Refer to the [Context documentation](/servers/context) for more details on these
201
203
 
202
204
  ### Duplicate Prompts
203
205
 
206
+ <VersionBadge version="2.1.0" />
207
+
204
208
  You can configure how the FastMCP server handles attempts to register multiple prompts with the same name. Use the `on_duplicate_prompts` setting during `FastMCP` initialization.
205
209
 
206
210
  ```python
@@ -5,6 +5,8 @@ description: Expose data sources and dynamic content generators to your MCP clie
5
5
  icon: database
6
6
  ---
7
7
 
8
+ import { VersionBadge } from "/snippets/version-badge.mdx"
9
+
8
10
  Resources represent data or files that an MCP client can read, and resource templates extend this concept by allowing clients to request dynamically generated resources based on parameters passed in the URI.
9
11
 
10
12
  FastMCP simplifies defining both static and dynamic resources, primarily using the `@mcp.resource` decorator.
@@ -183,6 +185,8 @@ Use these when the content is static or sourced directly from a file/URL, bypass
183
185
 
184
186
  #### Custom Resource Keys
185
187
 
188
+ <VersionBadge version="2.2.0" />
189
+
186
190
  When adding resources directly with `mcp.add_resource()`, you can optionally provide a custom storage key:
187
191
 
188
192
  ```python
@@ -201,6 +205,10 @@ Note that this parameter is only available when using `add_resource()` directly
201
205
 
202
206
  Resource Templates allow clients to request resources whose content depends on parameters embedded in the URI. Define a template using the **same `@mcp.resource` decorator**, but include `{parameter_name}` placeholders in the URI string and add corresponding arguments to your function signature.
203
207
 
208
+ Resource templates generate a new resource for each unique set of parameters, which means that resources can be dynamically created on-demand. For example, if the resource template `"user://profile/{name}"` is registered, MCP clients could request `"user://profile/ford"` or `"user://profile/marvin"` to retrieve either of those two user profiles as resources, without having to register each resource individually.
209
+
210
+ Here is a complete example that shows how to define two resource templates:
211
+
204
212
  ```python
205
213
  from fastmcp import FastMCP
206
214
 
@@ -233,11 +241,61 @@ def get_repo_info(owner: str, repo: str) -> dict:
233
241
  }
234
242
  ```
235
243
 
236
- With these templates defined, clients can request:
244
+ With these two templates defined, clients can request a variety of resources:
237
245
  - `weather://london/current` → Returns weather for London
238
- - `repos://fastmcp/docs/info` → Returns info about the fastmcp/docs repository
246
+ - `weather://paris/current` → Returns weather for Paris
247
+ - `repos://jlowin/fastmcp/info` → Returns info about the jlowin/fastmcp repository
248
+ - `repos://prefecthq/prefect/info` → Returns info about the prefecthq/prefect repository
249
+
250
+ ### Wildcard Parameters
251
+
252
+ <VersionBadge version="2.2.3" />
239
253
 
240
- ### Parameters and Default Values
254
+ Resource templates support wildcard parameters that can match multiple path segments. While standard parameters (`{param}`) only match a single path segment and don't cross "/" boundaries, wildcard parameters (`{param*}`) can capture multiple segments including slashes. Wildcards capture all subsequent path segments *up until* the defined part of the URI template (whether literal or another parameter). This allows you to have multiple wildcard parameters in a single URI template.
255
+
256
+ ```python
257
+ from fastmcp import FastMCP
258
+
259
+ mcp = FastMCP(name="DataServer")
260
+
261
+ # Standard parameter only matches one segment
262
+ @mcp.resource("files://{filename}")
263
+ def get_file(filename: str) -> str:
264
+ """Retrieves a file by name."""
265
+ # Will only match files://<single-segment>
266
+ return f"File content for: {filename}"
267
+
268
+ # Wildcard parameter can match multiple segments
269
+ @mcp.resource("path://{filepath*}")
270
+ def get_path_content(filepath: str) -> str:
271
+ """Retrieves content at a specific path."""
272
+ # Can match path://docs/server/resources.mdx
273
+ return f"Content at path: {filepath}"
274
+
275
+ # Mixing standard and wildcard parameters
276
+ @mcp.resource("repo://{owner}/{path*}/template.py")
277
+ def get_template_file(owner: str, path: str) -> dict:
278
+ """Retrieves a file from a specific repository and path, but
279
+ only if the resource ends with `template.py`"""
280
+ # Can match repo://jlowin/fastmcp/src/resources/template.py
281
+ return {
282
+ "owner": owner,
283
+ "path": path + "/template.py",
284
+ "content": f"File at {path}/template.py in {owner}'s repository"
285
+ }
286
+ ```
287
+
288
+ Wildcard parameters are useful when:
289
+
290
+ - Working with file paths or hierarchical data
291
+ - Creating APIs that need to capture variable-length path segments
292
+ - Building URL-like patterns similar to REST APIs
293
+
294
+ Note that like regular parameters, each wildcard parameter must still be a named parameter in your function signature, and all required function parameters must appear in the URI template.
295
+
296
+ ### Default Values
297
+
298
+ <VersionBadge version="2.2.0" />
241
299
 
242
300
  When creating resource templates, FastMCP enforces two rules for the relationship between URI template parameters and function parameters:
243
301
 
@@ -315,6 +373,8 @@ Templates provide a powerful way to expose parameterized data access points foll
315
373
 
316
374
  ### Custom Template Keys
317
375
 
376
+ <VersionBadge version="2.2.0" />
377
+
318
378
  Similar to resources, you can provide custom keys when directly adding templates:
319
379
 
320
380
  ```python
@@ -337,6 +397,8 @@ This allows accessing the same template implementation through different URI pat
337
397
 
338
398
  ### Duplicate Resources
339
399
 
400
+ <VersionBadge version="2.1.0" />
401
+
340
402
  You can configure how the FastMCP server handles attempts to register multiple resources or templates with the same URI. Use the `on_duplicate_resources` setting during `FastMCP` initialization.
341
403
 
342
404
  ```python
@@ -209,13 +209,18 @@ FastMCP automatically converts the value returned by your function into the appr
209
209
  - **`str`**: Sent as `TextContent`.
210
210
  - **`dict`, `list`, Pydantic `BaseModel`**: Serialized to a JSON string and sent as `TextContent`.
211
211
  - **`bytes`**: Base64 encoded and sent as `BlobResourceContents` (often within an `EmbeddedResource`).
212
- - **`fastmcp.utilities.types.Image`**: A helper class to easily return image data. Sent as `ImageContent`.
212
+ - **`fastmcp.Image`**: A helper class for easily returning image data. Sent as `ImageContent`.
213
213
  - **`None`**: Results in an empty response (no content is sent back to the client).
214
214
 
215
215
  ```python
216
- from fastmcp.utilities.types import Image
217
- from PIL import Image as PILImage
216
+ from fastmcp import FastMCP, Image
218
217
  import io
218
+ try:
219
+ from PIL import Image as PILImage
220
+ except ImportError:
221
+ raise ImportError("Please install the `pillow` library to run this example.")
222
+
223
+ mcp = FastMCP("Image Demo")
219
224
 
220
225
  @mcp.tool()
221
226
  def generate_image(width: int, height: int, color: str) -> Image:
@@ -306,6 +311,8 @@ For full documentation on the Context object and all its capabilities, see the [
306
311
 
307
312
  ### Duplicate Tools
308
313
 
314
+ <VersionBadge version="2.1.0" />
315
+
309
316
  You can control how the FastMCP server behaves if you try to register multiple tools with the same name. This is configured using the `on_duplicate_tools` argument when creating the `FastMCP` instance.
310
317
 
311
318
  ```python
@@ -0,0 +1,13 @@
1
+ export const VersionBadge = ({ version }) => {
2
+ return (
3
+ <code className="version-badge-container">
4
+ <div className="version-badge">
5
+ <span className="version-badge-label">New in version:</span>&nbsp;
6
+ <span className="version-badge-version">{version}</span>
7
+ </div>
8
+ </code>
9
+
10
+
11
+
12
+ );
13
+ };
@@ -14,16 +14,18 @@ h6 code:not(pre code) {
14
14
 
15
15
  /* Version badge -- display a badge with the current version of the documentation */
16
16
  .version-badge {
17
- display: inline-flex;
17
+ display: inline-block;
18
18
  align-items: center;
19
19
  gap: 0.3em;
20
- padding: 0.32em 1em;
21
- font-size: 0.92em;
22
- font-weight: 600;
23
- letter-spacing: 0.01em;
24
- color: #7417e5;
25
- background: #f3e8ff;
26
- border: 1.5px solid #c084fc;
20
+ padding: 0.2em 0.8em;
21
+ font-size: 1.1em;
22
+ font-weight: 400;
23
+
24
+ font-family: "Inter", sans-serif;
25
+ letter-spacing: 0.025em;
26
+ color: #ff5400;
27
+ background: #ffeee6;
28
+ border: 1px solid rgb(255, 84, 0, 0.5);
27
29
  border-radius: 6px;
28
30
  box-shadow: none;
29
31
  vertical-align: middle;
@@ -31,6 +33,11 @@ h6 code:not(pre code) {
31
33
  transition: box-shadow 0.2s, transform 0.15s;
32
34
  }
33
35
 
36
+ .version-badge-container {
37
+ margin: 0;
38
+ padding: 0;
39
+ }
40
+
34
41
  .version-badge:hover {
35
42
  box-shadow: 0 2px 8px 0 rgba(160, 132, 252, 0.1);
36
43
  transform: translateY(-1px) scale(1.03);
@@ -41,13 +48,3 @@ h6 code:not(pre code) {
41
48
  background: #312e81;
42
49
  border: 1.5px solid #a78bfa;
43
50
  }
44
-
45
- .badge-emoji {
46
- font-size: 1.15em;
47
- line-height: 1;
48
- text-shadow: 0 1px 2px #fff, 0 0px 2px #c084fc;
49
- }
50
-
51
- .dark .badge-emoji {
52
- text-shadow: 0 1px 2px #312e81, 0 0px 2px #a78bfa;
53
- }
@@ -186,7 +186,7 @@ def version(ctx: Context):
186
186
  "MCP version": importlib.metadata.version("mcp"),
187
187
  "Python version": platform.python_version(),
188
188
  "Platform": platform.platform(),
189
- "FastMCP root path": f"~/{Path(__file__).resolve().parents[3].relative_to(Path.home())}",
189
+ "FastMCP root path": Path(fastmcp.__file__).resolve().parents[1],
190
190
  }
191
191
 
192
192
  g = Table.grid(padding=(0, 1))
@@ -45,7 +45,8 @@ class Client:
45
45
  ):
46
46
  self.transport = infer_transport(transport)
47
47
  self._session: ClientSession | None = None
48
- self._session_cms: list[AbstractAsyncContextManager[ClientSession]] = []
48
+ self._session_cm: AbstractAsyncContextManager[ClientSession] | None = None
49
+ self._nesting_counter: int = 0
49
50
 
50
51
  self._session_kwargs: SessionKwargs = {
51
52
  "sampling_callback": None,
@@ -85,29 +86,21 @@ class Client:
85
86
  return self._session is not None
86
87
 
87
88
  async def __aenter__(self):
88
- if self.is_connected():
89
- # We're already connected, no need to add None to the session_cms list
90
- return self
91
-
92
- try:
93
- session_cm = self.transport.connect_session(**self._session_kwargs)
94
- self._session_cms.append(session_cm)
95
- self._session = await self._session_cms[-1].__aenter__()
96
- return self
97
- except Exception as e:
98
- # Ensure cleanup if __aenter__ fails partially
99
- self._session = None
100
- if self._session_cms:
101
- self._session_cms.pop()
102
- raise ConnectionError(
103
- f"Failed to connect using {self.transport}: {e}"
104
- ) from e
89
+ if self._nesting_counter == 0:
90
+ # create new session
91
+ self._session_cm = self.transport.connect_session(**self._session_kwargs)
92
+ self._session = await self._session_cm.__aenter__()
93
+
94
+ self._nesting_counter += 1
95
+ return self
105
96
 
106
97
  async def __aexit__(self, exc_type, exc_val, exc_tb):
107
- if self._session_cms:
108
- await self._session_cms[-1].__aexit__(exc_type, exc_val, exc_tb)
98
+ self._nesting_counter -= 1
99
+
100
+ if self._nesting_counter == 0 and self._session_cm is not None:
101
+ await self._session_cm.__aexit__(exc_type, exc_val, exc_tb)
102
+ self._session_cm = None
109
103
  self._session = None
110
- self._session_cms.pop()
111
104
 
112
105
  # --- MCP Client Methods ---
113
106
  async def ping(self) -> None:
@@ -3,6 +3,7 @@ import contextlib
3
3
  import datetime
4
4
  import os
5
5
  import shutil
6
+ import sys
6
7
  from collections.abc import AsyncIterator
7
8
  from pathlib import Path
8
9
  from typing import (
@@ -185,7 +186,7 @@ class PythonStdioTransport(StdioTransport):
185
186
  args: list[str] | None = None,
186
187
  env: dict[str, str] | None = None,
187
188
  cwd: str | None = None,
188
- python_cmd: str = "python",
189
+ python_cmd: str = sys.executable,
189
190
  ):
190
191
  """
191
192
  Initialize a Python transport.
@@ -6,4 +6,14 @@ This directory holds community-contributed modules for FastMCP. These modules ex
6
6
  * Modules in `contrib` may have different testing requirements or stability guarantees compared to the core library.
7
7
  * Changes to the core FastMCP library might break modules in `contrib` without explicit warnings in the main changelog.
8
8
 
9
- Use these modules at your own discretion. Contributions are welcome, but please include tests and documentation.
9
+ Use these modules at your own discretion. Contributions are welcome, but please include tests and documentation.
10
+
11
+ ## Usage
12
+
13
+ To use a contrib module, import it from the `fastmcp.contrib` package.
14
+
15
+ ```python
16
+ from fastmcp.contrib import my_module
17
+ ```
18
+
19
+ Note that the contrib modules may have different dependencies than the core library, which can be noted in their respective README's or even separate requirements / dependency files.
@@ -3,10 +3,14 @@ from typing import Any
3
3
  from mcp.types import CallToolResult
4
4
  from pydantic import BaseModel, Field
5
5
 
6
- from contrib.mcp_mixin.mcp_mixin import _DEFAULT_SEPARATOR_TOOL, MCPMixin, mcp_tool
7
6
  from fastmcp import FastMCP
8
7
  from fastmcp.client import Client
9
8
  from fastmcp.client.transports import FastMCPTransport
9
+ from fastmcp.contrib.mcp_mixin.mcp_mixin import (
10
+ _DEFAULT_SEPARATOR_TOOL,
11
+ MCPMixin,
12
+ mcp_tool,
13
+ )
10
14
 
11
15
 
12
16
  class CallToolRequest(BaseModel):
@@ -1,7 +1,7 @@
1
1
  """Sample code for FastMCP using MCPMixin."""
2
2
 
3
- from contrib.bulk_tool_caller import BulkToolCaller
4
3
  from fastmcp import FastMCP
4
+ from fastmcp.contrib.bulk_tool_caller import BulkToolCaller
5
5
 
6
6
  mcp = FastMCP()
7
7
 
@@ -10,7 +10,7 @@ Inherit from `MCPMixin` and use the decorators on the methods you want to regist
10
10
 
11
11
  ```python
12
12
  from fastmcp import FastMCP
13
- from contrib.mcp_mixin import MCPMixin, mcp_tool, mcp_resource
13
+ from fastmcp.contrib.mcp_mixin import MCPMixin, mcp_tool, mcp_resource
14
14
 
15
15
  class MyComponent(MCPMixin):
16
16
  @mcp_tool(name="my_tool", description="Does something cool.")
@@ -2,13 +2,13 @@
2
2
 
3
3
  import asyncio
4
4
 
5
- from contrib.mcp_mixin import (
5
+ from fastmcp import FastMCP
6
+ from fastmcp.contrib.mcp_mixin import (
6
7
  MCPMixin,
7
8
  mcp_prompt,
8
9
  mcp_resource,
9
10
  mcp_tool,
10
11
  )
11
- from fastmcp import FastMCP
12
12
 
13
13
  mcp = FastMCP()
14
14
 
@@ -24,13 +24,16 @@ from fastmcp.utilities.types import _convert_set_defaults
24
24
 
25
25
 
26
26
  def build_regex(template: str) -> re.Pattern:
27
- # Escape all non-brace characters, then restore {var} placeholders
28
27
  parts = re.split(r"(\{[^}]+\})", template)
29
28
  pattern = ""
30
29
  for part in parts:
31
30
  if part.startswith("{") and part.endswith("}"):
32
31
  name = part[1:-1]
33
- pattern += f"(?P<{name}>[^/]+)"
32
+ if name.endswith("*"):
33
+ name = name[:-1]
34
+ pattern += f"(?P<{name}>.+)"
35
+ else:
36
+ pattern += f"(?P<{name}>[^/]+)"
34
37
  else:
35
38
  pattern += re.escape(part)
36
39
  return re.compile(f"^{pattern}$")