Skip to main content
Glama
RomanovVIII

ST67 Home Assistant MCP

by RomanovVIII

English · Русский

Studio 67 Home Assistant MCP: local MCP client connected to Home Assistant through REST and WebSocket

ST67 Home Assistant MCP

Control Home Assistant from an MCP client: read device states, call services, and run configuration commands through REST and WebSocket.

A lightweight, open-source Home Assistant MCP server by Studio 67. It runs locally over the Model Context Protocol (MCP), connects to your own Home Assistant on demand, and keeps each installation's configuration separate from the code.

0.2.0 · Node.js 24 · TypeScript · MIT license

Install · Connect your client · Tools · Security and scope · Русская инструкция

What you can do

Your task

How the bridge helps

Check a temperature or device state

Read Home Assistant states over REST

Turn on a light or activate a scene

Call Home Assistant services

Work with the entity registry

Send supported WebSocket commands

Wait for an event during a task

Collect a bounded number of events within one call

Connect more than one home

Run independent processes with separate settings and credentials

Three general-purpose tools cover the API; two additional tools preview and apply bounded Lovelace card edits. REST and WebSocket complement each other; available operations depend on your Home Assistant version, integrations, and token permissions.

There is no background monitoring, persistent subscription, database, web dashboard, or separate daemon. The MCP client starts the local process. API connections open when a tool is called.

Verified: macOS, registration in Codex, the installed STDIO process through an MCP SDK client, HTTPS and secure WebSocket with Home Assistant 2026.9.1, and a real light switched on and off with state read-back. Other MCP clients and Windows/Linux have not been independently tested.

Related MCP server: Home Assistant MCP Server

Installation

You need Node.js 24, npm, access to your Home Assistant, and a token with the permissions required for your tasks. macOS Keychain is supported on macOS. The environment source does not depend on Keychain, but Windows/Linux remain unverified.

Download the repository source, open its directory in Terminal, and run:

npm ci --ignore-scripts --no-audit --no-fund
npm run typecheck
npm test
npm run pack:dry

npm test builds fresh code before running tests. Test data is synthetic; tests need temporary loopback HTTP/WS ports. The TLS test requires OpenSSL and removes its temporary certificate and key. Tests do not read your real Keychain.

For a separate runtime installation, build a package:

npm run build
npm pack --ignore-scripts

Extract st67-home-assistant-mcp-0.2.0.tgz into a separate version directory. Open its package directory and install runtime dependencies:

npm ci --omit=dev --ignore-scripts --no-audit --no-fund

The included npm-shrinkwrap.json pins dependencies for both source and packaged installations. Configure your client to run node with that installation's dist/index.js as its argument. Use an installed copy for everyday operation rather than a changing development checkout.

Running node dist/index.js directly starts a STDIO server waiting for an MCP client; it is not an interactive command prompt. Without configuration it provides local status and returns a clear error for API calls without contacting Home Assistant.

Connect an MCP client

Your client must support local STDIO servers. The following fields were checked against the Codex form; names may differ in other clients. A saved server may require reconnection before its tools appear in the current conversation.

  1. Open your client's MCP settings and add a custom server.

  2. Select STDIO.

  3. Choose a name, for example home-assistant-example.

  4. Set the command to the absolute path to Node.js. On macOS, command -v node shows it; use your platform's equivalent on Windows.

  5. Add the absolute path to the installed dist/index.js as one argument. A path containing spaces must remain one argument, following the client's input format.

  6. Add the nonsecret environment settings below. Do not paste the token into ordinary MCP configuration.

  7. Save and reconnect. Check for ha_status, ha_rest, ha_ws, ha_lovelace_preview, and ha_lovelace_apply; call ha_status first.

  8. With authorization to access your instance, call ha_rest with method: "GET", path: "". This verifies actual authentication; ha_status alone does not validate a token.

