- Add config_paths.py for XDG-compliant path resolution - Update all servers to use user-writable locations (logs, tokens, .env) - Make .env file optional - server works with environment variables only - Default paths: ~/.local/share for data, ~/.local/state for logs - Update Nix wrapper with XDG defaults and helpful postInstall message - Update README.md with environment variable configuration documentation Fixes OSError when running in Nix store (read-only filesystem)
93 lines
2.6 KiB
Python
93 lines
2.6 KiB
Python
"""
|
|
Centralized path resolution for Basecamp MCP Server.
|
|
|
|
All paths can be overridden via environment variables.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
|
|
def get_log_directory() -> Path:
|
|
"""
|
|
Get the directory for log files.
|
|
|
|
Priority order:
|
|
1. BASECAMP_LOG_DIR env variable
|
|
2. XDG_STATE_HOME (typically ~/.local/state)
|
|
3. ~/.local/state/basecamp-mcp (fallback)
|
|
"""
|
|
if log_dir := os.getenv("BASECAMP_LOG_DIR"):
|
|
return Path(log_dir)
|
|
|
|
if xdg_state := os.getenv("XDG_STATE_HOME"):
|
|
return Path(xdg_state) / "basecamp-mcp"
|
|
|
|
return Path.home() / ".local/state/basecamp-mcp"
|
|
|
|
|
|
def get_config_directory() -> Path:
|
|
"""
|
|
Get the directory for configuration files (.env).
|
|
|
|
Priority order:
|
|
1. BASECAMP_CONFIG_DIR env variable
|
|
2. XDG_CONFIG_HOME (typically ~/.config)
|
|
3. ~/.config/basecamp-mcp (fallback)
|
|
|
|
NOTE: This is only used if BASECAMP_ENV_FILE is not set and
|
|
a .env file exists in the config directory. The server works
|
|
entirely with environment variables and doesn't require .env files.
|
|
"""
|
|
if config_dir := os.getenv("BASECAMP_CONFIG_DIR"):
|
|
return Path(config_dir)
|
|
|
|
if xdg_config := os.getenv("XDG_CONFIG_HOME"):
|
|
return Path(xdg_config) / "basecamp-mcp"
|
|
|
|
return Path.home() / ".config/basecamp-mcp"
|
|
|
|
|
|
def get_env_file_path() -> Path:
|
|
"""
|
|
Get the path for .env file (optional).
|
|
|
|
Priority order:
|
|
1. BASECAMP_ENV_FILE env variable (explicitly specified)
|
|
2. Config directory + / .env
|
|
|
|
The server does NOT require this file - it's optional.
|
|
If not found, environment will be used as-is.
|
|
"""
|
|
if env_file := os.getenv("BASECAMP_ENV_FILE"):
|
|
return Path(env_file)
|
|
|
|
return get_config_directory() / ".env"
|
|
|
|
|
|
def get_token_file_path() -> Path:
|
|
"""
|
|
Get the path for OAuth token storage.
|
|
|
|
Priority order:
|
|
1. BASECAMP_TOKEN_FILE env variable
|
|
2. XDG_DATA_HOME (typically ~/.local/share)
|
|
3. ~/.local/share/basecamp-mcp/oauth_tokens.json (fallback)
|
|
"""
|
|
if token_file := os.getenv("BASECAMP_TOKEN_FILE"):
|
|
return Path(token_file)
|
|
|
|
if xdg_data := os.getenv("XDG_DATA_HOME"):
|
|
return Path(xdg_data) / "basecamp-mcp" / "oauth_tokens.json"
|
|
|
|
return Path.home() / ".local/share/basecamp-mcp" / "oauth_tokens.json"
|
|
|
|
|
|
def ensure_directories_exist() -> None:
|
|
"""
|
|
Create all necessary directories if they don't exist.
|
|
"""
|
|
get_log_directory().mkdir(parents=True, exist_ok=True)
|
|
get_config_directory().mkdir(parents=True, exist_ok=True)
|
|
get_token_file_path().parent.mkdir(parents=True, exist_ok=True)
|