| Developer: | VTMikel's Plugins Like this plugin? Show your appreciation! |
| Category: | Hubs and Protocol Bridges |
| Github: | Github Repo |
| Assistance: | Get help! |
| Plugin ID: | com.vtmikel.mcp_server |
| Latest release: | v2026.11.2 released on Oct. 30, 2026 |
| Release downloaded: | 14 times |
| Requires: | Indigo v2026.1.0 or higher |
| (Check the Releases tab below for older releases that may have different requirements) | |
| Download latest release |
Indigo 2026.1 has its own MCP server built in, MCP Control. It lets an AI assistant control devices, set variables and run action groups. MCP Advanced Tools is a second MCP server that runs next to it and covers what MCP Control leaves out:
Example questions:
outside"npx mcp-remote: brew install node.The Model preference (default gpt-6-luna) is the OpenAI model used to expand search queries.
Embeddings always use text-embedding-3-large.
Connect your AI client to both servers. Both run on the Indigo Web Server and accept the same key.
| Server | Endpoint path | Use it for |
|---|---|---|
| Indigo MCP Control | /v3/api/mcp |
controlling devices, variables, running action groups/triggers/schedules, listing objects, plugins |
| MCP Advanced Tools | /message/com.vtmikel.mcp_server/mcp/ |
everything listed above |
Key. Send an Indigo API key or a local secret as Authorization: Bearer <key>. Create API keys under
Authorizations in your Indigo Account; local secrets go
in Preferences/secrets.json in your Indigo install folder (see Indigo's
connection guide).
Base URL. Put the endpoint path after one of these (default port 8176):
http://localhost:8176http://<indigo-ip>:8176https://<your-reflector>.indigodomo.netVS Code, Cursor, Claude Code (direct HTTP: .vscode/mcp.json, Cursor's MCP settings,
~/.claude.json or a project .mcp.json):
{
"mcpServers": {
"indigo": {
"type": "http",
"url": "http://localhost:8176/v3/api/mcp",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
},
"indigo-advanced-tools": {
"type": "http",
"url": "http://localhost:8176/message/com.vtmikel.mcp_server/mcp/",
"headers": { "Authorization": "Bearer YOUR_API_KEY" }
}
}
}
Claude Desktop has no direct HTTP support, so it goes through mcp-remote
(~/Library/Application Support/Claude/claude_desktop_config.json). Add one entry per server:
{
"mcpServers": {
"indigo-advanced-tools": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://your-reflector.indigodomo.net/message/com.vtmikel.mcp_server/mcp/",
"--header", "Authorization:Bearer YOUR_API_KEY"
]
}
}
}
For plain HTTP on the LAN, add "--allow-http" to args. For a self-signed HTTPS certificate, add
"env": { "NODE_TLS_REJECT_UNAUTHORIZED": "0" } to the entry.
Transport. The endpoint speaks MCP streamable HTTP: POST only (GET returns 405), no server push.
It serves protocol 2026-07-28 statelessly and the older session-based 2025-11-25 / 2025-06-18
(sessions expire after 2 hours idle).
| You want to… | MCP Control | MCP Advanced Tools |
|---|---|---|
| Control devices, set or create variables | ✓ | — |
| Run an action group, trigger or schedule | ✓ (with confirmation) | — |
| List and look up objects | ✓ published objects | triggers and schedules |
| Find things by meaning ("entryway light" → Foyer Light) | ✓ published objects | ✓ every object |
| See an automation's steps and conditions | ✗ | ✓ |
| "What could change this device?" / "What caused this?" | ✗ | ✓ |
| Search the event log | recent lines | ✓ full history |
| Enable/disable, duplicate, move, delete, rename automations | ✗ | ✓ |
| Read tags | ✓ | ✓ |
| Create, edit, delete and apply tags | ✗ | ✓ |
| Webhooks to your own server | ✗ | ✓ |
| Tools from other plugins | ✗ | ✓ |
list_triggers, list_schedules and query_event_log exist on both servers. This plugin's versions add
trigger summaries, next run times and full log history.Seventeen tools, three more when webhooks are on, plus any plugin-provided tools. List tools page with
limit (default 50, max 500) and offset.
device_types, state_filter and tags (tag_match: all or any). Returns 10 results unless you set
limit.enable / disable (with
duration_seconds to revert automatically, or delay_seconds to start later), duplicate,
move_to_folder, remove_delayed_actions, delete. Action groups support duplicate, move and delete.To run an automation, use MCP Control's execute_trigger, execute_schedule or execute_action_group.
query, regex, types, start_time or end_time it searches the full history.create (name and hex color), update (rename or recolor), delete. Names are
lowercase words joined by dashes (holiday-lighting).add or remove one tag on up to 200 objects of any type (device, variable,
trigger, schedule, action_group, control_page). Each object reports its outcome; dry_run=true
previews.| Setting | Default | Effect |
|---|---|---|
| Allow AI to delete automations | off | Required, with confirm=true, to delete a trigger, schedule or action group |
| Allow AI to delete tags | off | Required, with confirm=true, to delete a tag |
| Confirmation tag | ask-first |
Automations carrying this tag need confirm=true for any change. Empty turns it off |
| Allow plugin-provided tools to make changes | on | Off makes plugin-provided write tools refuse |
Removing a tag from more than 25 objects, or removing or renaming the confirmation tag, also needs
confirm=true.
Other Indigo plugins can add tools to this server. The plugin finds them automatically and lists them under
the provider's prefix, for example autolights_update_zone from
Auto Lights.
Full rules: docs/mcp-provider-manifest.md.
Ship Contents/Resources/mcp-manifest.json:
json
{
"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": []}
}
]
}
Declare a hidden action in Actions.xml and handle it in plugin.py:
xml
<Action id="mcp_tool_invoke" uiPath="hidden">
<Name>MCP Tool Invocation Endpoint</Name>
<CallbackMethod>handle_mcp_tool_invoke</CallbackMethod>
</Action>
python
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}"}})
Optionally, announce your tools from startup() so they register immediately:
python
try:
indigo.server.broadcastToSubscribers("mcp_tools_updated")
except Exception:
pass
Your plugin works the same without MCP Advanced Tools installed.
An event subscription sends an HTTP POST to your own server when a device or variable condition matches — "the next time the front door opens", "if the garage stays open for 10 minutes".
The plugin only sends. It does not work with stock Claude Desktop or other clients that can't receive a webhook; it is meant for agents and automation systems with their own HTTP endpoint.
Turn it on in Plugins → MCP Advanced Tools → Configure → Enable Event Webhooks.
| Parameter | Required | Description |
|---|---|---|
webhook_url |
yes | Your endpoint |
entity_type |
yes | "device" or "variable" |
conditions |
yes | State conditions, combined with AND |
entity_id |
no | One device/variable; omit to watch all of that type |
auth |
no | { "mode": "none"\|"bearer"\|"hmac", "token": "…", "verify_ssl": true } |
duration_seconds |
no | Condition must hold this long before firing |
max_fires |
no | Delete after this many deliveries (1 = one-shot) |
description |
no | Label |
A subscription fires when the state changes into a match, not repeatedly while it stays matched.
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",
)
Match any state key, including plugin states, by value or with an operator:
{ "onState": true }
{ "temperatureInput1": { "gt": 80 }, "onState": true }
Operators: eq, ne, gt, gte, lt, lte, contains, regex. Variables match on value; booleans and
numbers are compared as such. { "any_change": true } fires on every variable change (not combinable with
duration_seconds).
bearer: sends Authorization: Bearer <token>.hmac: sends X-Webhook-Signature: sha256=<HMAC-SHA256(token, body)> and X-Webhook-Timestamp.
python
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 for a self-signed receiver.
A JSON POST with headers X-Event-Id, X-Event-Type and X-Subscription-Id:
{
"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 events use event_type: "variable.value_changed" and entity.kind: "variable".
event_id. Respond with any 2xx.5xx and network errors; a 4xx is not retried.…/Preferences/Plugins/com.vtmikel.mcp_server/subscriptions.json (mode 0600). A pending
duration_seconds wait does not survive a restart.When webhooks are on, http://<indigo-host>:8176/message/com.vtmikel.mcp_server/events_ui/ lists active
subscriptions and lets you remove them. It uses normal Indigo Web Server login. Plugins → MCP Advanced
Tools → Print Event Subscriptions Web UI URL logs the URLs.

Sent to OpenAI to build the search index (stored on your Indigo Mac): names, descriptions, models and types of devices, variables, action groups, triggers and schedules, plus your search queries. Never sent: device states or values, addresses, credentials, URLs, network configuration or history.
Every MCP request needs a key. Use the Indigo Reflector for encrypted remote access.
| Released on: | Oct. 30, 2026 |
| Requires: | Indigo v2026.1.0+ |
| Downloaded: | 14 times |
| Download this release | |
Stable release for Indigo 2026.1.0, now that Indigo 2026.1 is out of beta. Same code as the 2026.11.1 beta. MCP Server is now MCP Advanced Tools, the companion to Indigo MCP Control (the MCP server built into Indigo 2026.1).
What's in it, compared with MCP Server 2026.10.1:
manage_tags creates, renames and recolors tags (deleting needs the Allow AI to delete tags preference and confirm=true); tag_objects puts a tag on, or takes it off, up to 200 objects per call, with a dry run.search_entities, list_triggers and list_schedules take a tags filter (all or any), and every result carries the object's tags. The search index rebuilds once after the upgrade.ask-first) need confirm=true before an AI can enable, disable, edit, move, duplicate or delete them.influxlog_query_history tool (Grafana Home Dashboard 2026.12.1). The InfluxDB settings are gone from this plugin.get_*_details now names the folder of triggers, schedules and action groups.| Released on: | Oct. 14, 2026 |
| Requires: | Indigo v2025.2.0+ |
| Downloaded: | 30 times |
| Download this release | |
search_entities)alarm_enabled.device_types filters before ranking, so limit returns that many devices of the type, and limit/offset page through the full result set with a correct has_more. The default is still 10 results. Above 20 results, devices come back with minimal fields.text-embedding-3-large.gpt-6-luna) is now actually used; earlier versions ignored it. A saved gpt-5-mini moves to gpt-6-luna. These calls use the lowest reasoning effort the model allows, which keeps searches fast.text-embedding-3-large and the model chosen in the plugin config.| Released on: | Oct. 14, 2026 |
| Requires: | Indigo v2025.2.0+ |
| Downloaded: | 28 times |
| Download this release | |
action_execute_group with a delay, and control_trigger / control_schedule / control_action_group with delay_seconds on the execute command, passed a delay argument that Indigo's execute() does not accept, so every delayed run failed with a Boost.Python "did not match C++ signature" error. The delay is now emulated inside the plugin: the reply carries job_id and scheduled_in_seconds, and the item runs once the delay has passed. Because Indigo has no delayed execute for triggers, schedules or action groups, a pending delayed run does not appear in Indigo's UI or event log, cannot be cancelled with remove_delayed_actions, and is lost if the plugin restarts. Immediate executes are unchanged.pandas>=3.0.6,<4, was >=2.3.3,<3). pandas is used only indirectly, by the semantic-search index (LanceDB). Indigo reinstalls the plugin's packages on the first start after the update; this takes a few seconds.Unchanged: Indigo 2025.2 or later on Apple Silicon, and an OpenAI API key for semantic search.
| Released on: | Aug. 29, 2026 |
| Requires: | Indigo v2025.2.0+ |
| Downloaded: | 65 times |
| Download this release | |
Triggers and schedules that use a scripted condition (the "If Python script returns True" option on the Condition tab) were previously invisible to the server: the details tools reported conditions: {type: "none"}, and find_automation_references never saw entities referenced only inside a condition script — so a variable used only there looked unused and safe to delete. Both are fixed (forum request: Expose scripted conditions).
get_trigger_details / get_schedule_details now render a scripted condition as conditions: {type: "scripted"} with the same fields as embedded action scripts: language, script_length, and either the full script_source (truncated over 4000 chars) or just script_first_line when include_scripts is false.find_automation_references now text-scans embedded Python for references. Condition scripts report under the existing condition_reads role; embedded action-step scripts (which were also unscanned before) report under a new script_reference role. Matches are found by known entity id (e.g. indigo.variables[123456789]) and by exact quoted entity name (e.g. indigo.devices["Living Room Sonos"]), and every script match is tagged confidence: "heuristic" with the matched token in detail.investigate_event cause ranking — a script that merely logs an entity's name won't be blamed for a state change.conditions: {type: "unknown", raw: ...} instead of being misreported as none.| Released on: | Aug. 24, 2026 |
| Requires: | Indigo v2025.2.0+ |
| Downloaded: | 74 times |
| Download this release | |
Other Indigo plugins can now contribute their own MCP tools to this server. A provider plugin ships a small JSON manifest in its bundle; this server discovers it automatically, lists the tools to AI clients under the provider's prefix, and forwards calls to the provider over Indigo's native plugin messaging. No configuration is needed on this server, and no MCP protocol knowledge is needed by the provider.
First provider: Auto Lights v2026.8.0, which contributes 15 autolights_* config-authoring tools — AI assistants can now read and edit Auto Lights zones, lighting periods, and settings through validated tools instead of touching its JSON config file.
How it works:
Contents/Resources/mcp-manifest.json. Providers also announce themselves with an mcp_tools_updated broadcast, so their tools register the moment the provider starts or updates, with no MCP Server restart. A Plugins → MCP Server → Rescan Plugin-Provided MCP Tools menu item forces a re-discovery.{prefix}_{name} (e.g. autolights_update_zone). The prefix is enforced by this server (derived from the provider's plugin ID by default) with first-come uniqueness across providers, so tools are always attributable and can never collide with built-ins or each other.automation_gates.json override.With no provider plugins installed, the server behaves exactly as before — the tool set is unchanged and nothing new runs.
For plugin developers: adding tools to your own plugin takes a manifest file, one hidden action, and one broadcast line — see the quick-start in the README and the full provider contract in docs/mcp-provider-manifest.md. Your plugin remains fully functional for users who don't have the MCP Server installed.
ServerApiVersion raised from 3.6 to 3.8 (Indigo 2025.2).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.| Released on: | Aug. 8, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 74 times |
| Download this release | |
First stable release of the 2026.8.0 line, promoting v2026.8.0-beta.1 out of beta.
2026-07-28The server now speaks the stateless "modern era" revision alongside the session-based ones, both concurrently on the same endpoint.
| Revision | Style |
|---|---|
2026-07-28 |
Stateless — no initialize handshake, no session header. Each request carries MCP-Protocol-Version, Mcp-Method (plus Mcp-Name for tools/call, resources/read, prompts/get) and params._meta. |
2025-11-25, 2025-06-18 |
Session-based. Deprecated — support will be removed once clients have migrated. |
analyze_historical_data — answers short-window questionsThe tool could not express "the past 4 hours": time_range_days was validated to 1–365, so the shortest window was a full day, and the output was a per-change duration narrative built for on/off devices with no aggregation anywhere.
time_range_hours (1–8760), taking precedence over time_range_days. Use it for any "last N hours" question.sensorValue.ui state, since Indigo files every sensor reading under the generic sensorValue. On/off and enum devices keep the duration narrative unchanged.search_entities — live device stateResults came from the vector store, which only rewrites a record when an entity's static fields change — so state values froze at whenever the record was last written and could be a year out of date. Each hit is now re-read from the live data provider, preserving search relevance and falling back to the stored record for entities the provider no longer knows. This happens before state filtering, so state_filter matches current values too.
gpt-4, and no longer offers the model field names the device doesn't have — each miss previously cost two wasted InfluxDB round-trips.| Released on: | July 18, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 97 times |
| Download this release | |
The analyze_historical_data tool now works with InfluxDB 3 (Core/Enterprise) via its v1-compatibility API, while InfluxDB 1.8 remains fully supported — same configuration, same code path, no new dependencies.
To use InfluxDB 3: enter an https:// (or http://) URL, your v3 database token as the password (username can be anything), and the database name. That's it — no version selector needed.
https:// InfluxDB URL now actually enables TLS. Previously the scheme was stripped and the client sent plaintext HTTP to the TLS port, failing with errors like 404 page not found. (#49)SHOW DATABASES (admin-only on InfluxDB 3) or the 1.x ping() (incompatible with v3's /ping response). It now uses a database-scoped SHOW MEASUREMENTS LIMIT 1, which also validates auth and database access on both versions. (#49, #50)'list' object has no attribute 'get'). (#51)| Released on: | July 3, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 91 times |
| Download this release | |
Major release: triggers, schedules, and action groups are now first-class citizens of the MCP server. Eight new tools close the gap Indigo's scripting API leaves around understanding and managing automations.
query/regex/types/start_time/end_time and it scans the full historical daily log files instead. One tool, filters optional, consistent {timestamp, type, message} output.duration_seconds auto-revert: "disable this trigger for 2 hours"), execute, duplicate, move to folder, remove delayed actions, delete. Deletion requires confirm=true and the Allow AI to delete automations preference (off by default); every other action is always available.control_trigger, get_schedule_details) rather than one tool with an entity_type parameter — clearer, self-documenting names.confirm=true). Reading, control, and editing are always available.replaceOnServer() preserves action steps and conditions exactly.PluginVersion instead of CFBundleVersion.query_event_log covers both the recent live tail and filtered historical search behind one interface.| Released on: | June 2, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 121 times |
| Download this release | |
Event subscriptions get a management web UI, smarter variable matching, an "any change" trigger, and — most importantly — persistence across restarts.
/message/com.vtmikel.mcp_server/events_ui/ (behind the same auth as the rest of IWS). A new plugin menu item, Print Event Subscriptions Web UI URL, prints the link.conditions={"any_change": true} fires the webhook on every change to a variable's value. Variable-only.{"value": true} never matched (bool ≠ string) and numeric operators like {"value": {"gt": 50}} silently failed. Conditions now coerce booleans and numbers, so these work as expected. The fix is in the shared filter, so it also hardens list_devices / search / get_devices_by_state.…/Preferences/Plugins/com.vtmikel.mcp_server/subscriptions.json) contains your webhook auth tokens — required so authenticated webhooks can re-authenticate after a restart. It is written 0600 inside Indigo's protected app-support directory. Pending dwell timers are not persisted (they re-arm on the next matching transition).Download MCP Server.indigoPlugin.zip below, unzip, and double-click the .indigoPlugin to install (or update in place).
| Released on: | May 1, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 147 times |
| Download this release | |
Dependency bump to fix Indigo 2025.2 (Python 3.13) startup crash.
Impact: - Now requires Indigo 2025.2 or later (Python 3.13) - Apple Silicon only — Intel Mac (x86) is no longer supported (lancedb 0.27+ dropped x86 wheels)
What changed: - lancedb: 0.25.x → 0.30.2 - pyarrow: 23.0.x → 23.0.x (range widened)
| Released on: | March 21, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 137 times |
| Download this release | |
*/* Accept header — Fixes internal server error when MCP clients send Accept: */* instead of application/json.headers key, causing Indigo Web Server to return generic errors instead of proper error details.| Released on: | Jan. 17, 2026 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 136 times |
| Download this release | |
langgraph, langgraph-checkpoint, langgraph-prebuilt, langgraph-sdk (never imported)influxdb-client (code uses legacy 1.x influxdb only)pydantic-settings, python-dotenv, dicttoxmlopenai >=2.15.0 (was >=2.3.0)tiktoken >=0.12.0 (was >=0.11.0)pydantic >=2.12.5 (was >=2.12.2)jinja2 >=3.1.5 (was >=3.1.0)lancedb <0.27.0 (0.26+ deprecates Intel Mac support)langsmith <0.6.0 (0.6+ requires Python 3.10+)matplotlib <4.0.0Full Changelog: https://github.com/mlamoure/indigo-mcp-server/compare/v2025.1.5...v2025.1.6
| Released on: | Dec. 22, 2025 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 129 times |
| Download this release | |
Fixes internal server error when MCP clients send Accept: */* header.
*/* (wildcard) as valid Accept header in addition to application/json and text/event-stream"headers" key to 406 response in mcp_handler.py"headers" key to 500 error response in plugin.pyThe missing "headers" key in error responses caused Indigo Web Server to return a generic "internal server error" instead of the proper error response. Clients like mcp-remote send Accept: */* which was incorrectly rejected.
Related to #5 (investigation ongoing)
| Released on: | Nov. 6, 2025 |
| Requires: | Indigo v2024.2.0+ |
| Downloaded: | 121 times |
| Download this release | |
_restart_mcp_server_from_device() method callsFixes https://github.com/mlamoure/indigo-mcp-server/issues/4