Verified MCP server: Home Assistant

The Home Assistant MCP server, enumerated live on a real Mac.

  • Tools enumerated2026-08-04macOS 15.7.7
  • Packagehass-mcp 0.5.0
  • Self-reportedHass-MCP 1.29.0
  • MCP protocol2025-06-18
  • Runtimev24.18.0

The tool list below is a live capture from the running server; an authenticated tool call is still pending credentials.

The short answer

Last verified 2026-08-04

The Home Assistant MCP server connects an AI assistant to the hub that already runs your lights, thermostats, locks, blinds and sensors. Its 16 tools read the state of any entity, switch things on and off, group entities by room, list your automations, pull history and long-term statistics, filter the error log, call any Home Assistant service, and restart the hub itself. It is not published by the Home Assistant project: this page covers hass-mcp, an independent MIT-licensed package by the GitHub developer voska, 312 stars and a push dated 2026-07-28, installed and started with one uvx command. Its credential story is short: two environment variables, HA_URL for the address you already open Home Assistant at and HA_TOKEN for a long-lived access token you generate inside it, with no OAuth screen and no third-party account in between. What follows is the run itself, including the part that failed. We started it on a Mac with uvx, completed the MCP handshake, and it answered tools/list with all 16 tools, which is the table below, word for word. The one real tool call we made, get_version, came back with the server's own connection error rather than a version number, because there is no Home Assistant instance on this Mac and none reachable from it. So the tool table is enumerated live and every error on this page is captured output, while a call that actually reaches a hub still waits on one of your own. [1][3][4]

  • Tools

    16, enumerated live

  • Credentials

    Hub address and token [4]

  • Transport

    stdio, runs on your Mac [4]

  • Maintainer

    voska, community [3][1]

  • Downloads

    1,257 last week [2]

  • License

    MIT [3]

Verification

How this MCP server was verified.

Method

We spawned the server with uvx over stdio, with HA_URL pointing at http://homeassistant.local:8123, the same address the config blocks on this page use, and HA_TOKEN set to an obvious placeholder string, because this Mac runs no Home Assistant instance and none is reachable from it. The MCP initialize handshake completed, the server introduced itself as Hass-MCP 1.29.0 on protocol 2025-06-18, and tools/list answered with all 16 tools, which is the table below, word for word. It prints no banner of its own at startup: the first line quoted below is uv reporting the packages it put in place, and the four after it are everything the server itself wrote to stderr, its own log of the two requests we sent it. We then made one real tool call, get_version with no arguments, and it returned the connection error quoted under the sample call, so the excerpt on this page is an error and not a result: the server tried to reach Home Assistant, failed, and reported the failure as ordinary tool text rather than as a protocol error. The tools are therefore enumerated live and every error here is captured output, while a successful authenticated call still waits on a Home Assistant address and a long-lived access token, neither of which exists on this Mac. Four deliberate failure probes ran on the same Mac minutes later and are quoted in full in the troubleshooting section: no credentials at all, a bad argument shape, an unroutable hub address, and a real host that is not Home Assistant.

Startup banner

Installed 39 packages in 155ms
2026-08-04 01:11:09,736 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest
2026-08-04 01:11:09,738 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest
2026-08-04 01:11:09,738 - app.server - INFO - Executing command: get_version
2026-08-04 01:11:09,738 - app.server - INFO - Getting Home Assistant version

One real tool call

tools/call get_version {}
Connection error: Cannot connect to Home Assistant at http://homeassistant.local:8123

Real lines from the captured result: enough to prove the call answered.

Tools

Every tool, enumerated from the running server.

The server answered tools/list with 16 tools on 2026-08-04. The names, descriptions and parameters below are its own words, copied from that response and never edited.

ToolWhat it does
get_version

Get the Home Assistant version Returns: A string with the Home Assistant version (e.g., "2025.3.0")

get_entityentity_id*fieldsdetailed

Get the state of a Home Assistant entity with optional field filtering Args: entity_id: The entity ID to get (e.g. 'light.living_room') fields: Optional list of fields to include (e.g. ['state', 'attr.brightness']) detailed: If True, returns all entity fields without filtering Examples: entity_id="light.living_room" - basic state check entity_id="light.living_room", fields=["state", "attr.brightness"] - specific fields entity_id="light.living_room", detailed=True - all details

