Two bugs made `uvx --from . nextcloud-mcp-server run` (and any pip install) unusable outside Docker: 1. Dynaconf was configured with ignore_unknown_envvars=True and relied on settings.toml to declare the key schema. With no settings.toml in a wheel install, every env var (NEXTCLOUD_HOST, MCP_DEPLOYMENT_MODE, ...) was silently dropped. Moved the schema into a Python _DEFAULTS dict passed directly to Dynaconf, kept settings.toml as an optional external override (renamed to settings.toml.example, gitignored), and pointed docker-compose at the example file. 2. Token SQLite DB defaulted to /app/data/tokens.db in multiple places (auth/storage.py, migrations.py, alembic/env.py, cli.py db subcommands), which blew up at uvicorn startup with FileNotFoundError on non-Docker hosts. Replaced with a new config.get_token_db_path() helper that resolves TOKEN_STORAGE_DB if explicitly set, otherwise allocates a per-process tempfile cleaned up at interpreter exit via atexit — mirroring the "ephemeral by default" pattern used for QDRANT_LOCATION=:memory:. Containers are unaffected: docker-compose services now explicitly set TOKEN_STORAGE_DB=/app/data/tokens.db (the fourth service that was missing this pin has been brought in line with the other three). Verified end-to-end in an isolated /tmp venv: env-var-only startup, Alembic migrations run against the tempfile, Application startup complete, /health/live returns 200, tempfile deleted on SIGTERM. Unit tests (464) + ruff + ty pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
92 lines
2.3 KiB
INI
92 lines
2.3 KiB
INI
# Alembic configuration file for nextcloud-mcp-server
|
|
|
|
[alembic]
|
|
# Path to migration scripts
|
|
script_location = nextcloud_mcp_server/alembic
|
|
|
|
# Template used to generate migration file names
|
|
# Default: %%(rev)s_%%(slug)s
|
|
file_template = %%(year)d%%(month).2d%%(day).2d_%%(hour).2d%%(minute).2d_%%(rev)s_%%(slug)s
|
|
|
|
# Timezone for migration timestamps
|
|
# Default: utc
|
|
timezone = utc
|
|
|
|
# Max length of characters to apply to the "slug" field
|
|
# Default: 40
|
|
# truncate_slug_length = 40
|
|
|
|
# Set to 'true' to run the environment during the 'revision' command
|
|
# Default: false
|
|
# revision_environment = false
|
|
|
|
# Set to 'true' to allow .pyc and .pyo files without a source .py file
|
|
# Default: false
|
|
# sourceless = false
|
|
|
|
# Version location specification
|
|
# Supports single or multiple directories
|
|
version_locations = nextcloud_mcp_server/alembic/versions
|
|
|
|
# Path separator for version locations (required to suppress deprecation warning)
|
|
# Use os (for cross-platform compatibility)
|
|
path_separator = os
|
|
|
|
# Set to 'true' to search source files recursively in each "version_locations" directory
|
|
# Default: false
|
|
# recursive_version_locations = false
|
|
|
|
# Output encoding used when revision files are written
|
|
# Default: utf-8
|
|
# output_encoding = utf-8
|
|
|
|
# Database URL - placeholder only.
|
|
# Runtime code (migrations.get_alembic_config / alembic/env.get_database_url)
|
|
# overrides this with config.get_token_db_path() which defaults to an
|
|
# ephemeral per-process tempfile unless TOKEN_STORAGE_DB is set.
|
|
# This value only matters for manual `alembic` invocations from the repo root.
|
|
sqlalchemy.url = sqlite+aiosqlite:///./tokens.db
|
|
|
|
[post_write_hooks]
|
|
# Post-write hooks allow you to run scripts after generating migration files
|
|
# Example: format migrations with ruff
|
|
# hooks = ruff
|
|
# ruff.type = exec
|
|
# ruff.executable = ruff
|
|
# ruff.options = format REVISION_SCRIPT_FILENAME
|
|
|
|
# Logging configuration
|
|
[loggers]
|
|
keys = root,sqlalchemy,alembic
|
|
|
|
[handlers]
|
|
keys = console
|
|
|
|
[formatters]
|
|
keys = generic
|
|
|
|
[logger_root]
|
|
level = WARN
|
|
handlers = console
|
|
qualname =
|
|
|
|
[logger_sqlalchemy]
|
|
level = WARN
|
|
handlers =
|
|
qualname = sqlalchemy.engine
|
|
|
|
[logger_alembic]
|
|
level = INFO
|
|
handlers =
|
|
qualname = alembic
|
|
|
|
[handler_console]
|
|
class = StreamHandler
|
|
args = (sys.stderr,)
|
|
level = NOTSET
|
|
formatter = generic
|
|
|
|
[formatter_generic]
|
|
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
datefmt = %H:%M:%S
|