SurfSense/surfsense_mcp/mcp_server/config.py
CREDO23 116291a3b6 refactor(mcp): flatten to mcp_server package, drop src layout
Rename the import package surfsense_mcp -> mcp_server and remove the
src/ layer so the project mirrors the backend's shape (project folder
!= package name, e.g. surfsense_backend/app). Kills the redundant
surfsense_mcp/src/surfsense_mcp nesting.

Distribution name and console command (surfsense-mcp) are unchanged;
only python -m and internal import paths move to mcp_server. Dockerfile
CMD updated; no PYTHONPATH added since the editable install already
makes the package importable.
2026-07-07 20:24:53 +02:00

71 lines
2.2 KiB
Python

"""Runtime configuration, read once from the environment.
Secrets never live in code or client config files — the client (Cursor/Claude)
passes them as environment variables when it launches this server (see README).
"""
from __future__ import annotations
import os
from dataclasses import dataclass
DEFAULT_BASE_URL = "http://localhost:8000"
DEFAULT_API_PREFIX = "/api/v1"
DEFAULT_TIMEOUT_SECONDS = 180.0
DEFAULT_HTTP_HOST = "127.0.0.1"
DEFAULT_HTTP_PORT = 8080
@dataclass(frozen=True)
class Settings:
"""Resolved configuration for a server process."""
base_url: str
api_key: str | None
api_prefix: str
timeout: float
default_workspace: str | None
host: str
port: int
@property
def api_base(self) -> str:
return f"{self.base_url}{self.api_prefix}"
@classmethod
def from_env(cls) -> Settings:
# Optional here: remote (http) callers pass their own key per request in
# a header. ``__main__`` enforces it for stdio, its only source of a key.
api_key = os.environ.get("SURFSENSE_API_KEY", "").strip() or None
base_url = (
os.environ.get("SURFSENSE_BASE_URL", DEFAULT_BASE_URL).strip().rstrip("/")
)
api_prefix = "/" + os.environ.get(
"SURFSENSE_API_PREFIX", DEFAULT_API_PREFIX
).strip().strip("/")
raw_timeout = os.environ.get("SURFSENSE_TIMEOUT", "").strip()
try:
timeout = float(raw_timeout) if raw_timeout else DEFAULT_TIMEOUT_SECONDS
except ValueError:
timeout = DEFAULT_TIMEOUT_SECONDS
default_workspace = os.environ.get("SURFSENSE_WORKSPACE", "").strip() or None
host = os.environ.get("SURFSENSE_MCP_HOST", "").strip() or DEFAULT_HTTP_HOST
raw_port = os.environ.get("SURFSENSE_MCP_PORT", "").strip()
try:
port = int(raw_port) if raw_port else DEFAULT_HTTP_PORT
except ValueError:
port = DEFAULT_HTTP_PORT
return cls(
base_url=base_url,
api_key=api_key,
api_prefix=api_prefix,
timeout=timeout,
default_workspace=default_workspace,
host=host,
port=port,
)