entity_actionentity_id*action*params

Perform an action on a Home Assistant entity (on, off, toggle) Args: entity_id: The entity ID to control (e.g. 'light.living_room') action: The action to perform ('on', 'off', 'toggle') params: Optional dictionary of additional parameters for the service call Returns: The response from Home Assistant Examples: entity_id="light.living_room", action="on", params={"brightness": 255} entity_id="switch.garden_lights", action="off" entity_id="climate.living_room", action="on", params={"temperature": 22.5} Domain-Specific Parameters: - Lights: brightness (0-255), color_temp, rgb_color, transition, effect - Covers: position (0-100), tilt_position - Climate: temperature, target_temp_high, target_temp_low, hvac_mode - Media players: source, volume_level (0-1)

list_entitiesdomainsearch_querylimitfieldsdetailed

Get a list of Home Assistant entities with optional filtering Args: domain: Optional domain to filter by (e.g., 'light', 'switch', 'sensor') search_query: Optional search term to filter entities by name, id, or attributes (Note: Does not support wildcards. To get all entities, leave this empty) limit: Maximum number of entities to return (default: 100) fields: Optional list of specific fields to include in each entity detailed: If True, returns all entity fields without filtering Returns: A list of entity dictionaries with lean formatting by default Examples: domain="light" - get all lights search_query="kitchen", limit=20 - search entities domain="sensor", detailed=True - full sensor details Best Practices: - Use lean format (default) for most operations - Prefer domain filtering over no filtering - For domain overviews, use domain_summary_tool instead of list_entities - Only request detailed=True when necessary for full attribute inspection - To get all entity types/domains, use list_entities without a domain filter, then extract domains from entity_ids

get_entities_by_areaarea*domainlean

Get all entities assigned to a specific Home Assistant area (room). Area lookup is case-insensitive and matches the area's name as configured in Home Assistant (e.g., "Kitchen", "Living Room"). Entities inherit their area from their parent device when no area is set directly, matching HA's own resolution behavior. Args: area: Name of the area to filter by (case-insensitive) domain: Optional domain to further filter results (e.g., 'light') lean: If True (default), returns token-efficient entity records Returns: A dictionary containing: - area: The matched area name (as canonicalized by HA) - count: Number of matching entities - entities: List of entity records with their state and area Examples: get_entities_by_area(area="Kitchen") - everything in the kitchen get_entities_by_area(area="Living Room", domain="light") - lights only

search_entities_toolquery*limit

Search for entities matching a query string Args: query: The search query to match against entity IDs, names, and attributes. (Note: Does not support wildcards. To get all entities, leave this blank or use list_entities tool) limit: Maximum number of results to return (default: 20) Returns: A dictionary containing search results and metadata: - count: Total number of matching entities found - results: List of matching entities with essential information - domains: Map of domains with counts (e.g. {"light": 3, "sensor": 2}) Examples: query="temperature" - find temperature entities query="living room", limit=10 - find living room entities query="", limit=500 - list all entity types

domain_summary_tooldomain*example_limit

Get a summary of entities in a specific domain Args: domain: The domain to summarize (e.g., 'light', 'switch', 'sensor') example_limit: Maximum number of examples to include for each state Returns: A dictionary containing: - total_count: Number of entities in the domain - state_distribution: Count of entities in each state - examples: Sample entities for each state - common_attributes: Most frequently occurring attributes Examples: domain="light" - get light summary domain="climate", example_limit=5 - climate summary with more examples Best Practices: - Use this before retrieving all entities in a domain to understand what's available

system_overview

Get a comprehensive overview of the entire Home Assistant system Returns: A dictionary containing: - total_entities: Total count of all entities - domains: Dictionary of domains with their entity counts and state distributions - domain_samples: Representative sample entities for each domain (2-3 per domain) - domain_attributes: Common attributes for each domain - area_distribution: Entities grouped by area (if available) Examples: Returns domain counts, sample entities, and common attributes Best Practices: - Use this as the first call when exploring an unfamiliar Home Assistant instance - Perfect for building context about the structure of the smart home - After getting an overview, use domain_summary_tool to dig deeper into specific domains