A form accepting only a server URL cannot connect to this STDIO implementation. Your Home Assistant URL is not an MCP server URL.

For another Home Assistant instance, create a separate entry with its own URL and credential reference. The Node executable and installed code can be shared; processes and credentials remain independent.

Bounded Lovelace card edits

Version 0.2.0 adds ha_lovelace_preview (read-only) and ha_lovelace_apply (write). They do not change approval policies or replay a rejected action. Review and approve each fresh apply separately; if that review rejects it, stop. The helper does not evaluate JavaScript, templates or arbitrary editing code.

Preview one existing card using explicit operations:

{"dashboard":"example-dashboard","cardPath":["views",0,"sections",1,"cards",0],"operations":[{"op":"replace","path":["name"],"value":"New title"}]}

dashboard: null selects the default dashboard. cardPath starts with views, index, optionally sections, index, then cards, index; nested card and cards, index are allowed. Other dashboard/view/section paths are rejected. Each operation has a nonempty path relative to this one card. replace and remove require an existing element; add requires a missing object property or a valid array insertion index. Parents must already exist. Only add, replace, and remove are accepted; no move, copy, wildcards or code execution. The resulting card must retain a nonempty string type.

Preview returns the complete card before and after, the exact operations, expectedVersion (SHA-256 of the complete canonical dashboard), and previewHash (bound to instance, version, target, operations and card contents). These are content identifiers, not authorization tokens. A preview containing redacted content or exceeding its review budget is refused, never silently shortened. Adjacent cards and global templates are neither returned nor changed.

For apply, copy the same dashboard, cardPath and operations and add the two returned hashes:

{"dashboard":"example-dashboard","cardPath":["views",0,"sections",1,"cards",0],"operations":[{"op":"replace","path":["name"],"value":"New title"}],"expectedVersion":"<expectedVersion from preview>","expectedPreviewHash":"<previewHash from preview>","acknowledgeNonAtomicSave":true}

Replace the explanatory hash placeholders with the actual 64-character hashes. Apply reads the complete dashboard, checks both hashes, reads again immediately before writing, and verifies the complete result afterwards. A stale dashboard is rejected even when another editor changed a neighboring card. Successful output includes verified: true and the resulting version. An explicit HA refusal returns DASHBOARD_SAVE_REJECTED; an uncertain write or failed readback carries resultUnknown: true. Do not retry it automatically or restore old data over a later edit. Inspect the current state before deciding a new action.

Not atomic: Home Assistant's official lovelace/config/save saves the entire dashboard and provides no compare-and-swap/expected-version parameter. Another client can change it between the final read and save; this race can overwrite that change and readback cannot always detect it. Pause other dashboard editors before applying. The required acknowledgement exposes this limitation. The per-dashboard lock covers only this bridge instance, including competing generic save/delete calls; other processes and HA UI are not locked. These helpers do not guarantee conflict-free updates.

Limits: one existing card; at most 16 operations; 32,000 bytes of input; 65,536 UTF-8 JSON bytes each for before/after (64 KiB; conditional on the total review budget); 160,000 bytes for the complete serialized MCP preview; depth 64 and 150,000 JSON nodes. The existing 1 MiB save-request and 2 MiB response limits still apply to the whole dashboard. The total preview is measured after serializing both MCP text and structuredContent, including JSON escaping, operations, hashes and warning fields. A 64 KiB card is not guaranteed to fit: similar-sized before/after alone can exceed 160,000 bytes once duplicated. CARD_TOO_LARGE means an individual card exceeds 64 KiB; PREVIEW_TOO_LARGE means the full review exceeds its independent budget. Nothing is truncated. Input (including apply hashes and acknowledgement) remains capped at 32,000 bytes; the bridge also measures the actual whole-dashboard save request against 1 MiB. These budgets do not guarantee acceptance by a client approval system. A large dashboard with a reviewable card can work, but an oversized card, review or full save is refused. Credentials remain inside the runtime; the token provider and generic tools retain their behavior. YAML-mode saving is not supported by HA.

