Spaces:
Running
Running
Merge pull request #747 from jlowin/cache
Browse filesRespect cache setting, set default to 1 second
- src/fastmcp/server/server.py +6 -1
- src/fastmcp/settings.py +1 -1
- tests/server/test_mount.py +13 -0
src/fastmcp/server/server.py
CHANGED
|
@@ -41,6 +41,7 @@ from starlette.requests import Request
|
|
| 41 |
from starlette.responses import Response
|
| 42 |
from starlette.routing import BaseRoute, Route
|
| 43 |
|
|
|
|
| 44 |
import fastmcp.server
|
| 45 |
import fastmcp.settings
|
| 46 |
from fastmcp.exceptions import NotFoundError
|
|
@@ -131,6 +132,8 @@ class FastMCP(Generic[LifespanResultT]):
|
|
| 131 |
tools: list[Tool | Callable[..., Any]] | None = None,
|
| 132 |
**settings: Any,
|
| 133 |
):
|
|
|
|
|
|
|
| 134 |
self.settings = fastmcp.settings.ServerSettings(**settings)
|
| 135 |
|
| 136 |
# If mask_error_details is provided, override the settings value
|
|
@@ -148,7 +151,9 @@ class FastMCP(Generic[LifespanResultT]):
|
|
| 148 |
self.tags: set[str] = tags or set()
|
| 149 |
self.dependencies = dependencies
|
| 150 |
self._cache = TimedCache(
|
| 151 |
-
expiration=datetime.timedelta(
|
|
|
|
|
|
|
| 152 |
)
|
| 153 |
self._mounted_servers: dict[str, MountedServer] = {}
|
| 154 |
self._additional_http_routes: list[BaseRoute] = []
|
|
|
|
| 41 |
from starlette.responses import Response
|
| 42 |
from starlette.routing import BaseRoute, Route
|
| 43 |
|
| 44 |
+
import fastmcp
|
| 45 |
import fastmcp.server
|
| 46 |
import fastmcp.settings
|
| 47 |
from fastmcp.exceptions import NotFoundError
|
|
|
|
| 132 |
tools: list[Tool | Callable[..., Any]] | None = None,
|
| 133 |
**settings: Any,
|
| 134 |
):
|
| 135 |
+
if cache_expiration_seconds is not None:
|
| 136 |
+
settings["cache_expiration_seconds"] = cache_expiration_seconds
|
| 137 |
self.settings = fastmcp.settings.ServerSettings(**settings)
|
| 138 |
|
| 139 |
# If mask_error_details is provided, override the settings value
|
|
|
|
| 151 |
self.tags: set[str] = tags or set()
|
| 152 |
self.dependencies = dependencies
|
| 153 |
self._cache = TimedCache(
|
| 154 |
+
expiration=datetime.timedelta(
|
| 155 |
+
seconds=self.settings.cache_expiration_seconds
|
| 156 |
+
)
|
| 157 |
)
|
| 158 |
self._mounted_servers: dict[str, MountedServer] = {}
|
| 159 |
self._additional_http_routes: list[BaseRoute] = []
|
src/fastmcp/settings.py
CHANGED
|
@@ -170,7 +170,7 @@ class ServerSettings(BaseSettings):
|
|
| 170 |
),
|
| 171 |
] = []
|
| 172 |
|
| 173 |
-
# cache settings (for
|
| 174 |
cache_expiration_seconds: float = 0
|
| 175 |
|
| 176 |
# StreamableHTTP settings
|
|
|
|
| 170 |
),
|
| 171 |
] = []
|
| 172 |
|
| 173 |
+
# cache settings (for getting attributes from servers, used to avoid repeated calls)
|
| 174 |
cache_expiration_seconds: float = 0
|
| 175 |
|
| 176 |
# StreamableHTTP settings
|
tests/server/test_mount.py
CHANGED
|
@@ -304,6 +304,19 @@ class TestDynamicChanges:
|
|
| 304 |
tools = await main_app.get_tools()
|
| 305 |
assert "sub_temp_tool" not in tools
|
| 306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
|
| 308 |
class TestResourcesAndTemplates:
|
| 309 |
"""Test mounting with resources and resource templates."""
|
|
|
|
| 304 |
tools = await main_app.get_tools()
|
| 305 |
assert "sub_temp_tool" not in tools
|
| 306 |
|
| 307 |
+
async def test_cache_expiration(self):
|
| 308 |
+
main_app = FastMCP("MainApp", cache_expiration_seconds=2)
|
| 309 |
+
sub_app = FastMCP("SubApp")
|
| 310 |
+
tools = await main_app.get_tools()
|
| 311 |
+
assert len(tools) == 0
|
| 312 |
+
|
| 313 |
+
@sub_app.tool
|
| 314 |
+
def sub_tool():
|
| 315 |
+
return "sub_tool"
|
| 316 |
+
|
| 317 |
+
tools = await main_app.get_tools()
|
| 318 |
+
assert len(tools) == 0
|
| 319 |
+
|
| 320 |
|
| 321 |
class TestResourcesAndTemplates:
|
| 322 |
"""Test mounting with resources and resource templates."""
|