Connect an AI client
ATM exposes an MCP endpoint at /api/atm/mcp. The examples below use Claude Code, but any MCP-capable client connects the same way: a URL and a bearer token.
First time? Use the guided setup
The Quick start walks you through creating a token, granting one device, and testing the connection in a few minutes. This page is the reference for connecting any client by hand, including per-agent commands and the agent skill.
Don't want to install a client?
Agent Chat runs the agent inside the ATM panel using your own Claude, DeepSeek, ChatGPT, Gemini, Grok, MiniMax, OpenRouter, or Ollama account, with nothing to install and the same scoping and approvals. This page is for connecting an external MCP client instead.
The five steps
Create a token
In the ATM panel, open the Tokens tab and click Create Token. Give it a name like claude-code and create it.
Copy it now
The token value is shown exactly once and cannot be retrieved later. Copy it before you close the dialog.
Set its permissions
A new token has no access by default. Use the permission tree to grant the domains, devices, and entities you want the client to work with, and enable any capability flags it needs.
Add the MCP server
Run this in your terminal, substituting your Home Assistant address and the token you copied. ATM derives a distinct server name from each token's name (atm-<token-name>), so a token named claude-code registers as atm-claude-code.
claude mcp add --transport http atm-claude-code \
http://your-ha-address:8123/api/atm/mcp \
--header "Authorization: Bearer atm_your_token_here"
If you reach Home Assistant through Nabu Casa or a custom domain, use that URL instead.
claude mcp add --transport http atm-claude-code \
https://your-instance.ui.nabu.casa/api/atm/mcp \
--header "Authorization: Bearer atm_your_token_here"
This example uses Claude Code's CLI. For Cursor, Codex, Gemini CLI, or any other MCP client, the panel's Connect step generates the ready-made command or config for that agent and links to its own MCP setup docs. Every client needs the same two things: the endpoint ending in /api/atm/mcp and an Authorization: Bearer header carrying your token.
Verify the connection
Start a new Claude Code session and run /mcp. The atm-<token-name> server should show as connected. Ask the client to list your entities or check a light to confirm.
Adding more tokens as separate profiles
Because each token gets its own server name, you can keep several configured in one client at once, one entry per token, all pointing at the same ATM URL with a different bearer token each. To add another, create a second token in the panel, and on the screen shown after it is created choose Connect to an Agent… and run the command it shows, the same way you did for the first. Switch between them by toggling which entry is enabled in the client (in Claude Code, /mcp) instead of clearing and retyping credentials. Enable only one atm-* server at a time: enabling several gives your agent duplicate Home Assistant toolsets with different permissions.
Save each token's command when you first see it
ATM stores only a hash of a token's value, so the panel cannot show a token's config again after you close its creation (or rotation) dialog. If you lose it, rotate the token to get a fresh value and command.
The agent skill optional
You do not have to brief the client yourself. On connection, ATM already sends it a short, token-aware primer (see below) that links to the full guide it can fetch on demand. Installing the skill is an optional extra that loads the complete guidance from the first turn.
The agent skill
The skill is a usage guide for the connected AI. You get it two ways, and you do not have to choose; the primer always ships, the installed skill is extra.
Automatic primer
On every connection, ATM sends a short, token-aware primer in the MCP initialize response. It names which of this token's capabilities are approval-gated and links to the full guide. No install, nothing to maintain.
Installed skill
The full guide is served, unauthenticated, at /api/atm/skill. The Connect step in the panel shows a per-agent install command. For Claude Code it installs as a real skill.
mkdir -p ~/.claude/skills/atm-home-assistant && \
curl -fsSL http://your-ha-address:8123/api/atm/skill \
-o ~/.claude/skills/atm-home-assistant/SKILL.md
Other agents (Cursor, Codex, Gemini CLI, and so on) download the same guide and reference it from their project rules or context file; the panel shows the exact path per agent. The guide is generic and contains no token or entity data.
The skill is advisory only
ATM's permission tree, approval gate, and MESA remain the enforcement regardless of what any connected AI has been told. The skill changes behavior, not access.
Reconnect when the tool list changes
Moving a capability between deny and allow/confirm changes which tools your token can see, so your MCP client must reconnect to pick up the new list. Changing a token's write scope or announce_all_tools also changes the list. Switching a capability between allow and confirm only changes whether a call needs approval; it takes effect on the next call with no reconnect, though some clients still cache tool metadata. In Claude Code, open /mcp and select Reconnect.
Use with Home Assistant Assist and voice
Besides external MCP clients and Agent Chat, you can put ATM behind Home Assistant's own Assist, so a voice or chat conversation runs through one token's scope, MESA safety, approvals, and audit instead of the unscoped default assistant. There are two ways to do this; pick whichever fits. For generating data inside automations rather than driving a conversation, see AI Task below.
Option A: bring your own model
ATM registers a control API named ATM (scoped) that hands its scoped tools to a model an LLM conversation integration already supplies (OpenAI, Google, Anthropic, Ollama, and so on).
- In the ATM panel, open Settings > Assist Tool Provider and choose the Bound token. Only one token can be bound at a time; a least-privilege token (for example the Voice Assistant persona) is recommended.
- In your LLM conversation integration (Settings > Devices & Services), set its Control Home Assistant option to ATM (scoped), then select that agent in Settings > Voice assistants. This applies to LLM-backed conversation agents, not the default template Assist pipeline.
Option B: let ATM be the agent (no external software)
If you would rather not install a separate LLM app, ATM can register itself as a conversation agent and run its own model, using an existing Agent Chat provider account.
- In Settings > Voice Agent (the ATM panel), enable it and pick a token, a provider account, and a model.
- Let ATM set it up for you: on the first enable it offers to create an Assist assistant pointed at ATM (and, if you leave the option on, make it your preferred assistant). Or use Set up ATM assistant in that card any time.
- Prefer to do it by hand? In Settings > Voice assistants, set your assistant's conversation agent to ATM.
Turn off "Prefer handling commands locally"
For either option, open your assistant in Settings > Voice assistants and ensure "Prefer handling commands locally" is off. It is on by default. When this is on, Home Assistant will never reach ATM. Making the ATM assistant your Preferred one is the simplest way to route to it (there is no per-command picker for satellites).
Confirm gates still need a panel approval
Voice has no inline Approve button, so a Confirm-gated action is reported as queued and waits for you to approve it in the ATM panel.
Generate data in automations with AI Task
Home Assistant's AI Task feature lets an automation, script, or dashboard ask an AI model to produce text or structured data on demand, through the ai_task.generate_data action. ATM can be that model: it registers an ATM AI Task entity that runs ATM's own model on a token's scope, so a task reads only what the token can see and every tool call it makes is gated, MESA-checked, and audited like any other.
- In Settings > AI Task (the ATM panel), enable it and pick a token, an Agent Chat provider account, and a model. The ATM AI Task entity appears once all four are set, and disappears again if you disable it or clear one of them.
- Optionally click Set up AI Task to make ATM your default entity for Data generation tasks, so an
ai_task.generate_dataaction that does not name an entity runs through ATM. Home Assistant keeps a single default, so the panel confirms before replacing an existing one. - Point an AI Task action at the ATM AI Task entity by
entity_id, or leave the entity unset to use your default.
Here a example script which asks ATM to summarize the home and shows the answer as a notification. Because the task runs ATM's scoped tool loop, the model looks up the lights itself, within the token's scope, before it writes the sentence:
sequence:
- action: ai_task.generate_data
data:
task_name: home_summary
entity_id: ai_task.atm_ai_task
instructions: >-
Check how many lights are on and reply with one short,
friendly sentence naming a few of them.
response_variable: result
- action: persistent_notification.create
data:
title: Home summary
message: "{{ result.data }}"
Pass a structure to the action and ATM returns a validated JSON object instead of prose (for example { "count": 3, "names": […] }), which an automation can branch on directly.
A confirm-gated task queues for approval
AI Task is not interactive, so if the model calls a Confirm-gated tool the call is reported as queued; you will need to approve it later in the ATM panel. AI Task needs reuses an Agent Chat provider account for its model. Revoking or expiring the token it uses, or deleting that provider account, removes the ATM AI Task entity and clears it as your default.