Validation includes a synthetic dashboard larger than 200 KB, exact preservation of neighboring cards/templates, stale versions and preview tampering, invalid paths, redaction and size limits, save rejection, readback mismatch, disconnect/unknown outcome, competing writes, and end-to-end STDIO preview/apply. Passing tests do not establish visual correctness of a particular dashboard.

Official behavior checked against HA WebSocket handlers and storage dashboard implementation; Context7 did not establish an additional CAS API.

Configuration and credentials

Variable

Purpose

HA_BASE_URL

Root URL such as https://ha.example.invalid; path prefixes, query strings, and embedded credentials are rejected

HA_TOKEN_SOURCE

keychain or environment

HA_KEYCHAIN_SERVICE

Service name of your Keychain item

HA_KEYCHAIN_ACCOUNT

Account name of your Keychain item

HA_TOKEN_ENV_NAME

Name of an already inherited environment variable containing the token, not the token itself

HA_ALLOW_HTTP

Only the exact value true allows unencrypted HTTP/WS; disabled by default

Synthetic macOS example containing no credentials:

HA_BASE_URL=https://ha.example.invalid
HA_TOKEN_SOURCE=keychain
HA_KEYCHAIN_SERVICE=home-assistant-example
HA_KEYCHAIN_ACCOUNT=mcp-example

Create a password item in macOS Keychain using your chosen service/account and enter the token yourself in the application's protected field. The bridge reads that specific item using /usr/bin/security without shell interpolation. It does not create or modify credentials. macOS may require the owner's approval.

Repeated Keychain prompts

ha_status never reads a token. API calls allow up to 10 seconds to retrieve it. Configure access for the system utility before using the bridge; a one-time Allow is not persistent authorization. If Always Allow does not resolve repeated prompts, check the specific item's partition list as well as its trusted applications. Do not broaden permissions for the entire keychain or unrelated items.

Use Keychain Access's protected field for long tokens. On the tested macOS, the interactive security add-generic-password -w input truncated values at 128 characters, making that entry method unsuitable for long Home Assistant tokens. Do not work around it by putting the token in command-line arguments.

SECRET_UNAVAILABLE means credential retrieval failed before the API request. If Home Assistant rejects authentication, stop retries and check the token: repeated failed authentication can trigger an IP ban.

Environment source

Supply the secret through a protected launch environment beforehand. Setting HA_TOKEN_ENV_NAME does not create that variable. A graphical client may not inherit your Terminal environment; verify its behavior during setup.

Do not store a token in .env, JSON, TOML, examples, launch arguments, shell history, or ordinary MCP configuration. The runtime obtains it during an API call; the assistant does not need its value. JavaScript cannot guarantee physical erasure of every in-memory string copy.

Tools

ha_status

Reports the bridge version, whether configuration is valid, the credential source type, and the absence of monitoring. It does not contact Home Assistant or read credentials. Invalid configuration produces a safe error code without exposing values.

ha_rest

Calls a supported method under Home Assistant's /api/:

  • method: GET, HEAD, OPTIONS, POST, PUT, PATCH, or DELETE. Home Assistant determines which method/path combinations are supported.

  • path: relative API path, such as states or services/light/turn_on. Use "" for /api/. Leading slashes, .., fragments, embedded queries, and other hosts are rejected.

  • query: optional array of string pairs; repeated keys are allowed.

  • body: optional JSON value. For text, specify contentType: "text/plain" or "application/yaml"; JSON is the default. GET and HEAD cannot contain a body.

  • allowBinary: defaults to false; enable only when the user explicitly permits returning the particular binary content.

Read a state:

{"method":"GET","path":"states/sensor.example"}

Turn on an explicitly authorized light:

{"method":"POST","path":"services/light/turn_on","body":{"entity_id":"light.example"}}

