homeassistant-ai/ha-mcp
Configure and automate Home Assistant with Claude, ChatGPT, and other AI assistants.
The score is jscpd's own --health model: markup, data and text left out, tests kept. The numbers below are the trending scan's.
Most complex files
- src/ha_mcp/backup_manager.py625 cx
- tests/addon/test_webhook_proxy.py570 cx
- src/ha_mcp/tools/tools_addons.py504 cx
- custom_components/ha_mcp_tools/__init__.py488 cx
- src/ha_mcp/tools/tools_config_dashboards.py415 cx
- tests/src/unit/test_tools_addons.py382 cx
- tests/initial_test_state/custom_components/hacs/repositories/base.py337 cx
- src/ha_mcp/_vendor/fastmcp/server/server.py317 cx
- src/ha_mcp/client/rest_client.py306 cx
- tests/src/unit/test_backup_manager.py292 cx
Dead code 9.22% unused · 309 findings
- src/ha_mcp/tools/tools_entities.pyunused-file
- src/ha_mcp/tools/tools_system.pyunused-file
- src/ha_mcp/tools/tools_config_automations.pyunused-file
- src/ha_mcp/tools/tools_config_scenes.pyunused-file
- src/ha_mcp/tools/tools_config_scripts.pyunused-file
- src/ha_mcp/tools/tools_registry.pyunused-file
- src/ha_mcp/_vendor/websockets/sync/client.pyunused-file
- src/ha_mcp/tools/tools_history.pyunused-file
- src/ha_mcp/tools/tools_updates.pyunused-file
- src/ha_mcp/tools/tools_hacs.pyunused-file
The code number leaves out tests, fixtures, docs, examples, data files, styles, translations and vendored code, and 3 generated files: src/ha_mcp/_vendor/mcp_types/_v2025_11_25/__init__.py, src/ha_mcp/_vendor/mcp_types/_v2026_07_28/__init__.py, src/ha_mcp/settings_ui/settings_js/05_feature_flags.js.
Largest clones in the code
- 714 lines in 2 placespython4,040 tokenshomeassistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth_indirect.py:1–714homeassistant-addon-webhook-proxy/mcp_proxy/oauth_indirect.py:1–714
1"""ha_auth-mode OAuth indirection in front of Home Assistant core. 2 3The proxy-owned authorize and token routes keep client endpoint caches stable 4while Home Assistant core remains the authorization server. This module also 5validates cross-origin Client ID Metadata Documents before translating their 6client identities into the same-origin form accepted by core. 7 8MIRROR: this module is the near-verbatim twin of 9``custom_components/ha_mcp_tools/oauth_ha_auth.py``. Keep behavioural changes 10on the two sides in step. This pair has exactly TWO intended deltas. TheFirst 10 of 714 lines.
- 361 lines in 2 placespython2,058 tokenshomeassistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth.py:396–756homeassistant-addon-webhook-proxy/mcp_proxy/oauth.py:396–756
396HEARTBEAT_FILE = Path("/config/.mcp_proxy_dev_heartbeat") 397_HEARTBEAT_MAX_AGE = 90.0 # three missed 30-second touches 398# Only the NEGATIVE verdict is cached (#2218 review): a clean shutdown deletes 399# the heartbeat file but cannot clear a cache in the integration process, so a 400# cached True would keep the surface serving after the stop. A fresh stat per 401# request while alive is microseconds in the executor; the cache exists so an 402# anonymous flood against a STOPPED install does not stat per request. 403# 404# The lease MUST stay shorter than start.py's `_probe_oauth_active` delay 405# (2 s between 3 attempts): that probe drives a DESTRUCTIVE path — it tearsFirst 10 of 361 lines.
- 333 lines in 2 placespython2,050 tokenshomeassistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth_autoapprove.py:269–601homeassistant-addon-webhook-proxy/mcp_proxy/oauth_autoapprove.py:269–601
269def __init__(self, hass: HomeAssistant) -> None: 270 """Bind the view to the HA instance; liveness is resolved per request.""" 271 self._hass = hass 272 273async def get(self, request: web.Request) -> web.Response: 274 """Dispatch an authorization request to the currently active mode.""" 275 if not await _addon_alive(self._hass): 276 return _json_not_found() 277 data = _domain_data(self._hass) 278 if data is None:First 10 of 333 lines.
7 more
- 396 lines in 2 placespython2,010 tokens
- 267 lines in 2 placespython1,724 tokens
- 241 lines in 2 placespython1,671 tokens
- 326 lines in 2 placespython1,590 tokens
- 127 lines in 3 placespython770 tokens
- 291 lines in 2 placespython1,365 tokens
- 202 lines in 2 placespython1,288 tokens
Largest clones over all files, tests and data included
- 6608 lines in 2 placesmarkdowndocs and examples88,409 tokens
1# CHANGELOG 2 3<!-- version list --> 4 5 6## v9.1.2 (2026-11-08) 7 8### Fixed 9 10- **hacs**: Keep HA-MCP on one store listing and repair installs that got twoFirst 10 of 6608 lines.
- 714 lines in 2 placespython4,040 tokenshomeassistant-addon-webhook-proxy-dev/mcp_proxy_dev/oauth_indirect.py:1–714homeassistant-addon-webhook-proxy/mcp_proxy/oauth_indirect.py:1–714
1"""ha_auth-mode OAuth indirection in front of Home Assistant core. 2 3The proxy-owned authorize and token routes keep client endpoint caches stable 4while Home Assistant core remains the authorization server. This module also 5validates cross-origin Client ID Metadata Documents before translating their 6client identities into the same-origin form accepted by core. 7 8MIRROR: this module is the near-verbatim twin of 9``custom_components/ha_mcp_tools/oauth_ha_auth.py``. Keep behavioural changes 10on the two sides in step. This pair has exactly TWO intended deltas. TheFirst 10 of 714 lines.
- 171 lines in 2 placesmarkdowndocs and examples3,118 tokenshomeassistant-addon-webhook-proxy-dev/DOCS.md:21–191homeassistant-addon-webhook-proxy/DOCS.md:20–190
21Assistant notification). Stop the stable app first; the notification clears 22automatically on the next clean start. 23 24## Prerequisites 25 26- **Home Assistant MCP Server** app must be installed and running (stable or dev channel) 27- For Nabu Casa auto-detection: active Nabu Casa subscription with remote UI enabled 28- For other setups: a working reverse proxy pointing at your HA instance 29 30## SetupFirst 10 of 171 lines.
- 361 lines in 2 placespython2,058 tokens
- 333 lines in 2 placespython2,050 tokens
By format, code only
| Format | Files | Lines | Clones | Duplicated lines | Duplication |
|---|---|---|---|---|---|
| python | 834 | 335,132 | 892 | 18,762 | 5.6% |
| html | 12 | 2,933 | 37 | 439 | 14.97% |
| javascript | 27 | 10,431 | 12 | 258 | 2.47% |
| typescript | 11 | 414 | 4 | 32 | 7.73% |
| css | 5 | 277 | 3 | 34 | 12.27% |
| astro | 12 | 3,917 | 0 | 0 | 0% |
| bash | 5 | 603 | 0 | 0 | 0% |
| powershell | 1 | 170 | 0 | 0 | 0% |
By format, all files
| Format | Files | Lines | Clones | Duplicated lines | Duplication |
|---|---|---|---|---|---|
| python | 1,840 | 779,432 | 2,874 | 44,820 | 5.75% |
| yaml | 148 | 23,689 | 204 | 6,019 | 25.41% |
| html | 12 | 2,933 | 37 | 439 | 14.97% |
| markdown | 76 | 27,747 | 32 | 7,312 | 26.35% |
| javascript | 45 | 16,347 | 30 | 423 | 2.59% |
| json | 58 | 28,398 | 5 | 439 | 1.55% |
| css | 7 | 1,719 | 4 | 42 | 2.44% |
| typescript | 11 | 414 | 4 | 32 | 7.73% |
| docker | 6 | 286 | 3 | 60 | 20.98% |
| bash | 31 | 1,466 | 2 | 12 | 0.82% |
Trending appearances
| Day | Rank | Stars | Files | Lines | Clones | All files | Code | Health | Commit |
|---|---|---|---|---|---|---|---|---|---|
| Nov 10, 2026 | #7 | 6,124 (+31) | 2,269 | 888,327 | 3,199 | 6.72% | 5.52% | D 48.6 | ceb8bed |
Want this for your own project? Install jscpd and run jscpd ., or measure it the way the baselines were measured.