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.
Files changed (122) hide show
  1. mcp_nixos-0.2.0/.cursorrules +341 -0
  2. mcp_nixos-0.2.0/.envrc +5 -0
  3. mcp_nixos-0.2.0/.flake8 +3 -0
  4. mcp_nixos-0.2.0/.github/workflows/ci.yml +198 -0
  5. mcp_nixos-0.2.0/.gitignore +71 -0
  6. mcp_nixos-0.2.0/.goosehints +341 -0
  7. mcp_nixos-0.2.0/.vscode/extensions.json +13 -0
  8. mcp_nixos-0.2.0/.vscode/launch.json +34 -0
  9. mcp_nixos-0.2.0/.vscode/settings.json +71 -0
  10. mcp_nixos-0.2.0/.windsurfrules +341 -0
  11. mcp_nixos-0.2.0/CLAUDE.md +371 -0
  12. mcp_nixos-0.2.0/LICENSE +21 -0
  13. mcp_nixos-0.2.0/MANIFEST.in +6 -0
  14. mcp_nixos-0.2.0/PKG-INFO +592 -0
  15. mcp_nixos-0.2.0/README.md +567 -0
  16. mcp_nixos-0.2.0/TEST_PROMPTS.md +404 -0
  17. mcp_nixos-0.2.0/configuration.nix +610 -0
  18. mcp_nixos-0.2.0/coverage_report/.gitignore +2 -0
  19. mcp_nixos-0.2.0/coverage_report/class_index.html +139 -0
  20. mcp_nixos-0.2.0/coverage_report/coverage_html_cb_6fb7b396.js +733 -0
  21. mcp_nixos-0.2.0/coverage_report/favicon_32_cb_58284776.png +0 -0
  22. mcp_nixos-0.2.0/coverage_report/function_index.html +443 -0
  23. mcp_nixos-0.2.0/coverage_report/index.html +111 -0
  24. mcp_nixos-0.2.0/coverage_report/keybd_closed_cb_ce680311.png +0 -0
  25. mcp_nixos-0.2.0/coverage_report/server_py.html +1635 -0
  26. mcp_nixos-0.2.0/coverage_report/status.json +1 -0
  27. mcp_nixos-0.2.0/coverage_report/style_cb_8e611ae1.css +337 -0
  28. mcp_nixos-0.2.0/flake.lock +96 -0
  29. mcp_nixos-0.2.0/flake.nix +248 -0
  30. mcp_nixos-0.2.0/mcp_nixos/__init__.py +23 -0
  31. mcp_nixos-0.2.0/mcp_nixos/__main__.py +13 -0
  32. mcp_nixos-0.2.0/mcp_nixos/cache/__init__.py +5 -0
  33. mcp_nixos-0.2.0/mcp_nixos/cache/html_cache.py +534 -0
  34. mcp_nixos-0.2.0/mcp_nixos/cache/simple_cache.py +62 -0
  35. mcp_nixos-0.2.0/mcp_nixos/clients/__init__.py +6 -0
  36. mcp_nixos-0.2.0/mcp_nixos/clients/darwin/__init__.py +5 -0
  37. mcp_nixos-0.2.0/mcp_nixos/clients/darwin/darwin_client.py +751 -0
  38. mcp_nixos-0.2.0/mcp_nixos/clients/elasticsearch_client.py +632 -0
  39. mcp_nixos-0.2.0/mcp_nixos/clients/home_manager_client.py +708 -0
  40. mcp_nixos-0.2.0/mcp_nixos/clients/html_client.py +125 -0
  41. mcp_nixos-0.2.0/mcp_nixos/completions/__init__.py +330 -0
  42. mcp_nixos-0.2.0/mcp_nixos/completions/home_manager.py +228 -0
  43. mcp_nixos-0.2.0/mcp_nixos/completions/nixos.py +415 -0
  44. mcp_nixos-0.2.0/mcp_nixos/completions/utils.py +27 -0
  45. mcp_nixos-0.2.0/mcp_nixos/contexts/__init__.py +6 -0
  46. mcp_nixos-0.2.0/mcp_nixos/contexts/darwin/__init__.py +5 -0
  47. mcp_nixos-0.2.0/mcp_nixos/contexts/darwin/darwin_context.py +224 -0
  48. mcp_nixos-0.2.0/mcp_nixos/contexts/home_manager_context.py +357 -0
  49. mcp_nixos-0.2.0/mcp_nixos/contexts/nixos_context.py +138 -0
  50. mcp_nixos-0.2.0/mcp_nixos/logging.py +53 -0
  51. mcp_nixos-0.2.0/mcp_nixos/resources/__init__.py +6 -0
  52. mcp_nixos-0.2.0/mcp_nixos/resources/darwin/__init__.py +5 -0
  53. mcp_nixos-0.2.0/mcp_nixos/resources/darwin/darwin_resources.py +473 -0
  54. mcp_nixos-0.2.0/mcp_nixos/resources/home_manager_resources.py +210 -0
  55. mcp_nixos-0.2.0/mcp_nixos/resources/nixos_resources.py +96 -0
  56. mcp_nixos-0.2.0/mcp_nixos/server.py +558 -0
  57. mcp_nixos-0.2.0/mcp_nixos/tools/__init__.py +6 -0
  58. mcp_nixos-0.2.0/mcp_nixos/tools/darwin/__init__.py +19 -0
  59. mcp_nixos-0.2.0/mcp_nixos/tools/darwin/darwin_tools.py +290 -0
  60. mcp_nixos-0.2.0/mcp_nixos/tools/home_manager_tools.py +769 -0
  61. mcp_nixos-0.2.0/mcp_nixos/tools/nixos_tools.py +591 -0
  62. mcp_nixos-0.2.0/mcp_nixos/utils/__init__.py +5 -0
  63. mcp_nixos-0.2.0/mcp_nixos/utils/cache_helpers.py +131 -0
  64. mcp_nixos-0.2.0/mcp_nixos/utils/helpers.py +336 -0
  65. mcp_nixos-0.2.0/pyproject.toml +50 -0
  66. mcp_nixos-0.2.0/pyrightconfig.json +19 -0
  67. mcp_nixos-0.2.0/pytest.ini +11 -0
  68. mcp_nixos-0.2.0/requirements.txt +13 -0
  69. mcp_nixos-0.2.0/setup.py +16 -0
  70. mcp_nixos-0.2.0/tests/__init__.py +71 -0
  71. mcp_nixos-0.2.0/tests/cache/__init__.py +0 -0
  72. mcp_nixos-0.2.0/tests/cache/test_cache_ttl_expiration.py +116 -0
  73. mcp_nixos-0.2.0/tests/cache/test_cross_platform_cache.py +180 -0
  74. mcp_nixos-0.2.0/tests/cache/test_html_cache.py +313 -0
  75. mcp_nixos-0.2.0/tests/cache/test_simple_cache.py +192 -0
  76. mcp_nixos-0.2.0/tests/clients/__init__.py +0 -0
  77. mcp_nixos-0.2.0/tests/clients/darwin/__init__.py +0 -0
  78. mcp_nixos-0.2.0/tests/clients/darwin/test_darwin_cache.py +680 -0
  79. mcp_nixos-0.2.0/tests/clients/darwin/test_darwin_client.py +531 -0
  80. mcp_nixos-0.2.0/tests/clients/darwin/test_darwin_serialization.py +178 -0
  81. mcp_nixos-0.2.0/tests/clients/test_elasticsearch_client.py +376 -0
  82. mcp_nixos-0.2.0/tests/clients/test_home_manager_client.py +405 -0
  83. mcp_nixos-0.2.0/tests/clients/test_html_client.py +186 -0
  84. mcp_nixos-0.2.0/tests/completions/__init__.py +0 -0
  85. mcp_nixos-0.2.0/tests/completions/test_completion.py +279 -0
  86. mcp_nixos-0.2.0/tests/completions/test_completion_home_manager.py +200 -0
  87. mcp_nixos-0.2.0/tests/completions/test_completion_nixos.py +233 -0
  88. mcp_nixos-0.2.0/tests/completions/test_mcp_completions.py +84 -0
  89. mcp_nixos-0.2.0/tests/contexts/__init__.py +0 -0
  90. mcp_nixos-0.2.0/tests/contexts/darwin/__init__.py +0 -0
  91. mcp_nixos-0.2.0/tests/contexts/darwin/test_darwin_context.py +232 -0
  92. mcp_nixos-0.2.0/tests/contexts/test_home_manager.py +487 -0
  93. mcp_nixos-0.2.0/tests/contexts/test_nixos_context.py +146 -0
  94. mcp_nixos-0.2.0/tests/integration/__init__.py +0 -0
  95. mcp_nixos-0.2.0/tests/integration/test_darwin_integration.py +256 -0
  96. mcp_nixos-0.2.0/tests/integration/test_home_manager_integration.py +219 -0
  97. mcp_nixos-0.2.0/tests/integration/test_home_manager_mcp_integration.py +323 -0
  98. mcp_nixos-0.2.0/tests/integration/test_mcp_nixos.py +877 -0
  99. mcp_nixos-0.2.0/tests/resources/__init__.py +0 -0
  100. mcp_nixos-0.2.0/tests/resources/darwin/__init__.py +0 -0
  101. mcp_nixos-0.2.0/tests/resources/test_home_manager_resources.py +341 -0
  102. mcp_nixos-0.2.0/tests/resources/test_mcp_resources.py +280 -0
  103. mcp_nixos-0.2.0/tests/test_app_lifespan.py +99 -0
  104. mcp_nixos-0.2.0/tests/test_eager_loading.py +175 -0
  105. mcp_nixos-0.2.0/tests/test_hierarchical_paths.py +236 -0
  106. mcp_nixos-0.2.0/tests/test_server_lifespan.py +225 -0
  107. mcp_nixos-0.2.0/tests/test_server_logging.py +104 -0
  108. mcp_nixos-0.2.0/tests/tools/__init__.py +0 -0
  109. mcp_nixos-0.2.0/tests/tools/darwin/__init__.py +0 -0
  110. mcp_nixos-0.2.0/tests/tools/darwin/test_darwin_tools_coroutine.py +253 -0
  111. mcp_nixos-0.2.0/tests/tools/test_home_manager_hierarchy.py +184 -0
  112. mcp_nixos-0.2.0/tests/tools/test_mcp_tools.py +691 -0
  113. mcp_nixos-0.2.0/tests/tools/test_option_documentation.py +91 -0
  114. mcp_nixos-0.2.0/tests/tools/test_package_documentation.py +128 -0
  115. mcp_nixos-0.2.0/tests/tools/test_service_options.py +483 -0
  116. mcp_nixos-0.2.0/tests/tools/test_suggestions.py +291 -0
  117. mcp_nixos-0.2.0/tests/tools/test_version_display.py +61 -0
  118. mcp_nixos-0.2.0/tests/utils/__init__.py +0 -0
  119. mcp_nixos-0.2.0/tests/utils/test_cache_helpers.py +126 -0
  120. mcp_nixos-0.2.0/tests/utils/test_helper_functions.py +59 -0
  121. mcp_nixos-0.2.0/tests/utils/test_multi_word_query.py +135 -0
  122. 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
@@ -0,0 +1,5 @@
1
+ # Use direnv to load the Nix development environment from flake.nix
2
+ use flake
3
+
4
+ # Uncomment to allow the use of unfree packages if needed
5
+ # export NIXPKGS_ALLOW_UNFREE=1
@@ -0,0 +1,3 @@
1
+ [flake8]
2
+ max-line-length = 120
3
+ ignore = E402, E203, W503
@@ -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