Skip to main content
Glama

darwin_stats

Retrieve statistics about nix-darwin configuration options, including total count, categories, and top categories for system configuration analysis.

Instructions

Get statistics about nix-darwin options.

Retrieves overall statistics including total options, categories, and top categories.

Returns: Plain text summary with total options, category count, and top 5 categories

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The 'darwin_stats' tool handler: parses nix-darwin HTML docs using parse_html_options, computes category and type statistics, formats and returns plain text summary of total options, categories, and top categories.
    @mcp.tool()
    async def darwin_stats() -> str:
        """Get statistics about nix-darwin options.
    
        Retrieves overall statistics including total options, categories, and top categories.
    
        Returns:
            Plain text summary with total options, category count, and top 5 categories
        """
        try:
            # Parse all options to get statistics
            options = parse_html_options(DARWIN_URL, limit=3000)
    
            if not options:
                return error("Failed to fetch nix-darwin statistics")
    
            # Count categories
            categories: dict[str, int] = {}
            for opt in options:
                cat = opt["name"].split(".")[0]
                categories[cat] = categories.get(cat, 0) + 1
    
            # Count types
            types: dict[str, int] = {}
            for opt in options:
                opt_type = opt.get("type", "unknown")
                if opt_type:
                    # Simplify complex types
                    if "null or" in opt_type:
                        opt_type = "nullable"
                    elif "list of" in opt_type:
                        opt_type = "list"
                    elif "attribute set" in opt_type:
                        opt_type = "attribute set"
                    types[opt_type] = types.get(opt_type, 0) + 1
    
            # Build statistics
            return f"""nix-darwin Statistics:
    • Total options: {len(options):,}
    • Categories: {len(categories)}
    • Top categories:
      - services: {categories.get("services", 0):,} options
      - system: {categories.get("system", 0):,} options
      - launchd: {categories.get("launchd", 0):,} options
      - programs: {categories.get("programs", 0):,} options
      - homebrew: {categories.get("homebrew", 0):,} options"""
        except Exception as e:
            return error(str(e))
  • Shared helper function parse_html_options used by darwin_stats (and others) to scrape option definitions from HTML documentation pages using BeautifulSoup, extracting name, description, and type for each option.
    def parse_html_options(url: str, query: str = "", prefix: str = "", limit: int = 100) -> list[dict[str, str]]:
        """Parse options from HTML documentation."""
        try:
            resp = requests.get(url, timeout=30)  # Increase timeout for large docs
            resp.raise_for_status()
            # Use resp.content to let BeautifulSoup handle encoding detection
            # This prevents encoding errors like "unknown encoding: windows-1252"
            soup = BeautifulSoup(resp.content, "html.parser")
            options = []
    
            # Get all dt elements
            dts = soup.find_all("dt")
    
            for dt in dts:
                # Get option name
                name = ""
                if "home-manager" in url:
                    # Home Manager uses anchor IDs like "opt-programs.git.enable"
                    anchor = dt.find("a", id=True)
                    if anchor:
                        anchor_id = anchor.get("id", "")
                        # Remove "opt-" prefix and convert underscores
                        if anchor_id.startswith("opt-"):
                            name = anchor_id[4:]  # Remove "opt-" prefix
                            # Convert _name_ placeholders back to <name>
                            name = name.replace("_name_", "<name>")
                    else:
                        # Fallback to text content
                        name_elem = dt.find(string=True, recursive=False)
                        if name_elem:
                            name = name_elem.strip()
                        else:
                            name = dt.get_text(strip=True)
                else:
                    # Darwin and fallback - use text content
                    name = dt.get_text(strip=True)
    
                # Skip if it doesn't look like an option (must contain a dot)
                # But allow single-word options in some cases
                if "." not in name and len(name.split()) > 1:
                    continue
    
                # Filter by query or prefix
                if query and query.lower() not in name.lower():
                    continue
                if prefix and not (name.startswith(prefix + ".") or name == prefix):
                    continue
    
                # Find the corresponding dd element
                dd = dt.find_next_sibling("dd")
                if dd:
                    # Extract description (first p tag or direct text)
                    desc_elem = dd.find("p")
                    if desc_elem:
                        description = desc_elem.get_text(strip=True)
                    else:
                        # Get first text node, handle None case
                        text = dd.get_text(strip=True)
                        description = text.split("\n")[0] if text else ""
    
                    # Extract type info - look for various patterns
                    type_info = ""
                    # Pattern 1: <span class="term">Type: ...</span>
                    type_elem = dd.find("span", class_="term")
                    if type_elem and "Type:" in type_elem.get_text():
                        type_info = type_elem.get_text(strip=True).replace("Type:", "").strip()
                    # Pattern 2: Look for "Type:" in text
                    elif "Type:" in dd.get_text():
                        text = dd.get_text()
                        type_start = text.find("Type:") + 5
                        type_end = text.find("\n", type_start)
                        if type_end == -1:
                            type_end = len(text)
                        type_info = text[type_start:type_end].strip()
    
                    options.append(
                        {
                            "name": name,
                            "description": description[:200] if len(description) > 200 else description,
                            "type": type_info,
                        }
                    )
    
                    if len(options) >= limit:
                        break
    
            return options
        except Exception as exc:
            raise DocumentParseError(f"Failed to fetch docs: {str(exc)}") from exc

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/utensils/mcp-nixos'

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