This repository has been archived on 2026-03-10. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Torjus Håkestad fd40e73f1b feat: add package indexing to MCP index_revision tool
The options server's index_revision now also indexes packages when running
under nixpkgs-search, matching the CLI behavior. The packages server gets
its own index_revision tool for standalone package indexing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:12:08 +01:00
2026-02-06 20:02:44 +01:00

LabMCP

A collection of Model Context Protocol (MCP) servers written in Go.

MCP Servers

Nixpkgs Search (nixpkgs-search) - Primary

Combined search for NixOS options and Nix packages from nixpkgs. Provides two separate MCP servers:

  • Options server: Search NixOS configuration options (nixpkgs-search options serve)
  • Packages server: Search Nix packages (nixpkgs-search packages serve)

Both servers share the same database, allowing you to index once and serve both.

Home Manager Options (hm-options)

Search and query Home Manager configuration options across multiple home-manager revisions. Designed to help Claude (and other MCP clients) answer questions about Home Manager configuration.

Lab Monitoring (lab-monitoring)

Query Prometheus metrics, Alertmanager alerts, and Loki logs from your monitoring stack. Unlike other servers, this queries live HTTP APIs — no database or indexing needed.

  • List and inspect alerts from Alertmanager
  • Execute PromQL queries against Prometheus
  • Search metric names with metadata
  • View scrape target health
  • Manage alert silences
  • Query logs via LogQL (when Loki is configured)

Git Explorer (git-explorer)

Read-only access to git repository information. Designed for deployment verification — comparing deployed flake revisions against source repositories.

  • Resolve refs (branches, tags, commits) to commit hashes
  • View commit logs with filtering by author, path, or range
  • Get full commit details including file change statistics
  • Compare commits to see which files changed
  • Read file contents at any commit
  • Check ancestry relationships between commits
  • Search commit messages

All operations are read-only and will never modify the repository.

NixOS Options (nixos-options) - Legacy

Search and query NixOS configuration options. Note: Prefer using nixpkgs-search instead, which includes this functionality plus package search.

Shared Features (nixpkgs-search, hm-options, nixos-options)

  • Full-text search across option/package names and descriptions
  • Query specific options/packages with full metadata
  • Index multiple revisions (by git hash or channel name)
  • Fetch module source files
  • Support for PostgreSQL and SQLite backends

Installation

Using Nix Flakes

# Build the packages
nix build git+https://git.t-juice.club/torjus/labmcp#nixpkgs-search
nix build git+https://git.t-juice.club/torjus/labmcp#hm-options
nix build git+https://git.t-juice.club/torjus/labmcp#lab-monitoring
nix build git+https://git.t-juice.club/torjus/labmcp#git-explorer

# Or run directly
nix run git+https://git.t-juice.club/torjus/labmcp#nixpkgs-search -- --help
nix run git+https://git.t-juice.club/torjus/labmcp#hm-options -- --help
nix run git+https://git.t-juice.club/torjus/labmcp#lab-monitoring -- --help
nix run git+https://git.t-juice.club/torjus/labmcp#git-explorer -- --help

From Source

go install git.t-juice.club/torjus/labmcp/cmd/nixpkgs-search@latest
go install git.t-juice.club/torjus/labmcp/cmd/hm-options@latest
go install git.t-juice.club/torjus/labmcp/cmd/lab-monitoring@latest
go install git.t-juice.club/torjus/labmcp/cmd/git-explorer@latest

Usage

As MCP Server (STDIO)

Configure in your MCP client (e.g., Claude Desktop):

{
  "mcpServers": {
    "nixpkgs-options": {
      "command": "nixpkgs-search",
      "args": ["options", "serve"],
      "env": {
        "NIXPKGS_SEARCH_DATABASE": "sqlite:///path/to/nixpkgs-search.db"
      }
    },
    "nixpkgs-packages": {
      "command": "nixpkgs-search",
      "args": ["packages", "serve"],
      "env": {
        "NIXPKGS_SEARCH_DATABASE": "sqlite:///path/to/nixpkgs-search.db"
      }
    },
    "hm-options": {
      "command": "hm-options",
      "args": ["serve"],
      "env": {
        "HM_OPTIONS_DATABASE": "sqlite:///path/to/hm-options.db"
      }
    },
    "lab-monitoring": {
      "command": "lab-monitoring",
      "args": ["serve"],
      "env": {
        "PROMETHEUS_URL": "http://prometheus.example.com:9090",
        "ALERTMANAGER_URL": "http://alertmanager.example.com:9093",
        "LOKI_URL": "http://loki.example.com:3100"
      }
    },
    "git-explorer": {
      "command": "git-explorer",
      "args": ["serve"],
      "env": {
        "GIT_REPO_PATH": "/path/to/your/repo"
      }
    }
  }
}

