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>
When indexing a revision that already exists, the indexer now returns
early with information about the existing revision instead of re-indexing.
Use the --force flag to re-index an existing revision.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Provides guidance to AI assistants on how to index the nixpkgs
revision from a project's flake.lock file, ensuring option
documentation matches the project's actual nixpkgs version.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
File indexing only adds ~3 seconds to the indexing process, so enable
it by default to make the get_file tool work out of the box.
- MCP index_revision tool now indexes files automatically
- CLI flag changed from --files to --no-files (opt-out)
- Update README examples
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- BenchmarkIndexRevisionWithFiles now reports separate timing for
options indexing (options_ms) and file indexing (files_ms)
- Add BenchmarkIndexFilesOnly to measure file indexing in isolation
Run with:
go test -bench=BenchmarkIndexFilesOnly -benchtime=1x -timeout=60m ./internal/nixos/...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Module provides:
- services.nixos-options-mcp.enable - Enable the service
- services.nixos-options-mcp.package - Package to use
- services.nixos-options-mcp.database.type - sqlite or postgres
- services.nixos-options-mcp.database.name - SQLite filename
- services.nixos-options-mcp.database.connectionString - PostgreSQL URL
- services.nixos-options-mcp.indexOnStart - Revisions to index on start
- services.nixos-options-mcp.user/group - Service user/group
- services.nixos-options-mcp.dataDir - Data directory
Includes systemd hardening options.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When searching for option paths like "services.nginx", use name-based
LIKE matching instead of full-text search. This ensures the results
are options that start with the query, not random options that mention
the term somewhere in their description.
- Path queries (containing dots): use LIKE for name prefix matching
- Text queries (no dots): use FTS for full-text search on name+description
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wrap search queries in double quotes for FTS5 literal matching.
This prevents dots, colons, and other special characters from
being interpreted as FTS5 operators.
Fixes: "fts5: syntax error near '.'" when searching for option
paths like "services.nginx".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests searching with dots, colons, hyphens, and parentheses.
Currently fails on SQLite due to FTS5 syntax interpretation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add installation instructions (nix flakes, go install)
- Add MCP server configuration example
- Add CLI examples for all commands
- Document environment variables and database connection strings
- List available MCP tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The indexer requires nix-build to evaluate NixOS options.
Use makeWrapper to add nix to the binary's PATH.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- BenchmarkIndexRevision: benchmark full nixpkgs indexing
- BenchmarkIndexRevisionWithFiles: benchmark with file content storage
- TestIndexRevision: integration test for indexer
- Uses nixpkgs revision from flake.lock (e6eae2ee...)
- Skips if nix-build not available or in short mode
Run with: go test -bench=BenchmarkIndexRevision -benchtime=1x -timeout=30m ./internal/nixos/...
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Wire up all CLI commands to database operations
- Add 'get' command for single option details
- Add '--files' flag to 'index' for file content indexing
- Support postgres:// and sqlite:// connection strings
- Default to SQLite database file
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add options.json parser with mdDoc support
- Add nixpkgs indexer using nix-build
- Implement all MCP tool handlers:
- search_options: Full-text search with filters
- get_option: Option details with children
- get_file: Fetch file contents
- index_revision: Build and index options
- list_revisions: Show indexed versions
- delete_revision: Remove indexed data
- Add parser tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add comprehensive test suite for Store interface
- Test schema initialization, revisions, options, search, declarations, files
- SQLite tests use in-memory database for speed
- PostgreSQL tests require TEST_POSTGRES_CONN environment variable
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>