fastmcp 2.7.1__py3-none-any.whl → 2.8.1__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.
- fastmcp/__init__.py +32 -3
- fastmcp/cli/cli.py +3 -2
- fastmcp/client/auth/oauth.py +1 -1
- fastmcp/client/client.py +6 -5
- fastmcp/client/sampling.py +5 -9
- fastmcp/client/transports.py +42 -33
- fastmcp/exceptions.py +4 -0
- fastmcp/prompts/prompt.py +11 -21
- fastmcp/prompts/prompt_manager.py +13 -9
- fastmcp/resources/resource.py +21 -26
- fastmcp/resources/resource_manager.py +15 -12
- fastmcp/resources/template.py +8 -16
- fastmcp/server/auth/providers/bearer_env.py +8 -11
- fastmcp/server/auth/providers/in_memory.py +2 -2
- fastmcp/server/context.py +12 -10
- fastmcp/server/openapi.py +87 -57
- fastmcp/server/proxy.py +29 -20
- fastmcp/server/server.py +422 -206
- fastmcp/settings.py +113 -37
- fastmcp/tools/__init__.py +2 -1
- fastmcp/tools/tool.py +125 -85
- fastmcp/tools/tool_manager.py +12 -11
- fastmcp/tools/tool_transform.py +669 -0
- fastmcp/utilities/components.py +55 -0
- fastmcp/utilities/exceptions.py +1 -1
- fastmcp/utilities/mcp_config.py +1 -1
- fastmcp/utilities/tests.py +3 -3
- fastmcp/utilities/types.py +82 -14
- {fastmcp-2.7.1.dist-info → fastmcp-2.8.1.dist-info}/METADATA +48 -26
- {fastmcp-2.7.1.dist-info → fastmcp-2.8.1.dist-info}/RECORD +33 -31
- {fastmcp-2.7.1.dist-info → fastmcp-2.8.1.dist-info}/WHEEL +0 -0
- {fastmcp-2.7.1.dist-info → fastmcp-2.8.1.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.7.1.dist-info → fastmcp-2.8.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Annotated, TypeVar
|
|
3
|
+
|
|
4
|
+
from pydantic import BeforeValidator, Field
|
|
5
|
+
|
|
6
|
+
from fastmcp.utilities.types import FastMCPBaseModel
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]:
|
|
12
|
+
"""Convert a sequence to a set, defaulting to an empty set if None."""
|
|
13
|
+
if maybe_set is None:
|
|
14
|
+
return set()
|
|
15
|
+
if isinstance(maybe_set, set):
|
|
16
|
+
return maybe_set
|
|
17
|
+
return set(maybe_set)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FastMCPComponent(FastMCPBaseModel):
|
|
21
|
+
"""Base class for FastMCP tools, prompts, resources, and resource templates."""
|
|
22
|
+
|
|
23
|
+
name: str = Field(
|
|
24
|
+
description="The name of the component.",
|
|
25
|
+
)
|
|
26
|
+
description: str | None = Field(
|
|
27
|
+
default=None,
|
|
28
|
+
description="The description of the component.",
|
|
29
|
+
)
|
|
30
|
+
tags: Annotated[set[str], BeforeValidator(_convert_set_default_none)] = Field(
|
|
31
|
+
default_factory=set,
|
|
32
|
+
description="Tags for the component.",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
enabled: bool = Field(
|
|
36
|
+
default=True,
|
|
37
|
+
description="Whether the component is enabled.",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def __eq__(self, other: object) -> bool:
|
|
41
|
+
if type(self) is not type(other):
|
|
42
|
+
return False
|
|
43
|
+
assert isinstance(other, type(self))
|
|
44
|
+
return self.model_dump() == other.model_dump()
|
|
45
|
+
|
|
46
|
+
def __repr__(self) -> str:
|
|
47
|
+
return f"{self.__class__.__name__}(name={self.name!r}, description={self.description!r}, tags={self.tags}, enabled={self.enabled})"
|
|
48
|
+
|
|
49
|
+
def enable(self) -> None:
|
|
50
|
+
"""Enable the component."""
|
|
51
|
+
self.enabled = True
|
|
52
|
+
|
|
53
|
+
def disable(self) -> None:
|
|
54
|
+
"""Disable the component."""
|
|
55
|
+
self.enabled = False
|
fastmcp/utilities/exceptions.py
CHANGED
|
@@ -43,7 +43,7 @@ def get_catch_handlers() -> Mapping[
|
|
|
43
43
|
type[BaseException] | Iterable[type[BaseException]],
|
|
44
44
|
Callable[[BaseExceptionGroup[Any]], Any],
|
|
45
45
|
]:
|
|
46
|
-
if fastmcp.settings.
|
|
46
|
+
if fastmcp.settings.client_raise_first_exceptiongroup_error:
|
|
47
47
|
return _catch_handlers
|
|
48
48
|
else:
|
|
49
49
|
return {}
|
fastmcp/utilities/mcp_config.py
CHANGED
|
@@ -55,7 +55,7 @@ class StdioMCPServer(FastMCPBaseModel):
|
|
|
55
55
|
class RemoteMCPServer(FastMCPBaseModel):
|
|
56
56
|
url: str
|
|
57
57
|
headers: dict[str, str] = Field(default_factory=dict)
|
|
58
|
-
transport: Literal["streamable-http", "sse"
|
|
58
|
+
transport: Literal["streamable-http", "sse"] | None = None
|
|
59
59
|
auth: Annotated[
|
|
60
60
|
str | Literal["oauth"] | None,
|
|
61
61
|
Field(
|
fastmcp/utilities/tests.py
CHANGED
|
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Any, Literal
|
|
|
10
10
|
|
|
11
11
|
import uvicorn
|
|
12
12
|
|
|
13
|
-
from fastmcp
|
|
13
|
+
from fastmcp import settings
|
|
14
14
|
from fastmcp.utilities.http import find_available_port
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
@@ -32,8 +32,8 @@ def temporary_settings(**kwargs: Any):
|
|
|
32
32
|
from fastmcp.utilities.tests import temporary_settings
|
|
33
33
|
|
|
34
34
|
with temporary_settings(log_level='DEBUG'):
|
|
35
|
-
assert fastmcp.settings.
|
|
36
|
-
assert fastmcp.settings.
|
|
35
|
+
assert fastmcp.settings.log_level == 'DEBUG'
|
|
36
|
+
assert fastmcp.settings.log_level == 'INFO'
|
|
37
37
|
```
|
|
38
38
|
"""
|
|
39
39
|
old_settings = copy.deepcopy(settings.model_dump())
|
fastmcp/utilities/types.py
CHANGED
|
@@ -6,13 +6,21 @@ from collections.abc import Callable
|
|
|
6
6
|
from functools import lru_cache
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from types import UnionType
|
|
9
|
-
from typing import Annotated, TypeVar, Union, get_args, get_origin
|
|
10
|
-
|
|
11
|
-
from mcp.types import
|
|
9
|
+
from typing import Annotated, TypeAlias, TypeVar, Union, get_args, get_origin
|
|
10
|
+
|
|
11
|
+
from mcp.types import (
|
|
12
|
+
Annotations,
|
|
13
|
+
AudioContent,
|
|
14
|
+
EmbeddedResource,
|
|
15
|
+
ImageContent,
|
|
16
|
+
TextContent,
|
|
17
|
+
)
|
|
12
18
|
from pydantic import BaseModel, ConfigDict, TypeAdapter
|
|
13
19
|
|
|
14
20
|
T = TypeVar("T")
|
|
15
21
|
|
|
22
|
+
MCPContent: TypeAlias = TextContent | ImageContent | AudioContent | EmbeddedResource
|
|
23
|
+
|
|
16
24
|
|
|
17
25
|
class FastMCPBaseModel(BaseModel):
|
|
18
26
|
"""Base model for FastMCP models."""
|
|
@@ -80,15 +88,6 @@ def find_kwarg_by_type(fn: Callable, kwarg_type: type) -> str | None:
|
|
|
80
88
|
return None
|
|
81
89
|
|
|
82
90
|
|
|
83
|
-
def _convert_set_defaults(maybe_set: set[T] | list[T] | None) -> set[T]:
|
|
84
|
-
"""Convert a set or list to a set, defaulting to an empty set if None."""
|
|
85
|
-
if maybe_set is None:
|
|
86
|
-
return set()
|
|
87
|
-
if isinstance(maybe_set, set):
|
|
88
|
-
return maybe_set
|
|
89
|
-
return set(maybe_set)
|
|
90
|
-
|
|
91
|
-
|
|
92
91
|
class Image:
|
|
93
92
|
"""Helper class for returning images from tools."""
|
|
94
93
|
|
|
@@ -97,6 +96,7 @@ class Image:
|
|
|
97
96
|
path: str | Path | None = None,
|
|
98
97
|
data: bytes | None = None,
|
|
99
98
|
format: str | None = None,
|
|
99
|
+
annotations: Annotations | None = None,
|
|
100
100
|
):
|
|
101
101
|
if path is None and data is None:
|
|
102
102
|
raise ValueError("Either path or data must be provided")
|
|
@@ -107,6 +107,7 @@ class Image:
|
|
|
107
107
|
self.data = data
|
|
108
108
|
self._format = format
|
|
109
109
|
self._mime_type = self._get_mime_type()
|
|
110
|
+
self.annotations = annotations
|
|
110
111
|
|
|
111
112
|
def _get_mime_type(self) -> str:
|
|
112
113
|
"""Get MIME type from format or guess from file extension."""
|
|
@@ -124,7 +125,11 @@ class Image:
|
|
|
124
125
|
}.get(suffix, "application/octet-stream")
|
|
125
126
|
return "image/png" # default for raw binary data
|
|
126
127
|
|
|
127
|
-
def to_image_content(
|
|
128
|
+
def to_image_content(
|
|
129
|
+
self,
|
|
130
|
+
mime_type: str | None = None,
|
|
131
|
+
annotations: Annotations | None = None,
|
|
132
|
+
) -> ImageContent:
|
|
128
133
|
"""Convert to MCP ImageContent."""
|
|
129
134
|
if self.path:
|
|
130
135
|
with open(self.path, "rb") as f:
|
|
@@ -134,4 +139,67 @@ class Image:
|
|
|
134
139
|
else:
|
|
135
140
|
raise ValueError("No image data available")
|
|
136
141
|
|
|
137
|
-
return ImageContent(
|
|
142
|
+
return ImageContent(
|
|
143
|
+
type="image",
|
|
144
|
+
data=data,
|
|
145
|
+
mimeType=mime_type or self._mime_type,
|
|
146
|
+
annotations=annotations or self.annotations,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class Audio:
|
|
151
|
+
"""Helper class for returning audio from tools."""
|
|
152
|
+
|
|
153
|
+
def __init__(
|
|
154
|
+
self,
|
|
155
|
+
path: str | Path | None = None,
|
|
156
|
+
data: bytes | None = None,
|
|
157
|
+
format: str | None = None,
|
|
158
|
+
annotations: Annotations | None = None,
|
|
159
|
+
):
|
|
160
|
+
if path is None and data is None:
|
|
161
|
+
raise ValueError("Either path or data must be provided")
|
|
162
|
+
if path is not None and data is not None:
|
|
163
|
+
raise ValueError("Only one of path or data can be provided")
|
|
164
|
+
|
|
165
|
+
self.path = Path(path) if path else None
|
|
166
|
+
self.data = data
|
|
167
|
+
self._format = format
|
|
168
|
+
self._mime_type = self._get_mime_type()
|
|
169
|
+
self.annotations = annotations
|
|
170
|
+
|
|
171
|
+
def _get_mime_type(self) -> str:
|
|
172
|
+
"""Get MIME type from format or guess from file extension."""
|
|
173
|
+
if self._format:
|
|
174
|
+
return f"audio/{self._format.lower()}"
|
|
175
|
+
|
|
176
|
+
if self.path:
|
|
177
|
+
suffix = self.path.suffix.lower()
|
|
178
|
+
return {
|
|
179
|
+
".wav": "audio/wav",
|
|
180
|
+
".mp3": "audio/mpeg",
|
|
181
|
+
".ogg": "audio/ogg",
|
|
182
|
+
".m4a": "audio/mp4",
|
|
183
|
+
".flac": "audio/flac",
|
|
184
|
+
}.get(suffix, "application/octet-stream")
|
|
185
|
+
return "audio/wav" # default for raw binary data
|
|
186
|
+
|
|
187
|
+
def to_audio_content(
|
|
188
|
+
self,
|
|
189
|
+
mime_type: str | None = None,
|
|
190
|
+
annotations: Annotations | None = None,
|
|
191
|
+
) -> AudioContent:
|
|
192
|
+
if self.path:
|
|
193
|
+
with open(self.path, "rb") as f:
|
|
194
|
+
data = base64.b64encode(f.read()).decode()
|
|
195
|
+
elif self.data is not None:
|
|
196
|
+
data = base64.b64encode(self.data).decode()
|
|
197
|
+
else:
|
|
198
|
+
raise ValueError("No audio data available")
|
|
199
|
+
|
|
200
|
+
return AudioContent(
|
|
201
|
+
type="audio",
|
|
202
|
+
data=data,
|
|
203
|
+
mimeType=mime_type or self._mime_type,
|
|
204
|
+
annotations=annotations or self.annotations,
|
|
205
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmcp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.1
|
|
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
|
|
@@ -20,7 +20,7 @@ Requires-Python: >=3.10
|
|
|
20
20
|
Requires-Dist: authlib>=1.5.2
|
|
21
21
|
Requires-Dist: exceptiongroup>=1.2.2
|
|
22
22
|
Requires-Dist: httpx>=0.28.1
|
|
23
|
-
Requires-Dist: mcp<2.0.0,>=1.9.
|
|
23
|
+
Requires-Dist: mcp<2.0.0,>=1.9.4
|
|
24
24
|
Requires-Dist: openapi-pydantic>=0.5.1
|
|
25
25
|
Requires-Dist: python-dotenv>=1.1.0
|
|
26
26
|
Requires-Dist: rich>=13.9.4
|
|
@@ -33,8 +33,11 @@ Description-Content-Type: text/markdown
|
|
|
33
33
|
|
|
34
34
|
<!-- omit in toc -->
|
|
35
35
|
# FastMCP v2 🚀
|
|
36
|
+
|
|
36
37
|
<strong>The fast, Pythonic way to build MCP servers and clients.</strong>
|
|
37
38
|
|
|
39
|
+
*FastMCP is made with 💙 by [Prefect](https://www.prefect.io/)*
|
|
40
|
+
|
|
38
41
|
[](https://gofastmcp.com)
|
|
39
42
|
[](https://pypi.org/project/fastmcp)
|
|
40
43
|
[](https://github.com/jlowin/fastmcp/actions/workflows/run-tests.yml)
|
|
@@ -44,13 +47,16 @@ Description-Content-Type: text/markdown
|
|
|
44
47
|
</div>
|
|
45
48
|
|
|
46
49
|
> [!Note]
|
|
50
|
+
>
|
|
47
51
|
> #### Beyond the Protocol
|
|
48
|
-
>
|
|
49
|
-
> FastMCP is the standard framework for working with the Model Context Protocol. FastMCP 1.0 was incorporated into the [official low-level Python SDK](https://github.com/modelcontextprotocol/python-sdk), and FastMCP 2.0 *(this project)* provides a complete toolkit for working with the MCP ecosystem.
|
|
50
52
|
>
|
|
51
|
-
> FastMCP
|
|
53
|
+
> FastMCP is the standard framework for working with the Model Context Protocol. FastMCP 1.0 was incorporated into the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) in 2024.
|
|
52
54
|
>
|
|
53
|
-
>
|
|
55
|
+
> This is FastMCP 2.0, the **actively maintained version** that provides a complete toolkit for working with the MCP ecosystem.
|
|
56
|
+
>
|
|
57
|
+
> FastMCP 2.0 has a comprehensive set of features that go far beyond the core MCP specification, all in service of providing **the simplest path to production**. These include deployment, auth, clients, server proxying and composition, generating servers from REST APIs, dynamic tool rewriting, built-in testing tools, integrations, and more.
|
|
58
|
+
>
|
|
59
|
+
> Ready to upgrade or get started? Follow the [installation instructions](https://gofastmcp.com/getting-started/installation), which include steps for upgrading from the official MCP SDK.
|
|
54
60
|
|
|
55
61
|
---
|
|
56
62
|
|
|
@@ -72,6 +78,7 @@ if __name__ == "__main__":
|
|
|
72
78
|
```
|
|
73
79
|
|
|
74
80
|
Run the server locally:
|
|
81
|
+
|
|
75
82
|
```bash
|
|
76
83
|
fastmcp run server.py
|
|
77
84
|
```
|
|
@@ -80,9 +87,10 @@ fastmcp run server.py
|
|
|
80
87
|
|
|
81
88
|
FastMCP's complete documentation is available at **[gofastmcp.com](https://gofastmcp.com)**, including detailed guides, API references, and advanced patterns. This readme provides only a high-level overview.
|
|
82
89
|
|
|
83
|
-
Documentation is also available in [llms.txt format](https://llmstxt.org/), which is a simple markdown standard that LLMs can consume easily.
|
|
90
|
+
Documentation is also available in [llms.txt format](https://llmstxt.org/), which is a simple markdown standard that LLMs can consume easily.
|
|
84
91
|
|
|
85
92
|
There are two ways to access the LLM-friendly documentation:
|
|
93
|
+
|
|
86
94
|
- [`llms.txt`](https://gofastmcp.com/llms.txt) is essentially a sitemap, listing all the pages in the documentation.
|
|
87
95
|
- [`llms-full.txt`](https://gofastmcp.com/llms-full.txt) contains the entire documentation. Note this may exceed the context window of your LLM.
|
|
88
96
|
|
|
@@ -172,7 +180,7 @@ Learn more in the [**FastMCP Server Documentation**](https://gofastmcp.com/serve
|
|
|
172
180
|
|
|
173
181
|
### Tools
|
|
174
182
|
|
|
175
|
-
Tools allow LLMs to perform actions by executing your Python functions (sync or async). Ideal for computations, API calls, or side effects (like `POST`/`PUT`). FastMCP handles schema generation from type hints and docstrings. Tools can return various types, including text, JSON-serializable objects, and even images
|
|
183
|
+
Tools allow LLMs to perform actions by executing your Python functions (sync or async). Ideal for computations, API calls, or side effects (like `POST`/`PUT`). FastMCP handles schema generation from type hints and docstrings. Tools can return various types, including text, JSON-serializable objects, and even images or audio aided by the FastMCP media helper classes.
|
|
176
184
|
|
|
177
185
|
```python
|
|
178
186
|
@mcp.tool
|
|
@@ -218,12 +226,13 @@ Learn more in the [**Prompts Documentation**](https://gofastmcp.com/servers/prom
|
|
|
218
226
|
### Context
|
|
219
227
|
|
|
220
228
|
Access MCP session capabilities within your tools, resources, or prompts by adding a `ctx: Context` parameter. Context provides methods for:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
229
|
+
|
|
230
|
+
- **Logging:** Log messages to MCP clients with `ctx.info()`, `ctx.error()`, etc.
|
|
231
|
+
- **LLM Sampling:** Use `ctx.sample()` to request completions from the client's LLM.
|
|
232
|
+
- **HTTP Request:** Use `ctx.http_request()` to make HTTP requests to other servers.
|
|
233
|
+
- **Resource Access:** Use `ctx.read_resource()` to access resources on the server
|
|
234
|
+
- **Progress Reporting:** Use `ctx.report_progress()` to report progress to the client.
|
|
235
|
+
- and more...
|
|
227
236
|
|
|
228
237
|
To access the context, add a parameter annotated as `Context` to any mcp-decorated function. FastMCP will automatically inject the correct context object when the function is called.
|
|
229
238
|
|
|
@@ -363,16 +372,19 @@ if __name__ == "__main__":
|
|
|
363
372
|
FastMCP supports three transport protocols:
|
|
364
373
|
|
|
365
374
|
**STDIO (Default)**: Best for local tools and command-line scripts.
|
|
375
|
+
|
|
366
376
|
```python
|
|
367
377
|
mcp.run(transport="stdio") # Default, so transport argument is optional
|
|
368
378
|
```
|
|
369
379
|
|
|
370
380
|
**Streamable HTTP**: Recommended for web deployments.
|
|
381
|
+
|
|
371
382
|
```python
|
|
372
383
|
mcp.run(transport="streamable-http", host="127.0.0.1", port=8000, path="/mcp")
|
|
373
384
|
```
|
|
374
385
|
|
|
375
386
|
**SSE**: For compatibility with existing SSE clients.
|
|
387
|
+
|
|
376
388
|
```python
|
|
377
389
|
mcp.run(transport="sse", host="127.0.0.1", port=8000)
|
|
378
390
|
```
|
|
@@ -385,22 +397,26 @@ Contributions are the core of open source! We welcome improvements and features.
|
|
|
385
397
|
|
|
386
398
|
### Prerequisites
|
|
387
399
|
|
|
388
|
-
|
|
389
|
-
|
|
400
|
+
- Python 3.10+
|
|
401
|
+
- [uv](https://docs.astral.sh/uv/) (Recommended for environment management)
|
|
390
402
|
|
|
391
403
|
### Setup
|
|
392
404
|
|
|
393
|
-
1. Clone the repository:
|
|
405
|
+
1. Clone the repository:
|
|
406
|
+
|
|
394
407
|
```bash
|
|
395
408
|
git clone https://github.com/jlowin/fastmcp.git
|
|
396
409
|
cd fastmcp
|
|
397
410
|
```
|
|
398
|
-
|
|
411
|
+
|
|
412
|
+
2. Create and sync the environment:
|
|
413
|
+
|
|
399
414
|
```bash
|
|
400
415
|
uv sync
|
|
401
416
|
```
|
|
417
|
+
|
|
402
418
|
This installs all dependencies, including dev tools.
|
|
403
|
-
|
|
419
|
+
|
|
404
420
|
3. Activate the virtual environment (e.g., `source .venv/bin/activate` or via your IDE).
|
|
405
421
|
|
|
406
422
|
### Unit Tests
|
|
@@ -408,10 +424,13 @@ Contributions are the core of open source! We welcome improvements and features.
|
|
|
408
424
|
FastMCP has a comprehensive unit test suite. All PRs must introduce or update tests as appropriate and pass the full suite.
|
|
409
425
|
|
|
410
426
|
Run tests using pytest:
|
|
427
|
+
|
|
411
428
|
```bash
|
|
412
429
|
pytest
|
|
413
430
|
```
|
|
431
|
+
|
|
414
432
|
or if you want an overview of the code coverage
|
|
433
|
+
|
|
415
434
|
```bash
|
|
416
435
|
uv run pytest --cov=src --cov=examples --cov-report=html
|
|
417
436
|
```
|
|
@@ -421,10 +440,13 @@ uv run pytest --cov=src --cov=examples --cov-report=html
|
|
|
421
440
|
FastMCP uses `pre-commit` for code formatting, linting, and type-checking. All PRs must pass these checks (they run automatically in CI).
|
|
422
441
|
|
|
423
442
|
Install the hooks locally:
|
|
443
|
+
|
|
424
444
|
```bash
|
|
425
445
|
uv run pre-commit install
|
|
426
446
|
```
|
|
447
|
+
|
|
427
448
|
The hooks will now run automatically on `git commit`. You can also run them manually at any time:
|
|
449
|
+
|
|
428
450
|
```bash
|
|
429
451
|
pre-commit run --all-files
|
|
430
452
|
# or via uv
|
|
@@ -433,11 +455,11 @@ uv run pre-commit run --all-files
|
|
|
433
455
|
|
|
434
456
|
### Pull Requests
|
|
435
457
|
|
|
436
|
-
1.
|
|
437
|
-
2.
|
|
438
|
-
3.
|
|
439
|
-
4.
|
|
440
|
-
5.
|
|
441
|
-
6.
|
|
458
|
+
1. Fork the repository on GitHub.
|
|
459
|
+
2. Create a feature branch from `main`.
|
|
460
|
+
3. Make your changes, including tests and documentation updates.
|
|
461
|
+
4. Ensure tests and pre-commit hooks pass.
|
|
462
|
+
5. Commit your changes and push to your fork.
|
|
463
|
+
6. Open a pull request against the `main` branch of `jlowin/fastmcp`.
|
|
442
464
|
|
|
443
|
-
Please open an issue or discussion for questions or suggestions before starting significant work!
|
|
465
|
+
Please open an issue or discussion for questions or suggestions before starting significant work!
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
fastmcp/__init__.py,sha256=
|
|
2
|
-
fastmcp/exceptions.py,sha256
|
|
1
|
+
fastmcp/__init__.py,sha256=5ChT4kg3srdFl0-9dZekGqpzCESlpc6ohrfPbWf1aTo,1300
|
|
2
|
+
fastmcp/exceptions.py,sha256=-krEavxwddQau6T7MESCR4VjKNLfP9KHJrU1p3y72FU,744
|
|
3
3
|
fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
fastmcp/settings.py,sha256=
|
|
4
|
+
fastmcp/settings.py,sha256=DZU5tmyNz7bzc3jhxE4wOzsj_TcPhXiXF_-OPbfr4d0,9009
|
|
5
5
|
fastmcp/cli/__init__.py,sha256=Ii284TNoG5lxTP40ETMGhHEq3lQZWxu9m9JuU57kUpQ,87
|
|
6
6
|
fastmcp/cli/claude.py,sha256=IAlcZ4qZKBBj09jZUMEx7EANZE_IR3vcu7zOBJmMOuU,4567
|
|
7
|
-
fastmcp/cli/cli.py,sha256=
|
|
7
|
+
fastmcp/cli/cli.py,sha256=NQ_byPYUhJ8zyMW6VV2JlUlBH8xwB4tRejLK7n-yypc,12681
|
|
8
8
|
fastmcp/cli/run.py,sha256=sGH7M3Yi8HGju4sPypKGk3P2cdZq1n3l-_CpJmdGvDc,6277
|
|
9
9
|
fastmcp/client/__init__.py,sha256=kd2hhSuD8rZuF87c9zlPJP_icJ-Rx3exyNoK0EzfOtE,617
|
|
10
|
-
fastmcp/client/client.py,sha256=
|
|
10
|
+
fastmcp/client/client.py,sha256=QrPWcf0mM5k32Sb8-SG8-3oua8-VxZwGg7egRWcBHho,24957
|
|
11
11
|
fastmcp/client/logging.py,sha256=hOPRailZUp89RUck6V4HPaWVZinVrNY8HD4hD0dd-fE,822
|
|
12
12
|
fastmcp/client/oauth_callback.py,sha256=ODAnVX-ettL82RuI5KpfkKf8iDtYMDue3Tnab5sjQtM,10071
|
|
13
13
|
fastmcp/client/progress.py,sha256=WjLLDbUKMsx8DK-fqO7AGsXb83ak-6BMrLvzzznGmcI,1043
|
|
14
14
|
fastmcp/client/roots.py,sha256=IxI_bHwHTmg6c2H-s1av1ZgrRnNDieHtYwdGFbzXT5c,2471
|
|
15
|
-
fastmcp/client/sampling.py,sha256=
|
|
16
|
-
fastmcp/client/transports.py,sha256=
|
|
15
|
+
fastmcp/client/sampling.py,sha256=Q8PzYCERa1W3xGGI9I9QOhhDM-M4i3P5lESb0cp2iI8,1595
|
|
16
|
+
fastmcp/client/transports.py,sha256=QdfWw2AQ6upx9pyInLaW14xcfzI9auA5G67Gy4aWeac,32930
|
|
17
17
|
fastmcp/client/auth/__init__.py,sha256=4DNsfp4iaQeBcpds0JDdMn6Mmfud44stWLsret0sVKY,91
|
|
18
18
|
fastmcp/client/auth/bearer.py,sha256=MFEFqcH6u_V86msYiOsEFKN5ks1V9BnBNiPsPLHUTqo,399
|
|
19
|
-
fastmcp/client/auth/oauth.py,sha256=
|
|
19
|
+
fastmcp/client/auth/oauth.py,sha256=xiwLftGkadRNsB5eNPl7JtjOI936qgVjsogvOzoxdO0,14700
|
|
20
20
|
fastmcp/contrib/README.md,sha256=rKknYSI1T192UvSszqwwDlQ2eYQpxywrNTLoj177SYU,878
|
|
21
21
|
fastmcp/contrib/bulk_tool_caller/README.md,sha256=5aUUY1TSFKtz1pvTLSDqkUCkGkuqMfMZNsLeaNqEgAc,1960
|
|
22
22
|
fastmcp/contrib/bulk_tool_caller/__init__.py,sha256=xvGSSaUXTQrc31erBoi1Gh7BikgOliETDiYVTP3rLxY,75
|
|
@@ -27,41 +27,43 @@ fastmcp/contrib/mcp_mixin/__init__.py,sha256=aw9IQ1ssNjCgws4ZNt8bkdpossAAGVAwwjB
|
|
|
27
27
|
fastmcp/contrib/mcp_mixin/example.py,sha256=GnunkXmtG5hLLTUsM8aW5ZURU52Z8vI4tNLl-fK7Dg0,1228
|
|
28
28
|
fastmcp/contrib/mcp_mixin/mcp_mixin.py,sha256=3e0wHlKI9OF12t-SbpRTL-TWjBBLw7T8ATjCdoDtX6k,8173
|
|
29
29
|
fastmcp/prompts/__init__.py,sha256=An8uMBUh9Hrb7qqcn_5_Hent7IOeSh7EA2IUVsIrtHc,179
|
|
30
|
-
fastmcp/prompts/prompt.py,sha256=
|
|
31
|
-
fastmcp/prompts/prompt_manager.py,sha256=
|
|
30
|
+
fastmcp/prompts/prompt.py,sha256=IZncQ5NrrAdbuQv9iMYGlBdkfteJpLdLGMK8cxVV3xw,9041
|
|
31
|
+
fastmcp/prompts/prompt_manager.py,sha256=TKFxndDH5mHzk2b35TlaNpMz0gRf2OV_17gH2bMKAcU,4369
|
|
32
32
|
fastmcp/resources/__init__.py,sha256=y1iAuqx-GIrS1NqIYzKezIDiYyjNEzzHD35epHpMnXE,463
|
|
33
|
-
fastmcp/resources/resource.py,sha256=
|
|
34
|
-
fastmcp/resources/resource_manager.py,sha256=
|
|
35
|
-
fastmcp/resources/template.py,sha256=
|
|
33
|
+
fastmcp/resources/resource.py,sha256=CY7clkTrF1_3z1yT2HvkA7tGSX9uY0iyZ2AVAXreCCE,4980
|
|
34
|
+
fastmcp/resources/resource_manager.py,sha256=y7J8nnLbCPl_9IASYw2IzmUEwDhS56FWi0Dare9Uf2U,11951
|
|
35
|
+
fastmcp/resources/template.py,sha256=ohbjlgMzkhVjmjhqa1Bkh5jzj6oWOHKwRxcneYZDt1Q,8415
|
|
36
36
|
fastmcp/resources/types.py,sha256=SiYNLnpXT-mHgNUrzqKUvXYUsY-V3gwJIrYdJfFwDDo,4868
|
|
37
37
|
fastmcp/server/__init__.py,sha256=bMD4aQD4yJqLz7-mudoNsyeV8UgQfRAg3PRwPvwTEds,119
|
|
38
|
-
fastmcp/server/context.py,sha256=
|
|
38
|
+
fastmcp/server/context.py,sha256=Ibn3nv2RpwttPzxElbAkZJNX_SiXrjCCjN5S0vwnGVY,10257
|
|
39
39
|
fastmcp/server/dependencies.py,sha256=iKJdz1XsVJcrfHo_reXj9ZSldw-HeAwsp9S6lAgfGA8,2358
|
|
40
40
|
fastmcp/server/http.py,sha256=2v4_N9piolv4z8Nbkn8K0TtHOZzs683mUNA81uGdDdY,11687
|
|
41
|
-
fastmcp/server/openapi.py,sha256=
|
|
42
|
-
fastmcp/server/proxy.py,sha256=
|
|
43
|
-
fastmcp/server/server.py,sha256=
|
|
41
|
+
fastmcp/server/openapi.py,sha256=rF8umkOQGLejDVH7Ef36QdMmjv6zwPB5tmkgmQscM7A,39539
|
|
42
|
+
fastmcp/server/proxy.py,sha256=t0y3mw4X5yO084nevBL-a5mvrLyGc8491F0OTHeuUPQ,10030
|
|
43
|
+
fastmcp/server/server.py,sha256=Umn_yjPHcwmxu-PTQGCmuD3GTbWEY2BcUBVqq5ej2CQ,73895
|
|
44
44
|
fastmcp/server/auth/__init__.py,sha256=doHCLwOIElvH1NrTdpeP9JKfnNf3MDYPSpQfdsQ-uI0,84
|
|
45
45
|
fastmcp/server/auth/auth.py,sha256=kz02HGwXYU0N0clURZDjFNWdKSpTYmgmCnGJN-jSG3Y,1640
|
|
46
46
|
fastmcp/server/auth/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
fastmcp/server/auth/providers/bearer.py,sha256=3pTKL3tEU7FlCD5yI81LTa2n0dBsM7GRpIIn30WCWsA,12679
|
|
48
|
-
fastmcp/server/auth/providers/bearer_env.py,sha256=
|
|
49
|
-
fastmcp/server/auth/providers/in_memory.py,sha256=
|
|
50
|
-
fastmcp/tools/__init__.py,sha256=
|
|
51
|
-
fastmcp/tools/tool.py,sha256=
|
|
52
|
-
fastmcp/tools/tool_manager.py,sha256=
|
|
48
|
+
fastmcp/server/auth/providers/bearer_env.py,sha256=zHbJmzT6RhEW9tGG-_aRACQ_t0GwXCvKEAnKQLCO9mY,1892
|
|
49
|
+
fastmcp/server/auth/providers/in_memory.py,sha256=_8hRo6KZEVqsSSMNxpseJH48LZEywF4uZ687XuOmqYw,13772
|
|
50
|
+
fastmcp/tools/__init__.py,sha256=vzqb-Y7Kf0d5T0aOsld-O-FA8kD7-4uFExChewFHEzY,201
|
|
51
|
+
fastmcp/tools/tool.py,sha256=UoqX8Hv2FsYYQkP8dpPlvPoDZMMZf4VJagt6_76iqtE,11123
|
|
52
|
+
fastmcp/tools/tool_manager.py,sha256=gq7wYrj1EMjmqJgnJ_ozipEVWmnlSNjIe1zL0-OObss,4805
|
|
53
|
+
fastmcp/tools/tool_transform.py,sha256=pBRLu6qoXsdg1fwkV219PyJQy_Rp6fFCNOqFFbI4VOc,27612
|
|
53
54
|
fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
|
|
54
55
|
fastmcp/utilities/cache.py,sha256=aV3oZ-ZhMgLSM9iAotlUlEy5jFvGXrVo0Y5Bj4PBtqY,707
|
|
55
|
-
fastmcp/utilities/
|
|
56
|
+
fastmcp/utilities/components.py,sha256=NJXop6vn42DC2MyLtJRuJ7QEyac4T5WcOsYaClIog6E,1669
|
|
57
|
+
fastmcp/utilities/exceptions.py,sha256=7Z9j5IzM5rT27BC1Mcn8tkS-bjqCYqMKwb2MMTaxJYU,1350
|
|
56
58
|
fastmcp/utilities/http.py,sha256=1ns1ymBS-WSxbZjGP6JYjSO52Wa_ls4j4WbnXiupoa4,245
|
|
57
59
|
fastmcp/utilities/json_schema.py,sha256=m65XU9lPq7pCxJ9vvCeGRl0HOFr6ArezvYpMBR6-gAg,3777
|
|
58
60
|
fastmcp/utilities/logging.py,sha256=B1WNO-ZWFjd9wiFSh13YtW1hAKaNmbpscDZleIAhr-g,1317
|
|
59
|
-
fastmcp/utilities/mcp_config.py,sha256=
|
|
61
|
+
fastmcp/utilities/mcp_config.py,sha256=kbmvpF5YE7eiDH68XObagFGPKw26SwuDchmH7pyFSD4,2519
|
|
60
62
|
fastmcp/utilities/openapi.py,sha256=ctceiGb4jYgzZGSseMb-yZccEEXf41P-dhB3ae9lGdk,38992
|
|
61
|
-
fastmcp/utilities/tests.py,sha256=
|
|
62
|
-
fastmcp/utilities/types.py,sha256=
|
|
63
|
-
fastmcp-2.
|
|
64
|
-
fastmcp-2.
|
|
65
|
-
fastmcp-2.
|
|
66
|
-
fastmcp-2.
|
|
67
|
-
fastmcp-2.
|
|
63
|
+
fastmcp/utilities/tests.py,sha256=72ryn-IyrvE9BKL_RPJ6T__qTcSRp8yzhOQSM6cdYpE,3903
|
|
64
|
+
fastmcp/utilities/types.py,sha256=Ro5UMB1K-uKtLgzbCCHAb_3ABh0v7QF5Or70_0Yyo00,6650
|
|
65
|
+
fastmcp-2.8.1.dist-info/METADATA,sha256=hJrGycsSOIR62GmBlTfYRS6GN7LjPa3eLsrpDO58HCM,17773
|
|
66
|
+
fastmcp-2.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
67
|
+
fastmcp-2.8.1.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
|
|
68
|
+
fastmcp-2.8.1.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
69
|
+
fastmcp-2.8.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|