Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Get Entity History or Statistics

ha_get_history
Read-onlyIdempotent

Retrieve Home Assistant history and statistics to troubleshoot value changes, inspect event sequences, or analyze long-term trends and period averages.

Instructions

Get historical data from Home Assistant's recorder.

WHEN NOT TO USE: For current values, use ha_get_state. To inspect Energy Dashboard preferences and configured statistics, use ha_manage_energy_prefs(mode="get", include_statistics=True).

WHEN TO USE: Use source="history" (default) to troubleshoot why a value changed, check event sequences, or analyze recent patterns. Use summary=True when the question needs a count or a duration ("was it ever unavailable?") rather than the rows. Use source="statistics" for long-term trends and period averages.

CAVEATS: History rows rename Core's compact keys once: s -> state, a -> attributes, lu -> last_updated, lc -> last_changed. History event times are ISO strings in HA's timezone (UTC if unavailable). When Core omits lc, last_changed falls back to last_updated; this may not be the actual state-change time with significant_changes_only (default) or a window-start snapshot. Attributes and unknown fields pass through unchanged. Statistics timestamps use Unix milliseconds. Minimal history may omit attributes. No duplicate compact aliases are added. include_schema=True retains core_contract even when fields selects other data keys.

Output units come from Core recorder metadata and reflect its display-unit conversion; unresolved units include a reason. statistics_metadata preserves Core's native fields.

All data is fetched from HA before slicing; limit/offset are client-side. With multiple entity_ids, offset must be 0 — use a single entity_id for offset > 0. Use has_more and next_offset from the response to paginate. With source="history", summary=True does not combine with offset > 0. Administrators can optionally enable recorder workload guardrails in Advanced settings. When enabled, oversized entity/time workloads are rejected before the recorder query is issued; narrow the time range or entity list to stay within the budget. Calendar statistics may first read HA's configured timezone so the estimate follows local calendar boundaries.

EXAMPLES:

  • ha_get_history(entity_ids="sensor.bedroom_temperature", start_time="24h")

  • Paginate oldest-first: ha_get_history(entity_ids="sensor.temperature", start_time="7d", limit=100, offset=100, order="asc")

  • Time per state: ha_get_history(entity_ids="binary_sensor.door", start_time="7d", summary=True)

  • ha_get_history(source="statistics", entity_ids="sensor.living_room_temperature", start_time="6m", period="month", statistic_types=["mean", "min", "max"])

Input Schema