Alternatively, if you have Nix installed, you can use the flake directly without installing the packages:

{
  "mcpServers": {
    "nixpkgs-options": {
      "command": "nix",
      "args": ["run", "git+https://git.t-juice.club/torjus/labmcp#nixpkgs-search", "--", "options", "serve"],
      "env": {
        "NIXPKGS_SEARCH_DATABASE": "sqlite:///path/to/nixpkgs-search.db"
      }
    },
    "nixpkgs-packages": {
      "command": "nix",
      "args": ["run", "git+https://git.t-juice.club/torjus/labmcp#nixpkgs-search", "--", "packages", "serve"],
      "env": {
        "NIXPKGS_SEARCH_DATABASE": "sqlite:///path/to/nixpkgs-search.db"
      }
    },
    "hm-options": {
      "command": "nix",
      "args": ["run", "git+https://git.t-juice.club/torjus/labmcp#hm-options", "--", "serve"],
      "env": {
        "HM_OPTIONS_DATABASE": "sqlite:///path/to/hm-options.db"
      }
    },
    "lab-monitoring": {
      "command": "nix",
      "args": ["run", "git+https://git.t-juice.club/torjus/labmcp#lab-monitoring", "--", "serve"],
      "env": {
        "PROMETHEUS_URL": "http://prometheus.example.com:9090",
        "ALERTMANAGER_URL": "http://alertmanager.example.com:9093",
        "LOKI_URL": "http://loki.example.com:3100"
      }
    },
    "git-explorer": {
      "command": "nix",
      "args": ["run", "git+https://git.t-juice.club/torjus/labmcp#git-explorer", "--", "serve"],
      "env": {
        "GIT_REPO_PATH": "/path/to/your/repo"
      }
    }
  }
}

As MCP Server (HTTP)

All servers can run over HTTP with Server-Sent Events (SSE) for web-based MCP clients:

# Start HTTP server on default address
nixpkgs-search options serve --transport http
nixpkgs-search packages serve --transport http
hm-options serve --transport http
lab-monitoring serve --transport http
git-explorer serve --transport http

# Custom address and CORS configuration
nixpkgs-search options serve --transport http \
  --http-address 0.0.0.0:8080 \
  --allowed-origins https://example.com

# With TLS
nixpkgs-search options serve --transport http \
  --tls-cert /path/to/cert.pem \
  --tls-key /path/to/key.pem

HTTP transport endpoints:

  • POST /mcp - JSON-RPC requests (returns Mcp-Session-Id header on initialize)
  • GET /mcp - SSE stream for server notifications (requires Mcp-Session-Id header)
  • DELETE /mcp - Terminate session

CLI Examples

Index a revision (nixpkgs-search):

# Index both options and packages
nixpkgs-search index nixos-unstable

# Index by git hash
nixpkgs-search index e6eae2ee2110f3d31110d5c222cd395303343b08

# Index options only (faster, skip packages)
nixpkgs-search index --no-packages nixos-unstable

# Index packages only (skip options)
nixpkgs-search index --no-options nixos-unstable

# Index without file contents (faster, disables get_file tool)
nixpkgs-search index --no-files nixos-unstable

Index a revision (hm-options):

# Index by channel name
hm-options index hm-unstable

# Index without file contents
hm-options index --no-files release-24.11

List indexed revisions:

nixpkgs-search list
hm-options list

Search for options:

# NixOS options via nixpkgs-search
nixpkgs-search options search nginx
nixpkgs-search options search -n 10 postgresql

# Home Manager options
hm-options search git
hm-options search -n 10 neovim

Search for packages:

nixpkgs-search packages search firefox
nixpkgs-search packages search -n 10 python

# Filter by status
nixpkgs-search packages search --unfree nvidia
nixpkgs-search packages search --broken deprecated-package

Get option/package details:

nixpkgs-search options get services.nginx.enable
nixpkgs-search packages get firefox
hm-options get programs.git.enable

Lab Monitoring CLI:

# List alerts (defaults to active only)
lab-monitoring alerts
lab-monitoring alerts --all           # Include silenced/inhibited alerts
lab-monitoring alerts --state all     # Same as --all
lab-monitoring alerts --severity critical

# Execute PromQL queries
lab-monitoring query 'up'
lab-monitoring query 'rate(http_requests_total[5m])'

# List scrape targets
lab-monitoring targets

# Search metrics
lab-monitoring metrics node
lab-monitoring metrics -n 20 cpu

# Query logs from Loki (requires LOKI_URL)
lab-monitoring logs '{job="varlogs"}'
lab-monitoring logs '{job="nginx"} |= "error"' --start 2h --limit 50
lab-monitoring logs '{job="systemd"}' --direction forward

# List Loki labels
lab-monitoring labels
lab-monitoring labels --values job

Git Explorer CLI:

# Resolve a ref to commit hash
git-explorer --repo /path/to/repo resolve main
git-explorer --repo /path/to/repo resolve v1.0.0

# View commit log
git-explorer --repo /path/to/repo log --limit 10
git-explorer --repo /path/to/repo log --author "John" --path src/

# Show commit details
git-explorer --repo /path/to/repo show HEAD
git-explorer --repo /path/to/repo show abc1234

# Compare commits
git-explorer --repo /path/to/repo diff HEAD~5 HEAD

# Show file at specific commit
git-explorer --repo /path/to/repo cat HEAD README.md

# List branches
git-explorer --repo /path/to/repo branches
git-explorer --repo /path/to/repo branches --remote

# Search commit messages
git-explorer --repo /path/to/repo search "fix bug"

Delete an indexed revision:

nixpkgs-search delete nixos-23.11
hm-options delete release-23.11

Configuration

Environment Variables

Variable Description Default
NIXPKGS_SEARCH_DATABASE Database connection string for nixpkgs-search sqlite://nixpkgs-search.db
HM_OPTIONS_DATABASE Database connection string for hm-options sqlite://hm-options.db
NIXOS_OPTIONS_DATABASE Database connection string for nixos-options (legacy) sqlite://nixos-options.db
PROMETHEUS_URL Prometheus base URL for lab-monitoring http://localhost:9090
ALERTMANAGER_URL Alertmanager base URL for lab-monitoring http://localhost:9093
LOKI_URL Loki base URL for lab-monitoring (optional, enables log tools) (none)

Database Connection Strings

SQLite:

export NIXPKGS_SEARCH_DATABASE="sqlite:///path/to/database.db"
export NIXPKGS_SEARCH_DATABASE="sqlite://:memory:"  # In-memory

PostgreSQL:

export NIXPKGS_SEARCH_DATABASE="postgres://user:pass@localhost/nixpkgs_search?sslmode=disable"

Command-Line Flags

The database can also be specified via the -d or --database flag:

nixpkgs-search -d "postgres://localhost/nixpkgs" options serve
nixpkgs-search -d "sqlite://my.db" index nixos-unstable
hm-options -d "sqlite://my.db" index hm-unstable

MCP Tools

Options Servers (nixpkgs-search options, hm-options)

Tool Description
search_options Search for options by name or description
get_option Get full details for a specific option
get_file Fetch source file contents from the repository
index_revision Index a revision (options, files, and packages for nixpkgs)
list_revisions List all indexed revisions
delete_revision Delete an indexed revision

Packages Server (nixpkgs-search packages)

Tool Description
search_packages Search for packages by name or description
get_package Get full details for a specific package
get_file Fetch source file contents from nixpkgs
index_revision Index a revision to make its packages searchable
list_revisions List all indexed revisions
delete_revision Delete an indexed revision

Monitoring Server (lab-monitoring)