list_automations

Get a list of all automations from Home Assistant This function retrieves all automations configured in Home Assistant, including their IDs, entity IDs, state, and display names. Returns: A list of automation dictionaries, each containing id, entity_id, state, and alias (friendly name) fields. Examples: Returns all automation objects with state and friendly names

restart_ha

Restart Home Assistant ⚠️ WARNING: Temporarily disrupts all Home Assistant operations Returns: Result of restart operation

call_service_tooldomain*service*data

Call any Home Assistant service (low-level API access) Args: domain: The domain of the service (e.g., 'light', 'switch', 'automation') service: The service to call (e.g., 'turn_on', 'turn_off', 'toggle') data: Optional data to pass to the service (e.g., {'entity_id': 'light.living_room'}) Returns: A dictionary with success status, the domain/service called, and the list of affected entity states returned by Home Assistant. Examples: domain='light', service='turn_on', data={'entity_id': 'light.x', 'brightness': 255} domain='automation', service='reload' domain='fan', service='set_percentage', data={'entity_id': 'fan.x', 'percentage': 50}

get_historyentity_id*hours

Get the history of an entity's state changes Args: entity_id: The entity ID to get history for hours: Number of hours of history to retrieve (default: 24) Returns: A dictionary containing: - entity_id: The entity ID requested - states: List of state objects with timestamps - count: Number of state changes found - first_changed: Timestamp of earliest state change - last_changed: Timestamp of most recent state change Examples: entity_id="light.living_room" - get 24h history entity_id="sensor.temperature", hours=168 - get 7 day history Best Practices: - Keep hours reasonable (24-72) for token efficiency - Use for entities with discrete state changes rather than continuously changing sensors - Consider the state distribution rather than every individual state

get_history_rangeentity_id*start_time*end_time

Get raw state-change history for an entity over a date/time range. Like `get_history`, but takes an explicit window instead of "N hours from now". Useful for inspecting what happened on a specific day or correlating with an external event. Args: entity_id: The entity to fetch history for. start_time: ISO-8601 start (e.g. `2026-05-15` or `2026-05-15T08:00:00Z`). Treated as UTC if no offset. end_time: ISO-8601 end. Defaults to now (UTC). Returns: Same shape as `get_history`: `entity_id`, `states`, `count`, `first_changed`, `last_changed`. Examples: get_history_range("light.kitchen", "2026-05-15") get_history_range("sensor.power", "2026-05-15T00:00:00Z", "2026-05-16T00:00:00Z") Best Practices: - Bound the window — wider ranges return more data and more tokens. - For aggregated long-term data, prefer `get_statistics_range`.

get_statisticsentity_id*hoursperiod

Get long-term aggregated statistics for an entity over the last N hours. Uses HA's recorder statistics (over WebSocket) — aggregated buckets (mean / min / max per period) that survive the short-term retention window. Use this instead of `get_history` when: - You want data older than the recorder's default 10-day window. - You want aggregated values rather than every individual change. - The entity is a high-frequency sensor (temperature, power) and raw history would be too many tokens. Args: entity_id: The entity (must have a `state_class` HA records as statistics — `measurement`, `total`, `total_increasing`). hours: How far back from now. Defaults to 24. period: Bucket size — `5minute`, `hour`, `day`, `week`, `month`. Defaults to `hour`. Returns: `entity_id`, `period`, `start_time`, `end_time`, `statistics` (list of `{start, end, mean, min, max, ...}` points). Examples: get_statistics("sensor.power_usage", hours=168, period="day") get_statistics("sensor.temperature", hours=24)

get_statistics_rangeentity_id*start_time*end_timeperiod

