forked from homeassistant-ai/ha-mcp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtools.json
More file actions
2879 lines (2879 loc) · 187 KB
/
Copy pathtools.json
File metadata and controls
2879 lines (2879 loc) · 187 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
[
{
"name": "ha_call_addon_api",
"title": "Call Add-on API",
"description": "Call an add-on's HTTP or WebSocket API.\n\nSends requests directly to add-on containers. Use `websocket=true` for\nstreaming endpoints (e.g., ESPHome compile/validate). Use `port` to bypass\nNginx IP restrictions on community add-ons. Use ha_get_addon(slug=\"...\")\nto discover available ports and endpoints.\n\n**Examples:**\n- HTTP: ha_call_addon_api(slug=\"...\", path=\"/api/events\")\n- Direct port: ha_call_addon_api(slug=\"...\", path=\"/flows\", port=1880)\n- WebSocket: ha_call_addon_api(slug=\"...\", path=\"/validate\", port=6052, websocket=true, body={\"type\": \"spawn\", \"configuration\": \"device.yaml\"})",
"inputSchema": {
"properties": {
"slug": {
"type": "Annotated[str, Field(description=\"Add-on slug (e.g., 'a0d7b954_nodered', 'ccab4aaf_frigate'). Use ha_get_addon() to find installed add-on slugs.\")]"
},
"path": {
"type": "Annotated[str, Field(description=\"API path relative to the add-on root (e.g., '/flows', '/api/events', '/api/stats').\")]"
},
"method": {
"type": "Annotated[str, Field(description='HTTP method: GET, POST, PUT, DELETE, PATCH. Defaults to GET.', default='GET')]",
"default": "GET"
},
"body": {
"type": "Annotated[dict[str, Any] | str | None, Field(description='Request body for POST/PUT/PATCH. Pass a JSON object or JSON string.', default=None)]",
"default": null
},
"debug": {
"type": "Annotated[bool, Field(description='Include diagnostic info (request URL, headers sent, response headers). Default: false.', default=False)]",
"default": false
},
"port": {
"type": "Annotated[int | None, Field(description=\"Connect to this port instead of the Ingress port. Use ha_get_addon(slug='...') to find available ports.\", default=None)]",
"default": null
},
"offset": {
"type": "Annotated[int, Field(description='HTTP only. Skip this many items in a JSON array response. Default: 0.', default=0)]",
"default": 0
},
"limit": {
"type": "Annotated[int | None, Field(description='HTTP only. Return at most this many items from a JSON array response (e.g., limit=20).', default=None)]",
"default": null
},
"websocket": {
"type": "Annotated[bool, Field(description=\"Use WebSocket instead of HTTP. For streaming endpoints (e.g., ESPHome /compile, /validate). Sends 'body' as initial message, collects responses. Default: false.\", default=False)]",
"default": false
},
"wait_for_close": {
"type": "Annotated[bool, Field(description='WebSocket only. True: wait for server to close (for compile/validate). False: return after first response batch (for quick commands). Default: true.', default=True)]",
"default": true
}
},
"required": [
"slug",
"path"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": false,
"readOnlyHint": false
},
"tags": [
"Add-ons"
],
"source_file": "tools_addons.py"
},
{
"name": "ha_get_addon",
"title": "Get Add-ons",
"description": "Get Home Assistant add-ons - list installed, available, or get details for one.\n\nThis tool retrieves add-on information based on the parameters:\n- slug provided: Returns detailed info for a single add-on (ingress, ports, options, state)\n- source='installed' (default): Lists currently installed add-ons\n- source='available': Lists add-ons available in the add-on store\n\n**Note:** This tool only works with Home Assistant OS or Supervised installations.\n\n**SINGLE ADD-ON (slug provided):**\nReturns comprehensive details including ingress entry, ports, options, and state.\nUseful for discovering what APIs an add-on exposes before calling ha_call_addon_api.\n\n**INSTALLED ADD-ONS (source='installed'):**\nReturns add-ons with version, state (started/stopped), and update availability.\n- include_stats: Optionally include CPU/memory usage statistics\n\n**AVAILABLE ADD-ONS (source='available'):**\nReturns add-ons from official and custom repositories that can be installed.\n- repository: Filter by repository slug (e.g., 'core', 'community')\n- query: Search by name or description (case-insensitive)\n\n**Example Usage:**\n- List installed add-ons: ha_get_addon()\n- Get Node-RED details: ha_get_addon(slug=\"a0d7b954_nodered\")\n- List with resource usage: ha_get_addon(include_stats=True)\n- List available add-ons: ha_get_addon(source=\"available\")\n- Search for MQTT: ha_get_addon(source=\"available\", query=\"mqtt\")",
"inputSchema": {
"properties": {
"source": {
"type": "Annotated[str | None, Field(description=\"Add-on source: 'installed' (default) for currently installed add-ons, 'available' for add-ons in the store that can be installed.\", default=None)]",
"default": null
},
"slug": {
"type": "Annotated[str | None, Field(description=\"Add-on slug for detailed info (e.g., 'a0d7b954_nodered'). Omit to list all add-ons.\", default=None)]",
"default": null
},
"include_stats": {
"type": "Annotated[bool, Field(description=\"Include CPU/memory usage statistics (only for source='installed')\", default=False)]",
"default": false
},
"repository": {
"type": "Annotated[str | None, Field(description=\"Filter by repository slug, e.g., 'core', 'community' (only for source='available')\", default=None)]",
"default": null
},
"query": {
"type": "Annotated[str | None, Field(description=\"Search filter for add-on names/descriptions (only for source='available')\", default=None)]",
"default": null
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Add-ons"
],
"source_file": "tools_addons.py"
},
{
"name": "ha_config_list_areas",
"title": "List Areas",
"description": "List all Home Assistant areas (rooms).\n\nReturns area ID, name, icon, floor assignment, aliases, and picture URL.",
"inputSchema": {},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Areas & Floors"
],
"source_file": "tools_areas.py"
},
{
"name": "ha_config_list_floors",
"title": "List Floors",
"description": "List all Home Assistant floors.\n\nReturns floor ID, name, icon, level (0=ground, 1=first, -1=basement), and aliases.",
"inputSchema": {},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Areas & Floors"
],
"source_file": "tools_areas.py"
},
{
"name": "ha_config_remove_area",
"title": "Remove Area",
"description": "Delete a Home Assistant area.\n\nEntities and devices in the area are not deleted, just unassigned.\nMay break automations referencing this area.",
"inputSchema": {
"properties": {
"area_id": {
"type": "Annotated[str, Field(description='Area ID to delete (use ha_config_list_areas to find IDs)')]"
}
},
"required": [
"area_id"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": true
},
"tags": [
"Areas & Floors"
],
"source_file": "tools_areas.py"
},
{
"name": "ha_config_remove_floor",
"title": "Remove Floor",
"description": "Delete a Home Assistant floor.\n\nAreas on this floor are not deleted, just unassigned.\nMay break automations referencing this floor.",
"inputSchema": {
"properties": {
"floor_id": {
"type": "Annotated[str, Field(description='Floor ID to delete (use ha_config_list_floors to find IDs)')]"
}
},
"required": [
"floor_id"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": true
},
"tags": [
"Areas & Floors"
],
"source_file": "tools_areas.py"
},
{
"name": "ha_config_set_area",
"title": "Create or Update Area",
"description": "Create or update a Home Assistant area (room).\n\nProvide name only to create a new area. Provide area_id to update existing.\nAreas organize entities by physical location for room-based control.",
"inputSchema": {
"properties": {
"name": {
"type": "Annotated[str | None, Field(description=\"Name for the area (required for create, optional for update, e.g., 'Living Room', 'Kitchen')\", default=None)]",
"default": null
},
"area_id": {
"type": "Annotated[str | None, Field(description='Area ID to update (omit to create new area, use ha_config_list_areas to find IDs)', default=None)]",
"default": null
},
"floor_id": {
"type": "Annotated[str | None, Field(description='Floor ID to assign this area to (use ha_config_list_floors to find IDs, empty string to remove)', default=None)]",
"default": null
},
"icon": {
"type": "Annotated[str | None, Field(description=\"Material Design Icon (e.g., 'mdi:sofa', 'mdi:bed', empty string to remove)\", default=None)]",
"default": null
},
"aliases": {
"type": "Annotated[str | list[str] | None, Field(description=\"Alternative names for voice assistant recognition (e.g., ['lounge', 'family room'], empty list to clear)\", default=None)]",
"default": null
},
"picture": {
"type": "Annotated[str | None, Field(description='URL to a picture representing the area (empty string to remove)', default=None)]",
"default": null
}
}
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Areas & Floors"
],
"source_file": "tools_areas.py"
},
{
"name": "ha_config_set_floor",
"title": "Create or Update Floor",
"description": "Create or update a Home Assistant floor.\n\nProvide name only to create a new floor. Provide floor_id to update existing.\nFloors organize areas into vertical levels for building-wide control.",
"inputSchema": {
"properties": {
"name": {
"type": "Annotated[str | None, Field(description=\"Name for the floor (required for create, optional for update, e.g., 'Ground Floor', 'Basement')\", default=None)]",
"default": null
},
"floor_id": {
"type": "Annotated[str | None, Field(description='Floor ID to update (omit to create new floor, use ha_config_list_floors to find IDs)', default=None)]",
"default": null
},
"level": {
"type": "Annotated[int | None, Field(description='Numeric level for ordering (0=ground, 1=first, -1=basement, etc.)', default=None)]",
"default": null
},
"icon": {
"type": "Annotated[str | None, Field(description=\"Material Design Icon (e.g., 'mdi:home-floor-1', 'mdi:home-floor-b', empty string to remove)\", default=None)]",
"default": null
},
"aliases": {
"type": "Annotated[str | list[str] | None, Field(description=\"Alternative names for voice assistant recognition (e.g., ['downstairs', 'main level'], empty list to clear)\", default=None)]",
"default": null
}
}
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Areas & Floors"
],
"source_file": "tools_areas.py"
},
{
"name": "ha_config_get_automation",
"title": "Get Automation Config",
"description": "Retrieve Home Assistant automation configuration.\n\nReturns the complete configuration including triggers, conditions, actions, and mode settings.\n\nEXAMPLES:\n- Get automation: ha_config_get_automation(\"automation.morning_routine\")\n- Get by unique_id: ha_config_get_automation(\"my_unique_automation_id\")\n\nFor comprehensive automation documentation, use ha_get_skill_home_assistant_best_practices.",
"inputSchema": {
"properties": {
"identifier": {
"type": "Annotated[str, Field(description=\"Automation entity_id (e.g., 'automation.morning_routine') or unique_id\")]"
}
},
"required": [
"identifier"
]
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Automations"
],
"source_file": "tools_config_automations.py"
},
{
"name": "ha_config_remove_automation",
"title": "Remove Automation",
"description": "Delete a Home Assistant automation.\n\nEXAMPLES:\n- Delete automation: ha_config_remove_automation(\"automation.old_automation\")\n- Delete by unique_id: ha_config_remove_automation(\"my_unique_id\")\n\n**WARNING:** Deleting an automation removes it permanently from your Home Assistant configuration.",
"inputSchema": {
"properties": {
"identifier": {
"type": "Annotated[str, Field(description=\"Automation entity_id (e.g., 'automation.old_automation') or unique_id to delete\")]"
},
"wait": {
"type": "Annotated[bool | str, Field(description='Wait for automation to be fully removed before returning. Default: True.', default=True)]",
"default": true
}
},
"required": [
"identifier"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": true
},
"tags": [
"Automations"
],
"source_file": "tools_config_automations.py"
},
{
"name": "ha_config_set_automation",
"title": "Create or Update Automation",
"description": "Create or update a Home Assistant automation.\n\nCreates a new automation (if identifier omitted) or updates existing automation with provided configuration.\n\nAUTOMATION TYPES:\n\n1. Regular Automations - Define triggers and actions directly\n2. Blueprint Automations - Use pre-built templates with customizable inputs\n\nREQUIRED FIELDS (Regular Automations):\n- alias: Human-readable automation name\n- trigger: List of trigger conditions (time, state, event, etc.)\n- action: List of actions to execute\n\nREQUIRED FIELDS (Blueprint Automations):\n- alias: Human-readable automation name\n- use_blueprint: Blueprint configuration\n - path: Blueprint file path (e.g., \"motion_light.yaml\")\n - input: Dictionary of input values for the blueprint\n\nOPTIONAL CONFIG FIELDS (Regular Automations):\n- description: Detailed description of the user's intent (RECOMMENDED: helps safely modify implementation later)\n- category: Category ID for organization (use ha_config_get_category to list, ha_config_set_category to create)\n- condition: Additional conditions that must be met\n- mode: 'single' (default), 'restart', 'queued', 'parallel'\n- max: Maximum concurrent executions (for queued/parallel modes)\n- initial_state: Whether automation starts enabled (true/false)\n- variables: Variables for use in automation\n\nBASIC EXAMPLES:\n\nSimple time-based automation:\nha_config_set_automation({\n \"alias\": \"Morning Lights\",\n \"description\": \"Turn on bedroom lights at 7 AM to help wake up\",\n \"trigger\": [{\"platform\": \"time\", \"at\": \"07:00:00\"}],\n \"action\": [{\"service\": \"light.turn_on\", \"target\": {\"area_id\": \"bedroom\"}}]\n})\n\nMotion-activated lighting with condition:\nha_config_set_automation({\n \"alias\": \"Motion Light\",\n \"trigger\": [{\"platform\": \"state\", \"entity_id\": \"binary_sensor.motion\", \"to\": \"on\"}],\n \"condition\": [{\"condition\": \"sun\", \"after\": \"sunset\"}],\n \"action\": [\n {\"service\": \"light.turn_on\", \"target\": {\"entity_id\": \"light.hallway\"}},\n {\"delay\": {\"minutes\": 5}},\n {\"service\": \"light.turn_off\", \"target\": {\"entity_id\": \"light.hallway\"}}\n ],\n \"mode\": \"restart\"\n})\n\nUpdate existing automation:\nha_config_set_automation(\n identifier=\"automation.morning_routine\",\n config={\n \"alias\": \"Updated Morning Routine\",\n \"trigger\": [{\"platform\": \"time\", \"at\": \"06:30:00\"}],\n \"action\": [\n {\"service\": \"light.turn_on\", \"target\": {\"area_id\": \"bedroom\"}},\n {\"service\": \"climate.set_temperature\", \"target\": {\"entity_id\": \"climate.bedroom\"}, \"data\": {\"temperature\": 22}}\n ]\n }\n)\n\nBLUEPRINT AUTOMATION EXAMPLES:\n\nCreate automation from blueprint:\nha_config_set_automation({\n \"alias\": \"Motion Light Kitchen\",\n \"use_blueprint\": {\n \"path\": \"homeassistant/motion_light.yaml\",\n \"input\": {\n \"motion_entity\": \"binary_sensor.kitchen_motion\",\n \"light_target\": {\"entity_id\": \"light.kitchen\"},\n \"no_motion_wait\": 120\n }\n }\n})\n\nUpdate blueprint automation inputs:\nha_config_set_automation(\n identifier=\"automation.motion_light_kitchen\",\n config={\n \"alias\": \"Motion Light Kitchen\",\n \"use_blueprint\": {\n \"path\": \"homeassistant/motion_light.yaml\",\n \"input\": {\n \"motion_entity\": \"binary_sensor.kitchen_motion\",\n \"light_target\": {\"entity_id\": \"light.kitchen\"},\n \"no_motion_wait\": 300\n }\n }\n }\n})\n\nPREFER NATIVE SOLUTIONS OVER TEMPLATES:\nBefore using template triggers/conditions/actions, check if a native option exists:\n- Use `condition: state` with `state: [list]` instead of template for multiple states\n- Use `condition: state` with `attribute:` instead of template for attribute checks\n- Use `condition: numeric_state` instead of template for number comparisons\n- Use `wait_for_trigger` instead of `wait_template` when waiting for state changes\n- Use `choose` action instead of template-based service names\n\nTRIGGER TYPES: time, time_pattern, sun, state, numeric_state, event, device, zone, template, and more\nCONDITION TYPES: state, numeric_state, time, sun, template, device, zone, and more\nACTION TYPES: service calls, delays, wait_for_trigger, wait_template, if/then/else, choose, repeat, parallel\n\nFor comprehensive automation documentation with all trigger/condition/action types and advanced examples:\n- Use: ha_get_skill_home_assistant_best_practices\n- Or visit: https://www.home-assistant.io/docs/automation/\n\nTROUBLESHOOTING:\n- Use ha_get_state() to verify entity_ids exist\n- Use ha_search_entities() to find correct entity_ids\n- Use ha_eval_template() to test Jinja2 templates before using in automations\n- Use ha_search_entities(domain_filter='automation') to find existing automations",
"inputSchema": {
"properties": {
"config": {
"type": "Annotated[str | dict[str, Any], Field(description=\"Complete automation configuration with required fields: 'alias', 'trigger', 'action'. Optional: 'description', 'condition', 'mode', 'max', 'initial_state', 'variables'\")]"
},
"identifier": {
"type": "Annotated[str | None, Field(description='Automation entity_id or unique_id for updates. Omit to create new automation with generated unique_id.', default=None)]",
"default": null
},
"category": {
"type": "Annotated[str | None, Field(description=\"Category ID to assign to this automation. Use ha_config_get_category(scope='automation') to list available categories, or ha_config_set_category() to create one.\", default=None)]",
"default": null
},
"wait": {
"type": "Annotated[bool | str, Field(description='Wait for automation to be queryable before returning. Default: True. Set to False for bulk operations.', default=True)]",
"default": true
}
},
"required": [
"config"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Automations"
],
"source_file": "tools_config_automations.py"
},
{
"name": "ha_get_blueprint",
"title": "Get Blueprint",
"description": "Get blueprint information - list all blueprints or get details for a specific one.\n\nWithout a path: Lists all installed blueprints for the specified domain.\nWith a path: Retrieves full blueprint configuration including inputs, triggers,\nconditions, and actions.\n\nEXAMPLES:\n- List all automation blueprints: ha_get_blueprint(domain=\"automation\")\n- List script blueprints: ha_get_blueprint(domain=\"script\")\n- Get specific blueprint: ha_get_blueprint(path=\"homeassistant/motion_light.yaml\", domain=\"automation\")\n\nRETURNS (when listing):\n- List of blueprints with path, name, and domain information\n- Count of blueprints found\n\nRETURNS (when getting specific blueprint):\n- Blueprint metadata (name, description, author, source_url)\n- Input definitions with selectors and defaults\n- Blueprint configuration (triggers, conditions, actions for automations; sequence for scripts)",
"inputSchema": {
"properties": {
"path": {
"type": "Annotated[str | None, Field(description=\"Blueprint path to get details for (e.g., 'homeassistant/motion_light.yaml'). If omitted, lists all blueprints in the domain.\", default=None)]",
"default": null
},
"domain": {
"type": "Annotated[str, Field(description=\"Blueprint domain: 'automation' or 'script'\", default='automation')]",
"default": "automation"
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Blueprints"
],
"source_file": "tools_blueprints.py"
},
{
"name": "ha_import_blueprint",
"title": "Import Blueprint",
"description": "Import a blueprint from a URL.\n\nImports a blueprint from GitHub, Home Assistant Community forums,\nor any direct URL to a blueprint YAML file.\n\nEXAMPLES:\n- Import from GitHub: ha_import_blueprint(\"https://github.com/user/repo/blob/main/blueprint.yaml\")\n- Import from HA Community: ha_import_blueprint(\"https://community.home-assistant.io/t/motion-light/123456\")\n- Import direct YAML: ha_import_blueprint(\"https://example.com/my-blueprint.yaml\")\n\nSUPPORTED SOURCES:\n- GitHub repository URLs (will be converted to raw URLs)\n- Home Assistant Community forum posts with blueprint code\n- Direct URLs to YAML blueprint files\n\nRETURNS:\n- Import result with the blueprint path where it was saved\n- Blueprint metadata (name, domain, description)\n- Error details if import fails",
"inputSchema": {
"properties": {
"url": {
"type": "Annotated[str, Field(description='URL to import blueprint from (GitHub, Home Assistant Community, or direct YAML URL)')]"
}
},
"required": [
"url"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Blueprints"
],
"source_file": "tools_blueprints.py"
},
{
"name": "ha_config_get_calendar_events",
"title": "Get Calendar Events",
"description": "Retrieve calendar events from a calendar entity.\n\nRetrieves calendar events within a specified time range.\n\n**Parameters:**\n- entity_id: Calendar entity ID (e.g., 'calendar.family')\n- start: Start datetime in ISO format (default: now)\n- end: End datetime in ISO format (default: 7 days from start)\n- max_results: Maximum number of events to return (default: 20)\n\n**Example Usage:**\n```python\n# Get events for the next week\nevents = ha_config_get_calendar_events(\"calendar.family\")\n\n# Get events for a specific date range\nevents = ha_config_get_calendar_events(\n \"calendar.work\",\n start=\"2024-01-01T00:00:00\",\n end=\"2024-01-31T23:59:59\"\n)\n```\n\n**Note:** To find calendar entities, use ha_search_entities(query='calendar', domain_filter='calendar')\n\n**Returns:**\n- List of calendar events with summary, start, end, description, location",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str, Field(description=\"Calendar entity ID (e.g., 'calendar.family')\")]"
},
"start": {
"type": "Annotated[str | None, Field(description='Start datetime in ISO format (default: now)', default=None)]",
"default": null
},
"end": {
"type": "Annotated[str | None, Field(description='End datetime in ISO format (default: 7 days from start)', default=None)]",
"default": null
},
"max_results": {
"type": "Annotated[int, Field(description='Maximum number of events to return', default=20)]",
"default": 20
}
},
"required": [
"entity_id"
]
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Calendar"
],
"source_file": "tools_calendar.py"
},
{
"name": "ha_config_remove_calendar_event",
"title": "Remove Calendar Event",
"description": "Delete an event from a calendar.\n\nDeletes a calendar event using the calendar.delete_event service.\n\n**Parameters:**\n- entity_id: Calendar entity ID (e.g., 'calendar.family')\n- uid: Unique identifier of the event to delete\n- recurrence_id: Optional recurrence ID for recurring events\n- recurrence_range: Optional recurrence range ('THIS_AND_FUTURE' to delete this and future occurrences)\n\n**Example Usage:**\n```python\n# Delete a single event\nresult = ha_config_remove_calendar_event(\n \"calendar.family\",\n uid=\"event-12345\"\n)\n\n# Delete a recurring event instance and future occurrences\nresult = ha_config_remove_calendar_event(\n \"calendar.work\",\n uid=\"recurring-event-67890\",\n recurrence_id=\"20240115T100000\",\n recurrence_range=\"THIS_AND_FUTURE\"\n)\n```\n\n**Note:**\nTo get the event UID, first use ha_config_get_calendar_events() to list events.\nThe UID is returned in each event's data.\n\n**Returns:**\n- Success status and deletion confirmation",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str, Field(description=\"Calendar entity ID (e.g., 'calendar.family')\")]"
},
"uid": {
"type": "Annotated[str, Field(description='Unique identifier of the event to delete')]"
},
"recurrence_id": {
"type": "Annotated[str | None, Field(description='Optional recurrence ID for recurring events', default=None)]",
"default": null
},
"recurrence_range": {
"type": "Annotated[str | None, Field(description=\"Optional recurrence range ('THIS_AND_FUTURE' to delete this and future occurrences)\", default=None)]",
"default": null
}
},
"required": [
"entity_id",
"uid"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": true
},
"tags": [
"Calendar"
],
"source_file": "tools_calendar.py"
},
{
"name": "ha_config_set_calendar_event",
"title": "Create or Update Calendar Event",
"description": "Create a new event in a calendar.\n\nCreates a calendar event using the calendar.create_event service.\n\n**Parameters:**\n- entity_id: Calendar entity ID (e.g., 'calendar.family')\n- summary: Event title/summary\n- start: Event start datetime in ISO format\n- end: Event end datetime in ISO format\n- description: Optional event description\n- location: Optional event location\n\n**Example Usage:**\n```python\n# Create a simple event\nresult = ha_config_set_calendar_event(\n \"calendar.family\",\n summary=\"Doctor appointment\",\n start=\"2024-01-15T14:00:00\",\n end=\"2024-01-15T15:00:00\"\n)\n\n# Create an event with details\nresult = ha_config_set_calendar_event(\n \"calendar.work\",\n summary=\"Team meeting\",\n start=\"2024-01-16T10:00:00\",\n end=\"2024-01-16T11:00:00\",\n description=\"Weekly sync meeting\",\n location=\"Conference Room A\"\n)\n```\n\n**Returns:**\n- Success status and event details",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str, Field(description=\"Calendar entity ID (e.g., 'calendar.family')\")]"
},
"summary": {
"type": "Annotated[str, Field(description='Event title/summary')]"
},
"start": {
"type": "Annotated[str, Field(description='Event start datetime in ISO format')]"
},
"end": {
"type": "Annotated[str, Field(description='Event end datetime in ISO format')]"
},
"description": {
"type": "Annotated[str | None, Field(description='Optional event description', default=None)]",
"default": null
},
"location": {
"type": "Annotated[str | None, Field(description='Optional event location', default=None)]",
"default": null
}
},
"required": [
"entity_id",
"summary",
"start",
"end"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Calendar"
],
"source_file": "tools_calendar.py"
},
{
"name": "ha_get_camera_image",
"title": "Get Camera Image",
"description": "Retrieve a snapshot image from a Home Assistant camera entity.\n\nThis tool fetches the current camera image and returns it directly for visual\nanalysis. Use this when you need to see what a camera is currently viewing.\n\n**Parameters:**\n- entity_id: Camera entity ID (e.g., 'camera.front_door', 'camera.living_room')\n- width: Optional width to resize the image (reduces token usage for large images)\n- height: Optional height to resize the image\n\n**Use Cases:**\n- Security checks: \"Is someone at the front door?\"\n- Pet monitoring: \"Is my dog still on the couch?\"\n- Delivery verification: \"Did my package get delivered?\"\n- Visual confirmation: \"Did the garage door actually close?\"\n- Incident investigation: \"What triggered the motion sensor?\"\n\n**Example Usage:**\n```python\n# Get current snapshot from front door camera\nha_get_camera_image(entity_id=\"camera.front_door\")\n\n# Get resized image to reduce token usage\nha_get_camera_image(entity_id=\"camera.backyard\", width=640, height=480)\n```\n\n**Notes:**\n- Only cameras exposed to Home Assistant are accessible\n- The existing HA authentication/authorization applies\n- Images are returned in their native format (JPEG, PNG, or GIF)\n- Use width/height parameters for large high-resolution cameras to reduce\n token usage when full resolution is not needed\n\n**Related Services:**\n- camera.snapshot: Save snapshot to file on HA server\n- camera.turn_on/turn_off: Control camera power\n- camera.enable_motion_detection: Enable motion detection",
"inputSchema": {
"properties": {
"entity_id": {
"type": "str"
},
"width": {
"type": "int | None",
"default": null
},
"height": {
"type": "int | None",
"default": null
}
},
"required": [
"entity_id"
]
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Camera"
],
"source_file": "tools_camera.py"
},
{
"name": "ha_config_delete_dashboard",
"title": "Delete Dashboard",
"description": "Delete a storage-mode dashboard completely.\n\nWARNING: This permanently deletes the dashboard and all its configuration.\nCannot be undone. Does not work on YAML-mode dashboards.\n\nAccepts either the internal dashboard ID or the URL path.\nThe tool resolves url_path to internal ID automatically.\n\nEXAMPLES:\n- Delete dashboard: ha_config_delete_dashboard(\"mobile-dashboard\")\n\nNote: The default dashboard cannot be deleted via this method.",
"inputSchema": {
"properties": {
"dashboard_id": {
"type": "Annotated[str, Field(description=\"Dashboard ID or URL path to delete (e.g., 'my-dashboard' or 'my_dashboard')\")]"
}
},
"required": [
"dashboard_id"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_config_dashboards.py"
},
{
"name": "ha_config_delete_dashboard_resource",
"title": "Delete Dashboard Resource",
"description": "Delete a dashboard resource.\n\nRemoves a resource from Home Assistant. The resource will no longer\nbe loaded on dashboards.\n\nWARNING: Deleting a resource used by custom cards in your dashboards\nwill cause those cards to fail to load.\n\nEXAMPLES:\nha_config_delete_dashboard_resource(resource_id=\"abc123\")\n\nNote: Use ha_config_list_dashboard_resources() to find resource IDs\nbefore deleting. Ensure no dashboards depend on the resource.",
"inputSchema": {
"properties": {
"resource_id": {
"type": "Annotated[str, Field(description='Resource ID to delete. Get from ha_config_list_dashboard_resources()')]"
}
},
"required": [
"resource_id"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_resources.py"
},
{
"name": "ha_config_get_dashboard",
"title": "Get Dashboard",
"description": "Get dashboard info - list all dashboards or get config for a specific one.\n\nWithout url_path (or with list_only=True): Lists all storage-mode dashboards\nwith metadata including url_path, title, icon, admin requirements.\n\nWith url_path: Returns the full Lovelace dashboard configuration\nincluding all views and cards.\n\nEXAMPLES:\n- List all dashboards: ha_config_get_dashboard(list_only=True)\n- Get default dashboard: ha_config_get_dashboard(url_path=\"default\")\n- Get custom dashboard: ha_config_get_dashboard(url_path=\"lovelace-mobile\")\n- Force reload: ha_config_get_dashboard(url_path=\"lovelace-home\", force_reload=True)\n\nNote: YAML-mode dashboards (defined in configuration.yaml) are not included in list.",
"inputSchema": {
"properties": {
"url_path": {
"type": "Annotated[str | None, Field(description=\"Dashboard URL path (e.g., 'lovelace-home'). Use 'default' for default dashboard. If omitted with list_only=True, lists all dashboards.\")]",
"default": null
},
"list_only": {
"type": "Annotated[bool, Field(description='If True, list all dashboards instead of getting config. When True, url_path is ignored.')]",
"default": false
},
"force_reload": {
"type": "Annotated[bool, Field(description='Force reload from storage (bypass cache)')]",
"default": false
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_config_dashboards.py"
},
{
"name": "ha_config_list_dashboard_resources",
"title": "List Dashboard Resources",
"description": "List all Lovelace dashboard resources (custom cards, themes, CSS/JS).\n\nReturns all registered resources. For inline resources (created with\nha_config_set_dashboard_resource(content=...)), shows a preview of the content\ninstead of the full encoded URL to save tokens.\n\nArgs:\n include_content: If True, includes full decoded content for inline\n resources in \"_content\" field. Default False (150-char preview only).\n\nResource types:\n- module: ES6 JavaScript modules (modern custom cards)\n- js: Legacy JavaScript files\n- css: CSS stylesheets\n\nEach resource has a unique ID for update/delete operations.\n\nEXAMPLES:\n- List all resources: ha_config_list_dashboard_resources()\n- List with full content: ha_config_list_dashboard_resources(include_content=True)\n\nNote: Requires advanced mode to be enabled in Home Assistant for resource\nmanagement through the UI, but API access works regardless.",
"inputSchema": {
"properties": {
"include_content": {
"type": "Annotated[bool, Field(description='Include full decoded content for inline resources. Default False to save tokens (shows 150-char preview instead).')]",
"default": false
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_resources.py"
},
{
"name": "ha_config_set_dashboard",
"title": "Create or Update Dashboard",
"description": "Create or update a Home Assistant dashboard.\n\nCreates a new dashboard or updates an existing one with the provided configuration.\nSupports two modes: full config replacement OR Python transformation.\n\nUse 'default' or 'lovelace' to target the built-in default dashboard.\nNew dashboards require a hyphenated url_path (e.g., 'my-dashboard').\n\nWHEN TO USE WHICH MODE:\n- python_transform: RECOMMENDED for edits. Surgical/pattern-based updates, works on all platforms.\n- config: New dashboards only, or full restructure. Replaces everything.\n\nIMPORTANT: After delete/add operations, indices shift! Subsequent python_transform calls\nmust use fresh config_hash from ha_dashboard_find_card() or ha_config_get_dashboard()\nto get updated structure. Chain multiple ops in ONE expression when possible.\n\nTIP: Use ha_dashboard_find_card() to get the path for any card.\n\nPYTHON TRANSFORM EXAMPLES (RECOMMENDED):\n- Update card icon: 'config[\"views\"][0][\"cards\"][0][\"icon\"] = \"mdi:thermometer\"'\n- Add card: 'config[\"views\"][0][\"cards\"].append({\"type\": \"button\", \"entity\": \"light.bedroom\"})'\n- Delete card: 'del config[\"views\"][0][\"cards\"][2]'\n- Pattern-based update: 'for card in config[\"views\"][0][\"cards\"]: if \"light\" in card.get(\"entity\", \"\"): card[\"icon\"] = \"mdi:lightbulb\"'\n- Multi-operation: 'config[\"views\"][0][\"cards\"][0][\"icon\"] = \"mdi:a\"; config[\"views\"][0][\"cards\"][1][\"icon\"] = \"mdi:b\"'\n\nMODERN DASHBOARD BEST PRACTICES (2024+):\n- Use \"sections\" view type (default) with grid-based layouts\n- Use \"tile\" cards as primary card type (replaces legacy entity/light/climate cards)\n- Use \"grid\" cards for multi-column layouts within sections\n- Create multiple views with navigation paths (avoid single-view endless scrolling)\n- Use \"area\" cards with navigation for hierarchical organization\n\nDISCOVERING ENTITY IDs FOR DASHBOARDS:\nDo NOT guess entity IDs - use these tools to find exact entity IDs:\n1. ha_get_overview(include_entity_id=True) - Get all entities organized by domain/area\n2. ha_search_entities(query, domain_filter, area_filter) - Find specific entities\n3. ha_deep_search(query) - Comprehensive search across entities, areas, automations\n\nIf unsure about entity IDs, ALWAYS use one of these tools first.\n\nDASHBOARD DOCUMENTATION (via MCP skills):\n- skill://home-assistant-best-practices/references/dashboard-guide.md — comprehensive guide\n- skill://home-assistant-best-practices/references/dashboard-cards.md — card types list\n- ha_get_skill_home_assistant_best_practices — guidance on card types and configuration\n\nEXAMPLES:\n\nCreate empty dashboard:\nha_config_set_dashboard(\n url_path=\"mobile-dashboard\",\n title=\"Mobile View\",\n icon=\"mdi:cellphone\"\n)\n\nCreate dashboard with modern sections view:\nha_config_set_dashboard(\n url_path=\"home-dashboard\",\n title=\"Home Overview\",\n config={\n \"views\": [{\n \"title\": \"Home\",\n \"type\": \"sections\",\n \"sections\": [{\n \"title\": \"Climate\",\n \"cards\": [{\n \"type\": \"tile\",\n \"entity\": \"climate.living_room\",\n \"features\": [{\"type\": \"target-temperature\"}]\n }]\n }]\n }]\n }\n)\n\nCreate strategy-based dashboard (auto-generated):\nha_config_set_dashboard(\n url_path=\"my-home\",\n title=\"My Home\",\n config={\n \"strategy\": {\n \"type\": \"home\",\n \"favorite_entities\": [\"light.bedroom\"]\n }\n }\n)\n\nNote: Strategy dashboards cannot be converted to custom dashboards via this tool.\nUse the \"Take Control\" feature in the Home Assistant interface to convert them.\n\nUpdate existing dashboard config:\nha_config_set_dashboard(\n url_path=\"existing-dashboard\",\n config={\n \"views\": [{\n \"title\": \"Updated View\",\n \"type\": \"sections\",\n \"sections\": [{\n \"cards\": [{\"type\": \"markdown\", \"content\": \"Updated!\"}]\n }]\n }]\n }\n)\n\nNote: When updating an existing dashboard, title/icon/require_admin/show_in_sidebar\nare also updated if explicitly provided alongside (or instead of) a config change.",
"inputSchema": {
"properties": {
"url_path": {
"type": "Annotated[str, Field(description=\"Dashboard URL path (e.g., 'my-dashboard'). Use 'default' or 'lovelace' for the default dashboard. New dashboards must use a hyphenated path.\")]"
},
"config": {
"type": "Annotated[str | dict[str, Any] | None, Field(description='Dashboard configuration with views and cards. Can be dict or JSON string. Omit or set to None to create dashboard without initial config. Mutually exclusive with python_transform.')]",
"default": null
},
"python_transform": {
"type": "Annotated[str | None, Field(description='Python expression to transform existing dashboard config. Mutually exclusive with config. Requires config_hash for validation. See PYTHON TRANSFORM SECURITY below for allowed operations. Examples: Simple: python_transform=\"config[\\'views\\'][0][\\'cards\\'][0][\\'icon\\'] = \\'mdi:lamp\\'\" Pattern: python_transform=\"for card in config[\\'views\\'][0][\\'cards\\']: if \\'light\\' in card.get(\\'entity\\', \\'\\'): card[\\'icon\\'] = \\'mdi:lightbulb\\'\" Multi-op: python_transform=\"config[\\'views\\'][0][\\'cards\\'][0][\\'icon\\'] = \\'mdi:lamp\\'; del config[\\'views\\'][0][\\'cards\\'][2]\" \\n\\n' + get_security_documentation())]",
"default": null
},
"config_hash": {
"type": "Annotated[str | None, Field(description='Config hash from ha_config_get_dashboard for optimistic locking. REQUIRED for python_transform (validates dashboard unchanged). Optional for config (validates before full replacement if provided).')]",
"default": null
},
"title": {
"type": "Annotated[str | None, Field(description='Dashboard display name shown in sidebar')]",
"default": null
},
"icon": {
"type": "Annotated[str | None, Field(description=\"MDI icon name (e.g., 'mdi:home', 'mdi:cellphone'). Defaults to 'mdi:view-dashboard'\")]",
"default": null
},
"require_admin": {
"type": "Annotated[bool | None, Field(description='Restrict dashboard to admin users only. For existing dashboards, only updated when explicitly provided.')]",
"default": null
},
"show_in_sidebar": {
"type": "Annotated[bool | None, Field(description='Show dashboard in sidebar navigation. For existing dashboards, only updated when explicitly provided.')]",
"default": null
}
},
"required": [
"url_path"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_config_dashboards.py"
},
{
"name": "ha_config_set_dashboard_resource",
"title": "Set Dashboard Resource",
"description": "Create or update a dashboard resource (inline code or external URL).\n\nProvide exactly one of:\n- content: Inline JavaScript or CSS code (embedded in URL, no file storage needed)\n- url: External resource URL (/local/, /hacsfiles/, or https://...)\n\nINLINE MODE (content=):\n- Custom card code written inline\n- CSS styling for dashboards\n- Small utility modules (<24KB)\n- URLs are deterministic (same content = same URL)\n- Supports 'module' and 'css' types only (not 'js')\n\nURL MODE (url=):\n- Files in /config/www/ directory (/local/...)\n- HACS-installed cards (/hacsfiles/...)\n- External CDN resources (https://...)\n- Supports all types: 'module', 'js', 'css'\n\nRESOURCE TYPES:\n- module: ES6 JavaScript modules (recommended for custom cards)\n- js: Legacy JavaScript files (older custom cards, url mode only)\n- css: CSS stylesheets (themes, global styles)\n\nEXAMPLES:\n\nInline custom card:\nha_config_set_dashboard_resource(\n content=\"\"\"\n class MyCard extends HTMLElement {\n setConfig(config) { this.config = config; }\n set hass(hass) {\n this.innerHTML = `<ha-card>Hello ${hass.states[this.config.entity]?.state}</ha-card>`;\n }\n }\n customElements.define('my-card', MyCard);\n \"\"\",\n resource_type=\"module\"\n)\n\nAdd custom card from www/ directory:\nha_config_set_dashboard_resource(\n url=\"/local/my-custom-card.js\",\n resource_type=\"module\"\n)\n\nAdd HACS card (after installing via ha_hacs_download):\nha_config_set_dashboard_resource(\n url=\"/hacsfiles/lovelace-mushroom/mushroom.js\",\n resource_type=\"module\"\n)\n\nUpdate existing resource:\nha_config_set_dashboard_resource(\n url=\"/local/my-card-v2.js\",\n resource_type=\"module\",\n resource_id=\"abc123\"\n)\n\nNote: After adding a resource, clear browser cache or hard refresh\n(Ctrl+Shift+R) to load changes.",
"inputSchema": {
"properties": {
"content": {
"type": "Annotated[str | None, Field(description=\"JavaScript or CSS code to host inline (max ~24KB). The code is embedded in the URL via Cloudflare Worker - no file storage needed. Mutually exclusive with url. Supports 'module' and 'css' types only.\")]",
"default": null
},
"url": {
"type": "Annotated[str | None, Field(description='URL of the resource. Can be: /local/file.js (www/ directory), /hacsfiles/component/file.js (HACS), https://cdn.example.com/card.js (external). Mutually exclusive with content.')]",
"default": null
},
"resource_type": {
"type": "Annotated[Literal['module', 'js', 'css'], Field(description=\"Resource type: 'module' for ES6 modules (modern cards, default), 'js' for legacy JavaScript (url mode only), 'css' for stylesheets\")]",
"default": "module"
},
"resource_id": {
"type": "Annotated[str | None, Field(description='Resource ID to update. If omitted, creates a new resource. Get IDs from ha_config_list_dashboard_resources()')]",
"default": null
}
}
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_resources.py"
},
{
"name": "ha_dashboard_find_card",
"title": "Find Dashboard Card",
"description": "Find cards, badges, and header cards in a dashboard by entity_id, type, or heading text.\n\nReturns card/badge/header locations (view_index, section_index, card_index/badge_index)\nand path for use with ha_config_set_dashboard(python_transform=...).\n\nAlso searches view-level badges (views[n].badges) and sections-view header cards\n(views[n].header.card). Badges are the chip row at the top of a view, and header\ncards are Markdown cards in the view header — both reference entities and are\noften missed during entity rename operations.\n\nUse this tool BEFORE targeted updates to find exact card positions without\nmanually parsing the full dashboard config.\n\nSEARCH CRITERIA (at least one required):\n- entity_id: Match cards and badges containing this entity (supports wildcards with *)\n- card_type: Match cards of this type (e.g., 'tile', 'button', 'heading')\n- heading: Match cards with this text in heading/title (partial, case-insensitive)\n\nMultiple criteria are AND-ed together.\n\nEXAMPLES:\n\nFind all tile cards:\nha_dashboard_find_card(url_path=\"my-dashboard\", card_type=\"tile\")\n\nFind cards for a specific entity:\nha_dashboard_find_card(url_path=\"my-dashboard\", entity_id=\"light.living_room\")\n\nFind all temperature sensors (wildcard):\nha_dashboard_find_card(url_path=\"my-dashboard\", entity_id=\"sensor.temperature_*\")\n\nFind the \"Climate\" section heading:\nha_dashboard_find_card(url_path=\"my-dashboard\", heading=\"Climate\", card_type=\"heading\")\n\nWORKFLOW EXAMPLE:\n1. find = ha_dashboard_find_card(url_path=\"my-dash\", entity_id=\"light.bedroom\")\n2. # Use jq_path and config_hash from result to update:\n3. ha_config_set_dashboard(\n url_path=\"my-dash\",\n config_hash=find[\"config_hash\"],\n python_transform=f'config{find[\"matches\"][0][\"jq_path\"]}[\"icon\"] = \"mdi:lamp\"'\n )",
"inputSchema": {
"properties": {
"url_path": {
"type": "Annotated[str | None, Field(description=\"Dashboard URL path, e.g. 'lovelace-home'. Omit for default.\")]",
"default": null
},
"entity_id": {
"type": "Annotated[str | None, Field(description=\"Find cards by entity ID. Supports wildcards, e.g. 'sensor.temperature_*'. Matches cards with this entity in 'entity' or 'entities' field.\")]",
"default": null
},
"card_type": {
"type": "Annotated[str | None, Field(description=\"Find cards by type, e.g. 'tile', 'button', 'heading'.\")]",
"default": null
},
"heading": {
"type": "Annotated[str | None, Field(description=\"Find cards by heading/title text (case-insensitive partial match). Useful for finding section headings (type: 'heading').\")]",
"default": null
},
"include_config": {
"type": "Annotated[bool, Field(description='Include full card configuration in results (increases output size).')]",
"default": false
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Dashboards"
],
"source_file": "tools_config_dashboards.py"
},
{
"name": "ha_get_device",
"title": "Get Device",
"description": "Get device information - list all devices or get details for a specific one.\n\nWithout device_id/entity_id: Lists all devices with optional filters.\nWith device_id or entity_id: Returns detailed info for that specific device.\n\n**List all devices:**\n- All devices: ha_get_device()\n- By area: ha_get_device(area_id=\"living_room\")\n- By manufacturer: ha_get_device(manufacturer=\"Philips\")\n- By integration: ha_get_device(integration=\"zigbee2mqtt\")\n- Combined filters: ha_get_device(integration=\"zha\", area_id=\"kitchen\")\n\n**Single device lookup:**\n- By device_id: ha_get_device(device_id=\"abc123\")\n- By entity_id: ha_get_device(entity_id=\"light.living_room\")\n\n**Zigbee automation tips:**\n- ZHA triggers: Use `ieee_address` for zha_event triggers\n- Z2M triggers: Use `friendly_name` for MQTT topics (zigbee2mqtt/{friendly_name}/action)\n\n**Returns (list mode):**\n- List of devices with device_id, name, manufacturer, model, area_id\n\n**Returns (single device):**\n- Full device details including integration_type, ieee_address, entities",
"inputSchema": {
"properties": {
"device_id": {
"type": "Annotated[str | None, Field(description='Device ID to retrieve details for. If omitted, lists devices.', default=None)]",
"default": null
},
"entity_id": {
"type": "Annotated[str | None, Field(description=\"Entity ID to find the associated device for (e.g., 'light.living_room')\", default=None)]",
"default": null
},
"integration": {
"type": "Annotated[str | None, Field(description=\"Filter devices by integration: 'zha', 'zigbee2mqtt', 'mqtt', 'hue', etc.\", default=None)]",
"default": null
},
"area_id": {
"type": "Annotated[str | None, Field(description=\"Filter devices by area ID (e.g., 'living_room')\", default=None)]",
"default": null
},
"manufacturer": {
"type": "Annotated[str | None, Field(description=\"Filter devices by manufacturer name (e.g., 'Philips')\", default=None)]",
"default": null
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Device Registry"
],
"source_file": "tools_registry.py"
},
{
"name": "ha_remove_device",
"title": "Remove Device",
"description": "Remove an orphaned device from the Home Assistant device registry.\n\nWARNING: This removes the device entry from the registry.\n- Use only for orphaned devices that are no longer connected\n- Active devices will typically be re-added by their integration\n- Associated entities may also be removed\n\nThis uses the config entry removal which is the safe way to remove devices.\nIf the device has multiple config entries, they must all be removed.\n\nEXAMPLES:\n- Remove orphaned device: ha_remove_device(\"abc123def456\")\n\nNOTE: For most use cases, consider disabling the device instead:\nha_update_device(device_id=\"abc123\", disabled_by=\"user\")",
"inputSchema": {
"properties": {
"device_id": {
"type": "Annotated[str, Field(description='Device ID to remove from the registry')]"
}
},
"required": [
"device_id"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": true
},
"tags": [
"Device Registry"
],
"source_file": "tools_registry.py"
},
{
"name": "ha_rename_entity",
"title": "Rename Entity",
"description": "Rename a Home Assistant entity by changing its entity_id, optionally renaming its device too.\n\nChanges the entity_id (e.g., light.old_name -> light.new_name).\nThe domain must remain the same - you cannot change a light to a switch.\n\nDEVICE RENAME:\nProvide new_device_name to also rename the device associated with this entity.\nThe device is looked up automatically from the entity registry.\n\nVOICE ASSISTANT EXPOSURE:\nBy default, this function preserves voice assistant exposure settings\n(Alexa, Google Assistant, Assist) when renaming. The exposure settings\nare stored separately from the entity registry and must be migrated\nmanually. Set preserve_voice_exposure=False to skip this migration.\n\nIMPORTANT LIMITATIONS:\n- References in automations/scripts/dashboards are NOT automatically updated\n- Entity history is preserved (HA 2022.4+)\n- Some entities cannot be renamed:\n - Entities without unique IDs\n - Entities disabled by integration\n\nEXAMPLES:\n- Rename light: ha_rename_entity(\"light.bedroom_1\", \"light.master_bedroom\")\n- Rename with friendly name: ha_rename_entity(\"sensor.temp\", \"sensor.living_room_temp\", name=\"Living Room Temperature\")\n- Rename entity and device: ha_rename_entity(\"light.bedroom_1\", \"light.master_bedroom\", new_device_name=\"Master Bedroom Lamp\")\n- Rename without exposure migration: ha_rename_entity(\"light.old\", \"light.new\", preserve_voice_exposure=False)\n\nNOTE: Device and entity renaming are independent in HA. Renaming a device does\nNOT rename its entities. See ha_update_device() for device-only renaming.",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str, Field(description=\"Current entity ID to rename (e.g., 'light.old_name')\")]"
},
"new_entity_id": {
"type": "Annotated[str, Field(description=\"New entity ID (e.g., 'light.new_name'). Domain must match the original.\")]"
},
"name": {
"type": "Annotated[str | None, Field(description='Optional: New friendly name for the entity', default=None)]",
"default": null
},
"icon": {
"type": "Annotated[str | None, Field(description=\"Optional: New icon (e.g., 'mdi:lightbulb')\", default=None)]",
"default": null
},
"new_device_name": {
"type": "Annotated[str | None, Field(description='Optional: New display name for the associated device. If provided, both entity and device are renamed in one operation.', default=None)]",
"default": null
},
"preserve_voice_exposure": {
"type": "Annotated[bool | str | None, Field(description='Migrate voice assistant exposure settings to the new entity_id. Defaults to True. Set to False to skip exposure migration.', default=None)]",
"default": null
}
},
"required": [
"entity_id",
"new_entity_id"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Device Registry"
],
"source_file": "tools_registry.py"
},
{
"name": "ha_update_device",
"title": "Update Device",
"description": "Update device properties such as name, area, disabled state, or labels.\n\nIMPORTANT: Renaming a device does NOT rename its entities!\nDevice and entity names are independent. To rename entities, use ha_rename_entity().\n\nCommon workflow for full rename:\n1. ha_update_device(device_id=\"abc\", name=\"Living Room Sensor\") # Rename device\n2. ha_rename_entity(entity_id=\"sensor.old\", new_entity_id=\"sensor.living_room\") # Rename entities separately\n\nPARAMETERS:\n- name: Sets the user-defined display name (name_by_user)\n- area_id: Assigns device to an area/room. Use '' to remove from area.\n- disabled_by: Set to 'user' to disable, or empty to enable\n- labels: List of labels (replaces existing labels)\n\nEXAMPLES:\n- Rename device: ha_update_device(\"abc123\", name=\"Living Room Hub\")\n- Move to area: ha_update_device(\"abc123\", area_id=\"living_room\")\n- Disable device: ha_update_device(\"abc123\", disabled_by=\"user\")\n- Enable device: ha_update_device(\"abc123\", disabled_by=\"\")\n- Add labels: ha_update_device(\"abc123\", labels=[\"important\", \"sensor\"])",
"inputSchema": {
"properties": {
"device_id": {
"type": "Annotated[str, Field(description='Device ID to update')]"
},
"name": {
"type": "Annotated[str | None, Field(description='New display name for the device (sets name_by_user)', default=None)]",
"default": null
},
"area_id": {
"type": "Annotated[str | None, Field(description=\"Area/room ID to assign the device to. Use empty string '' to unassign.\", default=None)]",
"default": null
},
"disabled_by": {
"type": "Annotated[str | None, Field(description=\"Set to 'user' to disable, or None/empty string to enable\", default=None)]",
"default": null
},
"labels": {
"type": "Annotated[str | list[str] | None, Field(description='Labels to assign to the device (replaces existing labels)', default=None)]",
"default": null
}
},
"required": [
"device_id"
]
},
"annotations": {
"destructiveHint": true
},
"tags": [
"Device Registry"
],
"source_file": "tools_registry.py"
},
{
"name": "ha_get_entity",
"title": "Get Entity",
"description": "Get entity registry information for one or more entities.\n\nReturns detailed entity registry metadata including area assignment,\ncustom name/icon, enabled/hidden state, aliases, labels, and more.\n\nRELATED TOOLS:\n- ha_set_entity(): Modify entity properties (area, name, icon, enabled, hidden, aliases)\n- ha_get_state(): Get current state/attributes (on/off, temperature, etc.)\n- ha_search_entities(): Find entities by name, domain, or area\n\nEXAMPLES:\n- Single entity: ha_get_entity(\"sensor.temperature\")\n- Multiple entities: ha_get_entity([\"light.living_room\", \"switch.porch\"])\n\nRESPONSE FIELDS:\n- entity_id: Full entity identifier\n- name: Custom display name (null if using original_name)\n- original_name: Default name from integration\n- icon: Custom icon (null if using default)\n- area_id: Assigned area/room ID (null if unassigned)\n- disabled_by: Why disabled (null=enabled, \"user\"/\"integration\"/etc)\n- hidden_by: Why hidden (null=visible, \"user\"/\"integration\"/etc)\n- enabled: Boolean shorthand (True if disabled_by is null)\n- hidden: Boolean shorthand (True if hidden_by is not null)\n- aliases: Voice assistant aliases\n- labels: Assigned label IDs\n- categories: Category assignments (dict mapping scope to category_id)\n- platform: Integration platform (e.g., \"hue\", \"zwave_js\")\n- device_id: Associated device ID (null if standalone)\n- unique_id: Integration's unique identifier",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str | list[str], Field(description=\"Entity ID or list of entity IDs to retrieve (e.g., 'sensor.temperature' or ['light.living_room', 'switch.porch'])\")]"
}
},
"required": [
"entity_id"
]
},
"annotations": {
"readOnlyHint": true,
"idempotentHint": true
},
"tags": [
"Entity Registry"
],
"source_file": "tools_entities.py"
},
{
"name": "ha_get_entity_exposure",
"title": "Get Entity Exposure",
"description": "Get entity exposure settings - list all or get settings for a specific entity.\n\nWithout an entity_id: Lists all entities and their exposure status to\nvoice assistants (Alexa, Google Assistant, Assist).\n\nWith an entity_id: Returns which voice assistants the specific entity\nis exposed to.\n\nEXAMPLES:\n- List all exposures: ha_get_entity_exposure()\n- Filter by assistant: ha_get_entity_exposure(assistant=\"cloud.alexa\")\n- Get specific entity: ha_get_entity_exposure(entity_id=\"light.living_room\")\n\nRETURNS (when listing):\n- exposed_entities: Dict mapping entity_ids to their exposure status\n- summary: Count of entities exposed to each assistant\n\nRETURNS (when getting specific entity):\n- exposed_to: Dict of assistant -> True/False for each assistant\n- is_exposed_anywhere: True if exposed to at least one assistant",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str | None, Field(description='Entity ID to check exposure settings for. If omitted, lists all entities with exposure settings.', default=None)]",
"default": null
},
"assistant": {
"type": "Annotated[str | None, Field(description=\"Filter by assistant: 'conversation', 'cloud.alexa', or 'cloud.google_assistant'. If not specified, returns all.\", default=None)]",
"default": null
}
}
},
"annotations": {
"idempotentHint": true,
"readOnlyHint": true
},
"tags": [
"Entity Registry"
],
"source_file": "tools_voice_assistant.py"
},
{
"name": "ha_set_entity",
"title": "Set Entity",
"description": "Update entity properties in the entity registry.\n\nAllows modifying entity metadata such as area assignment, display name,\nicon, enabled/disabled state, visibility, aliases, labels, and voice\nassistant exposure in a single call.\n\nBULK OPERATIONS:\nWhen entity_id is a list, only labels and expose_to parameters are supported.\nOther parameters (area_id, name, icon, enabled, hidden, aliases) require single entity.\n\nLABEL OPERATIONS:\n- label_operation=\"set\" (default): Replace all labels with the provided list. Use [] to clear.\n- label_operation=\"add\": Add labels to existing ones without removing any.\n- label_operation=\"remove\": Remove specified labels from the entity.\n\nUse ha_search_entities() or ha_get_device() to find entity IDs.\nUse ha_config_get_label() to find available label IDs.\n\nEXAMPLES:\nSingle entity:\n- Assign to area: ha_set_entity(\"sensor.temp\", area_id=\"living_room\")\n- Rename: ha_set_entity(\"sensor.temp\", name=\"Living Room Temperature\")\n- Set labels: ha_set_entity(\"light.lamp\", labels=[\"outdoor\", \"smart\"])\n- Add labels: ha_set_entity(\"light.lamp\", labels=[\"new_label\"], label_operation=\"add\")\n- Remove labels: ha_set_entity(\"light.lamp\", labels=[\"old_label\"], label_operation=\"remove\")\n- Clear labels: ha_set_entity(\"light.lamp\", labels=[])\n- Expose to Alexa: ha_set_entity(\"light.lamp\", expose_to={\"cloud.alexa\": True})\n\nBulk operations:\n- Set labels on multiple: ha_set_entity([\"light.a\", \"light.b\"], labels=[\"outdoor\"])\n- Add labels to multiple: ha_set_entity([\"light.a\", \"light.b\"], labels=[\"new\"], label_operation=\"add\")\n- Expose multiple to Alexa: ha_set_entity([\"light.a\", \"light.b\"], expose_to={\"cloud.alexa\": True})\n\nNOTE: To rename an entity_id (e.g., sensor.old -> sensor.new), use ha_rename_entity() instead.\n\nENABLED/DISABLED WARNING:\nSetting enabled=False performs a **registry-level disable** — the entity is completely\nremoved from the Home Assistant state machine and hidden from the UI. It will NOT appear\nin state queries, dashboards, or automations until re-enabled AND the integration is\nreloaded. This is NOT the same as \"turning off\" an entity.\n\nFor automations and scripts, enabled=False is blocked. Use these instead:\n- ha_call_service(\"automation\", \"turn_off\", entity_id=\"automation.xxx\")\n- ha_call_service(\"script\", \"turn_off\", entity_id=\"script.xxx\")",
"inputSchema": {
"properties": {
"entity_id": {
"type": "Annotated[str | list[str], Field(description='Entity ID or list of entity IDs to update. Bulk operations (list) only support labels and expose_to parameters.')]"
},
"area_id": {
"type": "Annotated[str | None, Field(description=\"Area/room ID to assign the entity to. Use empty string '' to unassign from current area. Single entity only.\", default=None)]",
"default": null
},
"name": {
"type": "Annotated[str | None, Field(description=\"Display name for the entity. Use empty string '' to remove custom name and revert to default. Single entity only.\", default=None)]",
"default": null
},
"icon": {
"type": "Annotated[str | None, Field(description=\"Icon for the entity (e.g., 'mdi:thermometer'). Use empty string '' to remove custom icon. Single entity only.\", default=None)]",
"default": null
},
"enabled": {
"type": "Annotated[bool | str | None, Field(description='True to enable the entity, False to disable it. Single entity only. WARNING: Setting enabled=False is a registry-level disable — it completely removes the entity from the state machine and hides it from the UI. A reload or restart is required to restore it after re-enabling. NOT allowed for automation or script entities — use automation.turn_off / script.turn_off via ha_call_service() instead.', default=None)]",
"default": null
},
"hidden": {
"type": "Annotated[bool | str | None, Field(description='True to hide the entity from UI, False to show it. Single entity only.', default=None)]",
"default": null
},
"aliases": {
"type": "Annotated[str | list[str] | None, Field(description='List of voice assistant aliases for the entity (replaces existing aliases). Single entity only.', default=None)]",
"default": null
},
"categories": {
"type": "Annotated[str | dict[str, str | None] | None, Field(description='Category assignment as a dict mapping scope to category_id. Example: {\"automation\": \"category_id_here\"}. Use null value to clear: {\"automation\": null}. Single entity only.', default=None)]",
"default": null
},
"labels": {
"type": "Annotated[str | list[str] | None, Field(description='List of label IDs for the entity. Behavior depends on label_operation parameter. Supports bulk operations.', default=None)]",
"default": null
},
"label_operation": {
"type": "Annotated[Literal['set', 'add', 'remove'], Field(description=\"How to apply labels: 'set' replaces all labels, 'add' adds to existing, 'remove' removes specified labels.\", default='set')]",
"default": "set"
},
"expose_to": {
"type": "Annotated[str | dict[str, bool] | None, Field(description='Control voice assistant exposure. Pass a dict mapping assistant IDs to booleans. Valid assistants: \\'conversation\\' (Assist), \\'cloud.alexa\\', \\'cloud.google_assistant\\'. Example: {\"conversation\": true, \"cloud.alexa\": false}. Supports bulk operations.', default=None)]",
"default": null
}
},
"required": [
"entity_id"
]
},
"annotations": {
"destructiveHint": true,
"idempotentHint": true
},
"tags": [
"Entity Registry"
],
"source_file": "tools_entities.py"
},
{
"name": "ha_delete_file",
"title": "Delete File",
"description": "Delete a file from allowed directories in the Home Assistant config.\n\nPermanently removes a file from the allowed directories. This action\ncannot be undone.\n\n**Allowed Delete Directories:**\n- `www/` - Web assets\n- `themes/` - Theme files\n- `custom_templates/` - Template files\n\n**Security:**\n- Only the directories above allow deletions\n- Configuration files cannot be deleted\n- Path traversal (../) is blocked\n- Requires confirm=True to prevent accidents\n\n**Returns:**\n- success: Whether the operation succeeded\n- path: The file path that was deleted\n- message: Confirmation message\n\n**Example:**\n```python\n# Delete an old CSS file\nresult = ha_delete_file(\n path=\"www/deprecated-style.css\",\n confirm=True\n)\n```",
"inputSchema": {
"properties": {
"path": {
"type": "Annotated[str, Field(description=\"Relative path from config directory. Must be in www/, themes/, or custom_templates/. Example: 'www/old-file.css'\")]"
},
"confirm": {
"type": "Annotated[bool | str, Field(default=False, description='Must be True to confirm deletion. This is a safety measure to prevent accidental deletions.')]",
"default": false
}
},