Tool Description
list_alerts List alerts with optional filters (state, severity, receiver). Defaults to active alerts only; use state=all to include silenced/inhibited
get_alert Get full details for a specific alert by fingerprint
search_metrics Search metric names with substring filter, enriched with metadata
get_metric_metadata Get type, help text, and unit for a specific metric
query Execute an instant PromQL query
list_targets List scrape targets with health status
list_silences List active/pending alert silences
create_silence Create a new alert silence (requires --enable-silences flag)
query_logs Execute a LogQL range query against Loki (requires LOKI_URL)
list_labels List available label names from Loki (requires LOKI_URL)
list_label_values List values for a specific label from Loki (requires LOKI_URL)

Git Explorer Server (git-explorer)

Tool Description
resolve_ref Resolve a git ref (branch, tag, commit) to its full commit hash
get_log Get commit log with optional filters (author, path, limit)
get_commit_info Get full details for a specific commit
get_diff_files Get list of files changed between two commits
get_file_at_commit Get file contents at a specific commit
is_ancestor Check if one commit is an ancestor of another
commits_between Get all commits between two refs
list_branches List all branches in the repository
search_commits Search commit messages for a pattern

NixOS Modules

NixOS modules are provided for running the MCP servers as systemd services.

The nixpkgs-search module runs two separate MCP servers (options and packages) that share a database:

{
  inputs.labmcp.url = "git+https://git.t-juice.club/torjus/labmcp";

  outputs = { self, nixpkgs, labmcp }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        labmcp.nixosModules.nixpkgs-search-mcp
        {
          services.nixpkgs-search = {
            enable = true;
            indexOnStart = [ "nixos-unstable" ];
            # Both options and packages servers are enabled by default
          };
        }
      ];
    };
  };
}

Options-only configuration:

{
  services.nixpkgs-search = {
    enable = true;
    indexOnStart = [ "nixos-unstable" ];
    indexFlags = [ "--no-packages" ];  # Faster indexing
    packages.enable = false;  # Don't run packages server
  };
}

hm-options

{
  inputs.labmcp.url = "git+https://git.t-juice.club/torjus/labmcp";

  outputs = { self, nixpkgs, labmcp }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        labmcp.nixosModules.hm-options-mcp
        {
          services.hm-options-mcp = {
            enable = true;
            indexOnStart = [ "hm-unstable" ];
          };
        }
      ];
    };
  };
}

lab-monitoring

{
  inputs.labmcp.url = "git+https://git.t-juice.club/torjus/labmcp";

  outputs = { self, nixpkgs, labmcp }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        labmcp.nixosModules.lab-monitoring-mcp
        {
          services.lab-monitoring = {
            enable = true;
            prometheusUrl = "http://prometheus.example.com:9090";
            alertmanagerUrl = "http://alertmanager.example.com:9093";
            enableSilences = true;  # Optional: enable create_silence tool
          };
        }
      ];
    };
  };
}

git-explorer

{
  inputs.labmcp.url = "git+https://git.t-juice.club/torjus/labmcp";

  outputs = { self, nixpkgs, labmcp }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        labmcp.nixosModules.git-explorer-mcp
        {
          services.git-explorer = {
            enable = true;
            repoPath = "/path/to/your/git/repo";
          };
        }
      ];
    };
  };
}

nixos-options (Legacy)

{
  inputs.labmcp.url = "git+https://git.t-juice.club/torjus/labmcp";

  outputs = { self, nixpkgs, labmcp }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        labmcp.nixosModules.nixos-options-mcp
        {
          services.nixos-options-mcp = {
            enable = true;
            indexOnStart = [ "nixos-unstable" ];
          };
        }
      ];
    };
  };
}

Module Options

Option Type Default Description
enable bool false Enable the service
package package from flake Package to use
database.type enum "sqlite" "sqlite" or "postgres"
database.name string "nixpkgs-search.db" SQLite database filename
database.connectionString string "" PostgreSQL connection URL (stored in Nix store)
database.connectionStringFile path null Path to file with PostgreSQL connection URL (recommended for secrets)
indexOnStart list of string [] Revisions to index on service start
indexFlags list of string [] Additional flags for indexing (e.g., ["--no-packages"])
user string "nixpkgs-search" User to run the service as
group string "nixpkgs-search" Group to run the service as
dataDir path /var/lib/nixpkgs-search Directory for data storage
options.enable bool true Enable the options MCP server
options.http.address string "127.0.0.1:8082" HTTP listen address for options server
options.openFirewall bool false Open firewall for options HTTP port
packages.enable bool true Enable the packages MCP server
packages.http.address string "127.0.0.1:8083" HTTP listen address for packages server
packages.openFirewall bool false Open firewall for packages HTTP port

