Indigo MCP Server Plugin
Enables access to historical device data and trends stored in InfluxDB, allowing queries of past device states and analysis of usage patterns over time.
Uses OpenAI's API for semantic search capabilities by generating embeddings to power vector search functionality, enabling natural language understanding of home automation queries.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Indigo MCP Server Pluginturn off the living room lights"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Indigo MCP Server Plugin
A Model Context Protocol (MCP) server plugin that lets AI assistants like Claude search, understand, and control your Indigo home automation system through natural language.
"Find all light switches in the bedroom"
"What devices are currently on?"
"Turn on the garage lights" / "Execute the bedtime scene"
"What trigger turned off the porch light last night?"
Requirements
Indigo Domotics 2025.2 or later (ships Python 3.13)
macOS 10.15 (Catalina) or later
Apple Silicon (M-series) only — LanceDB 0.30+ no longer ships Intel Mac wheels
OpenAI API key for semantic search (get one). Only device names, types, and descriptions are sent, to generate embeddings (minimal cost) — see Privacy & Security.
Node.js (for Claude Desktop only, which connects via
npx mcp-remote):brew install node
Related MCP server: Hass-MCP
Installation
Install the MCP Server plugin in Indigo via the Plugin Manager.
Enter your OpenAI API key in the plugin's preferences.
Add a new MCP Server device in Indigo (this creates the actual server; one per install).
Wait for the plugin to index your database — the first run takes a while.
Connect an MCP client — see below.
Optional integrations, all off by default:
InfluxDB — required for the
analyze_historical_datatool.Event Webhooks — real-time outbound push notifications; requires a server you run, not stock Claude Desktop. See Event Subscriptions & Webhooks. (v2026.1.0)
LangSmith — AI prompt tracing for debugging; most people don't need it.
Connecting an MCP Client
1. Get an API key
Every connection authenticates with an Indigo API key sent as Authorization: Bearer <key>. Two kinds:
Reflector API key — from your Indigo Reflector settings. Use for remote/HTTPS access.
Local secret — for local/LAN access. Add one to
/Library/Application Support/Perceptive Automation/Indigo <VERSION>/Preferences/secrets.json(format), then restart the Indigo Web Server.
2. Pick your endpoint URL
The endpoint path is always /message/com.vtmikel.mcp_server/mcp/. Choose the base by where you connect
from (default Web Server port is 8176):
Access | Endpoint URL | Key |
Same machine as Indigo |
| Local secret |
Another machine on your LAN |
| Local secret |
Remote (outside your network) |
| Reflector key |
For HTTPS on the LAN with a self-signed certificate, use the https://<indigo-host>:8176/... URL and see
the self-signed note in the client examples below.
3. Configure your client
VS Code, Cursor, Claude Code support direct HTTP transport — simpler and more reliable. Add to your MCP
settings (.vscode/mcp.json, Cursor MCP settings, or ~/.claude.json / project .mcp.json):
{
"mcpServers": {
"indigo": {
"type": "http",
"url": "http://localhost:8176/message/com.vtmikel.mcp_server/mcp/",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
}
}
}Swap the url for the LAN or Reflector variant from the table above.
Claude Desktop does not support direct HTTP, so it proxies through mcp-remote. Add to
~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"indigo": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://your-reflector.indigodomo.net/message/com.vtmikel.mcp_server/mcp/",
"--header", "Authorization:Bearer YOUR_API_KEY"
]
}
}
}Plain HTTP (local/LAN): add
"--allow-http"toargs.Self-signed HTTPS (LAN): add
"env": { "NODE_TLS_REJECT_UNAUTHORIZED": "0" }to the server block.
Why the difference?
mcp-remoterequests OAuth endpoints that Indigo doesn't implement; direct HTTP transport avoids that entirely, so prefer it whenever your client supports it.
HTTP transport notes
The endpoint uses the MCP streamable-HTTP transport over the Indigo Web Server: POST carries all
messages, GET returns 405 (no server→client SSE stream), and sessions expire after 2 hours idle
(current Indigo Web Server versions reject the DELETE teardown before it reaches the plugin).
What's Possible
What the plugin can and can't do with each kind of Indigo entity.
Entity | Read | Create | Edit definition | Control / run | Delete |
Devices | ✓ full — state, properties, model, type, address | ✗ | ✗ | ✓ on/off, brightness, RGB/RGBW color, thermostat setpoints & modes | ✗ |
Variables | ✓ full — value, folder | ✓ | ~ value only | — | ✗ |
Action groups | ✓ full — every action step (scripts, plugin configs) | ✗ | ~ name / description | ✓ execute, duplicate, move | ✓ gated |
Triggers | ✓ full — event, condition tree, action steps | ✗ | ~ name / description, event settings | ✓ enable/disable (timed auto-revert), execute, duplicate, move, remove delayed actions | ✓ gated |
Schedules | ✓ full — timing, next run, condition tree, action steps | ✗ | ~ name / description | ✓ enable/disable (timed auto-revert), execute, duplicate, move, remove delayed actions | ✓ gated |
Legend: ✓ supported · ~ partial (see the cell) · ✗ not possible · — not applicable.
Action steps, conditions, and schedule timing are not editable via MCP — change those in the Indigo UI.
To make a variant: duplicate an automation (
control_trigger/control_schedule/control_action_group,action: "duplicate"), then edit the copy.Delete requires the Allow AI to delete automations preference (off by default) and
confirm=true.
Available Tools
Most list and search tools paginate with limit (default 50, max 500) and offset, and return
total_count / has_more for navigation.
Search and query
search_entities — natural-language search across devices, variables, action groups, triggers, and schedules
list_devices — all devices, with optional state filtering
list_variables / list_variable_folders — variables (with values) and their folders
list_action_groups — action groups / scenes
get_devices_by_state — devices matching state conditions
get_devices_by_type — devices of a type (dimmer, relay, sensor, …)
get_device_by_id / get_variable_by_id / get_action_group_by_id — exact lookups
Automation introspection (v2026.6.0)
Inspect triggers, schedules, and action groups in full — including the action steps and condition trees that Indigo's scripting API does not expose (read from the server's database file, refreshed within minutes of a change).
list_triggers — triggers with a one-line summary of what each watches; filter by name/type/enabled/folder
list_schedules — schedules with next execution time and a timing summary
get_trigger_details / get_schedule_details / get_action_group_details — the full explanation of one automation: its event/timing, condition tree, and every action step (device commands, variable writes, nested action groups, embedded Python, plugin actions with config), IDs resolved to names
find_automation_references — reverse lookup: which automations watch, act on, set, or condition-read a device/variable/action group — including indirect paths through nested action groups, cross-checked against Indigo's own dependency graph
Investigation (v2026.6.0)
investigate_event — "what caused this?" Finds a device's state-change in the log, collects the automations that fired around it, and ranks candidate causes by structural evidence (does it actually act on that device, directly or through action-group chains?) plus temporal proximity.
query_event_log — read the event log, newest first. With no filters it returns the recent tail from Indigo's live log; add
query/regex/types/start_time/end_timeto scan the full historical daily log files instead. Each entry is{timestamp, type, message}.
Automation control (v2026.6.0)
control_trigger / control_schedule / control_action_group — lifecycle actions:
enable/disable(with aduration_secondsauto-revert — "disable this trigger for 2 hours"),execute,duplicate,move_to_folder,remove_delayed_actions, anddelete. (Action groups support execute/duplicate/move/delete only.) Delete requiresconfirm=trueand the Allow AI to delete automations preference (off by default); every other action is always available.update_trigger — edit a trigger's name/description and its event settings (watched device/variable, comparison, value), returning a before/after diff.
update_schedule / update_action_group — edit name/description only.
Action steps, conditions, and schedule timing are read-only in Indigo's scripting API — change those in the
Indigo UI. Since there's no API to author actions from scratch, duplicate (via control_trigger) followed by
update_trigger is the supported way to make a trigger variant.
Device control
device_turn_on / device_turn_off — power state
device_set_brightness — dimmer level (0–100 or 0–1)
device_set_rgb_color / device_set_rgb_percent / device_set_hex_color / device_set_named_color (954 XKCD colors + aliases) / device_set_white_levels — RGB / RGBW control
thermostat_set_heat_setpoint / thermostat_set_cool_setpoint / thermostat_set_hvac_mode / thermostat_set_fan_mode — thermostat control
Variables, actions, and system
variable_create / variable_update — create or update variables
action_execute_group — run an action group / scene
list_plugins / get_plugin_by_id / get_plugin_status / restart_plugin — plugin management
analyze_historical_data — AI analysis of device/variable history (requires InfluxDB)
Event subscriptions (v2026.1.0, only when webhooks are enabled)
create_event_subscription — POST a JSON event to your webhook URL when device/variable conditions match
list_event_subscriptions — active subscriptions with delivery health stats (or one by ID)
delete_event_subscription — delete a subscription (cancels pending dwell timers)
See Event Subscriptions & Webhooks for the full guide.
Event Subscriptions & Webhooks
Added in v2026.1.0. Event subscriptions let an MCP client ask Indigo to notify it the next time something happens — "the next time the front door opens", "if the temperature goes above 80°F", "if the garage door stays open for 10 minutes".
⚠️ This is an outbound webhook — you must run your own server
When a subscription's conditions match, the plugin sends an HTTP POST to a URL you provide. It is a sender only — there is no built-in receiver. This will not work with stock Claude Desktop or most off-the-shelf MCP clients, which have no way to receive a proactive notification. It's meant for custom agents / automation systems that own a persistent HTTP endpoint (for example, OpenClaw).
Enable it under Plugins → MCP Server → Configure → Enable Event Webhooks (the three tools are hidden until then).
Creating a subscription
create_event_subscription accepts:
Parameter | Type | Required | Description |
| string | yes | HTTP(S) endpoint you run that events are POSTed to. |
|
| yes | What kind of entity to watch. |
| object | yes | State conditions that trigger the webhook (see operators below). |
| integer | no | A specific device/variable ID, or omit to watch all entities of that type. |
| object | no |
|
| integer (≥1) | no | Dwell time — the condition must stay matched this long before firing. If it reverts first, nothing is sent. |
| integer (≥1) | no | Auto-delete the subscription after this many successful deliveries. Use |
| string | no | Human-readable label for the subscription. |
A webhook fires on the transition into a matching state (not repeatedly while it stays matched). Multiple conditions are combined with AND.
# Notify me once, the next time the front door opens
create_event_subscription(
webhook_url="https://my-server.example.com/indigo-hook",
entity_type="device", entity_id=12345,
conditions={"onState": True}, max_fires=1,
description="Front door opened",
)
# Alert me if the garage door stays open for 10 minutes
create_event_subscription(
webhook_url="https://my-server.example.com/indigo-hook",
entity_type="device", entity_id=67890,
conditions={"onState": True}, duration_seconds=600,
description="Garage left open",
)Condition operators
Conditions match against device/variable state keys (including third-party plugin states). Use simple equality, or an operator object per key:
{ "onState": true } // equality
{ "brightness": { "gt": 50 } } // single operator
{ "temperatureInput1": { "gt": 80 }, "onState": true } // AND of multiple keysOperator | Meaning |
| equal to / not equal to |
| greater than / greater than or equal |
| less than / less than or equal |
| substring is contained in the value |
| value matches the regular expression |
Variables match on their value key. Indigo stores every value as a string, but booleans and
numbers in your conditions are coerced automatically, so { "value": true }, { "value": { "eq": "open" } },
and { "value": { "gt": 50 } } all work. To fire on every change regardless of the new value, use
{ "any_change": true } — variables only, and not combinable with duration_seconds.
Authentication
Set via the auth parameter; your receiver should validate it so only your Indigo server can post to your
endpoint.
none(default) — no auth headers.bearer— addsAuthorization: Bearer <token>.hmac— addsX-Webhook-Signature: sha256=<hexdigest>(HMAC-SHA256(token, raw_body_bytes)) andX-Webhook-Timestamp: <unix-seconds>. Verify on the receiver:import hmac, hashlib expected = "sha256=" + hmac.new(SECRET.encode(), raw_body, hashlib.sha256).hexdigest() ok = hmac.compare_digest(expected, request.headers["X-Webhook-Signature"])
Set "verify_ssl": false only if your receiver uses a self-signed certificate.
The webhook payload
Each delivery is a POST with Content-Type: application/json, the headers X-Event-Id, X-Event-Type
(device.state_changed | variable.value_changed), and X-Subscription-Id (plus any auth headers), and a
body like:
{
"event_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
"schema_version": "1.0",
"dedupe_key": "indigo:device:12345:state:onState:True",
"source": { "system": "indigo", "plugin": "com.vtmikel.mcp_server", "host": "my-indigo-mac" },
"timestamp": "2026-06-01T15:30:45.123456+00:00",
"event_type": "device.state_changed",
"entity": { "kind": "device", "id": 12345, "name": "Front Door", "device_type": "…" },
"state": { "changed_keys": ["onState"], "old": { "onState": false }, "new": { "onState": true } },
"trigger": { "subscription_id": "…", "conditions_matched": { "onState": true } },
"human": { "title": "Front Door state changed", "summary": "Front Door: onState=true" }
}Variable changes use event_type: "variable.value_changed", entity.kind: "variable", and a state of
{ "changed_keys": ["value"], "old": { "value": "…" }, "new": { "value": "…" } }.
Delivery behavior
At-least-once — retries mean an event can arrive more than once; your receiver must deduplicate by
event_id(ordedupe_key).Retries — up to 4 attempts (1 + 3 retries), 10s timeout each, exponential backoff (~1s/2s/4s), on
5xxand network errors. A4xxis a permanent rejection and is not retried. Success is any2xx— return200promptly.Persisted across restarts — subscriptions are saved (
0600) to…/Preferences/Plugins/com.vtmikel.mcp_server/subscriptions.jsonand reloaded on startup, so they survive restarts and upgrades. The file contains your webhook auth tokens (required so authenticated webhooks can re-authenticate). Pending dwell timers are not persisted — a held condition re-arms on its next matching transition.
Managing subscriptions in a browser (v2026.3.0)
When webhooks are enabled, the plugin serves a page that lists active subscriptions and lets you remove them (create/edit stays with the MCP tools; auth tokens are never shown).