Get long-term aggregated statistics for an entity over a date/time range. Same data source as `get_statistics`, but with an explicit window — useful for "what was my power usage from Jan 1 to Jan 31?" type questions. Aggregated bucket data survives the short-term retention window, so this works for data months/years old. Args: entity_id: The entity (must be statistics-tracked). start_time: ISO-8601 start (`2026-01-01` or `2026-01-01T00:00:00Z`). UTC if no offset. end_time: ISO-8601 end. Defaults to now. period: `5minute`, `hour`, `day`, `week`, or `month`. Returns: `entity_id`, `period`, `start_time`, `end_time`, `statistics`. Examples: get_statistics_range("sensor.energy", "2026-01-01", "2026-02-01", period="day") get_statistics_range("sensor.temperature", "2026-05-01", period="hour")

get_error_loglevelintegrationsearch_termlines

Get the Home Assistant error log for troubleshooting. All filters are optional and combine (AND semantics). Stats (error_count, warning_count, integration_mentions, total_lines) are computed over the filtered output so they match what's returned. Args: level: Filter to lines containing this log level — ERROR, WARNING, INFO, or DEBUG. Case-insensitive. integration: Filter to lines mentioning this integration. Matches `[name]` or `[homeassistant.components.name]`. Case-insensitive. search_term: Case-insensitive substring filter applied per line. Useful for entity IDs, exception names, etc. lines: Return only the most recent N lines (applied after other filters). Useful when you only care about the tail. Returns: A dictionary containing: - log_text: The (possibly filtered) error log text - error_count: Number of ERROR entries in the filtered output - warning_count: Number of WARNING entries in the filtered output - integration_mentions: Map of integration names to mention counts - total_lines: Number of lines in the filtered output - filters_applied: Map of which filter args were supplied - error: Error message if retrieval failed Examples: get_error_log() # full log get_error_log(level="ERROR") # errors only get_error_log(integration="zwave_js") # one integration get_error_log(search_term="light.kitchen") # specific entity get_error_log(level="ERROR", lines=50) # last 50 errors Best Practices: - Filter on the server side (here) rather than pulling the full log into Claude's context — saves tokens on noisy logs. - Combine `integration` + `level="ERROR"` to triage a single integration that's misbehaving. - Use `lines` to bound output when scanning a long-running HA.

Parameters marked with * are required.

Setup

Working configs, one per app.

Copy the block for the app you use. Each one is the configuration this server was verified with.

Claude Desktop

Open the file ~/Library/Application Support/Claude/claude_desktop_config.json (in Claude Desktop: Settings, then Developer, then Edit Config) and add:

{
  "mcpServers": {
    "hass-mcp": {
      "command": "uvx",
      "args": [
        "hass-mcp"
      ],
      "env": {
        "HA_URL": "http://homeassistant.local:8123",
        "HA_TOKEN": "YOUR_LONG_LIVED_TOKEN"
      }
    }
  }
}

Save the file, then quit and reopen Claude Desktop. HA_URL is the address you already open Home Assistant at, port included, and HA_TOKEN is a long-lived access token you create on your own hub. The uvx command comes with uv, the Python package runner this server is published for, so install uv first if your Mac does not have it. The project documents a Docker form of the same entry as well, with command docker and args run, -i, --rm, -e HA_URL, -e HA_TOKEN, voska/hass-mcp, keeping the same env block. [8][4]

Claude Code

One command in your terminal:

claude mcp add hass-mcp -e HA_URL=http://homeassistant.local:8123 -e HA_TOKEN=YOUR_LONG_LIVED_TOKEN -- uvx hass-mcp

Each -e flag sets one environment variable, and everything after the double dash is the exact command Claude Code will run, which is the command we verified. Swap the address for your own hub and the placeholder for your own token. Run claude mcp list afterwards to confirm the server was added. [9][4]

Cursor

Add to ~/.cursor/mcp.json for every project, or to .cursor/mcp.json inside one project:

{
  "mcpServers": {
    "hass-mcp": {
      "command": "uvx",
      "args": [
        "hass-mcp"
      ],
      "env": {
        "HA_URL": "http://homeassistant.local:8123",
        "HA_TOKEN": "YOUR_LONG_LIVED_TOKEN"
      }
    }
  }
}

Cursor picks the file up on restart. Keep the token in the env block rather than in args: args is a command line, and a command line is visible to anything that can list processes on your Mac. A project-level .cursor/mcp.json that you commit to git will carry the token with it, so prefer the file in your home folder. [10][4]