These entity names are placeholders. Select a real target before issuing a write.

Returns HTTP status, content type, encoding, and data. JSON, text, and small binary responses are supported. Opted-in binary data is returned as base64 with binaryUninspected: true: its contents are not guaranteed to be free of secrets. Literal-token byte checks cannot detect every encoding, compressed secret, or other private value in a container.

ha_ws

Sends a supported Home Assistant command. The bridge owns authentication and request IDs; user-supplied IDs and authentication messages are rejected.

{"command":{"type":"config/entity_registry/list"}}

Each call opens a connection, authenticates, sends one command, receives its result, and closes the socket. Home Assistant errors, result messages, and pong responses are handled explicitly. Some administrative commands require administrator permissions.

To collect events for a particular task, provide a subscription command, eventLimit from 1 to 100, and optionally waitMs from 1 to 30000. The default eventLimit: 0 disables event waiting. When enabled, its default duration is five seconds within the overall call deadline.

{"command":{"type":"subscribe_events","event_type":"state_changed"},"eventLimit":1,"waitMs":5000}

The response includes the command result, events, and completion reason. No events before the deadline is a normal empty result. Interrupted or size-limited event collection is marked incomplete. The connection and subscription end with the call; nothing is retained for a later call.

Limits and failures

  • Maximum request: 1 MiB. Raw response: 2 MiB. Final MCP representation, including duplicated content and JSON escaping: 2 MiB. Oversized output becomes an explicit error.

  • Overall call deadline, including credential retrieval: 30 seconds. WebSocket authentication and Keychain retrieval each allow up to 10 seconds within that deadline.

  • Up to four concurrent API calls per process; a fifth receives BUSY without an unbounded queue.

  • TLS verification is enabled; redirects are rejected. The bridge does not change DNS or network settings.

  • HTTP errors preserve their status. JSON and text are redacted for the known token, Bearer/JWT patterns, and credential fields. This is not universal data-loss prevention or a guarantee against encoded secrets.

  • Raw exceptions, Keychain stderr, authorization headers, and complete responses are not logged. stdout is reserved for MCP.

  • A timeout, cancellation, or disconnect after sending may leave the remote outcome unknown (resultUnknown). Commands are never retried automatically. Read the actual state before retrying a write.

Client shutdown or cancellation closes active connections. A new process does not restore or replay previous commands.

Security and scope

The bridge acts with your token's Home Assistant permissions. It does not bypass roles, sandbox the remote service, or independently provide SSH, operating-system access, arbitrary file access, or Supervisor access. Calling Home Assistant services can change devices and settings; authorization remains the responsibility of the client and user.

REST can control a light; WebSocket can manage entity-registry settings. Creating an entity depends on its integration: there is no universal operation to create any entity. Check version-specific and third-party capabilities separately.

Streaming video, SSE, multipart uploads, binary WebSocket frames, and shared WebSocket sessions across calls are not supported. Supporting both API transports does not imply complete parity with the Home Assistant interface.

Returned data reaches the MCP client and may enter model context and conversation history. The absence of bridge logging does not remove client history. There are no automatic event subscriptions, messages to conversations, or model wakeups.

Updates, rollback, and removal

Install a new version in a separate directory, verify it, then switch the client's launch path. Rollback means selecting a previously verified installed version. The previous 0.1.0 baseline is preserved in GitHub Release v0.1.0 with an installable archive and SHA256SUMS. Keep a verified rollback installation during candidate acceptance; permanent release archives belong on GitHub.

To uninstall, disable and remove the relevant MCP entry, ensure its process has stopped, and remove only the installed copy if no other entry uses it. Deleting the Keychain item and revoking the token are separate user actions. Other installations, source code, and credentials are not removed automatically.

