Problem
The MCP server's OAuth state storage uses DiskStore (SQLite via diskcache), which is hardcoded in FastMCP 2.14.x's OAuthProxy.__init__. SQLite is not safe on network filesystems (AWS EFS, NFS). A container restart that races with unflushed NFS writes corrupts the database, causing an unrecoverable crash loop:
File "fastmcp/server/auth/oauth_proxy.py", line 822, in __init__
key_value=DiskStore(directory=settings.home / "oauth-proxy"),
sqlite3.DatabaseError: database disk image is malformed
The only recovery is manually deleting the corrupted cache.db from the volume, destroying all OAuth sessions.
Why this happens
The storage backend is not configurable. When using FASTMCP_SERVER_AUTH, the auth provider is instantiated by FastMCP with no arguments, so client_storage=None, and OAuthProxy falls back to DiskStore:
FASTMCP_SERVER_AUTH env var
-> FastMCP instantiates AzureProvider() with no args
-> AzureProvider passes client_storage=None to OAuthProxy
-> OAuthProxy creates DiskStore(directory=settings.home / "oauth-proxy") <- hardcoded
FastMCP 3.x already solved this by switching the default to FileTreeStore (one JSON file per key, NFS-safe). The OAuthProxy in both 2.14.x and 3.x accepts a client_storage parameter, but the Exasol MCP server has no way to pass it through since auth is configured entirely via environment variables.
Proposed solution
Add an environment variable to select the storage backend. The store directory is already configurable via FASTMCP_HOME, so no additional path variable is needed.
EXA_MCP_STORAGE_BACKEND=filetree # default, NFS-safe, persistent
EXA_MCP_STORAGE_BACKEND=memory # no persistence, no corruption risk
EXA_MCP_STORAGE_BACKEND=disk # current behavior (SQLite, local FS only)
filetree should be the new default. It is persistent (same as current disk), safe on network filesystems, and aligns with FastMCP 3.x's own default. It uses FileTreeStore from py-key-value-aio >=0.3.0, which is already a dependency of FastMCP 2.14.x. The store reuses the existing path at $FASTMCP_HOME/oauth-proxy/ and needs the documented sanitization strategies:
from key_value.aio.stores.filetree import (
FileTreeStore,
FileTreeV1KeySanitizationStrategy,
FileTreeV1CollectionSanitizationStrategy,
)
storage_dir = settings.home / "oauth-proxy"
store = FileTreeStore(
data_directory=storage_dir,
key_sanitization_strategy=FileTreeV1KeySanitizationStrategy(storage_dir),
collection_sanitization_strategy=FileTreeV1CollectionSanitizationStrategy(storage_dir),
)
memory is useful for deployments where OAuth session loss on restart is acceptable and no persistent volume is needed.
Ideally, all backends from py-key-value-aio (Redis, DynamoDB, etc.) would be supported for production distributed deployments, but filetree and memory cover the most common cases.
Note: The filetree extra of py-key-value-aio (providing the aiofile runtime dependency) is not currently installed by FastMCP 2.14.x, which only declares [disk,keyring,memory]. The Docker image build would need to include py-key-value-aio[filetree], or alternatively, the minimum FastMCP version should be bumped to ^3.0.0 where [filetree] is a declared dependency and FileTreeStore is the default.
Environment
exadockerci4/exasol-mcp-server:1.6.0 (FastMCP 2.14.5)
- AWS Fargate Spot with EFS at
/root/.local/share/fastmcp
- Auth:
fastmcp.server.auth.providers.azure.AzureProvider
- Crash triggered by Fargate Spot interruption corrupting SQLite on EFS
Problem
The MCP server's OAuth state storage uses
DiskStore(SQLite viadiskcache), which is hardcoded in FastMCP 2.14.x'sOAuthProxy.__init__. SQLite is not safe on network filesystems (AWS EFS, NFS). A container restart that races with unflushed NFS writes corrupts the database, causing an unrecoverable crash loop:The only recovery is manually deleting the corrupted
cache.dbfrom the volume, destroying all OAuth sessions.Why this happens
The storage backend is not configurable. When using
FASTMCP_SERVER_AUTH, the auth provider is instantiated by FastMCP with no arguments, soclient_storage=None, andOAuthProxyfalls back to DiskStore:FastMCP 3.x already solved this by switching the default to
FileTreeStore(one JSON file per key, NFS-safe). TheOAuthProxyin both 2.14.x and 3.x accepts aclient_storageparameter, but the Exasol MCP server has no way to pass it through since auth is configured entirely via environment variables.Proposed solution
Add an environment variable to select the storage backend. The store directory is already configurable via
FASTMCP_HOME, so no additional path variable is needed.filetreeshould be the new default. It is persistent (same as currentdisk), safe on network filesystems, and aligns with FastMCP 3.x's own default. It usesFileTreeStorefrompy-key-value-aio >=0.3.0, which is already a dependency of FastMCP 2.14.x. The store reuses the existing path at$FASTMCP_HOME/oauth-proxy/and needs the documented sanitization strategies:memoryis useful for deployments where OAuth session loss on restart is acceptable and no persistent volume is needed.Ideally, all backends from
py-key-value-aio(Redis, DynamoDB, etc.) would be supported for production distributed deployments, butfiletreeandmemorycover the most common cases.Note: The
filetreeextra ofpy-key-value-aio(providing theaiofileruntime dependency) is not currently installed by FastMCP 2.14.x, which only declares[disk,keyring,memory]. The Docker image build would need to includepy-key-value-aio[filetree], or alternatively, the minimum FastMCP version should be bumped to^3.0.0where[filetree]is a declared dependency andFileTreeStoreis the default.Environment
exadockerci4/exasol-mcp-server:1.6.0(FastMCP 2.14.5)/root/.local/share/fastmcpfastmcp.server.auth.providers.azure.AzureProvider