Routines

No JSON file and no terminal, once uv is installed. In Routines: Settings, then Assistant, then Connections, then Add MCP Server. Switch the form to Command (stdio) and enter:

Name        Home Assistant
Command     uvx
Arguments   hass-mcp

Environment Variables
HA_URL      http://homeassistant.local:8123
HA_TOKEN    YOUR_LONG_LIVED_TOKEN

The Arguments field splits on spaces, so keep it to that one word, and put the token in Environment Variables, never in Arguments. Click Test Connection first: a working server answers with its tool count, sixteen for this one. A green test means the server started, not that your hub answered, because this server lists its tools before it contacts anything. Ask the assistant a small read-only question next, such as which version of Home Assistant is running. [11][4]

No terminal needed

Set the Home Assistant MCP server up without the terminal.

If you have never opened Terminal and never want to, this is your path, with one honest exception at the start: this server is a Python package, and the uvx command that runs it comes with uv, which you install once. Everything after that is a form. Routines is a Mac app that runs MCP servers for you: fill in a few fields once, and this server's tools are available to your AI in chat and in scheduled routines.

  1. 01

    Install Routines, then uv

    Download the app from getroutines.ai/download, drag it to Applications, and sign in. Then install uv, the Python package runner that provides the uvx command; if you already use Homebrew, that is the shortest way. Nothing else about Python needs your attention, because uv fetches the interpreter this package asks for the first time it runs, which is Python 3.13 or newer.

  2. 02

    Create a long-lived access token

    Open Home Assistant in a browser and go to Settings, then People, then your own user, then Long-Lived Access Tokens, and create one. Copy it straight away, because Home Assistant shows it once. While you are there, note the address you use to reach Home Assistant, port included, for example http://homeassistant.local:8123.

  3. 03

    Open the MCP settings

    Click your account at the bottom of the sidebar and choose Settings. Open the Assistant section, then the Connections tab, scroll to MCP Servers, and click Add MCP Server.

  4. 04

    Choose Command (stdio) and name it

    Switch the form to Command (stdio): this server is a command your Mac runs, not a web address. Name: Home Assistant. Command: uvx. Arguments: hass-mcp, one word, because the Arguments field splits on spaces.

  5. 05

    Add the two environment variables

    This is the step the server will not work without. Add a row HA_URL with the address you noted, and a row HA_TOKEN with the token you copied. Those two names are exact: nothing else unlocks the hub, and the token belongs here rather than in the Arguments field.

  6. 06

    Test, add, and use it

    Click Test Connection: Routines starts the server and reports how many tools it found, sixteen for this one. Then click Add Server. The tools work in chat right away, and to let a scheduled routine use them, open the routine, find the Tools & connections card, and tick the server under Apps.

Routine ideas

Routines worth scheduling.

Once the server is connected, a scheduled routine can use its tools while you are away. Copy a prompt, paste it into Routines, and pick a time.

A nightly house check

Prompt

Every evening at 22:30, check my Home Assistant for any door or window sensor still reading open and any light still on, and write the list with the room for each one to house-nightly-check.md so I can see what to close before bed.

A weekly energy summary

Prompt

Every Monday at 8:00, pull the last 7 days of daily statistics for my home energy sensor from Home Assistant, and save a short plain-English summary to energy-week.md with the daily numbers, the highest day, and whether usage is going up or down.

A morning hub health note

Prompt

Every morning at 7:30, read my Home Assistant error log filtered to ERROR lines only, and write one short paragraph to home-assistant-health.md naming any integration that keeps failing and how many times it appeared.

Troubleshooting

The errors we hit, and what fixed them.

Real errors captured during the verification run, printed exactly as the server returned them.

Every tool call answers that no token was provided

What you see

No Home Assistant token provided. Please set HA_TOKEN in .env file.

The fix

This server starts and lists all 16 of its tools with no credentials at all, which is how we enumerated them, so a passing connection test proves nothing about your token. The message mentions a .env file because that is how the project runs in development; in an MCP client you set HA_TOKEN in the env block or the Environment Variables rows shown in the setup section above. Create the token in Home Assistant under Settings, then People, then your own user, then Long-Lived Access Tokens, and paste it whole.

