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.
Files
labmcp/README.md
Torjus Håkestad f4f859fefa docs: add lab-monitoring to README and update CLAUDE.md planning notes
Add comprehensive lab-monitoring documentation to README including MCP
server description, installation, MCP client config examples, CLI usage,
environment variables, MCP tools table, NixOS module example, and module
options. Also add a reminder in CLAUDE.md to update the README after
implementing a plan.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 23:54:13 +01:00

569 lines
17 KiB
Markdown

# 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 and Alertmanager alerts 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
### 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
```bash
# 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
# 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
```
### From Source
```bash
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
```
## Usage
### As MCP Server (STDIO)
Configure in your MCP client (e.g., Claude Desktop):
```json
{
"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"
}
}
}
}
```
Alternatively, if you have Nix installed, you can use the flake directly without installing the packages:
```json
{
"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"
}
}
}
}
```
### As MCP Server (HTTP)
All servers can run over HTTP with Server-Sent Events (SSE) for web-based MCP clients:
```bash
# 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
# 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):**
```bash
# 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):**
```bash
# Index by channel name
hm-options index hm-unstable
# Index without file contents
hm-options index --no-files release-24.11
```
**List indexed revisions:**
```bash
nixpkgs-search list
hm-options list
```
**Search for options:**
```bash
# 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:**
```bash
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:**
```bash
nixpkgs-search options get services.nginx.enable
nixpkgs-search packages get firefox
hm-options get programs.git.enable
```
**Lab Monitoring CLI:**
```bash
# List alerts
lab-monitoring alerts
lab-monitoring alerts --state active
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
```
**Delete an indexed revision:**
```bash
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` |
### Database Connection Strings
**SQLite:**
```bash
export NIXPKGS_SEARCH_DATABASE="sqlite:///path/to/database.db"
export NIXPKGS_SEARCH_DATABASE="sqlite://:memory:" # In-memory
```
**PostgreSQL:**
```bash
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:
```bash
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 |
| `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 |
| `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) |
| `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) |
## 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:
```nix
{
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:**
```nix
{
services.nixpkgs-search = {
enable = true;
indexOnStart = [ "nixos-unstable" ];
indexFlags = [ "--no-packages" ]; # Faster indexing
packages.enable = false; # Don't run packages server
};
}
```
### hm-options
```nix
{
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
```nix
{
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
};
}
];
};
};
}
```
### nixos-options (Legacy)
```nix
{
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 |
| `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.
#### 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):
```nix
{
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
```bash
# 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
```
## License
MIT