"""Loki MCP Server Integration. Manages the local Loki MCP server that exposes homelab log querying through MCP tools. Unlike Cloudflare (remote via mcp-remote), this runs a local Python MCP server that talks to Loki's HTTP API directly. Architecture: Garvis → (stdio) → loki_server.py → HTTP → Loki (loki.apophisnetworking.net) Pattern mirrors cloudflare_mcp.py for consistency. """ import os import sys import logging from typing import Any, Dict, List logger = logging.getLogger(__name__) def _load_config() -> Dict[str, Any]: """Load Loki MCP configuration from environment.""" from mcp_servers.loki.config import ( LOKI_URL, LOKI_TIMEOUT, LOKI_MCP_ENABLED, ) return { "enabled": LOKI_MCP_ENABLED, "url": LOKI_URL, "timeout": LOKI_TIMEOUT, } def is_loki_enabled() -> bool: """Check if the Loki MCP integration is enabled.""" config = _load_config() if not config["enabled"]: return False if not config["url"]: logger.warning("[Loki MCP] Enabled but LOKI_URL is not set") return False return True def get_loki_server_config() -> Dict[str, Any]: """Build the MCP server configuration for Agent SDK registration. Returns the config dict suitable for ClaudeAgentOptions.mcp_servers. This runs a local Python MCP server via stdio (not mcp-remote). """ # Path to the MCP server script server_script = os.path.join( os.path.dirname(__file__), "loki_server.py" ) return { "command": sys.executable, # Use the same Python interpreter "args": [server_script], "env": { "PATH": os.environ.get("PATH", ""), "HOME": os.environ.get("HOME", os.environ.get("USERPROFILE", "")), "APPDATA": os.environ.get("APPDATA", ""), # Pass Loki config through to the subprocess "LOKI_URL": os.environ.get("LOKI_URL", "https://loki.apophisnetworking.net"), "LOKI_TIMEOUT": os.environ.get("LOKI_TIMEOUT", "30"), "LOKI_DEFAULT_LIMIT": os.environ.get("LOKI_DEFAULT_LIMIT", "100"), }, } # Tools exposed by the Loki MCP server. LOKI_TOOLS: List[str] = [ "loki_query", "loki_labels", "loki_label_values", "loki_series", "loki_health", ]