Removing central storage configuration for now

This commit is contained in:
William Easton 2025-10-06 11:58:11 -05:00
commit dd81a0beb3
No known key found for this signature in database
4 changed files with 9 additions and 53 deletions

View file

@ -12,6 +12,7 @@ import anyio
import httpx
from key_value.aio.adapters.pydantic import PydanticAdapter
from key_value.aio.protocols import AsyncKeyValue
from key_value.aio.stores.memory import MemoryStore
from mcp.client.auth import OAuthClientProvider, TokenStorage
from mcp.shared.auth import (
OAuthClientInformationFull,
@ -21,7 +22,6 @@ from mcp.shared.auth import (
from pydantic import AnyHttpUrl
from uvicorn.server import Server
from fastmcp import settings
from fastmcp.client.oauth_callback import (
create_oauth_callback_server,
)
@ -186,7 +186,7 @@ class OAuth(OAuthClientProvider):
)
# Create server-specific token storage
token_storage = token_storage or settings.key_value_store
token_storage = token_storage or MemoryStore()
self.token_storage_adapter: TokenStorageAdapter = TokenStorageAdapter(
async_key_value=token_storage, server_url=server_base_url

View file

@ -30,6 +30,7 @@ from authlib.common.security import generate_token
from authlib.integrations.httpx_client import AsyncOAuth2Client
from key_value.aio.adapters.pydantic import PydanticAdapter
from key_value.aio.protocols import AsyncKeyValue
from key_value.aio.stores.memory import MemoryStore
from mcp.server.auth.handlers.token import TokenErrorResponse, TokenSuccessResponse
from mcp.server.auth.handlers.token import TokenHandler as _SDKTokenHandler
from mcp.server.auth.json_response import PydanticJSONResponse
@ -52,7 +53,6 @@ from starlette.requests import Request
from starlette.responses import RedirectResponse
from starlette.routing import Route
from fastmcp import settings
from fastmcp.server.auth.auth import OAuthProvider, TokenVerifier
from fastmcp.server.auth.redirect_validation import validate_redirect_uri
from fastmcp.utilities.logging import get_logger
@ -386,7 +386,7 @@ class OAuthProxy(OAuthProvider):
self._extra_authorize_params = extra_authorize_params or {}
self._extra_token_params = extra_token_params or {}
self._client_storage: AsyncKeyValue = client_storage or settings.key_value_store
self._client_storage: AsyncKeyValue = client_storage or MemoryStore()
self._client_store = PydanticAdapter[ProxyDCRClient](
key_value=self._client_storage,

View file

@ -2,11 +2,9 @@ from __future__ import annotations as _annotations
import inspect
import warnings
from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING, Annotated, Any, Literal
from key_value.aio.protocols import AsyncKeyValue
from pydantic import Field, ImportString, field_validator
from pydantic.fields import FieldInfo
from pydantic_settings import (
@ -62,27 +60,6 @@ class ExtendedSettingsConfigDict(SettingsConfigDict, total=False):
env_prefixes: list[str] | None
class DiskStorageSettings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="FASTMCP_STORAGE_",
extra="ignore",
)
directory: Annotated[
str | None,
Field(
description="A custom path to store data in. If set to `None` (default), a folder called `data` will be created in the `home` directory."
),
] = None
max_collection_size: Annotated[
int,
Field(
description="The maximum size for each collection in the storage directory, in bytes."
),
] = TEN_MB_IN_BYTES # 10MB
class ExperimentalSettings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="FASTMCP_EXPERIMENTAL_",
@ -172,13 +149,6 @@ class Settings(BaseSettings):
home: Path = Path.home() / ".fastmcp"
storage: Annotated[
DiskStorageSettings | None,
Field(
description="The default storage settings for the server. Defaults to disk storage, if set to None, data will be stored in memory by default."
),
] = DiskStorageSettings()
test_mode: bool = False
log_enabled: bool = True
@ -411,22 +381,6 @@ class Settings(BaseSettings):
return auth_class
@cached_property
def key_value_store(self) -> AsyncKeyValue:
"""A default data store that can be leveraged as a fallback for components that require storage."""
if not self.storage:
from key_value.aio.stores.memory import MemoryStore
return MemoryStore()
from key_value.aio.stores.disk.multi_store import MultiDiskStore
base_directory: Path = self.storage.directory or (self.home / "data")
return MultiDiskStore(
base_directory=base_directory, max_size=self.storage.max_collection_size
)
def __getattr__(name: str):
"""

View file

@ -28,11 +28,13 @@ class TestOAuthProxyStorage:
@pytest.fixture
async def temp_storage(
self, tmp_path: Path
self
) -> AsyncGenerator[MultiDiskStore, None]:
"""Create file-based storage for testing."""
with tempfile.TemporaryDirectory() as temp_dir:
yield MultiDiskStore(base_directory=Path(temp_dir))
disk_store = MultiDiskStore(base_directory=Path(temp_dir))
yield disk_store
await disk_store.close()
@pytest.fixture
def memory_storage(self) -> MemoryStore:
@ -55,7 +57,7 @@ class TestOAuthProxyStorage:
async def test_default_storage_is_file_based(self, jwt_verifier):
"""Test that proxy defaults to file-based storage."""
proxy = self.create_proxy(jwt_verifier, storage=None)
assert isinstance(proxy._client_storage, MultiDiskStore)
assert isinstance(proxy._client_storage, MemoryStore)
async def test_register_and_get_client(self, jwt_verifier, temp_storage):
"""Test registering and retrieving a client."""