Skip to main content
Glama
config.py3.79 kB
"""Configuration module for the Zettelkasten MCP server.""" import os from pathlib import Path from dotenv import load_dotenv from pydantic import BaseModel, Field from sqlalchemy.engine.url import make_url def _default_database_setting() -> str: """Determine the default database configuration string.""" return ( os.getenv("ZETTELKASTEN_DATABASE") or os.getenv("ZETTELKASTEN_DATABASE_URL") or os.getenv("ZETTELKASTEN_DATABASE_PATH") or "data/db/zettelkasten.db" ) # Load environment variables load_dotenv() class ZettelkastenConfig(BaseModel): """Configuration for the Zettelkasten server.""" # Base directory for the project base_dir: Path = Field( default_factory=lambda: Path(os.getenv("ZETTELKASTEN_BASE_DIR") or ".") ) # Storage configuration notes_dir: Path = Field( default_factory=lambda: Path( os.getenv("ZETTELKASTEN_NOTES_DIR") or "data/notes" ) ) # Database configuration (path or SQLAlchemy URL) database: str = Field(default_factory=_default_database_setting) # Server configuration server_name: str = Field( default=os.getenv("ZETTELKASTEN_SERVER_NAME", "zettelkasten-mcp") ) server_version: str = Field(default="1.2.1") # Date format for ID generation (using ISO format for timestamps) id_date_format: str = Field(default="%Y%m%dT%H%M%S") # Default note template default_note_template: str = Field( default=( "# {title}\n\n" "## Metadata\n" "- Created: {created_at}\n" "- Tags: {tags}\n\n" "## Content\n\n" "{content}\n\n" "## Links\n" "{links}\n" ) ) def get_absolute_path(self, path: Path) -> Path: """Convert a relative path to an absolute path based on base_dir.""" if path.is_absolute(): return path return self.base_dir / path def _is_database_url(self) -> bool: """Return True when the database setting looks like a SQLAlchemy URL.""" value = (self.database or "").strip() return "://" in value def _ensure_sqlite_directory(self, db_url: str) -> None: """Ensure directories exist for SQLite URLs.""" try: url = make_url(db_url) except Exception: return if url.get_backend_name() != "sqlite" or not url.database: return db_path = Path(url.database) if not db_path.is_absolute(): db_path = self.get_absolute_path(db_path) db_path.parent.mkdir(parents=True, exist_ok=True) def get_db_url(self) -> str: """Return a SQLAlchemy-compatible database URL.""" if self._is_database_url(): url = make_url(self.database) if ( url.get_backend_name() == "sqlite" and url.database and url.database != ":memory:" ): db_path = Path(url.database) if not db_path.is_absolute(): db_path = self.get_absolute_path(db_path) url = url.set(database=str(db_path)) db_url = url.render_as_string(hide_password=False) else: db_path = self.get_absolute_path(Path(self.database)) db_url = f"sqlite:///{db_path}" self._ensure_sqlite_directory(db_url) return db_url def uses_sqlite(self) -> bool: """Return True if the database backend is SQLite.""" try: return make_url(self.get_db_url()).get_backend_name() == "sqlite" except Exception: return self.get_db_url().startswith("sqlite:") # Create a global config instance config = ZettelkastenConfig()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Liam-Deacon/zettelkasten-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server