Prevent unbounded memory usage by capping the limit parameter to 5000.
Validate direction against allowed values instead of passing through
to Loki unchecked.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add 3 opt-in Loki tools (query_logs, list_labels, list_label_values)
that are registered when LOKI_URL is configured. Includes Loki HTTP
client, CLI commands (logs, labels), NixOS module option, formatting,
and tests.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
The create_silence tool is a write operation that can suppress alerts.
Disable it by default and require explicit opt-in via --enable-silences
CLI flag (or enableSilences NixOS option) as a safety measure.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add InstructionsFunc callback to ServerConfig, called during each
initialize handshake to generate dynamic instructions. The lab-monitoring
server uses this to query Alertmanager and include a count of active
non-silenced alerts, so the LLM can proactively inform the user.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New MCP server that queries live Prometheus and Alertmanager HTTP APIs
with 8 tools: list_alerts, get_alert, search_metrics, get_metric_metadata,
query (PromQL), list_targets, list_silences, and create_silence.
Extends the MCP core with ModeCustom and NewGenericServer for servers
that don't require a database. Includes CLI with direct commands
(alerts, query, targets, metrics), NixOS module, and comprehensive
httptest-based tests.
Bumps existing binaries to 0.2.1 due to shared internal/mcp change.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Package search now prioritizes results in this order:
1. Exact pname match
2. Exact attr_path match
3. pname starts with query
4. attr_path starts with query
5. FTS ranking (bm25 for SQLite, ts_rank for PostgreSQL)
This ensures searching for "git" returns the "git" package first,
rather than packages that merely mention "git" in their description.
Also update CLAUDE.md to clarify using `nix run` instead of
`go build -o` for testing binaries.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update .mcp.json to use nixpkgs-search options/packages servers
- Update CLAUDE.md example to use nixpkgs-search
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document nixpkgs-search as the primary MCP server
- Add package search CLI examples and MCP tools
- Update installation and usage examples
- Add nixpkgs-search-mcp NixOS module documentation
- Mark nixos-options as legacy
- Update environment variable documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add NixOS module for deploying nixpkgs-search as systemd services:
- Runs separate MCP servers for options (port 8082) and packages (port 8083)
- Shared database configuration (SQLite or PostgreSQL)
- Separate indexing service that runs before servers start
- options.enable and packages.enable flags (both default to true)
- indexFlags option for customizing index command (--no-packages, etc.)
Also update flake.nix:
- Register new module as nixpkgs-search-mcp
- Set as default nixosModule
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a new nixpkgs-search CLI that combines NixOS options search with
Nix package search functionality. This provides two MCP servers from
a single binary:
- `nixpkgs-search options serve` for NixOS options
- `nixpkgs-search packages serve` for Nix packages
Key changes:
- Add packages table to database schema (version 3)
- Add Package type and search methods to database layer
- Create internal/packages/ with indexer and parser for nix-env JSON
- Add MCP server mode (options/packages) with separate tool sets
- Add package handlers: search_packages, get_package
- Create cmd/nixpkgs-search with combined indexing support
- Update flake.nix with nixpkgs-search package (now default)
- Bump version to 0.2.0
The index command can index both options and packages together, or
use --no-packages/--no-options flags for partial indexing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the requirement to run golangci-lint, govulncheck, and go vet
before completing work on a feature branch.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add //nolint:errcheck comments to intentionally unchecked error returns:
- defer X.Close() calls: errors from closing read-only resources, rows
after iteration, files, response bodies, and gzip readers are not
actionable and don't affect correctness
- defer tx.Rollback(): standard Go pattern where rollback after
successful commit returns an error, which is expected behavior
- defer stmt.Close(): statements are closed with their transactions
- Cleanup operations: DeleteRevision on failure and os.RemoveAll for
temp directories are best-effort cleanup
- HTTP response encoding: if JSON encoding fails at response time,
there's nothing useful we can do
- Test/benchmark code: unchecked errors in test setup/cleanup where
failures will surface through test assertions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The argNum variable tracks parameter positions but the final value is
unused. Added explicit acknowledgment to silence the linter.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use t.Fatal instead of t.Error when retrieved session is nil to prevent
subsequent nil pointer dereference on retrieved.ID.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- testFileRange: test GetFileWithRange with various offset/limit values
- testDeclarationsWithMetadata: test file metadata in declarations
- Verify byte_size and line_count are computed correctly
- Test edge cases: offset beyond EOF, non-indexed files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add offset and limit parameters to get_file tool schema
- Default limit is 250 lines, offset is 0
- Show "Showing lines X-Y of Z total" header when range is applied
- Update handleGetOption to use GetDeclarationsWithMetadata
- Display file size metadata (bytes, lines) in declarations output
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add file size metadata to get_option declarations
- Add range parameters to get_file with sensible defaults
- New MCP server idea for indexing nixpkgs packages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document expected indexing times so appropriate timeouts are used:
- nixos-options: ~5-6 minutes for nixos-unstable
- hm-options: ~1-2 minutes for master
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The options.json parser expected declarations as []string (NixOS format),
but Home Manager uses [{name, url}] objects. This caused most HM options
to be silently skipped during parsing (27 vs 4880 options).
Changes:
- Parse declarations as json.RawMessage and try both formats
- Handle HM path format <home-manager/modules/...> in normalizeDeclarationPath
- Add /modules/ marker for HM store paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add hm-options documentation to README.md
- Update CLAUDE.md with hm-options info, repository structure
- Add note about git-tracking new files before nix build/run
- Add version bump rules documentation
- Bump version from 0.1.0 to 0.1.1 (patch bump for internal/ changes)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a new MCP server for Home Manager options, mirroring the
functionality of nixos-options but targeting the home-manager
repository.
Changes:
- Add shared options.Indexer interface for both implementations
- Add internal/homemanager package with indexer and channel aliases
- Add cmd/hm-options CLI entry point
- Parameterize MCP server with ServerConfig for name/instructions
- Parameterize nix/package.nix for building both packages
- Add hm-options package and NixOS module to flake.nix
- Add nix/hm-options-module.nix for systemd deployment
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update flake URL from github:torjus/labmcp to the correct
git+https://git.t-juice.club/torjus/labmcp
- Add alternative MCP client configuration using nix run with
the flake URL directly (no installation required)
- Fix NixOS module example to use correct flake URL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update README.md:
- Add HTTP transport usage section with examples
- Document HTTP endpoints (POST/GET/DELETE)
- Add HTTP-related NixOS module options to the table
Update CLAUDE.md:
- Update protocol description to include HTTP/SSE
- Add new transport files to repository structure
- Add Transports section explaining STDIO vs HTTP
- Add HTTP security hardening details
- Update CLI commands with HTTP transport examples
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add configurable MaxSessions limit (default: 10000) to SessionStore.
When the limit is reached, new session creation returns ErrTooManySessions
and HTTP transport responds with 503 Service Unavailable.
This prevents attackers from exhausting server memory by creating
unlimited sessions through repeated initialize requests.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Configure HTTP server with sensible timeouts:
- ReadTimeout: 30s (time to read entire request)
- WriteTimeout: 30s (time to write response)
- IdleTimeout: 120s (keep-alive connection timeout)
- ReadHeaderTimeout: 10s (time to read request headers)
For SSE connections, use http.ResponseController to extend write
deadlines before each write, preventing timeout on long-lived streams
while still protecting against slow clients.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add MaxRequestSize configuration to HTTPConfig with a default of 1MB.
Use http.MaxBytesReader to enforce the limit, returning 413 Request
Entity Too Large when exceeded.
This prevents memory exhaustion attacks where an attacker sends
arbitrarily large request bodies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for running the MCP server over HTTP with Server-Sent Events
(SSE) using the MCP Streamable HTTP specification, alongside the existing
STDIO transport.
New features:
- Transport abstraction with Transport interface
- HTTP transport with session management
- SSE support for server-initiated notifications
- CORS security with configurable allowed origins
- Optional TLS support
- CLI flags for HTTP configuration (--transport, --http-address, etc.)
- NixOS module options for HTTP transport
The HTTP transport implements:
- POST /mcp: JSON-RPC requests with session management
- GET /mcp: SSE stream for server notifications
- DELETE /mcp: Session termination
- Origin validation (localhost-only by default)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The file was still showing "Planning phase" with outdated next steps.
Updated to reflect the complete implementation:
- Changed status to "Complete and maintained"
- Updated repository structure to match actual layout
- Documented all 6 MCP tools as implemented
- Added key implementation details (database, indexing, security)
- Added CLI command reference
- Consolidated development notes
- Removed obsolete planning sections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Example configuration for running the nixos-options MCP server
via Claude Code or other MCP clients.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The connectionString option stores credentials in the world-readable
Nix store. This adds connectionStringFile as an alternative that reads
the connection string from a file at runtime, compatible with secret
management tools like agenix or sops-nix.
Changes:
- Add database.connectionStringFile option (mutually exclusive with connectionString)
- Read connection string from file at service start when configured
- Add warning to connectionString documentation about Nix store visibility
- Update README with examples for both approaches
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous check only looked for ".." substring, which missed:
- Absolute paths (/etc/passwd)
- URL-encoded traversal patterns
- Paths that clean to traversal (./../../etc)
Now uses filepath.Clean() and filepath.IsAbs() for robust validation:
- Rejects absolute paths
- Cleans paths before checking for traversal
- Uses cleaned path for database lookup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The revision parameter was interpolated directly into a Nix expression,
allowing potential injection of arbitrary Nix code. An attacker could
craft a revision string like:
"; builtins.readFile /etc/passwd; "
This adds ValidateRevision() which ensures revisions only contain safe
characters (alphanumeric, hyphens, underscores, dots) and are at most
64 characters long.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Go commands should be run via nix develop -c to ensure the proper
build environment with all dependencies (like gcc for cgo).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>