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>
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 (returnsMcp-Session-Idheader on initialize)GET /mcp- SSE stream for server notifications (requiresMcp-Session-Idheader)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.
nixpkgs-search (Recommended)
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
nixpkgs-search
| 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