URL:
http://<your-indigo-host>:8176/message/com.vtmikel.mcp_server/events_ui/— served by the Indigo Web Server under the same authentication as the rest of IWS (open it from a browser logged into Indigo).Plugins → MCP Server → Print Event Subscriptions Web UI URL prints the local/LAN/Reflector URLs to the log.
Minimal example receiver
Any HTTPS endpoint reachable from your Indigo host works. A dependency-free Python receiver to test with:
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
# (Optional) verify X-Webhook-Signature here if using HMAC auth.
event = json.loads(body)
# Dedupe by event_id — at-least-once delivery means retries can repeat.
print(f"{event['event_type']} {event['event_id']}: {event['human']['summary']}")
self.send_response(200) # any 2xx = success
self.end_headers()
HTTPServer(("0.0.0.0", 8888), Handler).serve_forever()Tips for Better Results
Be specific — include location and device type in queries.
Use device Notes — descriptions in the Notes field are included in the AI's context.
State vs. search — use
list_devices({"onState": true})for state queries,search_entities("lights")for discovery.
Privacy & Security
Sent to OpenAI (only to generate search embeddings, stored locally on your Indigo server): device name/description/model/type/address, variable name/description, and action-group name/description — sent on install and when entities are added or changed. Never sent: device states or values, credentials, URLs, IP/network configuration, or historical/usage data.
Network — every MCP connection requires Bearer-token authentication. Local HTTP stays on your LAN; use the
Indigo Reflector for encrypted remote access. For self-signed HTTPS on the LAN, set
NODE_TLS_REJECT_UNAUTHORIZED=0 (Claude Desktop) as shown above.
Support
Issues: the project repository
Questions: Indigo Domotics Forum
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mlamoure/indigo-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server