Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 60 additions & 27 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CLAUDE.md - NixMCP Project Guidelines
# CLAUDE.md - MCP-NixOS Project Guidelines

## IMPORTANT: Source of Truth Rule
CLAUDE.md is the primary source of truth for coding rules and guidelines.
Expand All @@ -23,40 +23,40 @@ When modifying or adding to this codebase, always:
This ensures the codebase remains cohesive and maintainable.

## Project Overview
NixMCP is a Model Context Protocol (MCP) server for NixOS resources, Home Manager configuration options, and nix-darwin macOS configuration options. It provides MCP resources and tools that allow AI assistants to search and retrieve information about NixOS packages, system options, Home Manager user configuration options, and nix-darwin macOS system configuration options. Communication happens over standard input/output streams using a JSON-based message format.
MCP-NixOS is a Model Context Protocol (MCP) server for NixOS resources, Home Manager configuration options, and nix-darwin macOS configuration options. It provides MCP resources and tools that allow AI assistants to search and retrieve information about NixOS packages, system options, Home Manager user configuration options, and nix-darwin macOS system configuration options. Communication happens over standard input/output streams using a JSON-based message format.

**NOTE:** MCP completions support is temporarily disabled as it's specified in the MCP protocol but not yet fully implemented in the MCP SDK. Completion support will be added once the upstream SDK implementation is available.

## Project Structure
The codebase follows a modular architecture:

- `nixmcp/__init__.py` - Package version and metadata
- `nixmcp/__main__.py` - Entry point for direct execution
- `nixmcp/cache/` - Caching components:
- `mcp-nixos/__init__.py` - Package version and metadata
- `mcp-nixos/__main__.py` - Entry point for direct execution
- `mcp-nixos/cache/` - Caching components:
- `simple_cache.py` - In-memory caching with TTL and size limits
- `html_cache.py` - Multi-format filesystem caching (HTML, JSON, binary data)
- `nixmcp/clients/` - API clients:
- `mcp-nixos/clients/` - API clients:
- `elasticsearch_client.py` - Client for NixOS Elasticsearch API
- `home_manager_client.py` - Client for parsing and caching Home Manager docs
- `darwin/darwin_client.py` - Client for parsing and caching nix-darwin docs
- `html_client.py` - HTTP client with filesystem caching
- `nixmcp/contexts/` - Application contexts:
- `mcp-nixos/contexts/` - Application contexts:
- `nixos_context.py` - NixOS context
- `home_manager_context.py` - Home Manager context
- `darwin/darwin_context.py` - nix-darwin context
- `nixmcp/resources/` - MCP resource definitions:
- `mcp-nixos/resources/` - MCP resource definitions:
- `nixos_resources.py` - NixOS resources
- `home_manager_resources.py` - Home Manager resources
- `darwin/darwin_resources.py` - nix-darwin resources
- `nixmcp/tools/` - MCP tool implementations:
- `mcp-nixos/tools/` - MCP tool implementations:
- `nixos_tools.py` - NixOS tools
- `home_manager_tools.py` - Home Manager tools
- `darwin/darwin_tools.py` - nix-darwin tools
- `nixmcp/utils/` - Utility functions and helpers:
- `mcp-nixos/utils/` - Utility functions and helpers:
- `cache_helpers.py` - Cross-platform cache directory management
- `helpers.py` - General utility functions
- `nixmcp/logging.py` - Centralized logging configuration
- `nixmcp/server.py` - FastMCP server implementation
- `mcp-nixos/logging.py` - Centralized logging configuration
- `mcp-nixos/server.py` - FastMCP server implementation

## MCP Implementation Guidelines

Expand Down Expand Up @@ -87,9 +87,15 @@ The codebase follows a modular architecture:
### Best Practices
- Use resources for retrieving data, tools for actions/processing with formatted output
- Always use proper type annotations (Optional, Union, List, Dict, etc.)
- Follow strict null safety guidelines:
- Always check for None before accessing attributes (`if ctx is not None: ctx.method()`)
- Use the Optional type for attributes or parameters that may be None
- Add defensive guards for regex match operations and string comparisons
- Check result values from external APIs and provide appropriate fallbacks
- Log all errors with appropriate detail
- Return user-friendly error messages with suggestions where possible
- For search tools, handle empty results gracefully and support wildcards
- Ensure code passes both linting (`lint`) and type checking (`typecheck`) before committing

## MCP Resources

Expand Down Expand Up @@ -168,7 +174,7 @@ Both tools above support the `channel` parameter with values:

