Skip to main content
Glama

nixhub_find_version

Find specific package versions in NixHub by searching with increasing limits. Input package name and version to get version info and commit hash.

Instructions

Find a specific version of a package in NixHub with smart search.

Automatically searches with increasing limits to find the requested version.

Args: package_name: Name of the package to query (e.g., "ruby", "python") version: Specific version to find (e.g., "2.6.7", "3.5.9")

Returns: Plain text with version info and commit hash if found, or helpful message if not

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
package_nameYes
versionYes

Implementation Reference

  • The main execution logic for the 'nixhub_find_version' tool. This async function queries NixHub API to find specific package versions, handles errors, formats responses with commit hashes and installation instructions.
    @mcp.tool() async def nixhub_find_version(package_name: str, version: str) -> str: """Find a specific version of a package in NixHub with smart search. Automatically searches with increasing limits to find the requested version. Args: package_name: Name of the package to query (e.g., "ruby", "python") version: Specific version to find (e.g., "2.6.7", "3.5.9") Returns: Plain text with version info and commit hash if found, or helpful message if not """ # Validate inputs if not package_name or not package_name.strip(): return error("Package name is required") if not version or not version.strip(): return error("Version is required") # Sanitize inputs if not re.match(r"^[a-zA-Z0-9\-_.]+$", package_name): return error("Invalid package name. Only letters, numbers, hyphens, underscores, and dots are allowed") # Try with incremental limits limits_to_try = [10, 25, 50] found_version = None all_versions: list[dict[str, Any]] = [] for limit in limits_to_try: try: # Make request - handle special cases for package names nixhub_name = package_name # Common package name mappings if package_name == "python": nixhub_name = "python3" elif package_name == "python2": nixhub_name = "python" url = f"https://www.nixhub.io/packages/{nixhub_name}?_data=routes%2F_nixhub.packages.%24pkg._index" headers = {"Accept": "application/json", "User-Agent": "mcp-nixos/1.0.0"} resp = requests.get(url, headers=headers, timeout=15) if resp.status_code == 404: return error(f"Package '{package_name}' not found in NixHub", "NOT_FOUND") if resp.status_code >= 500: return error("NixHub service temporarily unavailable", "SERVICE_ERROR") resp.raise_for_status() data = resp.json() if not isinstance(data, dict): return error("Invalid response format from NixHub") releases = data.get("releases", []) # Collect all versions seen for release in releases[:limit]: release_version = release.get("version", "") if release_version and release_version not in [v["version"] for v in all_versions]: all_versions.append({"version": release_version, "release": release}) # Check if this is the version we're looking for if release_version == version: found_version = release break if found_version: break except requests.Timeout: return error("Request to NixHub timed out", "TIMEOUT") except requests.RequestException as e: return error(f"Network error accessing NixHub: {str(e)}", "NETWORK_ERROR") except Exception as e: return error(f"Unexpected error: {str(e)}") # Format response if found_version: return _format_nixhub_found_version(package_name, version, found_version) # Version not found - provide helpful information results = [] results.append(f"✗ {package_name} version {version} not found in NixHub\n") # Show available versions if all_versions: results.append(f"Available versions (checked {len(all_versions)} total):") # Sort versions properly using version comparison sorted_versions = sorted(all_versions, key=lambda x: _version_key(x["version"]), reverse=True) # Find newest and oldest newest = sorted_versions[0]["version"] oldest = sorted_versions[-1]["version"] results.append(f"• Newest: {newest}") results.append(f"• Oldest: {oldest}") # Show version range summary major_versions = set() for v in all_versions: parts = v["version"].split(".") if parts: major_versions.add(parts[0]) if major_versions: results.append(f"• Major versions available: {', '.join(sorted(major_versions, reverse=True))}") # Check if requested version is older than available try: requested_parts = version.split(".") oldest_parts = oldest.split(".") if len(requested_parts) >= 2 and len(oldest_parts) >= 2: req_major = int(requested_parts[0]) req_minor = int(requested_parts[1]) old_major = int(oldest_parts[0]) old_minor = int(oldest_parts[1]) if req_major < old_major or (req_major == old_major and req_minor < old_minor): results.append(f"\nVersion {version} is older than the oldest available ({oldest})") results.append("This version may have been removed after reaching end-of-life.") except (ValueError, IndexError): pass results.append("\nAlternatives:") results.append("• Use a newer version if possible") results.append("• Build from source with a custom derivation") results.append("• Use Docker/containers with the specific version") results.append("• Find an old nixpkgs commit from before the version was removed") return "\n".join(results)
  • Input schema defined by function parameters (package_name: str, version: str) and output str as plain text response. Includes detailed docstring with examples.
    async def nixhub_find_version(package_name: str, version: str) -> str: """Find a specific version of a package in NixHub with smart search. Automatically searches with increasing limits to find the requested version. Args: package_name: Name of the package to query (e.g., "ruby", "python") version: Specific version to find (e.g., "2.6.7", "3.5.9") Returns: Plain text with version info and commit hash if found, or helpful message if not
  • Tool registration via FastMCP @mcp.tool() decorator, which registers the function under the name 'nixhub_find_version'.
    @mcp.tool()
  • Helper function used by nixhub_find_version to format successful version findings including commit hashes and usage instructions.
    def _format_nixhub_found_version(package_name: str, version: str, found_version: dict[str, Any]) -> str: """Format a found version for display.""" results = [] results.append(f"✓ Found {package_name} version {version}\n") last_updated = found_version.get("last_updated", "") if last_updated: try: from datetime import datetime dt = datetime.fromisoformat(last_updated.replace("Z", "+00:00")) formatted_date = dt.strftime("%Y-%m-%d %H:%M UTC") results.append(f"Last updated: {formatted_date}") except Exception: results.append(f"Last updated: {last_updated}") platforms_summary = found_version.get("platforms_summary", "") if platforms_summary: results.append(f"Platforms: {platforms_summary}") # Show commit hashes platforms = found_version.get("platforms", []) if platforms: results.append("\nNixpkgs commits:") seen_commits = set() for platform in platforms: attr_path = platform.get("attribute_path", "") commit_hash = platform.get("commit_hash", "") if commit_hash and commit_hash not in seen_commits: seen_commits.add(commit_hash) if re.match(r"^[a-fA-F0-9]{40}$", commit_hash): results.append(f"• {commit_hash}") if attr_path: results.append(f" Attribute: {attr_path}") results.append("\nTo use this version:") results.append("1. Pin nixpkgs to one of the commit hashes above") results.append("2. Install using the attribute path") return "\n".join(results)
  • Utility function to parse and compare version strings for sorting available versions when target not found.
    def _version_key(version_str: str) -> tuple[int, int, int]: """Convert version string to tuple for proper sorting.""" try: parts = version_str.split(".") # Handle versions like "3.9.9" or "3.10.0-rc1" numeric_parts = [] for part in parts[:3]: # Major.Minor.Patch # Extract numeric part numeric = "" for char in part: if char.isdigit(): numeric += char else: break if numeric: numeric_parts.append(int(numeric)) else: numeric_parts.append(0) # Pad with zeros if needed while len(numeric_parts) < 3: numeric_parts.append(0) return (numeric_parts[0], numeric_parts[1], numeric_parts[2]) except Exception: return (0, 0, 0)

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