Development and verification

  • src/config.ts, src/secrets.ts: nonsecret settings and lazy token retrieval.

  • src/rest.ts, src/websocket.ts: protocol handling and response limits.

  • src/bridge.ts, src/operation.ts: deadlines, cancellation, concurrency, and cleanup.

  • src/redaction.ts, src/errors.ts: redaction and safe failures.

  • src/lovelace.ts: bounded card preview/apply, canonical hashes, pre-write checks and readback.

  • src/server.ts, src/index.ts: five MCP tools and the STDIO entrypoint.

  • tests/: synthetic protocol servers and tests; no real Home Assistant or Keychain required.

The implementation passed 70 tests covering REST/WS, authentication failures, malformed messages, paths, redirects, TLS, binary opt-in, raw and serialized limits, concurrency, repeated cancellation, isolated instances, 200 sequential WebSocket calls, 1,000 events capped at 100, process shutdown/restart without replay, and MCP SDK calls over STDIO. Clean package installation and independent review were also completed.

Live testing of the installed bridge verified authenticated reading, WebSocket configuration reading, and an authorized light switched on and off with state read-back. Private connection settings and device data are excluded from this repository.

License

MIT, Copyright © 2026 Studio 67. private: true in package.json prevents accidental npm publication; it does not restrict source distribution under MIT. This is an independent Studio 67 project, not an official Home Assistant or OpenAI product.

References

Available Tools

5 tools
ha_lovelace_applyApply a reviewed Lovelace card editA
Destructive

WRITE: apply the exact operations from a fresh, separately approved preview. Requires expectedVersion, expectedPreviewHash and acknowledgeNonAtomicSave=true. Rechecks the WHOLE dashboard before saving and verifies full readback. Home Assistant saves the ENTIRE dashboard and has NO atomic CAS: another editor can race between check and write. Pause other editors. No automatic retry or rollback. Never use to evade an approval rejection; this new write requires its own review.

ParametersJSON Schema
NameRequiredDescriptionDefault
cardPathYes
dashboardYes
operationsYes
expectedVersionYes
expectedPreviewHashYes
acknowledgeNonAtomicSaveYes

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only say readOnly=false and destructiveHint=true, but the description goes far beyond that: it discloses non-atomic save behavior, whole-dashboard rechecking, full readback verification, lack of retry/rollback, and the race risk with other editors. This is exemplary behavioral disclosure for a destructive write tool.

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

Conciseness5/5

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

Every sentence carries operational weight: action type, prerequisites, verification behavior, concurrency hazard, pause instruction, and anti-abuse rule. The critical 'WRITE' signal is front-loaded, and there is no filler or repetition of schema details.

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 destructive, non-idempotent tool with no output schema and minimal annotations, the description fully covers the essential context: what it does, what it requires, what can go wrong, how to mitigate risk, and when not to call it. Nothing needed for safe invocation is missing.

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 description coverage is 0%, so the description must compensate for missing parameter explanations. It explains the meaning and purpose of expectedVersion, expectedPreviewHash, and acknowledgeNonAtomicSave=true, and why they matter for safety. It does not elaborate on cardPath, dashboard, or operations, but those are reasonably clear from the schema structure itself.

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?

The description begins with 'WRITE: apply the exact operations from a fresh, separately approved preview,' naming a specific verb, resource, and workflow stage. It clearly distinguishes this tool from ha_lovelace_preview by focusing on applying, not creating, a reviewed edit.

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?

It explicitly states the prerequisites (expectedVersion, expectedPreviewHash, acknowledgeNonAtomicSave=true), warns to pause other editors due to race conditions, and instructs never to use it to evade an approval rejection. This gives the agent both when-to-use and when-not-to-use guidance.

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

ha_lovelace_previewPreview a bounded Lovelace card editA
Read-onlyIdempotent

Read-only preview: explicit add/replace/remove operations within ONE existing card (max 65,536 UTF-8 JSON bytes; this is not a guaranteed supported size). The complete MCP preview, including both representations and escaping, must fit 160,000 bytes. Returns full before/after, exact operations, a whole-dashboard version and preview hash. No code execution or saving. Refuses truncated or redacted reviews. The hash is a content identifier, not permission to write.

