mcp-nixos 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_nixos-0.2.0/.cursorrules +341 -0
- mcp_nixos-0.2.0/.envrc +5 -0
- mcp_nixos-0.2.0/.flake8 +3 -0
- mcp_nixos-0.2.0/.github/workflows/ci.yml +198 -0
- mcp_nixos-0.2.0/.gitignore +71 -0
- mcp_nixos-0.2.0/.goosehints +341 -0
- mcp_nixos-0.2.0/.vscode/extensions.json +13 -0
- mcp_nixos-0.2.0/.vscode/launch.json +34 -0
- mcp_nixos-0.2.0/.vscode/settings.json +71 -0
- mcp_nixos-0.2.0/.windsurfrules +341 -0
- mcp_nixos-0.2.0/CLAUDE.md +371 -0
- mcp_nixos-0.2.0/LICENSE +21 -0
- mcp_nixos-0.2.0/MANIFEST.in +6 -0
- mcp_nixos-0.2.0/PKG-INFO +592 -0
- mcp_nixos-0.2.0/README.md +567 -0
- mcp_nixos-0.2.0/TEST_PROMPTS.md +404 -0
- mcp_nixos-0.2.0/configuration.nix +610 -0
- mcp_nixos-0.2.0/coverage_report/.gitignore +2 -0
- mcp_nixos-0.2.0/coverage_report/class_index.html +139 -0
- mcp_nixos-0.2.0/coverage_report/coverage_html_cb_6fb7b396.js +733 -0
- mcp_nixos-0.2.0/coverage_report/favicon_32_cb_58284776.png +0 -0
- mcp_nixos-0.2.0/coverage_report/function_index.html +443 -0
- mcp_nixos-0.2.0/coverage_report/index.html +111 -0
- mcp_nixos-0.2.0/coverage_report/keybd_closed_cb_ce680311.png +0 -0
- mcp_nixos-0.2.0/coverage_report/server_py.html +1635 -0
- mcp_nixos-0.2.0/coverage_report/status.json +1 -0
- mcp_nixos-0.2.0/coverage_report/style_cb_8e611ae1.css +337 -0
- mcp_nixos-0.2.0/flake.lock +96 -0
- mcp_nixos-0.2.0/flake.nix +248 -0
- mcp_nixos-0.2.0/mcp_nixos/__init__.py +23 -0
- mcp_nixos-0.2.0/mcp_nixos/__main__.py +13 -0
- mcp_nixos-0.2.0/mcp_nixos/cache/__init__.py +5 -0
- mcp_nixos-0.2.0/mcp_nixos/cache/html_cache.py +534 -0
- mcp_nixos-0.2.0/mcp_nixos/cache/simple_cache.py +62 -0
- mcp_nixos-0.2.0/mcp_nixos/clients/__init__.py +6 -0
- mcp_nixos-0.2.0/mcp_nixos/clients/darwin/__init__.py +5 -0
- mcp_nixos-0.2.0/mcp_nixos/clients/darwin/darwin_client.py +751 -0
- mcp_nixos-0.2.0/mcp_nixos/clients/elasticsearch_client.py +632 -0
- mcp_nixos-0.2.0/mcp_nixos/clients/home_manager_client.py +708 -0
- mcp_nixos-0.2.0/mcp_nixos/clients/html_client.py +125 -0
- mcp_nixos-0.2.0/mcp_nixos/completions/__init__.py +330 -0
- mcp_nixos-0.2.0/mcp_nixos/completions/home_manager.py +228 -0
- mcp_nixos-0.2.0/mcp_nixos/completions/nixos.py +415 -0
- mcp_nixos-0.2.0/mcp_nixos/completions/utils.py +27 -0
- mcp_nixos-0.2.0/mcp_nixos/contexts/__init__.py +6 -0
- mcp_nixos-0.2.0/mcp_nixos/contexts/darwin/__init__.py +5 -0
- mcp_nixos-0.2.0/mcp_nixos/contexts/darwin/darwin_context.py +224 -0
- mcp_nixos-0.2.0/mcp_nixos/contexts/home_manager_context.py +357 -0
- mcp_nixos-0.2.0/mcp_nixos/contexts/nixos_context.py +138 -0
- mcp_nixos-0.2.0/mcp_nixos/logging.py +53 -0
- mcp_nixos-0.2.0/mcp_nixos/resources/__init__.py +6 -0
- mcp_nixos-0.2.0/mcp_nixos/resources/darwin/__init__.py +5 -0
- mcp_nixos-0.2.0/mcp_nixos/resources/darwin/darwin_resources.py +473 -0
- mcp_nixos-0.2.0/mcp_nixos/resources/home_manager_resources.py +210 -0
- mcp_nixos-0.2.0/mcp_nixos/resources/nixos_resources.py +96 -0
- mcp_nixos-0.2.0/mcp_nixos/server.py +558 -0
- mcp_nixos-0.2.0/mcp_nixos/tools/__init__.py +6 -0
- mcp_nixos-0.2.0/mcp_nixos/tools/darwin/__init__.py +19 -0
- mcp_nixos-0.2.0/mcp_nixos/tools/darwin/darwin_tools.py +290 -0
- mcp_nixos-0.2.0/mcp_nixos/tools/home_manager_tools.py +769 -0
- mcp_nixos-0.2.0/mcp_nixos/tools/nixos_tools.py +591 -0
- mcp_nixos-0.2.0/mcp_nixos/utils/__init__.py +5 -0
- mcp_nixos-0.2.0/mcp_nixos/utils/cache_helpers.py +131 -0
- mcp_nixos-0.2.0/mcp_nixos/utils/helpers.py +336 -0
- mcp_nixos-0.2.0/pyproject.toml +50 -0
- mcp_nixos-0.2.0/pyrightconfig.json +19 -0
- mcp_nixos-0.2.0/pytest.ini +11 -0
- mcp_nixos-0.2.0/requirements.txt +13 -0
- mcp_nixos-0.2.0/setup.py +16 -0
- mcp_nixos-0.2.0/tests/__init__.py +71 -0
- mcp_nixos-0.2.0/tests/cache/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/cache/test_cache_ttl_expiration.py +116 -0
- mcp_nixos-0.2.0/tests/cache/test_cross_platform_cache.py +180 -0
- mcp_nixos-0.2.0/tests/cache/test_html_cache.py +313 -0
- mcp_nixos-0.2.0/tests/cache/test_simple_cache.py +192 -0
- mcp_nixos-0.2.0/tests/clients/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/clients/darwin/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/clients/darwin/test_darwin_cache.py +680 -0
- mcp_nixos-0.2.0/tests/clients/darwin/test_darwin_client.py +531 -0
- mcp_nixos-0.2.0/tests/clients/darwin/test_darwin_serialization.py +178 -0
- mcp_nixos-0.2.0/tests/clients/test_elasticsearch_client.py +376 -0
- mcp_nixos-0.2.0/tests/clients/test_home_manager_client.py +405 -0
- mcp_nixos-0.2.0/tests/clients/test_html_client.py +186 -0
- mcp_nixos-0.2.0/tests/completions/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/completions/test_completion.py +279 -0
- mcp_nixos-0.2.0/tests/completions/test_completion_home_manager.py +200 -0
- mcp_nixos-0.2.0/tests/completions/test_completion_nixos.py +233 -0
- mcp_nixos-0.2.0/tests/completions/test_mcp_completions.py +84 -0
- mcp_nixos-0.2.0/tests/contexts/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/contexts/darwin/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/contexts/darwin/test_darwin_context.py +232 -0
- mcp_nixos-0.2.0/tests/contexts/test_home_manager.py +487 -0
- mcp_nixos-0.2.0/tests/contexts/test_nixos_context.py +146 -0
- mcp_nixos-0.2.0/tests/integration/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/integration/test_darwin_integration.py +256 -0
- mcp_nixos-0.2.0/tests/integration/test_home_manager_integration.py +219 -0
- mcp_nixos-0.2.0/tests/integration/test_home_manager_mcp_integration.py +323 -0
- mcp_nixos-0.2.0/tests/integration/test_mcp_nixos.py +877 -0
- mcp_nixos-0.2.0/tests/resources/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/resources/darwin/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/resources/test_home_manager_resources.py +341 -0
- mcp_nixos-0.2.0/tests/resources/test_mcp_resources.py +280 -0
- mcp_nixos-0.2.0/tests/test_app_lifespan.py +99 -0
- mcp_nixos-0.2.0/tests/test_eager_loading.py +175 -0
- mcp_nixos-0.2.0/tests/test_hierarchical_paths.py +236 -0
- mcp_nixos-0.2.0/tests/test_server_lifespan.py +225 -0
- mcp_nixos-0.2.0/tests/test_server_logging.py +104 -0
- mcp_nixos-0.2.0/tests/tools/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/tools/darwin/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/tools/darwin/test_darwin_tools_coroutine.py +253 -0
- mcp_nixos-0.2.0/tests/tools/test_home_manager_hierarchy.py +184 -0
- mcp_nixos-0.2.0/tests/tools/test_mcp_tools.py +691 -0
- mcp_nixos-0.2.0/tests/tools/test_option_documentation.py +91 -0
- mcp_nixos-0.2.0/tests/tools/test_package_documentation.py +128 -0
- mcp_nixos-0.2.0/tests/tools/test_service_options.py +483 -0
- mcp_nixos-0.2.0/tests/tools/test_suggestions.py +291 -0
- mcp_nixos-0.2.0/tests/tools/test_version_display.py +61 -0
- mcp_nixos-0.2.0/tests/utils/__init__.py +0 -0
- mcp_nixos-0.2.0/tests/utils/test_cache_helpers.py +126 -0
- mcp_nixos-0.2.0/tests/utils/test_helper_functions.py +59 -0
- mcp_nixos-0.2.0/tests/utils/test_multi_word_query.py +135 -0
- mcp_nixos-0.2.0/uv.lock +683 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# CLAUDE.md - MCP-NixOS Project Guidelines
|
|
2
|
+
|
|
3
|
+
## IMPORTANT: Source of Truth Rule
|
|
4
|
+
CLAUDE.md is the primary source of truth for coding rules and guidelines.
|
|
5
|
+
When updating rules:
|
|
6
|
+
1. Modify CLAUDE.md first
|
|
7
|
+
2. Run these commands to sync to other rule files:
|
|
8
|
+
```
|
|
9
|
+
cp CLAUDE.md .windsurfrules
|
|
10
|
+
cp CLAUDE.md .cursorrules
|
|
11
|
+
cp CLAUDE.md .goosehints
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## IMPORTANT: Match Existing Code Patterns
|
|
15
|
+
When modifying or adding to this codebase, always:
|
|
16
|
+
1. Follow the existing code style and patterns in each module
|
|
17
|
+
2. Study nearby code before making changes to understand the established approach
|
|
18
|
+
3. Maintain consistency with the surrounding code (naming, structure, error handling)
|
|
19
|
+
4. Respect the architectural boundaries between modules
|
|
20
|
+
5. Use the same patterns for similar functionality
|
|
21
|
+
6. Adhere to Python best practices while maintaining consistency with the codebase
|
|
22
|
+
|
|
23
|
+
This ensures the codebase remains cohesive and maintainable.
|
|
24
|
+
|
|
25
|
+
## Project Overview
|
|
26
|
+
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.
|
|
27
|
+
|
|
28
|
+
**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.
|
|
29
|
+
|
|
30
|
+
## Project Structure
|
|
31
|
+
The codebase follows a modular architecture:
|
|
32
|
+
|
|
33
|
+
- `mcp-nixos/__init__.py` - Package version and metadata
|
|
34
|
+
- `mcp-nixos/__main__.py` - Entry point for direct execution
|
|
35
|
+
- `mcp-nixos/cache/` - Caching components:
|
|
36
|
+
- `simple_cache.py` - In-memory caching with TTL and size limits
|
|
37
|
+
- `html_cache.py` - Multi-format filesystem caching (HTML, JSON, binary data)
|
|
38
|
+
- `mcp-nixos/clients/` - API clients:
|
|
39
|
+
- `elasticsearch_client.py` - Client for NixOS Elasticsearch API
|
|
40
|
+
- `home_manager_client.py` - Client for parsing and caching Home Manager docs
|
|
41
|
+
- `darwin/darwin_client.py` - Client for parsing and caching nix-darwin docs
|
|
42
|
+
- `html_client.py` - HTTP client with filesystem caching
|
|
43
|
+
- `mcp-nixos/contexts/` - Application contexts:
|
|
44
|
+
- `nixos_context.py` - NixOS context
|
|
45
|
+
- `home_manager_context.py` - Home Manager context
|
|
46
|
+
- `darwin/darwin_context.py` - nix-darwin context
|
|
47
|
+
- `mcp-nixos/resources/` - MCP resource definitions:
|
|
48
|
+
- `nixos_resources.py` - NixOS resources
|
|
49
|
+
- `home_manager_resources.py` - Home Manager resources
|
|
50
|
+
- `darwin/darwin_resources.py` - nix-darwin resources
|
|
51
|
+
- `mcp-nixos/tools/` - MCP tool implementations:
|
|
52
|
+
- `nixos_tools.py` - NixOS tools
|
|
53
|
+
- `home_manager_tools.py` - Home Manager tools
|
|
54
|
+
- `darwin/darwin_tools.py` - nix-darwin tools
|
|
55
|
+
- `mcp-nixos/utils/` - Utility functions and helpers:
|
|
56
|
+
- `cache_helpers.py` - Cross-platform cache directory management
|
|
57
|
+
- `helpers.py` - General utility functions
|
|
58
|
+
- `mcp-nixos/logging.py` - Centralized logging configuration
|
|
59
|
+
- `mcp-nixos/server.py` - FastMCP server implementation
|
|
60
|
+
|
|
61
|
+
## MCP Implementation Guidelines
|
|
62
|
+
|
|
63
|
+
### Resource Definitions
|
|
64
|
+
- Use `nixos://` scheme for NixOS resources, `home-manager://` for Home Manager, `darwin://` for nix-darwin
|
|
65
|
+
- Follow consistent path hierarchy: `scheme://category/action/parameter`
|
|
66
|
+
- Place parameters in curly braces: `nixos://package/{package_name}`
|
|
67
|
+
- Use type hints and clear docstrings
|
|
68
|
+
- Return structured data as a dictionary
|
|
69
|
+
- For errors, use `{"error": message, "found": false}` pattern
|
|
70
|
+
|
|
71
|
+
### Tool Definitions
|
|
72
|
+
- Use clear function names with type hints (return type `str` for human-readable output)
|
|
73
|
+
- Include optional `context` parameter for dependency injection in tests
|
|
74
|
+
- Use detailed Google-style docstrings with Args/Returns sections
|
|
75
|
+
- Catch exceptions and return user-friendly error messages
|
|
76
|
+
- Use provided context or fall back to global contexts
|
|
77
|
+
|
|
78
|
+
### Context Management
|
|
79
|
+
- Use lifespan context manager for resource initialization
|
|
80
|
+
- Initialize shared resources at startup and clean up on shutdown:
|
|
81
|
+
- Home Manager and nix-darwin data are eagerly loaded during server startup
|
|
82
|
+
- 10-second timeout with fallback to background loading for resilience
|
|
83
|
+
- Proper shutdown and cleanup of all contexts
|
|
84
|
+
- Pass contexts to resources and tools that need them
|
|
85
|
+
- Prefer dependency injection over global state access
|
|
86
|
+
|
|
87
|
+
### Best Practices
|
|
88
|
+
- Use resources for retrieving data, tools for actions/processing with formatted output
|
|
89
|
+
- Always use proper type annotations (Optional, Union, List, Dict, etc.)
|
|
90
|
+
- Follow strict null safety guidelines:
|
|
91
|
+
- Always check for None before accessing attributes (`if ctx is not None: ctx.method()`)
|
|
92
|
+
- Use the Optional type for attributes or parameters that may be None
|
|
93
|
+
- Add defensive guards for regex match operations and string comparisons
|
|
94
|
+
- Check result values from external APIs and provide appropriate fallbacks
|
|
95
|
+
- Log all errors with appropriate detail
|
|
96
|
+
- Return user-friendly error messages with suggestions where possible
|
|
97
|
+
- For search tools, handle empty results gracefully and support wildcards
|
|
98
|
+
- Ensure code passes both linting (`lint`) and type checking (`typecheck`) before committing
|
|
99
|
+
|
|
100
|
+
## MCP Resources
|
|
101
|
+
|
|
102
|
+
### NixOS Resources
|
|
103
|
+
- `nixos://status`: NixOS server status information
|
|
104
|
+
- `nixos://package/{package_name}`: NixOS package information
|
|
105
|
+
- `nixos://search/packages/{query}`: NixOS package search
|
|
106
|
+
- `nixos://search/options/{query}`: NixOS options search
|
|
107
|
+
- `nixos://option/{option_name}`: NixOS option information
|
|
108
|
+
- `nixos://search/programs/{program}`: Packages providing specific programs
|
|
109
|
+
- `nixos://packages/stats`: NixOS package statistics
|
|
110
|
+
|
|
111
|
+
### Home Manager Resources
|
|
112
|
+
- `home-manager://status`: Home Manager context status information
|
|
113
|
+
- `home-manager://search/options/{query}`: Home Manager options search
|
|
114
|
+
- `home-manager://option/{option_name}`: Home Manager option information
|
|
115
|
+
- `home-manager://options/stats`: Home Manager options statistics
|
|
116
|
+
- `home-manager://options/list`: Hierarchical list of all top-level options
|
|
117
|
+
- `home-manager://options/prefix/{option_prefix}`: Get options by prefix path
|
|
118
|
+
- Category-specific endpoints for various option groups:
|
|
119
|
+
- `home-manager://options/programs`
|
|
120
|
+
- `home-manager://options/services`
|
|
121
|
+
- `home-manager://options/home`
|
|
122
|
+
- And many more (accounts, fonts, gtk, xdg, etc.)
|
|
123
|
+
|
|
124
|
+
### nix-darwin Resources
|
|
125
|
+
- `darwin://status`: nix-darwin context status information
|
|
126
|
+
- `darwin://search/options/{query}`: nix-darwin options search
|
|
127
|
+
- `darwin://option/{option_name}`: nix-darwin option information
|
|
128
|
+
- `darwin://options/stats`: nix-darwin options statistics
|
|
129
|
+
- `darwin://options/categories`: List of top-level option categories
|
|
130
|
+
- `darwin://options/prefix/{option_prefix}`: Get options by prefix path
|
|
131
|
+
- Category-specific endpoints for macOS configuration areas:
|
|
132
|
+
- `darwin://options/documentation`
|
|
133
|
+
- `darwin://options/environment`
|
|
134
|
+
- `darwin://options/fonts`
|
|
135
|
+
- `darwin://options/homebrew`
|
|
136
|
+
- `darwin://options/launchd`
|
|
137
|
+
- `darwin://options/networking`
|
|
138
|
+
- `darwin://options/nix`
|
|
139
|
+
- `darwin://options/nixpkgs`
|
|
140
|
+
- `darwin://options/power`
|
|
141
|
+
- `darwin://options/programs`
|
|
142
|
+
- `darwin://options/security`
|
|
143
|
+
- `darwin://options/services`
|
|
144
|
+
- `darwin://options/system`
|
|
145
|
+
- `darwin://options/time`
|
|
146
|
+
- `darwin://options/users`
|
|
147
|
+
|
|
148
|
+
## MCP Tools
|
|
149
|
+
|
|
150
|
+
### NixOS Tools
|
|
151
|
+
- `nixos_search(query, type="packages", limit=20, channel="unstable", context=None)`:
|
|
152
|
+
Search for packages, options, or programs with automatic wildcard handling
|
|
153
|
+
- `nixos_info(name, type="package", channel="unstable", context=None)`:
|
|
154
|
+
Get detailed information about a specific package or option
|
|
155
|
+
|
|
156
|
+
Both tools above support the `channel` parameter with values:
|
|
157
|
+
- `"unstable"`: Latest NixOS unstable channel (default)
|
|
158
|
+
- `"stable"`: Current stable NixOS release (currently 24.11)
|
|
159
|
+
- `"24.11"`: Specific version reference (same as "stable" currently)
|
|
160
|
+
- `nixos_stats(channel="unstable", context=None)`:
|
|
161
|
+
Get statistical information about NixOS packages and options, with accurate option counts using Elasticsearch's Count API
|
|
162
|
+
|
|
163
|
+
### Home Manager Tools
|
|
164
|
+
- `home_manager_search(query, limit=20, context=None)`:
|
|
165
|
+
Search for Home Manager options with automatic wildcard handling
|
|
166
|
+
- `home_manager_info(name, context=None)`:
|
|
167
|
+
Get detailed information about a specific Home Manager option
|
|
168
|
+
- `home_manager_stats(context=None)`:
|
|
169
|
+
Get statistical information about Home Manager options
|
|
170
|
+
- `home_manager_list_options(context=None)`:
|
|
171
|
+
List all top-level Home Manager option categories
|
|
172
|
+
- `home_manager_options_by_prefix(option_prefix, context=None)`:
|
|
173
|
+
Get all Home Manager options under a specific prefix
|
|
174
|
+
|
|
175
|
+
### nix-darwin Tools
|
|
176
|
+
- `darwin_search(query, limit=20, context=None)`:
|
|
177
|
+
Search for nix-darwin options with automatic wildcard handling and enhanced fuzzy search using Levenshtein distance
|
|
178
|
+
- `darwin_info(name, context=None)`:
|
|
179
|
+
Get detailed information about a specific nix-darwin option
|
|
180
|
+
- `darwin_stats(context=None)`:
|
|
181
|
+
Get statistical information about nix-darwin options
|
|
182
|
+
- `darwin_list_options(context=None)`:
|
|
183
|
+
List all top-level nix-darwin option categories
|
|
184
|
+
- `darwin_options_by_prefix(option_prefix, context=None)`:
|
|
185
|
+
Get all nix-darwin options under a specific prefix
|
|
186
|
+
|
|
187
|
+
## Searching for Options
|
|
188
|
+
|
|
189
|
+
### Best Practices
|
|
190
|
+
- Use full hierarchical paths for precise option searching:
|
|
191
|
+
- NixOS: `services.postgresql` for all PostgreSQL options
|
|
192
|
+
- Home Manager: `programs.git` for all Git options
|
|
193
|
+
- nix-darwin: `system.defaults.dock` for all dock options
|
|
194
|
+
- Wildcards are automatically added where appropriate (services.postgresql*)
|
|
195
|
+
- Service paths get special handling with automatic suggestions
|
|
196
|
+
- Multiple query strategies are used: exact match, prefix match, wildcard match
|
|
197
|
+
- For NixOS specifically, multiple channels are supported: unstable (default), stable (current release), or specific version (e.g., 24.11)
|
|
198
|
+
|
|
199
|
+
## System Requirements
|
|
200
|
+
|
|
201
|
+
### Elasticsearch API (NixOS features)
|
|
202
|
+
- Uses NixOS search Elasticsearch API
|
|
203
|
+
- Configure with environment variables (defaults provided):
|
|
204
|
+
```
|
|
205
|
+
ELASTICSEARCH_URL=https://search.nixos.org/backend
|
|
206
|
+
ELASTICSEARCH_USER=aWVSALXpZv
|
|
207
|
+
ELASTICSEARCH_PASSWORD=X8gPHnzL52wFEekuxsfQ9cSh
|
|
208
|
+
```
|
|
209
|
+
- Supports multiple channels (unstable, 24.11) via different indices
|
|
210
|
+
- Uses Elasticsearch's Count API for accurate option counts beyond the default 10,000 result limit
|
|
211
|
+
- Provides enhanced search capabilities with field-specific boosts and query optimization
|
|
212
|
+
|
|
213
|
+
### HTML Documentation Parsing (Home Manager and nix-darwin features)
|
|
214
|
+
- Fetches and parses HTML docs from:
|
|
215
|
+
- Home Manager: nix-community.github.io/home-manager/
|
|
216
|
+
- nix-darwin: nix-darwin.github.io/nix-darwin/manual/
|
|
217
|
+
- Multi-level caching system for improved performance and resilience:
|
|
218
|
+
- HTML content cache to filesystem using cross-platform cache paths
|
|
219
|
+
- Processed in-memory data structures persisted to disk cache
|
|
220
|
+
- Option data serialized to both JSON and binary formats for complex structures
|
|
221
|
+
- Uses OS-specific standard cache locations
|
|
222
|
+
- Implements proper TTL expiration of cached content with legacy cache cleanup
|
|
223
|
+
- Provides comprehensive fallback mechanisms and error handling
|
|
224
|
+
- Tracks detailed cache statistics for monitoring
|
|
225
|
+
- Options are indexed in memory with specialized search indices
|
|
226
|
+
- Enhanced eager loading during server startup:
|
|
227
|
+
- First tries to load from serialized memory cache (fastest)
|
|
228
|
+
- If that fails, loads from HTML cache (medium speed)
|
|
229
|
+
- If both fail, fetches fresh HTML from web (slowest)
|
|
230
|
+
- 10-second timeout prevents hanging if there are loading issues
|
|
231
|
+
- Falls back to background loading if all methods fail
|
|
232
|
+
- Maintains resilience with multiple fallback mechanisms
|
|
233
|
+
- Supports force refresh to bypass cache when needed
|
|
234
|
+
- Related options are automatically suggested based on hierarchical paths
|
|
235
|
+
|
|
236
|
+
## Configuration
|
|
237
|
+
- `LOG_LEVEL`: Set logging level (default: INFO)
|
|
238
|
+
- `LOG_FILE`: Optional log file path (default: logs to stdout/stderr)
|
|
239
|
+
- `MCP_NIXOS_CACHE_DIR`: Custom directory for filesystem cache (default: OS-specific standard location)
|
|
240
|
+
- `MCP_NIXOS_CACHE_TTL`: Time-to-live for cached content in seconds (default: 86400 - 24 hours)
|
|
241
|
+
- Environment variables for Elasticsearch API credentials (see above)
|
|
242
|
+
|
|
243
|
+
### Cache Directory Locations
|
|
244
|
+
- Linux: `$XDG_CACHE_HOME/mcp-nixos/` (typically `~/.cache/mcp-nixos/`)
|
|
245
|
+
- macOS: `~/Library/Caches/mcp-nixos/`
|
|
246
|
+
- Windows: `%LOCALAPPDATA%\mcp-nixos\Cache\`
|
|
247
|
+
|
|
248
|
+
### Cache File Types
|
|
249
|
+
- `*.html` - Raw HTML content from Home Manager documentation
|
|
250
|
+
- `*.data.json` - Serialized structured data (options metadata, statistics)
|
|
251
|
+
- `*.data.pickle` - Binary serialized complex data structures (search indices, default dictionaries, sets)
|
|
252
|
+
|
|
253
|
+
## Testing
|
|
254
|
+
- Use pytest with code coverage reporting (target: 80%)
|
|
255
|
+
- Run static type checking with `typecheck` command:
|
|
256
|
+
- Zero-tolerance policy for type errors
|
|
257
|
+
- Checks for null safety and proper type usage
|
|
258
|
+
- Run on CI for all pull requests
|
|
259
|
+
- Run linting checks with `lint` command:
|
|
260
|
+
- Enforces code style with Black
|
|
261
|
+
- Checks for issues with Flake8
|
|
262
|
+
- No unused imports allowed
|
|
263
|
+
- No f-string placeholders without variables
|
|
264
|
+
- Test organization follows the module structure:
|
|
265
|
+
- `tests/cache/` - Tests for caching components
|
|
266
|
+
- `tests/clients/` - Tests for API clients (with nested `darwin/` directory)
|
|
267
|
+
- `tests/contexts/` - Tests for application contexts (with nested `darwin/` directory)
|
|
268
|
+
- `tests/completions/` - Tests for MCP completions
|
|
269
|
+
- `tests/resources/` - Tests for MCP resources (with nested `darwin/` directory)
|
|
270
|
+
- `tests/tools/` - Tests for MCP tools (with nested `darwin/` directory)
|
|
271
|
+
- `tests/utils/` - Tests for utility functions
|
|
272
|
+
- `tests/integration/` - End-to-end integration tests
|
|
273
|
+
- Use dependency injection for testable components:
|
|
274
|
+
- Pass mock contexts directly to resource/tool functions
|
|
275
|
+
- Avoid patching global state
|
|
276
|
+
- Mock external dependencies (Elasticsearch, Home Manager docs)
|
|
277
|
+
- Test both success paths and error handling
|
|
278
|
+
- Always check for None values before accessing attributes in tests
|
|
279
|
+
- **IMPORTANT**: Mock test functions, not production code:
|
|
280
|
+
```python
|
|
281
|
+
# GOOD: Clean production code with mocking in tests
|
|
282
|
+
def production_function():
|
|
283
|
+
result = make_api_request()
|
|
284
|
+
return process_result(result)
|
|
285
|
+
|
|
286
|
+
# In tests:
|
|
287
|
+
@patch("module.make_api_request")
|
|
288
|
+
def test_production_function(mock_api):
|
|
289
|
+
mock_api.return_value = {"test": "data"}
|
|
290
|
+
result = production_function()
|
|
291
|
+
assert result == expected_result
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Installation and Usage
|
|
295
|
+
|
|
296
|
+
### Installation Methods
|
|
297
|
+
- pip: `pip install mcp-nixos`
|
|
298
|
+
- uv: `uv pip install mcp-nixos`
|
|
299
|
+
- uvx (for Claude Code): `uvx mcp-nixos`
|
|
300
|
+
|
|
301
|
+
### MCP Configuration
|
|
302
|
+
To configure Claude Code to use mcp-nixos, add to `~/.config/claude/config.json`:
|
|
303
|
+
```json
|
|
304
|
+
{
|
|
305
|
+
"mcpServers": {
|
|
306
|
+
"nixos": {
|
|
307
|
+
"command": "uvx",
|
|
308
|
+
"args": ["mcp-nixos"],
|
|
309
|
+
"env": {
|
|
310
|
+
"LOG_LEVEL": "INFO",
|
|
311
|
+
"LOG_FILE": "/path/to/mcp-nixos.log"
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Development Commands
|
|
319
|
+
- Development environment: `nix develop`
|
|
320
|
+
- Run server: `run [--port=PORT]`
|
|
321
|
+
- Run tests: `run-tests [--no-coverage]`
|
|
322
|
+
- List commands: `menu`
|
|
323
|
+
- Lint and format: `lint`, `format`
|
|
324
|
+
- Setup uv: `setup-uv`
|
|
325
|
+
- Count lines of code: `loc`
|
|
326
|
+
- Build distributions: `build`
|
|
327
|
+
- Publish to PyPI: `publish`
|
|
328
|
+
|
|
329
|
+
## Code Style
|
|
330
|
+
- Python 3.11+ with type hints
|
|
331
|
+
- 4-space indentation, 120 characters max line length
|
|
332
|
+
- PEP 8 naming: snake_case for functions/variables, CamelCase for classes
|
|
333
|
+
- Google-style docstrings
|
|
334
|
+
- Specific exception handling (avoid bare except)
|
|
335
|
+
- Black for formatting, Flake8 for linting
|
|
336
|
+
- Flake8 config: max-line-length=120, ignore=E402,E203
|
|
337
|
+
- Strict null safety to prevent "None" type errors:
|
|
338
|
+
- Check for None before accessing attributes (`if obj is not None: obj.method()`)
|
|
339
|
+
- Guard regex match results with if statements before accessing group() methods
|
|
340
|
+
- Add type assertion for string operations (`if s is not None: "text" in s`)
|
|
341
|
+
- Use pyright's strict type checking with zero-tolerance policy for type errors
|
mcp_nixos-0.2.0/.envrc
ADDED
mcp_nixos-0.2.0/.flake8
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# .github/workflows/ci.yml
|
|
2
|
+
|
|
3
|
+
name: CI
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
tags: ["v*"] # Run CI on version tags
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
workflow_dispatch: # Allow manual trigger
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
name: Build Flake
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout code
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
- name: Install Nix
|
|
25
|
+
uses: cachix/install-nix-action@v27
|
|
26
|
+
with:
|
|
27
|
+
nix_path: nixpkgs=channel:nixos-unstable
|
|
28
|
+
extra_nix_config: |
|
|
29
|
+
experimental-features = nix-command flakes
|
|
30
|
+
accept-flake-config = true
|
|
31
|
+
- name: Cache Nix store
|
|
32
|
+
uses: actions/cache@v4
|
|
33
|
+
with:
|
|
34
|
+
path: |
|
|
35
|
+
~/.cache/nix
|
|
36
|
+
/nix/store
|
|
37
|
+
key: ${{ runner.os }}-nix-${{ hashFiles('flake.lock') }}
|
|
38
|
+
restore-keys: |
|
|
39
|
+
${{ runner.os }}-nix-
|
|
40
|
+
- name: Build flake and check dev environment
|
|
41
|
+
run: |
|
|
42
|
+
nix flake check --accept-flake-config
|
|
43
|
+
nix develop -c echo "Flake development environment builds successfully"
|
|
44
|
+
|
|
45
|
+
lint:
|
|
46
|
+
name: Lint Code
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
needs: [build]
|
|
49
|
+
steps:
|
|
50
|
+
- name: Checkout code
|
|
51
|
+
uses: actions/checkout@v4
|
|
52
|
+
- name: Install Nix
|
|
53
|
+
uses: cachix/install-nix-action@v27
|
|
54
|
+
with:
|
|
55
|
+
nix_path: nixpkgs=channel:nixos-unstable
|
|
56
|
+
extra_nix_config: |
|
|
57
|
+
experimental-features = nix-command flakes
|
|
58
|
+
accept-flake-config = true
|
|
59
|
+
- name: Cache Nix store
|
|
60
|
+
uses: actions/cache@v4
|
|
61
|
+
with:
|
|
62
|
+
path: |
|
|
63
|
+
~/.cache/nix
|
|
64
|
+
/nix/store
|
|
65
|
+
key: ${{ runner.os }}-nix-${{ hashFiles('flake.lock') }}
|
|
66
|
+
restore-keys: |
|
|
67
|
+
${{ runner.os }}-nix-
|
|
68
|
+
- name: Run linters (Black, Flake8)
|
|
69
|
+
run: |
|
|
70
|
+
nix develop --command lint
|
|
71
|
+
|
|
72
|
+
typecheck:
|
|
73
|
+
name: Type Check (pyright)
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
needs: [build]
|
|
76
|
+
steps:
|
|
77
|
+
- name: Checkout code
|
|
78
|
+
uses: actions/checkout@v4
|
|
79
|
+
- name: Install Nix
|
|
80
|
+
uses: cachix/install-nix-action@v27
|
|
81
|
+
with:
|
|
82
|
+
nix_path: nixpkgs=channel:nixos-unstable
|
|
83
|
+
extra_nix_config: |
|
|
84
|
+
experimental-features = nix-command flakes
|
|
85
|
+
accept-flake-config = true
|
|
86
|
+
- name: Cache Nix store
|
|
87
|
+
uses: actions/cache@v4
|
|
88
|
+
with:
|
|
89
|
+
path: |
|
|
90
|
+
~/.cache/nix
|
|
91
|
+
/nix/store
|
|
92
|
+
key: ${{ runner.os }}-nix-${{ hashFiles('flake.lock') }}
|
|
93
|
+
restore-keys: |
|
|
94
|
+
${{ runner.os }}-nix-
|
|
95
|
+
- name: Run pyright type checker
|
|
96
|
+
run: |
|
|
97
|
+
# Use the new 'typecheck' command from flake.nix
|
|
98
|
+
nix develop --command typecheck
|
|
99
|
+
|
|
100
|
+
test:
|
|
101
|
+
name: Run Tests
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
needs: [build]
|
|
104
|
+
steps:
|
|
105
|
+
- name: Checkout code
|
|
106
|
+
uses: actions/checkout@v4
|
|
107
|
+
- name: Install Nix
|
|
108
|
+
uses: cachix/install-nix-action@v27
|
|
109
|
+
with:
|
|
110
|
+
nix_path: nixpkgs=channel:nixos-unstable
|
|
111
|
+
extra_nix_config: |
|
|
112
|
+
experimental-features = nix-command flakes
|
|
113
|
+
accept-flake-config = true
|
|
114
|
+
- name: Cache Nix store
|
|
115
|
+
uses: actions/cache@v4
|
|
116
|
+
with:
|
|
117
|
+
path: |
|
|
118
|
+
~/.cache/nix
|
|
119
|
+
/nix/store
|
|
120
|
+
key: ${{ runner.os }}-nix-${{ hashFiles('flake.lock') }}
|
|
121
|
+
restore-keys: |
|
|
122
|
+
${{ runner.os }}-nix-
|
|
123
|
+
- name: Cache Python virtual environment
|
|
124
|
+
id: cache-venv
|
|
125
|
+
uses: actions/cache@v4
|
|
126
|
+
with:
|
|
127
|
+
path: .venv
|
|
128
|
+
key: ${{ runner.os }}-venv-${{ hashFiles('requirements.txt', 'pyproject.toml', 'setup.py') }}
|
|
129
|
+
restore-keys: |
|
|
130
|
+
${{ runner.os }}-venv-
|
|
131
|
+
- name: Setup Python environment and run tests
|
|
132
|
+
run: |
|
|
133
|
+
nix develop --command setup
|
|
134
|
+
nix develop --command run-tests
|
|
135
|
+
|
|
136
|
+
- name: Upload coverage reports to Codecov
|
|
137
|
+
uses: codecov/codecov-action@v4
|
|
138
|
+
with:
|
|
139
|
+
file: ./coverage.xml
|
|
140
|
+
fail_ci_if_error: true
|
|
141
|
+
env:
|
|
142
|
+
# Add the Codecov token from repository secrets
|
|
143
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
144
|
+
|
|
145
|
+
- name: Upload coverage artifact
|
|
146
|
+
uses: actions/upload-artifact@v4
|
|
147
|
+
with:
|
|
148
|
+
name: coverage-report-${{ runner.os }}
|
|
149
|
+
path: |
|
|
150
|
+
./htmlcov/
|
|
151
|
+
./coverage.xml
|
|
152
|
+
|
|
153
|
+
publish:
|
|
154
|
+
name: Build and Publish to PyPI
|
|
155
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
156
|
+
needs: [lint, typecheck, test]
|
|
157
|
+
runs-on: ubuntu-latest
|
|
158
|
+
environment:
|
|
159
|
+
name: pypi
|
|
160
|
+
url: https://pypi.org/p/mcp-nixos
|
|
161
|
+
permissions:
|
|
162
|
+
id-token: write
|
|
163
|
+
steps:
|
|
164
|
+
- name: Checkout code
|
|
165
|
+
uses: actions/checkout@v4
|
|
166
|
+
- name: Install Nix
|
|
167
|
+
uses: cachix/install-nix-action@v27
|
|
168
|
+
with:
|
|
169
|
+
nix_path: nixpkgs=channel:nixos-unstable
|
|
170
|
+
extra_nix_config: |
|
|
171
|
+
experimental-features = nix-command flakes
|
|
172
|
+
accept-flake-config = true
|
|
173
|
+
- name: Cache Nix store
|
|
174
|
+
uses: actions/cache@v4
|
|
175
|
+
with:
|
|
176
|
+
path: |
|
|
177
|
+
~/.cache/nix
|
|
178
|
+
/nix/store
|
|
179
|
+
key: ${{ runner.os }}-nix-${{ hashFiles('flake.lock') }}
|
|
180
|
+
restore-keys: |
|
|
181
|
+
${{ runner.os }}-nix-
|
|
182
|
+
- name: Build package distributions using Nix environment
|
|
183
|
+
run: |
|
|
184
|
+
nix develop --command build
|
|
185
|
+
ls -l dist/
|
|
186
|
+
- name: Verify built package installation (Wheel)
|
|
187
|
+
run: |
|
|
188
|
+
python3 -m venv .verifier-venv
|
|
189
|
+
source .verifier-venv/bin/activate
|
|
190
|
+
python -m pip install --upgrade pip
|
|
191
|
+
WHEEL_FILE=$(ls dist/*.whl)
|
|
192
|
+
echo "Verifying wheel: $WHEEL_FILE"
|
|
193
|
+
python -m pip install "$WHEEL_FILE"
|
|
194
|
+
echo "Checking installation..."
|
|
195
|
+
python -c "import mcp_nixos; print(f'Successfully installed mcp_nixos version: {mcp_nixos.__version__}')"
|
|
196
|
+
deactivate
|
|
197
|
+
- name: Publish package distributions to PyPI
|
|
198
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# Virtual Environment
|
|
25
|
+
.venv/
|
|
26
|
+
venv/
|
|
27
|
+
ENV/
|
|
28
|
+
|
|
29
|
+
# Unit test / coverage reports
|
|
30
|
+
htmlcov/
|
|
31
|
+
.tox/
|
|
32
|
+
.nox/
|
|
33
|
+
.coverage
|
|
34
|
+
.coverage.*
|
|
35
|
+
.cache
|
|
36
|
+
nosetests.xml
|
|
37
|
+
coverage.xml
|
|
38
|
+
*.cover
|
|
39
|
+
.hypothesis/
|
|
40
|
+
.pytest_cache/
|
|
41
|
+
|
|
42
|
+
# Environments
|
|
43
|
+
# Note: We're keeping .env in the repo since it contains public credentials
|
|
44
|
+
# .env
|
|
45
|
+
.venv
|
|
46
|
+
env/
|
|
47
|
+
venv/
|
|
48
|
+
ENV/
|
|
49
|
+
env.bak/
|
|
50
|
+
venv.bak/
|
|
51
|
+
|
|
52
|
+
# Nix
|
|
53
|
+
.direnv/
|
|
54
|
+
|
|
55
|
+
# IDE
|
|
56
|
+
.idea/
|
|
57
|
+
*.swp
|
|
58
|
+
*.swo
|
|
59
|
+
*~
|
|
60
|
+
|
|
61
|
+
# Misc
|
|
62
|
+
temp
|
|
63
|
+
tmp
|
|
64
|
+
uv-*.lock
|
|
65
|
+
.aider*
|
|
66
|
+
.pypirc
|
|
67
|
+
mcp-completion-docs.md
|
|
68
|
+
TODO.md
|
|
69
|
+
|
|
70
|
+
# Logs
|
|
71
|
+
*.log
|