darwin_list_options
List and categorize all nix-darwin configuration options with their counts, sorted alphabetically for easy reference and system configuration management.
Instructions
List all nix-darwin option categories.
Enumerates all top-level categories with their option counts.
Returns: Plain text list of categories sorted alphabetically with option counts
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- mcp_nixos/server.py:1043-1108 (handler)Handler function for the 'darwin_list_options' tool. Lists nix-darwin option categories by parsing HTML docs, categorizing options, filtering valid categories, and sorting by count.async def darwin_list_options() -> str: """List all nix-darwin option categories. Enumerates all top-level categories with their option counts. Returns: Plain text list of categories sorted alphabetically with option counts """ try: # Get more options to see all categories (default 100 is too few) options = parse_html_options(DARWIN_URL, limit=2000) categories: dict[str, int] = {} for opt in options: name = opt["name"] # Process option names if name and not name.startswith("."): if "." in name: cat = name.split(".")[0] else: cat = name # Option without dot is its own category # Valid categories should: # - Be more than 1 character # - Be a valid identifier (allows underscores) # - Not be common value words # - Match typical nix option category patterns if ( len(cat) > 1 and cat.isidentifier() and (cat.islower() or cat.startswith("_")) ): # This ensures valid identifier # Additional filtering for known valid Darwin categories valid_categories = { "documentation", "environment", "fonts", "homebrew", "ids", "launchd", "networking", "nix", "nixpkgs", "power", "programs", "security", "services", "system", "targets", "time", "users", } # Only include if it's in the known valid list or looks like a typical category if cat in valid_categories or (len(cat) >= 3 and not any(char.isdigit() for char in cat)): categories[cat] = categories.get(cat, 0) + 1 results = [] results.append(f"nix-darwin option categories ({len(categories)} total):\n") # Sort by count descending, then alphabetically sorted_cats = sorted(categories.items(), key=lambda x: (-x[1], x[0])) for cat, count in sorted_cats: results.append(f"• {cat} ({count} options)") return "\n".join(results) except Exception as e: return error(str(e))
- mcp_nixos/server.py:247-336 (helper)Shared helper function parse_html_options that scrapes HTML documentation from nix-darwin site (or others) to extract option names, descriptions, and types. Used by darwin_list_options to fetch all options.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
- mcp_nixos/server.py:1043-1043 (registration)The @mcp.tool() decorator registers the darwin_list_options function as an MCP tool.async def darwin_list_options() -> str:
- mcp_nixos/server.py:52-52 (helper)Constant URL for nix-darwin documentation, used by darwin tools including darwin_list_options.DARWIN_URL = "https://nix-darwin.github.io/nix-darwin/manual/index.html"