Both options.http and packages.http also support:

  • endpoint (default: "/mcp")
  • allowedOrigins (default: [])
  • sessionTTL (default: "30m")
  • tls.enable, tls.certFile, tls.keyFile

lab-monitoring

Option Type Default Description
enable bool false Enable the service
package package from flake Package to use
prometheusUrl string "http://localhost:9090" Prometheus base URL
alertmanagerUrl string "http://localhost:9093" Alertmanager base URL
lokiUrl nullOr string null Loki base URL (enables log query tools when set)
enableSilences bool false Enable the create_silence tool (write operation)
http.address string "127.0.0.1:8084" HTTP listen address
http.endpoint string "/mcp" HTTP endpoint path
http.allowedOrigins list of string [] Allowed CORS origins (empty = localhost only)
http.sessionTTL string "30m" Session timeout (Go duration format)
http.tls.enable bool false Enable TLS
http.tls.certFile path null TLS certificate file
http.tls.keyFile path null TLS private key file
openFirewall bool false Open firewall for HTTP port

The lab-monitoring module uses DynamicUser=true, so no separate user/group configuration is needed.

git-explorer

Option Type Default Description
enable bool false Enable the service
package package from flake Package to use
repoPath string (required) Path to the git repository to serve
defaultRemote string "origin" Default remote name for ref resolution
http.address string "127.0.0.1:8085" HTTP listen address
http.endpoint string "/mcp" HTTP endpoint path
http.allowedOrigins list of string [] Allowed CORS origins
http.sessionTTL string "30m" Session timeout
http.tls.enable bool false Enable TLS
http.tls.certFile path null TLS certificate file
http.tls.keyFile path null TLS private key file
openFirewall bool false Open firewall for HTTP port

The git-explorer module uses DynamicUser=true and grants read-only access to the repository path.

hm-options-mcp / nixos-options-mcp (Legacy)

Option Type Default Description
enable bool false Enable the service
package package from flake Package to use
database.type enum "sqlite" "sqlite" or "postgres"
database.name string "*.db" SQLite database filename
database.connectionString string "" PostgreSQL connection URL (stored in Nix store)
database.connectionStringFile path null Path to file with PostgreSQL connection URL (recommended for secrets)
indexOnStart list of string [] Revisions to index on service start
user string "*-mcp" User to run the service as
group string "*-mcp" Group to run the service as
dataDir path /var/lib/*-mcp Directory for data storage
http.address string "127.0.0.1:808x" HTTP listen address
http.endpoint string "/mcp" HTTP endpoint path
http.allowedOrigins list of string [] Allowed CORS origins (empty = localhost only)
http.sessionTTL string "30m" Session timeout (Go duration format)
http.tls.enable bool false Enable TLS
http.tls.certFile path null TLS certificate file
http.tls.keyFile path null TLS private key file
openFirewall bool false Open firewall for HTTP port

PostgreSQL Example

Using connectionStringFile (recommended for production with sensitive credentials):

{
  services.nixpkgs-search = {
    enable = true;
    database = {
      type = "postgres";
      # File contains: postgres://user:secret@localhost/nixpkgs_search?sslmode=disable
      connectionStringFile = "/run/secrets/nixpkgs-search-db";
    };
    indexOnStart = [ "nixos-unstable" ];
  };

  # Example with agenix or sops-nix for secret management
  # age.secrets.nixpkgs-search-db.file = ./secrets/nixpkgs-search-db.age;
}

Development

# Enter development shell
nix develop

# Run tests
go test ./...

# Run benchmarks
go test -bench=. ./internal/database/...

# Build
go build ./cmd/nixpkgs-search
go build ./cmd/hm-options
go build ./cmd/lab-monitoring
go build ./cmd/git-explorer

License

MIT

Description
No description provided
Readme 834 KiB
Languages
Go 91.6%
Nix 8.4%