NameRequiredDescriptionDefault
limitNoMax entries per entity. Default: 100. For source="history": state rows; with summary=True, the states listed in summary.states, longest first. For source="statistics": aggregated rows. With multiple entity_ids, total rows returned can reach limit × len(entity_ids).
orderNoSort order for history entries. "desc": newest first. "asc": oldest first. Ignored when source="statistics".desc
fieldsNoReturn only the specified keys within data to reduce response size. None = full response. History keys: success, source, entities, period, query_params. Statistics keys: success, source, entities, period_type, time_range, statistic_types, query_params. Warnings and timezone metadata remain outside data and are always retained.
offsetNoNumber of entries to skip per entity for pagination.
periodNoAggregation period: "5minute", "hour", "day", "week", "month", "year". Ignored when source="history"day
sourceNoData source: "history" for raw state changes at full resolution (~10 day retention), or "statistics" for pre-aggregated long-term data (permanent, requires state_class).history
summaryNoReturn per-entity totals instead of state rows: changes (switches to a different state; the state at the window start is not one, but without that state, e.g. with core_options {'include_start_time_state': false} or purged history, the first recorded state counts as one), first_change and last_change (null without changes), and per state its periods (separate spells) and duration_s (seconds, up to end_time or now, whichever is earlier). distinct_states counts every state, listed or not. Ignored when source="statistics".
end_timeNoEnd time: same formats as start_time. Omit it to end at the current time
entity_idsYesEntity ID(s) to query. Can be a single ID, comma-separated string, or JSON array.
start_timeNoStart time: ISO datetime or a look-back from now with unit min, h, d, w or m (= 30 days), e.g. '30min' = 30 minutes ago. Default: 24h ago for history, 30d ago for statistics
core_optionsNoAdditional native Core request fields, e.g. {'units': {'energy': 'MWh'}} for statistics. Core validates them. Cannot override fields controlled by the tool's parameters or query limits.
include_schemaNoInclude the running Core's native request schema when the component supports discovery.
statistic_typesNoNative Core statistics types (for example "sum", "change", "last_reset"). Default: Core chooses all. Use include_schema=True to discover the installed contract. Ignored when source="history"
minimal_responseNoReturn only states/timestamps without attributes. Ignored when source="statistics"
significant_changes_onlyNoFilter to significant state changes only. Ignored when source="statistics"

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv9.0.0
    • changedInput schema / properties / end_time / description
      Previous value: -"End time: ISO datetime. Default: now"New value: +"End time: same formats as start_time. Omit it to end at the current time"
    • changedInput schema / properties / limit / description
      Previous value: -"Max entries per entity. Default: 100. For source=\"history\": state changes. For source=\"statistics\": aggregated rows. With multiple entity_ids, total rows returned can reach limit × len(entity_ids)."New value: +"Max entries per entity. Default: 100. For source=\"history\": state rows; with summary=True, the states listed in summary.states, longest first. For source=\"statistics\": aggregated rows. With multiple entity_ids, total rows returned can reach limit × len(entity_ids)."
    • changedInput schema / properties / start_time / description
      Previous value: -"Start time: ISO datetime or relative (e.g., '24h', '7d', '30d'). Default: 24h ago for history, 30d ago for statistics"New value: +"Start time: ISO datetime or a look-back from now with unit min, h, d, w or m (= 30 days), e.g. '30min' = 30 minutes ago. Default: 24h ago for history, 30d ago for statistics"
    • addedInput schema / properties / summary
      Added value: +{
      +  "default": false,
      +  "description": "Return per-entity totals instead of state rows: changes (switches to a different state; the state at the window start is not one, but without that state, e.g. with core_options {'include_start_time_state': false} or purged history, the first recorded state counts as one), first_change and last_change (null without changes), and per state its periods (separate spells) and duration_s (seconds, up to end_time or now, whichever is earlier). distinct_states counts every state, listed or not. Ignored when source=\"statistics\".",
      +  "type": "boolean"
      +}
  2. Changed4 schema fields changedv8.7.0
    • addedInput schema / properties / core_options
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Additional native Core request fields, e.g. {'units': {'energy': 'MWh'}} for statistics. Core validates them. Cannot override fields controlled by the tool's parameters or query limits."
      +}
    • changedInput schema / properties / fields / description
      Previous value: -"Return only the specified top-level response keys to reduce response size. None = full response. History keys: success, source, entities, period, query_params. Statistics keys: success, source, entities, period_type, time_range, statistic_types, query_params, warnings."New value: +"Return only the specified keys within data to reduce response size. None = full response. History keys: success, source, entities, period, query_params. Statistics keys: success, source, entities, period_type, time_range, statistic_types, query_params. Warnings and timezone metadata remain outside data and are always retained."
    • addedInput schema / properties / include_schema
      Added value: +{
      +  "default": false,
      +  "description": "Include the running Core's native request schema when the component supports discovery.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / statistic_types / description
      Previous value: -"Statistics types: \"mean\", \"min\", \"max\", \"sum\", \"state\", \"change\". Default: all. Ignored when source=\"history\""New value: +"Native Core statistics types (for example \"sum\", \"change\", \"last_reset\"). Default: Core chooses all. Use include_schema=True to discover the installed contract. Ignored when source=\"history\""
  3. Changed8 schema fields changedv8.6.0
    • changedInput schema / properties / fields / description
      Previous value: -"Return only the specified top-level response keys to reduce response size. None = full response (default). History keys: success, source, entities, period, query_params. Statistics keys: success, source, entities, period_type, time_range, statistic_types, query_params, warnings."New value: +"Return only the specified top-level response keys to reduce response size. None = full response. History keys: success, source, entities, period, query_params. Statistics keys: success, source, entities, period_type, time_range, statistic_types, query_params, warnings."
    • changedInput schema / properties / limit / description
      Previous value: -"Max entries per entity. Default: 100, Max: 1000. For source=\"history\": state changes. For source=\"statistics\": aggregated rows. With multiple entity_ids, offset must be 0 and total rows returned can reach limit × len(entity_ids)."New value: +"Max entries per entity. Default: 100. For source=\"history\": state changes. For source=\"statistics\": aggregated rows. With multiple entity_ids, total rows returned can reach limit × len(entity_ids)."
    • changedInput schema / properties / minimal_response / description
      Previous value: -"Return only states/timestamps without attributes. Default: true. Ignored when source=\"statistics\""New value: +"Return only states/timestamps without attributes. Ignored when source=\"statistics\""
    • changedInput schema / properties / offset / description
      Previous value: -"Number of entries to skip per entity for pagination. Default: 0. Offset > 0 requires a single entity_id. Use with limit and has_more/next_offset in the response."New value: +"Number of entries to skip per entity for pagination."
    • changedInput schema / properties / order / description
      Previous value: -"Sort order for history entries. \"desc\" (default): newest first. \"asc\": oldest first (chronological, as returned by HA API). Ignored when source=\"statistics\"."New value: +"Sort order for history entries. \"desc\": newest first. \"asc\": oldest first. Ignored when source=\"statistics\"."
    • changedInput schema / properties / period / description
      Previous value: -"Aggregation period: \"5minute\", \"hour\", \"day\", \"week\", \"month\", \"year\". Default: \"day\". Ignored when source=\"history\""New value: +"Aggregation period: \"5minute\", \"hour\", \"day\", \"week\", \"month\", \"year\". Ignored when source=\"history\""
    • changedInput schema / properties / significant_changes_only / description
      Previous value: -"Filter to significant state changes only. Default: true. Ignored when source=\"statistics\""New value: +"Filter to significant state changes only. Ignored when source=\"statistics\""
    • changedInput schema / properties / source / description
      Previous value: -"Data source: \"history\" (default) for raw state changes (~10 day retention), or \"statistics\" for pre-aggregated long-term data (permanent, requires state_class)."New value: +"Data source: \"history\" for raw state changes at full resolution (~10 day retention), or \"statistics\" for pre-aggregated long-term data (permanent, requires state_class)."
  4. First observedv7.14.2

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description adds genuinely new behavior: Core key renaming (s/a/lu/lc), ISO-with-HA-timezone timestamps, last_changed fallback to last_updated under significant_changes_only, statistics timestamps in Unix ms, and optional admin-enabled recorder workload guardrails that can reject oversized queries. These are operational facts no annotation or schema field carries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded with WHEN NOT TO USE first, then WHEN TO USE, CAVEATS, EXAMPLES — a clean scannable structure with four concrete invocations. It is long, and a few caveat sentences are near-opaque filler for a caller ('No duplicate compact aliases are added', 'include_schema=True retains core_contract even when fields selects other data keys') that could be trimmed without loss.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter tool with an output schema, the description supplies everything the schema cannot: source selection, retention asymmetry (history ~10 days vs permanent statistics requiring state_class), pagination protocol via has_more/next_offset, and guardrail behavior. Return-shape detail is correctly delegated to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, and the description clears that bar by documenting cross-parameter constraints the schema does not: limit/offset are client-side, offset must be 0 with multiple entity_ids, and summary=True cannot combine with offset>0 for history. It also ties source/summary/period to intent with worked examples. It stops short of a systematic per-parameter walkthrough, which is expected given the schema already does that work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get historical data from Home Assistant's recorder') and immediately partitions the domain into source="history" vs source="statistics" with what each is for. It also names the sibling it is not (ha_get_state for current values) so an agent can route without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit WHEN NOT TO USE block naming ha_get_state and ha_manage_energy_prefs(mode="get", include_statistics=True), followed by WHEN TO USE rules keyed to intent (troubleshoot a change, need a count/duration, long-term trends). This is the full when/when-not/alternative triad.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools