Skip to main content
Glama
path_utils.py5.98 kB
"""Path helpers for history and artifact storage defaults.""" from __future__ import annotations import os from pathlib import Path from typing import Optional DEFAULT_HISTORY_PATH = Path("logs/doc.jsonl") DEFAULT_ARTIFACT_ROOT = Path("logs/artifacts") DEFAULT_CACHE_SUBDIR = Path("cache") def _get_log_scope() -> str: """Get log scope from environment (global|repo).""" return os.environ.get("IGLOO_MCP_LOG_SCOPE", "global").lower() def _is_namespaced_logs() -> bool: """Check if namespaced logs are enabled.""" val = os.environ.get("IGLOO_MCP_NAMESPACED_LOGS", "false").lower() return val in ("true", "1", "yes", "on") def get_global_base() -> Path: """Return global base directory (~/.igloo_mcp).""" return Path.home() / ".igloo_mcp" def apply_namespacing(subpath: Path) -> Path: """Apply namespacing if enabled (logs/igloo_mcp/... instead of logs/...). Args: subpath: Relative path to modify (e.g., Path("logs/doc.jsonl")) Returns: Modified path with igloo_mcp inserted if namespacing enabled """ if _is_namespaced_logs(): # Replace logs/ with logs/igloo_mcp/ parts = list(subpath.parts) if parts and parts[0] == "logs": parts.insert(1, "igloo_mcp") subpath = Path(*parts) return subpath def _iter_candidate_roots(start: Path) -> list[Path]: """Return candidate repo roots walking up from *start*.""" if not start.is_absolute(): start = start.resolve() candidates = [start] candidates.extend(start.parents) return candidates def find_repo_root(start: Optional[Path] = None) -> Path: """Best-effort detection of the repository root. Walks upward from *start* (default: current working directory) until a directory containing a ``.git`` entry is found. Falls back to *start* if no explicit marker is detected. """ start_path = start or Path.cwd() for candidate in _iter_candidate_roots(start_path): if (candidate / ".git").exists(): return candidate return start_path def _resolve_with_repo_root(raw: str, repo_root: Path) -> Path: path = Path(raw).expanduser() if path.is_absolute(): return path return (repo_root / path).resolve() def resolve_history_path( raw: Optional[str] = None, *, start: Optional[Path] = None ) -> Path: """Return the desired path to the JSONL history file. Precedence: 1. Explicit env path (IGLOO_MCP_QUERY_HISTORY) if raw is None 2. Scope/namespacing defaults if no explicit path 3. Fallback to repo-based defaults Args: raw: Explicit path override (takes highest precedence) start: Starting directory for repo root detection Returns: Resolved path to history file """ # Explicit path takes precedence (back-compat) candidate = raw if raw is not None else os.environ.get("IGLOO_MCP_QUERY_HISTORY") if candidate: repo_root = find_repo_root(start=start) return _resolve_with_repo_root(candidate, repo_root) # Scope-based resolution scope = _get_log_scope() if scope == "global": base = get_global_base() subpath = apply_namespacing(DEFAULT_HISTORY_PATH) return (base / subpath).resolve() else: # repo scope repo_root = find_repo_root(start=start) subpath = apply_namespacing(DEFAULT_HISTORY_PATH) return (repo_root / subpath).resolve() def resolve_artifact_root( raw: Optional[str] = None, *, start: Optional[Path] = None ) -> Path: """Return the root directory for artifacts (queries/results/meta). Precedence: 1. Explicit env path (IGLOO_MCP_ARTIFACT_ROOT) if raw is None 2. Scope/namespacing defaults if no explicit path 3. Fallback to repo-based defaults Args: raw: Explicit path override (takes highest precedence) start: Starting directory for repo root detection Returns: Resolved path to artifact root directory """ # Explicit path takes precedence (back-compat) candidate = raw if raw is not None else os.environ.get("IGLOO_MCP_ARTIFACT_ROOT") if candidate: repo_root = find_repo_root(start=start) return _resolve_with_repo_root(candidate, repo_root) # Scope-based resolution scope = _get_log_scope() if scope == "global": base = get_global_base() subpath = apply_namespacing(DEFAULT_ARTIFACT_ROOT) return (base / subpath).resolve() else: # repo scope repo_root = find_repo_root(start=start) subpath = apply_namespacing(DEFAULT_ARTIFACT_ROOT) return (repo_root / subpath).resolve() def resolve_cache_root( raw: Optional[str] = None, *, start: Optional[Path] = None, artifact_root: Optional[Path] = None, ) -> Path: """Return the root directory for cached query results. Precedence: 1. Explicit env path (IGLOO_MCP_CACHE_ROOT) if raw is None 2. Derived from artifact_root if provided 3. Scope/namespacing defaults if no explicit path 4. Fallback to repo-based defaults Args: raw: Explicit path override (takes highest precedence) start: Starting directory for repo root detection artifact_root: Optional artifact root (cache is subdirectory) Returns: Resolved path to cache root directory """ # Explicit path takes precedence (back-compat) candidate = raw if raw is not None else os.environ.get("IGLOO_MCP_CACHE_ROOT") if candidate: repo_root = find_repo_root(start=start) return _resolve_with_repo_root(candidate, repo_root) # Derive from artifact_root if provided if artifact_root is not None: return (artifact_root / DEFAULT_CACHE_SUBDIR).resolve() # Scope-based resolution (inherits from artifact_root resolution) artifact_path = resolve_artifact_root(start=start) return (artifact_path / DEFAULT_CACHE_SUBDIR).resolve()

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/Evan-Kim2028/igloo-mcp'

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