ParametersJSON Schema
NameRequiredDescriptionDefault
cardPathYes
dashboardYes
operationsYes

TDQS

A4.4/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint, destructiveHint:false, idempotentHint:true), the description reveals key behaviors: hard size limits, refusal of truncated/redacted reviews, return of exact operations and whole-dashboard version, and that the hash is not a write permission. This gives the agent critical runtime expectations not encoded in annotations.

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

Conciseness5/5

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

Three dense sentences front-load the most important fact (read-only preview) and every clause earns its place, covering scope, limits, return values, side effects, hash semantics, and refusal behavior. No filler or redundancy.

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

Completeness4/5

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

For a tool with no output schema, the description provides a thorough picture of what is returned and what the tool refuses to do, and it covers safety and size limits. The only notable gap is the lack of parameter-level detail for dashboard and cardPath, which prevents it from being fully self-contained.

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

Parameters3/5

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

With 0% schema description coverage, the description must compensate, and it does add meaning around operations being explicit add/replace/remove within ONE existing card, plus size constraints. However, it does not explain the dashboard parameter (including null usage) or cardPath structure, which are central to calling the tool correctly.

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?

The description clearly identifies a read-only preview for explicit add/replace/remove operations within one existing Lovelace card, with specific return values like before/after and a preview hash. This differentiates it from ha_lovelace_apply and other siblings by focusing on preview semantics rather than mutation.

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

Usage Guidelines4/5

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

The description states this is a read-only preview with no code execution or saving, making it clear it should be used for dry-run/bounded card edits rather than applying changes. It does not explicitly name ha_lovelace_apply as the alternative, but the preview-vs-apply contrast is strongly implied by the sibling set and the wording.

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

ha_restHome Assistant REST APIA
Destructive

Call a supported method under /api/. Path is relative, for example states or services/light/turn_on. Never retries writes. Responses and duration are bounded.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyNo
pathYes
queryNo
methodYes
allowBinaryNoEnable only when the user explicitly authorizes returning this binary content. Its contents cannot be reliably scrubbed for secrets.
contentTypeNo

TDQS

A3.9/5.0
Behavior4/5

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

Beyond the annotations (destructiveHint, openWorldHint, etc.), the description adds important behaviors: 'Never retries writes' and 'Responses and duration are bounded'. These are not present in the annotations and provide meaningful operational guarantees. No contradictions with the annotations.

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

Conciseness5/5

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

The description is brief and front-loaded, with no redundant or filler content. Each sentence adds value: the core action, path semantics, and key behavioral guarantees.

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

Completeness3/5

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

For a generic REST caller, the description provides essential operation and guarantees but lacks guidance on how to structure query parameters or body content. It does not mention error handling, but given the absence of an output schema and the simplicity of the tool, it is reasonably complete, though not fully comprehensive.

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

Parameters3/5

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

Schema description coverage is only 17% (only allowBinary has a description), but the tool description clarifies the 'path' parameter by explaining it is relative to /api/ with examples. Other parameters like query, body, and contentType remain under-explained in both the schema and description, so the description only partially compensates for the low coverage.

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?

The description clearly states the action ('Call a supported method under /api/') and provides concrete path examples ('states', 'services/light/turn_on'). It is easily distinguished from sibling tools ha_status and ha_ws, which are status and websocket-specific.

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

Usage Guidelines3/5

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

The description gives usage context by defining paths as relative to /api/ and showing examples, but it does not explicitly compare with sibling tools or state when to use this REST tool versus ha_ws or ha_status. The warning 'Never retries writes' is a behavioral note rather than a usage directive.

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

ha_statusHome Assistant bridge statusA
Read-onlyIdempotent

Local configuration status only. Does not read credentials or contact Home Assistant.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior4/5

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

