ha-mcp-dev 7.4.1.dev500__tar.gz → 7.4.1.dev501__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.4.1.dev500/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.4.1.dev501}/PKG-INFO +1 -1
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/pyproject.toml +1 -1
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/config.py +9 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/server.py +202 -0
- ha_mcp_dev-7.4.1.dev501/src/ha_mcp/transforms/__init__.py +15 -0
- ha_mcp_dev-7.4.1.dev501/src/ha_mcp/transforms/lite_docstrings.py +62 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp_dev.egg-info/SOURCES.txt +1 -0
- ha_mcp_dev-7.4.1.dev500/src/ha_mcp/transforms/__init__.py +0 -9
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/LICENSE +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/README.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/setup.cfg +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/tests/test_env_manager.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.4.1.
|
|
7
|
+
version = "7.4.1.dev501"
|
|
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"
|
|
@@ -113,6 +113,15 @@ class Settings(BaseSettings):
|
|
|
113
113
|
# supervisor UI rejects out-of-range values before they reach env vars.
|
|
114
114
|
tool_search_max_results: int = Field(5, ge=2, le=10, alias="TOOL_SEARCH_MAX_RESULTS")
|
|
115
115
|
|
|
116
|
+
# Lite docstrings — replace selected heavy tool descriptions with
|
|
117
|
+
# shorter variants that defer detailed guidance to the
|
|
118
|
+
# ``ha_get_skill_home_assistant_best_practices`` skill tool/resource.
|
|
119
|
+
# Reduces idle catalog token usage at the cost of relying on the LLM
|
|
120
|
+
# to actually consult the skill when it needs detail. Beta feature
|
|
121
|
+
# (issue #1062); a startup WARNING is emitted when enabled so
|
|
122
|
+
# env-var users see the trade-off in their logs.
|
|
123
|
+
enable_lite_docstrings: bool = Field(False, alias="ENABLE_LITE_DOCSTRINGS")
|
|
124
|
+
|
|
116
125
|
# Code Mode — sandboxed Python execution via pydantic-monty.
|
|
117
126
|
# Provides an "escape hatch" tool (ha_manage_custom_tool) that lets LLMs write
|
|
118
127
|
# custom one-off Python code when no existing tool covers the request.
|
|
@@ -263,6 +263,12 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
|
|
|
263
263
|
# search indexing too).
|
|
264
264
|
self._apply_settings_visibility()
|
|
265
265
|
|
|
266
|
+
# Replace heavy tool descriptions with lite variants when
|
|
267
|
+
# ENABLE_LITE_DOCSTRINGS=true. Must come BEFORE keyword
|
|
268
|
+
# enrichment so BM25 keywords append to the lite text (instead
|
|
269
|
+
# of the full description we just discarded).
|
|
270
|
+
self._apply_lite_docstrings()
|
|
271
|
+
|
|
266
272
|
# Enrich tool descriptions with BM25 keyword boosts. Runs
|
|
267
273
|
# unconditionally so Claude's native deferred-tool search
|
|
268
274
|
# (claude.ai) benefits even when ENABLE_TOOL_SEARCH is off.
|
|
@@ -536,6 +542,147 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
|
|
|
536
542
|
),
|
|
537
543
|
}
|
|
538
544
|
|
|
545
|
+
# Lite docstrings — beta opt-in (enable_lite_docstrings, #1062).
|
|
546
|
+
# Each entry replaces the full docstring on a heavy tool with a
|
|
547
|
+
# shorter variant that defers schema/example detail to
|
|
548
|
+
# ha_get_skill_home_assistant_best_practices. Every entry preserves
|
|
549
|
+
# a pointer to that skill so the LLM still has a path to the full
|
|
550
|
+
# guidance from inside the trimmed description. The trade-off
|
|
551
|
+
# (LLMs that skip the skill tool get less guidance) is surfaced in
|
|
552
|
+
# the dev-addon toggle, docs/beta.md, and a startup WARNING.
|
|
553
|
+
_LITE_DOCSTRINGS: ClassVar[dict[str, str]] = {
|
|
554
|
+
"ha_config_get_automation": (
|
|
555
|
+
"Get a Home Assistant automation configuration by "
|
|
556
|
+
"entity_id or unique_id. Returns the full config "
|
|
557
|
+
"(trigger, condition, action, mode) plus a stable "
|
|
558
|
+
"config_hash for use with python_transform on "
|
|
559
|
+
"ha_config_set_automation.\n\n"
|
|
560
|
+
"For schema and field-level details, see "
|
|
561
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
562
|
+
),
|
|
563
|
+
"ha_config_set_automation": (
|
|
564
|
+
"Create or update a Home Assistant automation.\n\n"
|
|
565
|
+
"Supports two modes: full `config` replacement, or surgical "
|
|
566
|
+
"`python_transform` on an existing automation (requires "
|
|
567
|
+
"`identifier` and `config_hash` from "
|
|
568
|
+
"ha_config_get_automation). Omit `identifier` to create a "
|
|
569
|
+
"new automation.\n\n"
|
|
570
|
+
"For schema details, examples, and native-vs-template "
|
|
571
|
+
"guidance, see ha_get_skill_home_assistant_best_practices."
|
|
572
|
+
),
|
|
573
|
+
"ha_config_get_script": (
|
|
574
|
+
"Get a Home Assistant script configuration by "
|
|
575
|
+
"script_id or entity_id. Returns the full config (sequence, "
|
|
576
|
+
"mode, fields) plus a stable config_hash for use with "
|
|
577
|
+
"python_transform on ha_config_set_script.\n\n"
|
|
578
|
+
"For schema details, see "
|
|
579
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
580
|
+
),
|
|
581
|
+
"ha_config_set_script": (
|
|
582
|
+
"Create or update a Home Assistant script.\n\n"
|
|
583
|
+
"Supports two modes: full `config` replacement, or surgical "
|
|
584
|
+
"`python_transform` on an existing script (requires "
|
|
585
|
+
"`identifier` and `config_hash` from "
|
|
586
|
+
"ha_config_get_script). Omit `identifier` to create a new "
|
|
587
|
+
"script.\n\n"
|
|
588
|
+
"For schema details and examples, see "
|
|
589
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
590
|
+
),
|
|
591
|
+
"ha_config_get_scene": (
|
|
592
|
+
"Get a Home Assistant scene configuration by "
|
|
593
|
+
"scene_id or entity_id. Returns the full config plus a "
|
|
594
|
+
"stable config_hash for use with python_transform on "
|
|
595
|
+
"ha_config_set_scene.\n\n"
|
|
596
|
+
"For schema details, see "
|
|
597
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
598
|
+
),
|
|
599
|
+
"ha_config_set_scene": (
|
|
600
|
+
"Create or update a Home Assistant scene.\n\n"
|
|
601
|
+
"Supports two modes: full `config` replacement, or surgical "
|
|
602
|
+
"`python_transform` on an existing scene (requires "
|
|
603
|
+
"`identifier` and `config_hash`).\n\n"
|
|
604
|
+
"For schema details and examples, see "
|
|
605
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
606
|
+
),
|
|
607
|
+
"ha_config_list_helpers": (
|
|
608
|
+
"List Home Assistant helpers of a given simple type. "
|
|
609
|
+
"Accepts the 12 storage-backed helper types only: "
|
|
610
|
+
"input_button, input_boolean, input_select, input_number, "
|
|
611
|
+
"input_text, input_datetime, counter, timer, schedule, "
|
|
612
|
+
"zone, person, tag. Flow-based helpers (template, group, "
|
|
613
|
+
"utility_meter, derivative, statistics, trend, threshold, "
|
|
614
|
+
"filter, switch_as_x, etc.) cannot be listed through this "
|
|
615
|
+
"tool — use ha_search_entities or ha_deep_search.\n\n"
|
|
616
|
+
"For per-type schemas, see ha_get_helper_schema and "
|
|
617
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
618
|
+
),
|
|
619
|
+
"ha_config_set_helper": (
|
|
620
|
+
"Create or update a Home Assistant helper. Supports all "
|
|
621
|
+
"supported helper types: the simple types (input_*, "
|
|
622
|
+
"counter, timer, schedule, zone, person, tag) and the "
|
|
623
|
+
"flow-based types (template, group, utility_meter, "
|
|
624
|
+
"derivative, statistics, trend, threshold, filter, "
|
|
625
|
+
"switch_as_x, and others).\n\n"
|
|
626
|
+
"For per-type config schemas, call "
|
|
627
|
+
"ha_get_helper_schema(helper_type) first. For decision "
|
|
628
|
+
"matrix and worked examples (which helper type for which "
|
|
629
|
+
"use case), see ha_get_skill_home_assistant_best_practices."
|
|
630
|
+
),
|
|
631
|
+
"ha_config_get_dashboard": (
|
|
632
|
+
"Get Home Assistant dashboard info (list mode, search "
|
|
633
|
+
"mode, or full config).\n\n"
|
|
634
|
+
"Three modes: (1) list — `list_only=True` returns all "
|
|
635
|
+
"storage-mode dashboards with metadata. (2) search — pass "
|
|
636
|
+
"any of `entity_id`, `card_type`, `heading` to find cards "
|
|
637
|
+
"(and their `jq_path`) inside a specific dashboard; the "
|
|
638
|
+
"result includes a `config_hash` you can pair with "
|
|
639
|
+
"ha_config_set_dashboard(python_transform=...) to edit "
|
|
640
|
+
"matched cards surgically. (3) get — no search params "
|
|
641
|
+
"returns the full Lovelace config plus a stable "
|
|
642
|
+
"`config_hash`. Use `url_path='default'` for the main "
|
|
643
|
+
"dashboard.\n\n"
|
|
644
|
+
"For card-type taxonomy and search workflow examples, see "
|
|
645
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
646
|
+
),
|
|
647
|
+
"ha_config_set_dashboard": (
|
|
648
|
+
"Create or update a Home Assistant dashboard.\n\n"
|
|
649
|
+
"Supports two modes: full `config` replacement (new "
|
|
650
|
+
"dashboards or full restructures), or surgical "
|
|
651
|
+
"`python_transform` on an existing dashboard (requires "
|
|
652
|
+
"`config_hash` from ha_config_get_dashboard; recommended "
|
|
653
|
+
"for edits). Use `url_path` of 'default' or 'lovelace' "
|
|
654
|
+
"to target the built-in dashboard.\n\n"
|
|
655
|
+
"For card types, layout patterns, and python_transform "
|
|
656
|
+
"security rules, see "
|
|
657
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
658
|
+
),
|
|
659
|
+
"ha_call_service": (
|
|
660
|
+
"Execute a Home Assistant service to control entities or "
|
|
661
|
+
"trigger automations. Calls `<domain>.<service>` "
|
|
662
|
+
"(e.g., light.turn_on, climate.set_temperature). Use "
|
|
663
|
+
"ha_search_entities to find entity IDs and ha_get_state "
|
|
664
|
+
"to read current values before changing them.\n\n"
|
|
665
|
+
"For service-parameter details and per-domain guidance, "
|
|
666
|
+
"see ha_get_skill_home_assistant_best_practices."
|
|
667
|
+
),
|
|
668
|
+
"ha_config_set_yaml": (
|
|
669
|
+
"Update raw YAML in configuration.yaml or packages/*.yaml "
|
|
670
|
+
"via add / replace / remove on a single top-level key "
|
|
671
|
+
"(LAST RESORT).\n\n"
|
|
672
|
+
"Dedicated tools (ha_config_set_automation, "
|
|
673
|
+
"ha_config_set_script, ha_config_set_scene, "
|
|
674
|
+
"ha_config_set_helper) cover almost every use case and "
|
|
675
|
+
"should be preferred. Use this only for YAML-only "
|
|
676
|
+
"integrations (command_line, rest, shell_command, notify) "
|
|
677
|
+
"or registering YAML-mode dashboards via "
|
|
678
|
+
"`lovelace.dashboards.<url_path>`. Most edits require a "
|
|
679
|
+
"full HA restart; template, mqtt, and group support "
|
|
680
|
+
"reload.\n\n"
|
|
681
|
+
"For routing guidance and the full allowlist, see "
|
|
682
|
+
"ha_get_skill_home_assistant_best_practices."
|
|
683
|
+
),
|
|
684
|
+
}
|
|
685
|
+
|
|
539
686
|
# Description overrides that REPLACE the original description for BM25.
|
|
540
687
|
# Used to narrow overly broad tools so they stop matching generic queries
|
|
541
688
|
# against ha-mcp's internal BM25 search tool. Only applied when
|
|
@@ -552,6 +699,61 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
|
|
|
552
699
|
),
|
|
553
700
|
}
|
|
554
701
|
|
|
702
|
+
def _apply_lite_docstrings(self) -> None:
|
|
703
|
+
"""Swap heavy tool descriptions for shorter variants if enabled.
|
|
704
|
+
|
|
705
|
+
Beta feature gated on ``settings.enable_lite_docstrings`` /
|
|
706
|
+
``ENABLE_LITE_DOCSTRINGS=true``. Replaces the description on
|
|
707
|
+
each tool listed in ``_LITE_DOCSTRINGS`` with a shorter variant
|
|
708
|
+
that defers detail to
|
|
709
|
+
``ha_get_skill_home_assistant_best_practices``. Tools not in the
|
|
710
|
+
mapping pass through unchanged.
|
|
711
|
+
|
|
712
|
+
Emits a startup WARNING when enabled so non-addon users (Docker,
|
|
713
|
+
uvx, pip) see the trade-off in their logs — the addon UI surfaces
|
|
714
|
+
the same warning via the toggle description. A second WARNING is
|
|
715
|
+
emitted if the transform install fails, so users don't silently
|
|
716
|
+
get full descriptions back after explicitly enabling the toggle.
|
|
717
|
+
|
|
718
|
+
Runs before ``_apply_search_keyword_enrichment`` so BM25 keywords
|
|
719
|
+
append to the lite text instead of the discarded full description.
|
|
720
|
+
"""
|
|
721
|
+
if not self.settings.enable_lite_docstrings:
|
|
722
|
+
return
|
|
723
|
+
|
|
724
|
+
logger.warning(
|
|
725
|
+
"ENABLE_LITE_DOCSTRINGS=true: replacing %d tool descriptions "
|
|
726
|
+
"with shorter variants. This reduces idle catalog token usage "
|
|
727
|
+
"but may degrade LLM performance — the trimmed descriptions "
|
|
728
|
+
"rely on the LLM calling ha_get_skill_home_assistant_best_practices "
|
|
729
|
+
"(or reading skill:// resources) for detail, which is not "
|
|
730
|
+
"guaranteed. See docs/beta.md.",
|
|
731
|
+
len(self._LITE_DOCSTRINGS),
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
try:
|
|
735
|
+
from .transforms import LiteDocstringsTransform
|
|
736
|
+
except ImportError:
|
|
737
|
+
logger.exception(
|
|
738
|
+
"LiteDocstringsTransform not importable — please file a "
|
|
739
|
+
"bug. ENABLE_LITE_DOCSTRINGS=true is in effect but full "
|
|
740
|
+
"tool descriptions will be exposed."
|
|
741
|
+
)
|
|
742
|
+
return
|
|
743
|
+
|
|
744
|
+
try:
|
|
745
|
+
self.mcp.add_transform(
|
|
746
|
+
LiteDocstringsTransform(replacements=self._LITE_DOCSTRINGS)
|
|
747
|
+
)
|
|
748
|
+
except Exception:
|
|
749
|
+
logger.exception("Failed to apply LiteDocstringsTransform")
|
|
750
|
+
logger.warning(
|
|
751
|
+
"ENABLE_LITE_DOCSTRINGS=true was set but the transform "
|
|
752
|
+
"failed to install — full tool descriptions remain in "
|
|
753
|
+
"effect. Catalog token usage will be unchanged from the "
|
|
754
|
+
"default."
|
|
755
|
+
)
|
|
756
|
+
|
|
555
757
|
def _apply_search_keyword_enrichment(self) -> None:
|
|
556
758
|
"""Append BM25 keyword boosts to tool descriptions.
|
|
557
759
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Custom FastMCP transforms for ha-mcp."""
|
|
2
|
+
|
|
3
|
+
from .categorized_search import (
|
|
4
|
+
DEFAULT_PINNED_TOOLS,
|
|
5
|
+
CategorizedSearchTransform,
|
|
6
|
+
SearchKeywordsTransform,
|
|
7
|
+
)
|
|
8
|
+
from .lite_docstrings import LiteDocstringsTransform
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"CategorizedSearchTransform",
|
|
12
|
+
"DEFAULT_PINNED_TOOLS",
|
|
13
|
+
"LiteDocstringsTransform",
|
|
14
|
+
"SearchKeywordsTransform",
|
|
15
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Lite docstrings transform for ha-mcp.
|
|
2
|
+
|
|
3
|
+
Replaces the description on a configurable set of tools with a shorter,
|
|
4
|
+
"lite" variant that defers detailed guidance to the
|
|
5
|
+
``ha_get_skill_home_assistant_best_practices`` tool (or its skill://
|
|
6
|
+
resource). Trades catalog token usage for the assumption that the LLM
|
|
7
|
+
will read the skill when it needs more detail — see issue #1062.
|
|
8
|
+
|
|
9
|
+
Opt-in via ``enable_lite_docstrings``; see ``docs/beta.md`` for trade-offs.
|
|
10
|
+
Tools NOT in the mapping pass through unchanged, so smaller tools keep
|
|
11
|
+
their existing descriptions without us having to enumerate them.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from collections.abc import Sequence
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
18
|
+
|
|
19
|
+
from fastmcp.server.transforms import Transform
|
|
20
|
+
from fastmcp.tools import Tool
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from fastmcp.server.transforms import GetToolNext
|
|
24
|
+
from fastmcp.utilities.versions import VersionSpec
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class LiteDocstringsTransform(Transform):
|
|
28
|
+
"""Replace heavy tool descriptions with shorter variants.
|
|
29
|
+
|
|
30
|
+
Mirrors ``SearchKeywordsTransform``: an empty mapping is a no-op,
|
|
31
|
+
so installing the transform unconditionally would be safe. The
|
|
32
|
+
caller (``server._apply_lite_docstrings``) only installs it when
|
|
33
|
+
the feature flag is on, but the empty-dict-as-no-op contract keeps
|
|
34
|
+
the transform self-contained.
|
|
35
|
+
|
|
36
|
+
The transform deliberately does not auto-append a pointer to
|
|
37
|
+
``ha_get_skill_home_assistant_best_practices`` — the mapped lite
|
|
38
|
+
description owns its own pointer text so per-tool wording can stay
|
|
39
|
+
natural.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, replacements: dict[str, str] | None = None) -> None:
|
|
43
|
+
self._replacements: dict[str, str] = replacements or {}
|
|
44
|
+
|
|
45
|
+
def _rewrite(self, tool: Tool) -> Tool:
|
|
46
|
+
lite = self._replacements.get(tool.name)
|
|
47
|
+
if lite is None:
|
|
48
|
+
return tool
|
|
49
|
+
return tool.model_copy(update={"description": lite})
|
|
50
|
+
|
|
51
|
+
async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
|
|
52
|
+
return [self._rewrite(t) for t in tools]
|
|
53
|
+
|
|
54
|
+
async def get_tool(
|
|
55
|
+
self,
|
|
56
|
+
name: str,
|
|
57
|
+
call_next: GetToolNext,
|
|
58
|
+
*,
|
|
59
|
+
version: VersionSpec | None = None,
|
|
60
|
+
) -> Tool | None:
|
|
61
|
+
tool = await call_next(name, version=version)
|
|
62
|
+
return self._rewrite(tool) if tool else None
|
|
@@ -88,6 +88,7 @@ src/ha_mcp/tools/tools_zones.py
|
|
|
88
88
|
src/ha_mcp/tools/util_helpers.py
|
|
89
89
|
src/ha_mcp/transforms/__init__.py
|
|
90
90
|
src/ha_mcp/transforms/categorized_search.py
|
|
91
|
+
src/ha_mcp/transforms/lite_docstrings.py
|
|
91
92
|
src/ha_mcp/utils/__init__.py
|
|
92
93
|
src/ha_mcp/utils/config_hash.py
|
|
93
94
|
src/ha_mcp/utils/data_paths.py
|
|
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.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/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
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/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.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/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
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/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.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev500 → ha_mcp_dev-7.4.1.dev501}/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
|