### nix-darwin Tools
- `darwin_search(query, limit=20, context=None)`:
Search for nix-darwin options with automatic wildcard handling
Search for nix-darwin options with automatic wildcard handling and enhanced fuzzy search using Levenshtein distance
- `darwin_info(name, context=None)`:
Get detailed information about a specific nix-darwin option
- `darwin_stats(context=None)`:
Expand Down Expand Up @@ -207,13 +213,13 @@ Both tools above support the `channel` parameter with values:
### HTML Documentation Parsing (Home Manager and nix-darwin features)
- Fetches and parses HTML docs from:
- Home Manager: nix-community.github.io/home-manager/
- nix-darwin: daiderd.com/nix-darwin/manual/
- nix-darwin: nix-darwin.github.io/nix-darwin/manual/
- Multi-level caching system for improved performance and resilience:
- HTML content cache to filesystem using cross-platform cache paths
- Processed in-memory data structures persisted to disk cache
- Option data serialized to both JSON and binary formats for complex structures
- Uses OS-specific standard cache locations
- Implements proper TTL expiration of cached content
- Implements proper TTL expiration of cached content with legacy cache cleanup
- Provides comprehensive fallback mechanisms and error handling
- Tracks detailed cache statistics for monitoring
- Options are indexed in memory with specialized search indices
Expand All @@ -230,14 +236,14 @@ Both tools above support the `channel` parameter with values:
## Configuration
- `LOG_LEVEL`: Set logging level (default: INFO)
- `LOG_FILE`: Optional log file path (default: logs to stdout/stderr)
- `NIXMCP_CACHE_DIR`: Custom directory for filesystem cache (default: OS-specific standard location)
- `NIXMCP_CACHE_TTL`: Time-to-live for cached content in seconds (default: 86400 - 24 hours)
- `MCP_NIXOS_CACHE_DIR`: Custom directory for filesystem cache (default: OS-specific standard location)
- `MCP_NIXOS_CACHE_TTL`: Time-to-live for cached content in seconds (default: 86400 - 24 hours)
- Environment variables for Elasticsearch API credentials (see above)

### Cache Directory Locations
- Linux: `$XDG_CACHE_HOME/nixmcp/` (typically `~/.cache/nixmcp/`)
- macOS: `~/Library/Caches/nixmcp/`
- Windows: `%LOCALAPPDATA%\nixmcp\Cache\`
- Linux: `$XDG_CACHE_HOME/mcp-nixos/` (typically `~/.cache/mcp-nixos/`)
- macOS: `~/Library/Caches/mcp-nixos/`
- Windows: `%LOCALAPPDATA%\mcp-nixos\Cache\`

### Cache File Types
- `*.html` - Raw HTML content from Home Manager documentation
Expand All @@ -246,11 +252,30 @@ Both tools above support the `channel` parameter with values:

## Testing
- Use pytest with code coverage reporting (target: 80%)
- Run static type checking with `typecheck` command:
- Zero-tolerance policy for type errors
- Checks for null safety and proper type usage
- Run on CI for all pull requests
- Run linting checks with `lint` command:
- Enforces code style with Black
- Checks for issues with Flake8
- No unused imports allowed
- No f-string placeholders without variables
- Test organization follows the module structure:
- `tests/cache/` - Tests for caching components
- `tests/clients/` - Tests for API clients (with nested `darwin/` directory)
- `tests/contexts/` - Tests for application contexts (with nested `darwin/` directory)
- `tests/completions/` - Tests for MCP completions
- `tests/resources/` - Tests for MCP resources (with nested `darwin/` directory)
- `tests/tools/` - Tests for MCP tools (with nested `darwin/` directory)
- `tests/utils/` - Tests for utility functions
- `tests/integration/` - End-to-end integration tests
- Use dependency injection for testable components:
- Pass mock contexts directly to resource/tool functions
- Avoid patching global state
- Mock external dependencies (Elasticsearch, Home Manager docs)
- Test both success paths and error handling
- Always check for None values before accessing attributes in tests
- **IMPORTANT**: Mock test functions, not production code:
```python
# GOOD: Clean production code with mocking in tests
Expand All @@ -269,21 +294,21 @@ Both tools above support the `channel` parameter with values:
## Installation and Usage

### Installation Methods
- pip: `pip install nixmcp`
- uv: `uv pip install nixmcp`
- uvx (for Claude Code): `uvx nixmcp`
- pip: `pip install mcp-nixos`
- uv: `uv pip install mcp-nixos`
- uvx (for Claude Code): `uvx mcp-nixos`

### MCP Configuration
To configure Claude Code to use nixmcp, add to `~/.config/claude/config.json`:
To configure Claude Code to use mcp-nixos, add to `~/.config/claude/config.json`:
```json
{
"mcpServers": {
"nixos": {
"command": "uvx",
"args": ["nixmcp"],
"args": ["mcp-nixos"],
"env": {
"LOG_LEVEL": "INFO",
"LOG_FILE": "/path/to/nixmcp.log"
"LOG_FILE": "/path/to/mcp-nixos.log"
}
}
}
Expand All @@ -297,6 +322,9 @@ To configure Claude Code to use nixmcp, add to `~/.config/claude/config.json`:
- List commands: `menu`
- Lint and format: `lint`, `format`
- Setup uv: `setup-uv`
- Count lines of code: `loc`
- Build distributions: `build`
- Publish to PyPI: `publish`

## Code Style
- Python 3.11+ with type hints
Expand All @@ -305,4 +333,9 @@ To configure Claude Code to use nixmcp, add to `~/.config/claude/config.json`:
- Google-style docstrings
- Specific exception handling (avoid bare except)
- Black for formatting, Flake8 for linting
- Flake8 config: max-line-length=120, ignore=E402,E203
- Flake8 config: max-line-length=120, ignore=E402,E203
- Strict null safety to prevent "None" type errors:
- Check for None before accessing attributes (`if obj is not None: obj.method()`)
- Guard regex match results with if statements before accessing group() methods
- Add type assertion for string operations (`if s is not None: "text" in s`)
- Use pyright's strict type checking with zero-tolerance policy for type errors
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[flake8]
max-line-length = 120
ignore = E402, E203
ignore = E402, E203, W503
Loading
Loading