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.
- {fastmcp-2.2.1 → fastmcp-2.2.3}/PKG-INFO +19 -19
- {fastmcp-2.2.1 → fastmcp-2.2.3}/README.md +18 -18
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/clients/client.mdx +9 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/clients/transports.mdx +4 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/docs.json +2 -1
- fastmcp-2.2.3/docs/patterns/contrib.mdx +45 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/proxy.mdx +11 -9
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/fastmcp.mdx +6 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/prompts.mdx +4 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/resources.mdx +65 -3
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/tools.mdx +10 -3
- fastmcp-2.2.3/docs/snippets/version-badge.mdx +13 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/style.css +15 -18
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/cli/cli.py +1 -1
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/client.py +14 -21
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/transports.py +2 -1
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/README.md +11 -1
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/bulk_tool_caller.py +5 -1
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/example.py +1 -1
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/README.md +1 -1
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/example.py +2 -2
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/template.py +5 -2
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/proxy.py +34 -4
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/tools/tool.py +6 -1
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/test_client.py +30 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/contrib/test_bulk_tool_caller.py +2 -2
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/contrib/test_mcp_mixin.py +3 -3
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_resource_template.py +69 -2
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/tools/test_tool_manager.py +14 -20
- fastmcp-2.2.1/docs/snippets/version-badge.mdx +0 -8
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.cursor/rules/core-mcp-objects.mdc +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/release.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/workflows/publish.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/workflows/run-static.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.github/workflows/run-tests.yml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.gitignore +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/.pre-commit-config.yaml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/LICENSE +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/Windows_Notes.md +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/assets/demo-inspector.png +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/getting-started/installation.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/getting-started/quickstart.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/getting-started/welcome.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/composition.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/decorating-methods.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/fastapi.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/patterns/openapi.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/docs/servers/context.mdx +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/complex_inputs.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/desktop.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/echo.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/memory.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/mount_example.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/readme-quickstart.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/sampling.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/screenshot.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/simple_echo.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/README.md +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/pyproject.toml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/__main__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/hub.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/lights/server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/py.typed +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/src/smart_home/settings.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/smart_home/uv.lock +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/examples/text_me.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/justfile +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/pyproject.toml +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/cli/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/cli/claude.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/base.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/roots.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/client/sampling.py +0 -0
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/README.md +0 -0
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/__init__.py +0 -0
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/__init__.py +0 -0
- {fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/mcp_mixin/mcp_mixin.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/exceptions.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/prompts/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/prompts/prompt.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/prompts/prompt_manager.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/py.typed +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/resource.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/resource_manager.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/resources/types.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/context.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/openapi.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/server/server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/settings.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/tools/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/tools/tool_manager.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/decorators.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/func_metadata.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/logging.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/openapi.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/src/fastmcp/utilities/types.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/cli/test_run.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/test_roots.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/client/test_sampling.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/conftest.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/contrib/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/prompts/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/prompts/test_base.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/prompts/test_prompt_manager.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_file_resources.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_function_resources.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_resource_manager.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/resources/test_resources.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_file_server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_import_server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_lifespan.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_mount.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_openapi.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_proxy.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_run_server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/server/test_server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/test_servers/fastmcp_server.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/test_servers/sse.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/test_servers/stdio.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/tools/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/__init__.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/conftest.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/test_openapi.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/test_decorated_function.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/test_func_metadata.py +0 -0
- {fastmcp-2.2.1 → fastmcp-2.2.3}/tests/utilities/test_logging.py +0 -0
- {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.
|
|
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
|
|
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
|
|
369
|
-
|
|
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("
|
|
378
|
+
mcp = FastMCP("My App")
|
|
372
379
|
|
|
373
380
|
@mcp.tool()
|
|
374
|
-
def create_thumbnail(
|
|
375
|
-
"""
|
|
376
|
-
img = PILImage.open(
|
|
377
|
-
img.thumbnail((100, 100))
|
|
378
|
-
buffer =
|
|
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
|
-
|
|
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
|
|
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
|
|
340
|
-
|
|
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("
|
|
349
|
+
mcp = FastMCP("My App")
|
|
343
350
|
|
|
344
351
|
@mcp.tool()
|
|
345
|
-
def create_thumbnail(
|
|
346
|
-
"""
|
|
347
|
-
img = PILImage.open(
|
|
348
|
-
img.thumbnail((100, 100))
|
|
349
|
-
buffer =
|
|
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
|
-
|
|
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.
|
|
@@ -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
|
|
21
|
-
participant BackendServer as Backend MCP Server
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
BackendServer
|
|
26
|
-
|
|
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
|
-
- `
|
|
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
|
-
|
|
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.
|
|
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
|
|
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>
|
|
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-
|
|
17
|
+
display: inline-block;
|
|
18
18
|
align-items: center;
|
|
19
19
|
gap: 0.3em;
|
|
20
|
-
padding: 0.
|
|
21
|
-
font-size:
|
|
22
|
-
font-weight:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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":
|
|
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.
|
|
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.
|
|
89
|
-
#
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
108
|
-
|
|
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 =
|
|
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.
|
{fastmcp-2.2.1/src → fastmcp-2.2.3/src/fastmcp}/contrib/bulk_tool_caller/bulk_tool_caller.py
RENAMED
|
@@ -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):
|
|
@@ -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.")
|
|
@@ -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
|
-
|
|
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}$")
|