Skip to content

Commit 2933f9e

Browse files
committed
Merge branch 'pr-960' into addon-repo
2 parents dc7a93a + 041f1b6 commit 2933f9e

6 files changed

Lines changed: 641 additions & 1 deletion

File tree

homeassistant-addon-dev/config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ arch:
1010
init: false
1111
startup: application
1212
boot: manual
13+
ingress: true
14+
ingress_port: 9583
15+
ingress_stream: true
1316
hassio_api: true
1417
hassio_role: default
1518
homeassistant_api: true
@@ -21,12 +24,16 @@ options:
2124
enable_skills_as_tools: false
2225
enable_tool_search: false
2326
enable_yaml_config_editing: false
27+
disabled_tools: ""
28+
pinned_tools: ""
2429
schema:
2530
backup_hint: list(strong|normal|weak|auto)
2631
secret_path: str?
2732
enable_skills: bool?
2833
enable_skills_as_tools: bool?
2934
enable_tool_search: bool?
3035
enable_yaml_config_editing: bool?
36+
disabled_tools: str?
37+
pinned_tools: str?
3138
ports:
3239
9583/tcp: 9583

homeassistant-addon-dev/translations/en.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,16 @@ configuration:
3535
like homeassistant, http, and recorder are blocked. A backup is
3636
created before every edit. Use for YAML-only features that have no
3737
UI or API alternative. Requires restart to take effect.
38+
disabled_tools:
39+
name: Disabled tools (text fallback)
40+
description: >-
41+
Comma-separated tool names to disable. For a visual interface,
42+
click "Open Web UI" above. This field seeds the initial config
43+
when the web UI hasn't been used yet. Requires restart.
44+
pinned_tools:
45+
name: Pinned tools (text fallback)
46+
description: >-
47+
Comma-separated tool names to pin (always visible in tool search).
48+
For a visual interface, click "Open Web UI" above. This field
49+
seeds the initial config when the web UI hasn't been used yet.
50+
Requires restart.

src/ha_mcp/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ class Settings(BaseSettings):
112112
# files. Disabled by default; only for YAML-only features with no UI/API path.
113113
enable_yaml_config_editing: bool = Field(False, alias="ENABLE_YAML_CONFIG_EDITING")
114114

115+
# Seed values for tool visibility (comma-separated tool names).
116+
# Used as initial config when no tool_config.json exists.
117+
# The web settings UI (/settings) is the primary interface for managing these.
118+
disabled_tools: str = Field("", alias="DISABLED_TOOLS")
119+
pinned_tools: str = Field("", alias="PINNED_TOOLS")
120+
115121
@model_validator(mode="after")
116122
def _skills_dependency(self) -> "Settings":
117123
"""Auto-enable skills (resources) when skills-as-tools is on.

src/ha_mcp/server.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ def _initialize_server(self) -> None:
143143
# Register bundled skills as MCP resources
144144
self._register_skills()
145145

146+
# Apply user-configured tool visibility (after all tools registered,
147+
# before tool search transform wraps them)
148+
self._apply_settings_ui()
149+
146150
# Apply tool search transform (must come after all tools and
147151
# ResourcesAsTools are registered so it can wrap everything)
148152
self._apply_tool_search()
@@ -306,6 +310,23 @@ def _build_skill_block(self, skill_name: str, main_file: Path) -> str | None:
306310

307311
return f"\n### Skill: {skill_name} ({uri})\n{description.strip()}"
308312

313+
def _apply_settings_ui(self) -> None:
314+
"""Register settings web UI and apply persisted tool visibility."""
315+
from .settings_ui import (
316+
apply_tool_visibility,
317+
load_tool_config,
318+
register_settings_routes,
319+
)
320+
321+
register_settings_routes(self.mcp, self)
322+
323+
config = load_tool_config(self.settings)
324+
if config:
325+
pinned = apply_tool_visibility(self.mcp, config, self.settings)
326+
if pinned:
327+
self._user_pinned_tools = list(pinned)
328+
logger.info("Applied persisted tool config (%d entries)", len(config.get("tools", {})))
329+
309330
# Tools pinned outside the search transform for individual permission gating.
310331
# These are always visible in list_tools() regardless of search transform.
311332
_PINNED_TOOLS: ClassVar[list[str]] = list(DEFAULT_PINNED_TOOLS)
@@ -419,8 +440,9 @@ def _apply_tool_search(self) -> None:
419440
)
420441
return
421442

422-
# Build the always_visible list
443+
# Build the always_visible list: defaults + user-configured pins
423444
pinned = list(self._PINNED_TOOLS)
445+
pinned.extend(getattr(self, "_user_pinned_tools", []))
424446

425447
# Pin ResourcesAsTools and skill guidance tools if skills-as-tools is enabled
426448
if self.settings.enable_skills_as_tools:

0 commit comments

Comments
 (0)