The server cannot connect to Home Assistant

What you see

Connection error: Cannot connect to Home Assistant at http://homeassistant.local:8123

The fix

This is the exact reply our own sample call received, because nothing on this Mac or its network answers at that address. You will see the same sentence with your own address in it whenever HA_URL points somewhere your Mac cannot open a connection to: the wrong port, a hub that is switched off, or a machine on another network. Open the same address in a browser on the same Mac first. If Home Assistant loads there, copy that address into HA_URL exactly, port included.

A timeout instead of a connection error

What you see

Timeout error: Home Assistant at http://192.0.2.1:8123 did not respond in time

The fix

We triggered this on purpose with an address no network route can reach. The difference matters: a refused connection comes back immediately, while an address that swallows the request times out instead, which usually means a firewall, a VPN routing your traffic elsewhere, or an address that resolves to something that is not your hub. Try the same address in a browser from the same Mac and see which of the two you get.

An HTTP error instead of a version number

What you see

HTTP error: 404 - Not Found

The fix

The address answered, but not as Home Assistant. We produced this by pointing HA_URL at an ordinary website: the server asked it for /api/config and got a 404 back. The usual causes are an address with a path already on the end, or a reverse proxy that is not forwarding the API. Point HA_URL at the root of your hub with nothing after the port. A wrong or expired token looks different, because that comes back as a 401.

A tool call is refused before it leaves your Mac

What you see

