ha-mcp-dev 7.5.0.dev519__tar.gz → 7.5.0.dev521__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.
- {ha_mcp_dev-7.5.0.dev519/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.5.0.dev521}/PKG-INFO +38 -1
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/README.md +37 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/pyproject.toml +1 -1
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_search.py +44 -11
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_system.py +45 -8
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/util_helpers.py +41 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521/src/ha_mcp_dev.egg-info}/PKG-INFO +38 -1
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/LICENSE +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/setup.cfg +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/tests/test_env_manager.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ha-mcp-dev
|
|
3
|
-
Version: 7.5.0.
|
|
3
|
+
Version: 7.5.0.dev521
|
|
4
4
|
Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
|
|
5
5
|
Author-email: Julien <github@qc-h.net>
|
|
6
6
|
License: MIT
|
|
@@ -264,6 +264,43 @@ Skills can still be installed manually for clients that prefer local skill files
|
|
|
264
264
|
|
|
265
265
|
---
|
|
266
266
|
|
|
267
|
+
## 🔍 Tool Discovery for AI Agents
|
|
268
|
+
|
|
269
|
+
By default, the full tool catalog (~86 tools) is listed to the client through the standard MCP `tools/list` response. Clients with deferred / on-demand tool loading (Claude Sonnet, Claude Opus,) handle that fine — tools are pulled into context only when needed, so idle context cost is near-zero.
|
|
270
|
+
|
|
271
|
+
For models *without* deferred tool support — Claude Haiku, Gemini, ChatGPT OpenAI-compatible local models, smaller open-weights models — listing 86 tools eats ~46K tokens of idle context. To address that, the server ships with a **search-based discovery mode** built on top of FastMCP's BM25 search transform.
|
|
272
|
+
|
|
273
|
+
### Enable search-based discovery
|
|
274
|
+
|
|
275
|
+
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA add-on). The full catalog is replaced in the tool list with four entry points plus a small set of always-visible "pinned" tools (ha_search_entities, ha_get_overview, ha_restart, etc.). All tools remain callable directly by name once discovered:
|
|
276
|
+
|
|
277
|
+
| Tool | Purpose |
|
|
278
|
+
|------|---------|
|
|
279
|
+
| `ha_search_tools` | BM25 keyword search across all tools. Returns name, description, parameters, and annotations (`readOnlyHint` / `destructiveHint`) so the agent can pick the right one. |
|
|
280
|
+
| `ha_call_read_tool` | Execute a `readOnlyHint` tool by name. Safe — clients can auto-approve. |
|
|
281
|
+
| `ha_call_write_tool` | Execute a write tool that creates or updates data. |
|
|
282
|
+
| `ha_call_delete_tool` | Execute a tool that removes / deletes data. |
|
|
283
|
+
|
|
284
|
+
The proxy split lets MCP clients apply different permission policies per category (e.g. auto-approve reads, prompt for writes, confirm deletes) without parsing tool docstrings.
|
|
285
|
+
|
|
286
|
+
| Setting | Default | Description |
|
|
287
|
+
|---------|---------|-------------|
|
|
288
|
+
| `ENABLE_TOOL_SEARCH` | `false` | Replace full tool catalog with search-based discovery (~46K → ~5K idle tokens). |
|
|
289
|
+
| `TOOL_SEARCH_MAX_RESULTS` | `5` | Max results returned by `ha_search_tools` (range 2–10). |
|
|
290
|
+
| `PINNED_TOOLS` | empty | Comma-separated tool names to keep always visible. The web settings UI is the primary way to manage this. |
|
|
291
|
+
|
|
292
|
+
### When to enable
|
|
293
|
+
|
|
294
|
+
- **Claude Haiku, OpenAI-compatible local models, Gemini, ChatGPT or any model without native deferred tool support** — large idle-context savings.
|
|
295
|
+
- MCP clients that cap total tool count (some cap at 100) — surfaces a minimal set (~10 tools) instead of 86.
|
|
296
|
+
- **Cost-sensitive deployments** — fewer idle tokens per turn.
|
|
297
|
+
|
|
298
|
+
Leave it off when using Claude Sonnet/Opus or any client with deferred tool loading; the full catalog has no idle cost there and direct calls skip the search step. If you choose to use our toolsearch then you should disable the native Claude Opus/Sonnet toolsearch, which is called deferred tools in the settings.
|
|
299
|
+
|
|
300
|
+
For the HA add-on, the same option is documented in [`homeassistant-addon/DOCS.md`](homeassistant-addon/DOCS.md#enable_tool_search) along with the in-add-on settings UI for fine-grained tool enable/disable/pin.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
267
304
|
## 🧪 Dev Channel
|
|
268
305
|
|
|
269
306
|
Want early access to new features and fixes? Dev releases (`.devN`) are published on every push to master.
|
|
@@ -234,6 +234,43 @@ Skills can still be installed manually for clients that prefer local skill files
|
|
|
234
234
|
|
|
235
235
|
---
|
|
236
236
|
|
|
237
|
+
## 🔍 Tool Discovery for AI Agents
|
|
238
|
+
|
|
239
|
+
By default, the full tool catalog (~86 tools) is listed to the client through the standard MCP `tools/list` response. Clients with deferred / on-demand tool loading (Claude Sonnet, Claude Opus,) handle that fine — tools are pulled into context only when needed, so idle context cost is near-zero.
|
|
240
|
+
|
|
241
|
+
For models *without* deferred tool support — Claude Haiku, Gemini, ChatGPT OpenAI-compatible local models, smaller open-weights models — listing 86 tools eats ~46K tokens of idle context. To address that, the server ships with a **search-based discovery mode** built on top of FastMCP's BM25 search transform.
|
|
242
|
+
|
|
243
|
+
### Enable search-based discovery
|
|
244
|
+
|
|
245
|
+
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA add-on). The full catalog is replaced in the tool list with four entry points plus a small set of always-visible "pinned" tools (ha_search_entities, ha_get_overview, ha_restart, etc.). All tools remain callable directly by name once discovered:
|
|
246
|
+
|
|
247
|
+
| Tool | Purpose |
|
|
248
|
+
|------|---------|
|
|
249
|
+
| `ha_search_tools` | BM25 keyword search across all tools. Returns name, description, parameters, and annotations (`readOnlyHint` / `destructiveHint`) so the agent can pick the right one. |
|
|
250
|
+
| `ha_call_read_tool` | Execute a `readOnlyHint` tool by name. Safe — clients can auto-approve. |
|
|
251
|
+
| `ha_call_write_tool` | Execute a write tool that creates or updates data. |
|
|
252
|
+
| `ha_call_delete_tool` | Execute a tool that removes / deletes data. |
|
|
253
|
+
|
|
254
|
+
The proxy split lets MCP clients apply different permission policies per category (e.g. auto-approve reads, prompt for writes, confirm deletes) without parsing tool docstrings.
|
|
255
|
+
|
|
256
|
+
| Setting | Default | Description |
|
|
257
|
+
|---------|---------|-------------|
|
|
258
|
+
| `ENABLE_TOOL_SEARCH` | `false` | Replace full tool catalog with search-based discovery (~46K → ~5K idle tokens). |
|
|
259
|
+
| `TOOL_SEARCH_MAX_RESULTS` | `5` | Max results returned by `ha_search_tools` (range 2–10). |
|
|
260
|
+
| `PINNED_TOOLS` | empty | Comma-separated tool names to keep always visible. The web settings UI is the primary way to manage this. |
|
|
261
|
+
|
|
262
|
+
### When to enable
|
|
263
|
+
|
|
264
|
+
- **Claude Haiku, OpenAI-compatible local models, Gemini, ChatGPT or any model without native deferred tool support** — large idle-context savings.
|
|
265
|
+
- MCP clients that cap total tool count (some cap at 100) — surfaces a minimal set (~10 tools) instead of 86.
|
|
266
|
+
- **Cost-sensitive deployments** — fewer idle tokens per turn.
|
|
267
|
+
|
|
268
|
+
Leave it off when using Claude Sonnet/Opus or any client with deferred tool loading; the full catalog has no idle cost there and direct calls skip the search step. If you choose to use our toolsearch then you should disable the native Claude Opus/Sonnet toolsearch, which is called deferred tools in the settings.
|
|
269
|
+
|
|
270
|
+
For the HA add-on, the same option is documented in [`homeassistant-addon/DOCS.md`](homeassistant-addon/DOCS.md#enable_tool_search) along with the in-add-on settings UI for fine-grained tool enable/disable/pin.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
237
274
|
## 🧪 Dev Channel
|
|
238
275
|
|
|
239
276
|
Want early access to new features and fixes? Dev releases (`.devN`) are published on every push to master.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.5.0.
|
|
7
|
+
version = "7.5.0.dev521"
|
|
8
8
|
description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13,<3.14"
|
|
@@ -22,7 +22,9 @@ from .util_helpers import (
|
|
|
22
22
|
build_pagination_metadata,
|
|
23
23
|
coerce_bool_param,
|
|
24
24
|
coerce_int_param,
|
|
25
|
+
filter_active_repairs,
|
|
25
26
|
parse_string_list_param,
|
|
27
|
+
project_repair_fields,
|
|
26
28
|
public_fields,
|
|
27
29
|
)
|
|
28
30
|
|
|
@@ -852,6 +854,16 @@ def register_search_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
852
854
|
description="Include active persistent notifications (default: True). Set False to skip.",
|
|
853
855
|
),
|
|
854
856
|
] = True,
|
|
857
|
+
include_dismissed_repairs: Annotated[
|
|
858
|
+
bool | str | None,
|
|
859
|
+
Field(
|
|
860
|
+
default=False,
|
|
861
|
+
description=(
|
|
862
|
+
"Include user-dismissed/ignored repairs (default: False). "
|
|
863
|
+
"Matches the HA Repairs UI which hides dismissed items by default."
|
|
864
|
+
),
|
|
865
|
+
),
|
|
866
|
+
] = False,
|
|
855
867
|
) -> dict[str, Any]:
|
|
856
868
|
"""Get AI-friendly system overview with intelligent categorization.
|
|
857
869
|
|
|
@@ -873,6 +885,13 @@ def register_search_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
873
885
|
include_notifications_bool = coerce_bool_param(
|
|
874
886
|
include_notifications, "include_notifications", default=True
|
|
875
887
|
)
|
|
888
|
+
include_dismissed_repairs_bool = bool(
|
|
889
|
+
coerce_bool_param(
|
|
890
|
+
include_dismissed_repairs,
|
|
891
|
+
"include_dismissed_repairs",
|
|
892
|
+
default=False,
|
|
893
|
+
)
|
|
894
|
+
)
|
|
876
895
|
|
|
877
896
|
# Parse domains filter
|
|
878
897
|
parsed_domains = parse_string_list_param(domains, "domains", allow_csv=True)
|
|
@@ -951,25 +970,39 @@ def register_search_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
951
970
|
except Exception as e:
|
|
952
971
|
logger.warning(f"Failed to fetch notifications for overview: {e}")
|
|
953
972
|
|
|
954
|
-
#
|
|
973
|
+
# Active repairs only by default — matches the HA Repairs UI so agents
|
|
974
|
+
# don't chase problems the user already dismissed.
|
|
955
975
|
result["repair_count"] = 0
|
|
956
976
|
try:
|
|
957
977
|
repairs_result = await client.send_websocket_message(
|
|
958
978
|
{"type": "repairs/list_issues"}
|
|
959
979
|
)
|
|
960
980
|
if repairs_result.get("success"):
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
981
|
+
all_issues = repairs_result.get("result", {}).get("issues", [])
|
|
982
|
+
visible_issues = filter_active_repairs(
|
|
983
|
+
all_issues,
|
|
984
|
+
include_dismissed=include_dismissed_repairs_bool,
|
|
985
|
+
)
|
|
986
|
+
result["repair_count"] = len(visible_issues)
|
|
987
|
+
if not include_dismissed_repairs_bool:
|
|
988
|
+
dismissed_count = len(all_issues) - len(visible_issues)
|
|
989
|
+
if dismissed_count:
|
|
990
|
+
result["dismissed_repair_count"] = dismissed_count
|
|
991
|
+
if visible_issues:
|
|
964
992
|
result["repairs"] = [
|
|
965
|
-
|
|
966
|
-
"issue_id": r.get("issue_id"),
|
|
967
|
-
"domain": r.get("domain"),
|
|
968
|
-
"severity": r.get("severity"),
|
|
969
|
-
"translation_key": r.get("translation_key"),
|
|
970
|
-
}
|
|
971
|
-
for r in issues
|
|
993
|
+
project_repair_fields(r) for r in visible_issues
|
|
972
994
|
]
|
|
995
|
+
else:
|
|
996
|
+
err = repairs_result.get("error") or {}
|
|
997
|
+
err_msg = (
|
|
998
|
+
err.get("message")
|
|
999
|
+
if isinstance(err, dict)
|
|
1000
|
+
else str(err)
|
|
1001
|
+
) or "unknown error"
|
|
1002
|
+
logger.warning(
|
|
1003
|
+
"repairs/list_issues returned success=false: %s", err_msg
|
|
1004
|
+
)
|
|
1005
|
+
result["repairs_error"] = f"Could not fetch repairs: {err_msg}"
|
|
973
1006
|
except Exception as e:
|
|
974
1007
|
logger.warning("Failed to fetch repairs for overview: %s", e)
|
|
975
1008
|
result["repairs_error"] = f"Could not fetch repairs: {e}"
|
|
@@ -21,7 +21,7 @@ from .helpers import (
|
|
|
21
21
|
raise_tool_error,
|
|
22
22
|
register_tool_methods,
|
|
23
23
|
)
|
|
24
|
-
from .util_helpers import coerce_bool_param
|
|
24
|
+
from .util_helpers import coerce_bool_param, filter_active_repairs
|
|
25
25
|
|
|
26
26
|
logger = logging.getLogger(__name__)
|
|
27
27
|
|
|
@@ -339,6 +339,7 @@ class SystemTools:
|
|
|
339
339
|
async def ha_get_system_health(
|
|
340
340
|
self,
|
|
341
341
|
include: str | None = None,
|
|
342
|
+
include_dismissed_repairs: bool | str | None = False,
|
|
342
343
|
) -> dict[str, Any]:
|
|
343
344
|
"""
|
|
344
345
|
Get Home Assistant system health, including Zigbee (ZHA) and Z-Wave JS network diagnostics.
|
|
@@ -348,13 +349,21 @@ class SystemTools:
|
|
|
348
349
|
|
|
349
350
|
**Parameters:**
|
|
350
351
|
- include: Optional comma-separated list of additional data to include.
|
|
351
|
-
- "repairs": Repair items from Settings > System > Repairs
|
|
352
|
+
- "repairs": Repair items from Settings > System > Repairs (active only by default; pass `include_dismissed_repairs=True` for all)
|
|
352
353
|
- "zha_network": ZHA Zigbee devices with radio signal summary (name, LQI, RSSI)
|
|
353
354
|
- "zha_network_full": ZHA Zigbee devices with all device details (can be large on 100+ device networks; prefer "zha_network" for summary)
|
|
354
355
|
- "zwave_network": Z-Wave JS network status and node summary (status, security, routing)
|
|
355
356
|
- Example: include="repairs,zha_network,zwave_network"
|
|
357
|
+
- include_dismissed_repairs: Include user-dismissed/ignored repairs (default: False). Only meaningful when "repairs" is in `include`.
|
|
356
358
|
"""
|
|
357
359
|
includes = self._parse_includes(include)
|
|
360
|
+
include_dismissed_repairs_bool = bool(
|
|
361
|
+
coerce_bool_param(
|
|
362
|
+
include_dismissed_repairs,
|
|
363
|
+
"include_dismissed_repairs",
|
|
364
|
+
default=False,
|
|
365
|
+
)
|
|
366
|
+
)
|
|
358
367
|
|
|
359
368
|
ws_client = None
|
|
360
369
|
|
|
@@ -369,7 +378,10 @@ class SystemTools:
|
|
|
369
378
|
|
|
370
379
|
# Fetch optional sections
|
|
371
380
|
if "repairs" in includes:
|
|
372
|
-
result["repairs"] = await self._fetch_repairs(
|
|
381
|
+
result["repairs"] = await self._fetch_repairs(
|
|
382
|
+
ws_client,
|
|
383
|
+
include_dismissed=include_dismissed_repairs_bool,
|
|
384
|
+
)
|
|
373
385
|
|
|
374
386
|
zha_full = "zha_network_full" in includes
|
|
375
387
|
zha_summary = "zha_network" in includes
|
|
@@ -454,17 +466,42 @@ class SystemTools:
|
|
|
454
466
|
|
|
455
467
|
|
|
456
468
|
@staticmethod
|
|
457
|
-
async def _fetch_repairs(
|
|
458
|
-
|
|
469
|
+
async def _fetch_repairs(
|
|
470
|
+
ws_client: Any, *, include_dismissed: bool = False
|
|
471
|
+
) -> dict[str, Any]:
|
|
472
|
+
"""Fetch repair issues from Home Assistant.
|
|
473
|
+
|
|
474
|
+
Filters out user-dismissed ("ignored") repairs by default to match the
|
|
475
|
+
HA Repairs UI. Pass ``include_dismissed=True`` to return all issues
|
|
476
|
+
and report the dismissed count alongside the active count.
|
|
477
|
+
"""
|
|
459
478
|
repairs: dict[str, Any] = {"issues": [], "count": 0}
|
|
460
479
|
try:
|
|
461
480
|
repairs_result = await ws_client.send_command("repairs/list_issues")
|
|
462
481
|
if repairs_result.get("success"):
|
|
463
|
-
|
|
482
|
+
all_issues = repairs_result.get("result", {}).get("issues", [])
|
|
483
|
+
visible_issues = filter_active_repairs(
|
|
484
|
+
all_issues, include_dismissed=include_dismissed
|
|
485
|
+
)
|
|
464
486
|
repairs = {
|
|
465
|
-
"issues":
|
|
466
|
-
"count": len(
|
|
487
|
+
"issues": visible_issues,
|
|
488
|
+
"count": len(visible_issues),
|
|
467
489
|
}
|
|
490
|
+
if not include_dismissed:
|
|
491
|
+
dismissed_count = len(all_issues) - len(visible_issues)
|
|
492
|
+
if dismissed_count:
|
|
493
|
+
repairs["dismissed_count"] = dismissed_count
|
|
494
|
+
else:
|
|
495
|
+
err = repairs_result.get("error") or {}
|
|
496
|
+
err_msg = (
|
|
497
|
+
err.get("message")
|
|
498
|
+
if isinstance(err, dict)
|
|
499
|
+
else str(err)
|
|
500
|
+
) or "unknown error"
|
|
501
|
+
logger.warning(
|
|
502
|
+
"repairs/list_issues returned success=false: %s", err_msg
|
|
503
|
+
)
|
|
504
|
+
repairs["error"] = f"Repairs data not available: {err_msg}"
|
|
468
505
|
except Exception as e:
|
|
469
506
|
logger.warning("Failed to fetch repairs: %s", e)
|
|
470
507
|
repairs["error"] = f"Repairs data not available: {e}"
|
|
@@ -315,6 +315,47 @@ def unwrap_service_response(result: dict[str, Any]) -> dict[str, Any]:
|
|
|
315
315
|
return sr if isinstance(sr, dict) else result
|
|
316
316
|
|
|
317
317
|
|
|
318
|
+
# Fields surfaced from each repair issue. Includes `ignored` / `dismissed_version`
|
|
319
|
+
# so callers can distinguish active vs. user-dismissed repairs when both are
|
|
320
|
+
# returned (e.g., `include_dismissed_repairs=True`).
|
|
321
|
+
_REPAIR_PROJECTION_FIELDS = (
|
|
322
|
+
"issue_id",
|
|
323
|
+
"domain",
|
|
324
|
+
"severity",
|
|
325
|
+
"translation_key",
|
|
326
|
+
"ignored",
|
|
327
|
+
"dismissed_version",
|
|
328
|
+
"is_fixable",
|
|
329
|
+
"breaks_in_ha_version",
|
|
330
|
+
"created",
|
|
331
|
+
"issue_domain",
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def filter_active_repairs(
|
|
336
|
+
issues: list[dict[str, Any]], *, include_dismissed: bool = False
|
|
337
|
+
) -> list[dict[str, Any]]:
|
|
338
|
+
"""Drop user-dismissed repairs unless ``include_dismissed`` is set.
|
|
339
|
+
|
|
340
|
+
HA's `repairs/list_issues` returns both active and ignored repairs (the
|
|
341
|
+
Repairs UI hides ignored ones by default). Mirror that UI default so
|
|
342
|
+
overview / system-health responses don't surface repairs the user has
|
|
343
|
+
already dismissed.
|
|
344
|
+
"""
|
|
345
|
+
if include_dismissed:
|
|
346
|
+
return list(issues)
|
|
347
|
+
return [r for r in issues if not r.get("ignored")]
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def project_repair_fields(issue: dict[str, Any]) -> dict[str, Any]:
|
|
351
|
+
"""Project a repair issue dict to the public-facing field subset.
|
|
352
|
+
|
|
353
|
+
Drops verbose fields (`translation_placeholders`, `learn_more_url`) to
|
|
354
|
+
keep overview payloads compact.
|
|
355
|
+
"""
|
|
356
|
+
return {k: issue[k] for k in _REPAIR_PROJECTION_FIELDS if k in issue}
|
|
357
|
+
|
|
358
|
+
|
|
318
359
|
# Python logging numeric-level → canonical level name.
|
|
319
360
|
# Mirrors the values in HA's LOGSEVERITY constant (components/logger/const.py).
|
|
320
361
|
_LOG_LEVEL_NAMES: dict[int, str] = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ha-mcp-dev
|
|
3
|
-
Version: 7.5.0.
|
|
3
|
+
Version: 7.5.0.dev521
|
|
4
4
|
Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
|
|
5
5
|
Author-email: Julien <github@qc-h.net>
|
|
6
6
|
License: MIT
|
|
@@ -264,6 +264,43 @@ Skills can still be installed manually for clients that prefer local skill files
|
|
|
264
264
|
|
|
265
265
|
---
|
|
266
266
|
|
|
267
|
+
## 🔍 Tool Discovery for AI Agents
|
|
268
|
+
|
|
269
|
+
By default, the full tool catalog (~86 tools) is listed to the client through the standard MCP `tools/list` response. Clients with deferred / on-demand tool loading (Claude Sonnet, Claude Opus,) handle that fine — tools are pulled into context only when needed, so idle context cost is near-zero.
|
|
270
|
+
|
|
271
|
+
For models *without* deferred tool support — Claude Haiku, Gemini, ChatGPT OpenAI-compatible local models, smaller open-weights models — listing 86 tools eats ~46K tokens of idle context. To address that, the server ships with a **search-based discovery mode** built on top of FastMCP's BM25 search transform.
|
|
272
|
+
|
|
273
|
+
### Enable search-based discovery
|
|
274
|
+
|
|
275
|
+
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA add-on). The full catalog is replaced in the tool list with four entry points plus a small set of always-visible "pinned" tools (ha_search_entities, ha_get_overview, ha_restart, etc.). All tools remain callable directly by name once discovered:
|
|
276
|
+
|
|
277
|
+
| Tool | Purpose |
|
|
278
|
+
|------|---------|
|
|
279
|
+
| `ha_search_tools` | BM25 keyword search across all tools. Returns name, description, parameters, and annotations (`readOnlyHint` / `destructiveHint`) so the agent can pick the right one. |
|
|
280
|
+
| `ha_call_read_tool` | Execute a `readOnlyHint` tool by name. Safe — clients can auto-approve. |
|
|
281
|
+
| `ha_call_write_tool` | Execute a write tool that creates or updates data. |
|
|
282
|
+
| `ha_call_delete_tool` | Execute a tool that removes / deletes data. |
|
|
283
|
+
|
|
284
|
+
The proxy split lets MCP clients apply different permission policies per category (e.g. auto-approve reads, prompt for writes, confirm deletes) without parsing tool docstrings.
|
|
285
|
+
|
|
286
|
+
| Setting | Default | Description |
|
|
287
|
+
|---------|---------|-------------|
|
|
288
|
+
| `ENABLE_TOOL_SEARCH` | `false` | Replace full tool catalog with search-based discovery (~46K → ~5K idle tokens). |
|
|
289
|
+
| `TOOL_SEARCH_MAX_RESULTS` | `5` | Max results returned by `ha_search_tools` (range 2–10). |
|
|
290
|
+
| `PINNED_TOOLS` | empty | Comma-separated tool names to keep always visible. The web settings UI is the primary way to manage this. |
|
|
291
|
+
|
|
292
|
+
### When to enable
|
|
293
|
+
|
|
294
|
+
- **Claude Haiku, OpenAI-compatible local models, Gemini, ChatGPT or any model without native deferred tool support** — large idle-context savings.
|
|
295
|
+
- MCP clients that cap total tool count (some cap at 100) — surfaces a minimal set (~10 tools) instead of 86.
|
|
296
|
+
- **Cost-sensitive deployments** — fewer idle tokens per turn.
|
|
297
|
+
|
|
298
|
+
Leave it off when using Claude Sonnet/Opus or any client with deferred tool loading; the full catalog has no idle cost there and direct calls skip the search step. If you choose to use our toolsearch then you should disable the native Claude Opus/Sonnet toolsearch, which is called deferred tools in the settings.
|
|
299
|
+
|
|
300
|
+
For the HA add-on, the same option is documented in [`homeassistant-addon/DOCS.md`](homeassistant-addon/DOCS.md#enable_tool_search) along with the in-add-on settings UI for fine-grained tool enable/disable/pin.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
267
304
|
## 🧪 Dev Channel
|
|
268
305
|
|
|
269
306
|
Want early access to new features and fixes? Dev releases (`.devN`) are published on every push to master.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/resources/skills-vendor/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/transforms/lite_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev519 → ha_mcp_dev-7.5.0.dev521}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|