Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Indigo

БесплатноНе проверен

A MCP server for Indigo Home Automation System

GitHubEmbed

Описание

A MCP server for Indigo Home Automation System

README

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

Installation

  1. Install the MCP Server plugin in Indigo via the Plugin Manager.
  2. Enter your OpenAI API key in the plugin's preferences.
  3. Add a new MCP Server device in Indigo (this creates the actual server; one per install).
  4. Wait for the plugin to index your database — the first run takes a while.
  5. Connect an MCP client — see below.

Optional integrations, all off by default:

  • InfluxDB — required for the analyze_historical_data tool. Works with InfluxDB 1.x and InfluxDB 3 (via its v1-compatibility API): use an https:// URL to enable TLS, and for v3 enter a database token as the password (the username is ignored by v3).
  • 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 http://localhost:8176/message/com.vtmikel.mcp_server/mcp/ Local secret
Another machine on your LAN http://<indigo-ip>:8176/message/com.vtmikel.mcp_server/mcp/ Local secret
Remote (outside your network) https://<your-reflector>.indigodomo.net/message/com.vtmikel.mcp_server/mcp/ 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" to args.
  • Self-signed HTTPS (LAN): add "env": { "NODE_TLS_REJECT_UNAUTHORIZED": "0" } to the server block.

Why the difference? mcp-remote requests 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 and GET returns 405 (no server→client SSE stream).

Supported protocol revisions (both served concurrently on the same endpoint):

Revision Style Notes
2026-07-28 Stateless ("modern") Per-request _meta metadata, MCP-Protocol-Version / Mcp-Method / Mcp-Name headers, server/discover. No sessions.
2025-11-25, 2025-06-18 Session-based ("legacy") initialize handshake + Mcp-Session-Id header; sessions expire after 2 hours idle (current Indigo Web Server versions reject the DELETE teardown before it reaches the plugin). Deprecated — legacy support will be removed in a future release once MCP clients have migrated to 2026-07-28.

A request carrying the modern per-request metadata is served statelessly; an initialize request selects the legacy session flow. Server-push features (subscriptions/listen, listChanged notifications) are not offered — Indigo Web Server plugin responses are one-shot, so there is no SSE channel to deliver them on. Origin-header validation is likewise not enforced: the Indigo Web Server authenticates every request before the plugin sees it, which already defeats DNS rebinding.

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 variable_create ~ 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 (or embedded Python condition script), 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, heuristic id/name matches inside embedded Python (condition scripts and action scripts), 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_time to 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 a duration_seconds auto-revert — "disable this trigger for 2 hours"), execute, duplicate, move_to_folder, remove_delayed_actions, and delete. (Action groups support execute/duplicate/move/delete only.) Delete requires confirm=true and 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). Pass time_range_hours for "last N hours" questions; time_range_days cannot express windows shorter than a day. Numeric sensors also get a current/min/max/mean/trend summary, and a warning when the value never moved during the window — usually the sign of a sensor that has stopped reporting.

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.

Plugin-Provided Tools (v2026.8.1)

Other Indigo plugins can contribute their own MCP tools to this server. A provider plugin ships a small manifest in its bundle; this server discovers it automatically, lists the tools to AI clients under the provider's prefix (e.g. autolights_update_zone from the Auto Lights plugin), and forwards calls to the provider. No configuration is needed on this server.

  • Write gate: the plugin config checkbox "Allow plugin-provided tools to make changes" (default on) controls whether provider write tools work; read tools always do. Takes effect immediately.
  • Refresh: provider tools register automatically when the provider starts or updates. The menu item Plugins → MCP Server → Rescan Plugin-Provided MCP Tools forces a re-discovery.
  • Client cache caveat: tools/list responses carry a 1-hour cache hint, so an already-connected MCP client may not see newly installed provider tools until it starts a fresh session.

Add MCP tools to your plugin

Three steps — full details and rules in docs/mcp-provider-manifest.md:

1. Ship a manifest at Contents/Resources/mcp-manifest.json describing your tools:

{
  "manifest_version": 1,
  "provider": {"plugin_id": "com.example.myplugin", "display_name": "My Plugin"},
  "tools": [
    {
      "name": "get_status",
      "description": "Return the plugin's current status.",
      "write": false,
      "inputSchema": {"type": "object", "properties": {}, "required": []}
    }
  ]
}

2. Answer tool calls — declare a hidden action in Actions.xml:

<Action id="mcp_tool_invoke" uiPath="hidden">
    <Name>MCP Tool Invocation Endpoint</Name>
    <CallbackMethod>handle_mcp_tool_invoke</CallbackMethod>
</Action>

and implement the callback in plugin.py (arguments arrive as a JSON string; reply with a JSON-string envelope):

def handle_mcp_tool_invoke(self, action, dev=None, caller_waiting_for_result=True):
    import json
    tool = action.props.get("tool", "")
    args = json.loads(action.props.get("arguments", "{}"))
    if tool == "get_status":
        return json.dumps({"status": "ok", "result": {"state": "running"}})
    return json.dumps({"status": "error",
                       "error": {"type": "not_found", "message": f"unknown tool {tool}"}})

3. Announce yourself (recommended) — one line in your startup() so your tools register the moment your plugin starts, without an MCP Server restart:

try:
    indigo.server.broadcastToSubscribers("mcp_tools_updated")
except Exception:
    pass

Your plugin stays fully functional for users who don't have the MCP Server installed — the manifest is inert data, the hidden action is never called, and the broadcast is a no-op.

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
webhook_url string yes HTTP(S) endpoint you run that events are POSTed to.
entity_type "device" | "variable" yes What kind of entity to watch.
conditions object yes State conditions that trigger the webhook (see operators below).
entity_id integer no A specific device/variable ID, or omit to watch all entities of that type.
auth object no { "mode": "none"|"bearer"|"hmac", "token": "…", "verify_ssl": true } (see Authentication).
duration_seconds integer (≥1) no Dwell time — the condition must stay matched this long before firing. If it reverts first, nothing is sent.
max_fires integer (≥1) no Auto-delete the subscription after this many successful deliveries. Use 1 for a one-shot notification. Omit for unlimited.
description 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 keys
Operator Meaning
eq / ne equal to / not equal to
gt / gte greater than / greater than or equal
lt / lte less than / less than or equal
contains substring is contained in the value
regex 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 — adds Authorization: Bearer <token>.

  • hmac — adds X-Webhook-Signature: sha256=<hexdigest> (HMAC-SHA256(token, raw_body_bytes)) and X-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 (or dedupe_key).
  • Retries — up to 4 attempts (1 + 3 retries), 10s timeout each, exponential backoff (~1s/2s/4s), on 5xx and network errors. A 4xx is a permanent rejection and is not retried. Success is any 2xx — return 200 promptly.
  • Persisted across restarts — subscriptions are saved (0600) to …/Preferences/Plugins/com.vtmikel.mcp_server/subscriptions.json and 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).

Event Subscriptions web UI

  • 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

from github.com/mlamoure/indigo-mcp-server

Установка Indigo

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/mlamoure/indigo-mcp-server

FAQ

Indigo MCP бесплатный?

Да, Indigo MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Indigo?

Нет, Indigo работает без API-ключей и переменных окружения.

Indigo — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Indigo в Claude Desktop, Claude Code или Cursor?

Открой Indigo на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Indigo with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development