Error executing tool domain_summary_tool: 1 validation error for domain_summary_toolArguments
domain
  Field required [type=missing, input_value={}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.13/v/missing

The fix

The server validates arguments before it does anything, and this is what a missing required argument looks like. We called domain_summary_tool with no domain on purpose. A real client fills these in from the conversation, so if you meet this error, name the thing you meant: which domain, which entity, which area. The same check with the wrong type returns a string_type error instead, and a tool name that does not exist gets a blunter answer, Unknown tool followed by the name you sent.

Your MCP client cannot start the server at all

The fix

The uvx command belongs to uv, the Python package runner this server is published for. If uv is not installed on your Mac, every client on this page fails at the spawn step before the server can say anything. Install uv, restart your MCP client, and try again. The very first start is also the slowest, because uv downloads a Python interpreter and the package before the server answers, so give it a moment before deciding it is broken.

FAQ

Questions people ask.

What is the Home Assistant MCP server?

It is a local bridge between an AI assistant and your Home Assistant hub. The package on this page is hass-mcp, an independent MIT-licensed project by the GitHub developer voska with 312 stars, published to PyPI and started with a single uvx command. It runs as a process on your Mac, talks to your AI app over stdio, and reaches Home Assistant over that hub's own API using an address and a token you supply. Home Assistant itself does not publish it. [1][3][4]

What tools does the Home Assistant MCP server include?

The running server exposed 16 tools, and the table above is that live tools/list output, word for word. They fall into groups: reading state (get_entity, list_entities, get_entities_by_area, search_entities_tool, domain_summary_tool, system_overview), acting on things (entity_action, call_service_tool, restart_ha), automations (list_automations), history and trends (get_history, get_history_range, get_statistics, get_statistics_range), and housekeeping (get_version, get_error_log).

Is it safe to give an AI assistant control of my house?

Read what it can do before you decide. entity_action switches devices on and off, call_service_tool can call any Home Assistant service at all, and restart_ha restarts the hub, which the server's own description flags as disruptive. Your token is the boundary: a long-lived access token carries the permissions of the Home Assistant user who created it, so create it on a user with only the access you are willing to hand over, keep it in the env block rather than on a command line, and delete it in Home Assistant the day you stop using it. Worth being blunt about the limits of this page too: our run never reached a hub, so nothing here demonstrates a device being read or switched. [4]

What credentials does the Home Assistant MCP server need?

Exactly two environment variables, HA_URL and HA_TOKEN, and nothing else: no OAuth screen, no vendor account, no third-party API key. HA_URL is the address you already open Home Assistant at, port included. HA_TOKEN is a long-lived access token you create on your own hub, under Settings, then People, then your user, then Long-Lived Access Tokens. Without the token the server still starts and still lists all 16 tools, which is how the table above was captured, and every call then answers with the missing-token message quoted in the troubleshooting section. [4]

Is this the official Home Assistant MCP server?

No, and the distinction is worth understanding. hass-mcp is a community package your AI client starts on your Mac, which then calls out to your hub. Home Assistant separately ships its own built-in Model Context Protocol Server integration, which works the other way around: you enable it inside Home Assistant, and it exposes the hub itself as a remote MCP server at /api/mcp, surfacing only the entities you have exposed to Assist. If you want a portable bridge you can point any MCP client at, this page is the one. If you already run Home Assistant and want nothing extra installed on your Mac, look at the built-in integration instead. [6][7]

Do I need the terminal to set it up?

Once, to install uv, which provides the uvx command that starts this server. Nothing else about Python is your problem: the package declares Python 3.13 or newer and a console script named hass-mcp, and uv fetches an interpreter that fits on the first run. After that Routines is a form: a name, a command, one argument, two environment variables and a Test Connection button, and the walkthrough above shows every click. Claude Desktop and Cursor each need a small JSON file edited once. Only Claude Code is terminal-first by nature. [5][11][8]

Why does PyPI say 0.5.0 while the server reports 1.29.0?

Both numbers are real and we captured both. The latest hass-mcp release on PyPI is 0.5.0, published 2026-06-23. Over MCP, the running server introduces itself as Hass-MCP 1.29.0, an internal counter the maintainer tracks separately from the release tag. Same code, two numbering schemes, and neither one is a mistake. [1]

Sources

Every external claim, receipted.

Anything on this page we did not observe in the run is linked here, with the date we read it. The run itself is the receipt for the rest.

  1. [1]

    PyPI JSON API: hass-mcpaccessed 2026-08-03

    Latest version 0.5.0, published 2026-06-23.

  2. [2]

    PyPI download stats: hass-mcpaccessed 2026-08-03

    1,257 downloads in the last week, 10,428 in the last month and 154 in the last day at access time.

  3. [3]

    GitHub: voska/hass-mcpaccessed 2026-08-03

    312 stars, a push dated 2026-07-28, MIT license, not archived, 7 open issues, owner voska, per the GitHub API at access time.

  4. [4]

    hass-mcp README (master)accessed 2026-08-03

    Source for the HA_URL and HA_TOKEN environment variables, the client config blocks, the Docker alternative, and the streamable HTTP mode started with uvx hass-mcp --http --port 8000, which binds to 127.0.0.1.

  5. [5]

    hass-mcp pyproject.toml (master)accessed 2026-08-03

    requires-python is >=3.13, the dependency is mcp[cli] >=1.27,<2, and the console script is hass-mcp = "app.run:main", which is what uvx hass-mcp starts.

  6. [6]

    Home Assistant docs: Model Context Protocol Serveraccessed 2026-08-03

    Home Assistant's own built-in integration, which exposes the hub as a remote MCP server at /api/mcp: the opposite direction from hass-mcp.

  7. [7]

    Home Assistant docs: Expose devices to Assistaccessed 2026-08-03

    The exposed-entity list that the built-in MCP Server integration surfaces, and nothing beyond it.

  8. [8]

    modelcontextprotocol.io: Connect to local MCP serversaccessed 2026-08-03

    The claude_desktop_config.json shape and where the file lives on macOS.

  9. [9]

    Claude Code docs: MCPaccessed 2026-08-03

    The claude mcp add syntax for local stdio servers, including the -e flag and the double-dash separator.

  10. [10]

    Cursor docs: Model Context Protocolaccessed 2026-08-03

    The mcp.json shape and file locations.

  11. [11]

    Routines: Connectorsaccessed 2026-08-03

    How Routines runs one-click OAuth connectors and any MCP server.

This page describes Home Assistant as it behaved in one dated run on one Mac. Versions move: if something here no longer matches what you see, the capture date at the top says how old the reading is.

Behind this directory

Routines, the app behind this directory, runs MCP servers like this one without a terminal: see how connectors work. Your notes stay markdown files on your Mac, there is no cloud bill, and it works offline. Download Routines