Beyond the annotations (readOnly, idempotent, non-destructive), the description explicitly discloses that the tool makes no network calls and avoids sensitive credentials, adding meaningful behavioral context.

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?

The description is brief and direct, using two sentences to convey the essential scope and exclusions without extraneous detail. It is well-structured for quick comprehension.

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

Completeness3/5

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

The description explains what the tool does not do and its local-only nature, but it omits details about the expected output or what 'status' encompasses. Given no output schema, this leaves some uncertainty about the return value.

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?

With zero parameters and full schema coverage (vacuously), the baseline is 4. There is no parameter description needed, and the description adds no conflicting information.

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

Purpose3/5

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

The description states it provides local configuration status, but the exact nature of the status or its output is unspecified. It clearly distinguishes itself from siblings by noting it does not contact Home Assistant, but the core function remains somewhat vague.

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

Usage Guidelines3/5

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

The negative statements ('does not read credentials', 'does not contact Home Assistant') implicitly suggest using this tool for local-only status while delegating remote operations to ha_rest or ha_ws, but no explicit when-to-use guidance is provided.

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

ha_wsHome Assistant WebSocket APIA
Destructive

Send one supported Home Assistant command. The bridge owns authentication and request IDs. Optional bounded event collection stays within this call; the socket always closes afterwards. No monitoring or retries.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitMsNo
commandYes
eventLimitNo

TDQS

A4/5.0
Behavior4/5

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

Annotations already mark destructive/not read-only/non-idempotent; description adds behavior: bridge owns auth/request IDs, optional bounded event collection, socket closes, no retries. No contradiction.

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

Conciseness5/5

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

Two concise sentences; purpose is front-loaded and each clause adds meaningful constraints (auth ownership, bounded collection, socket lifecycle, no retries) without padding.

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

Completeness3/5

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

Covers lifecycle and constraints, but omits command format/examples and waitMs semantics; with no output schema it need not describe return values, but the nested command object is underspecified for a correct call.

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

Parameters2/5

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

Schema has no property descriptions; description only maps 'command' and hints at eventLimit via 'bounded event collection', but leaves waitMs and command structure/format unexplained, so it does not compensate for 0% schema description coverage.

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?

Description uses verb 'Send' and specifies resource 'Home Assistant command', plus 'one' to scope. It distinguishes from siblings ha_status and ha_rest by WebSocket bridge and 'socket always closes'.

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

Usage Guidelines4/5

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

It states 'Send one Home Assistant command' and 'no monitoring or retries', giving negative guidance; 'optional bounded event collection stays within this call' indicates a finite event-collection use. It does not explicitly name ha_status/ha_rest, but the WebSocket/command framing conveys when to choose this over status/REST.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.2.0
    • Addedha_lovelace_apply
    • Addedha_lovelace_preview
  2. 3 tool updatesv0.1.0
    • First observedha_rest
    • First observedha_status
    • First observedha_ws

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool occupies a distinct role: Lovelace preview and apply split read-only planning from approved writes, while ha_rest and ha_ws are clearly separated by protocol and ha_status is local-only. No two tools appear interchangeable, and the constraints in each description reinforce the boundary.

Naming Consistency4/5

All tools share the ha_ prefix and snake_case, and the Lovelace pair uses verb-like preview/apply. ha_rest, ha_ws, and ha_status are protocol/resource nouns rather than verb_noun actions, so the pattern is consistent but not a strict action-oriented convention.

Tool Count5/5

Five tools is a compact, appropriate surface for a Home Assistant bridge: two for Lovelace lifecycle, two generic protocol access points, and one status check. Nothing feels redundant or missing at the count level.

Completeness5/5

The generic ha_rest and ha_ws tools give broad coverage of Home Assistant's API surface, while ha_lovelace_preview/apply provide a safe complete edit workflow for dashboards. A local status check rounds out the set, leaving no obvious dead ends for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers