Skip to main content
Glama
misterboe

acinfinity-mcp

by misterboe
README.md
# acinfinity-mcp

[![CI](https://github.com/misterboe/acinfinity-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/misterboe/acinfinity-mcp/actions/workflows/ci.yml)
[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](pyproject.toml)
[![MCP SDK v2](https://img.shields.io/badge/MCP%20SDK-v2-black)](https://py.sdk.modelcontextprotocol.io/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)

MCP server for [AC Infinity](https://acinfinity.com) UIS grow controllers (Controller 69 Pro / Pro+, AI+, Outlet AI).
Lets Claude Code, Claude Desktop, Codex or any other MCP client read your tent's climate and change port settings
through natural language.

> "How is the tent doing?" → 26.5 °C / 57 % / 1.49 kPa, exhaust fan at level 3 driven by automation *Automatisierung 1* …

Uses the same unofficial cloud API as the AC Infinity app, so the controller must be connected to Wi‑Fi
(Bluetooth-only models such as Controller 67 are not supported). Not affiliated with AC Infinity.

## Status

| Area | State |
|------|-------|
| Reading controllers, sensors, port settings, automations | ✅ verified live on a Controller AI+ (CTR89Q) and a 69 Pro |
| Writing port modes / power / timers / triggers | ✅ verified live on the AI+ (mode + timer round trip); standard family follows the Home Assistant integration's proven path |
| Backup / compare / restore of the whole configuration | ✅ ports and automation rules; controller record is reported, not written |
| Renaming ports | ✅ verified live on the AI+ (ports with nothing plugged in are rejected by the controller) |
| Writing advanced settings (calibration, load type, …) | ⚠️ implemented on both families exactly like the app does it (decompiled 2.0.8); not yet exercised on hardware |
| API coverage | ✅ complete — all 179 endpoint declarations of the Android app are inventoried in [`docs/api/app-endpoints.md`](docs/api/app-endpoints.md) |
| Creating / editing automations | 🚧 in-place rule edits and enable/disable are wired (used by restore); create/delete next — see [`docs/api/automations.md`](docs/api/automations.md) |

## Tools

| Tool | What it does |
|------|--------------|
| `list_controllers` | All controllers with `tent` climate (probe: °C / % / kPa), `ambient` climate (AI+ onboard sensor, outside the tent), port status/power/mode and every raw sensor reading |
| `get_port_settings` | Decoded mode configuration of one port: on/off power, auto & VPD triggers, timers, cycle, schedule |
| `get_port_settings_raw` | Unmodified API object incl. advanced settings (`port=0` = controller) |
| `get_device_settings` | Advanced settings (calibration, load type, dynamic response, …) |
| `list_automations` | Advance Automation programs: rules per port with mode, power, time window, days, thresholds — the real configuration on AI+ controllers |
| `get_automations_raw` | Unmodified automation rules + alarms |
| `backup_settings` | Save every port's mode settings, the controller record, all automation rules and alarms to a local JSON file |
| `list_backups` / `compare_backup` | List saved backups; show every field that differs between a backup and the device now |
| `restore_settings` | Write a backup back (changed ports and automation rules), then re-read and report anything still different |
| `rename_port` | Change the port label shown in the app |
| `set_port_mode` | Switch a port to Off / On / Auto / Timer / Cycle / Schedule / VPD / … |
| `set_port_power` | On/off power level 0–10 |
| `set_port_timer` | Countdown to on / to off |
| `set_port_cycle` | Repeating on/off minutes |
| `set_port_schedule` | Daily HH:MM on/off window |
| `set_auto_triggers` | Auto-mode temperature / humidity thresholds |
| `set_vpd_triggers` | VPD-mode thresholds |

Every `set_*` tool refuses to run unless it is called with `user_authorized: true`, so the assistant has to ask you
before touching a device.

## Install

Requires Python ≥ 3.12 and [uv](https://docs.astral.sh/uv/).

```bash
uvx acinfinity-mcp          # once published to PyPI
# or from a checkout:
uv run acinfinity-mcp
```

Credentials are passed as environment variables — the e‑mail and password of your AC Infinity app account:

| Variable | Required | Description |
|----------|----------|-------------|
| `ACINFINITY_EMAIL` | yes | App login e‑mail |
| `ACINFINITY_PASSWORD` | yes | App password (only the first 25 characters are used — that's an API limitation) |
| `ACINFINITY_LOG_LEVEL` | no | `DEBUG`, `INFO` (default), `WARNING`, `ERROR` |
| `ACINFINITY_BACKUP_DIR` | no | Where `backup_settings` stores its JSON files (default `~/.acinfinity-mcp/backups`) |

## Client configuration

### Claude Code

```bash
claude mcp add acinfinity -e ACINFINITY_EMAIL=you@example.com -e ACINFINITY_PASSWORD=secret -- uvx acinfinity-mcp
```

or in `.mcp.json` / `~/.claude.json`:

```json
{
  "mcpServers": {
    "acinfinity": {
      "command": "uvx",
      "args": ["acinfinity-mcp"],
      "env": {
        "ACINFINITY_EMAIL": "you@example.com",
        "ACINFINITY_PASSWORD": "secret"
      }
    }
  }
}
```

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
`%APPDATA%\Claude\claude_desktop_config.json` (Windows). Use an absolute path to `uvx` if it is not on Claude's PATH.

```json
{
  "mcpServers": {
    "acinfinity": {
      "command": "uvx",
      "args": ["acinfinity-mcp"],
      "env": {
        "ACINFINITY_EMAIL": "you@example.com",
        "ACINFINITY_PASSWORD": "secret"
      }
    }
  }
}
```

### OpenAI Codex

`~/.codex/config.toml`:

```toml
[mcp_servers.acinfinity]
command = "uvx"
args = ["acinfinity-mcp"]

[mcp_servers.acinfinity.env]
ACINFINITY_EMAIL = "you@example.com"
ACINFINITY_PASSWORD = "secret"
```

## Development

```bash
uv sync                                        # deps into .venv
cp .env.example .env                           # local creds (git-ignored)
uv run --env-file .env acinfinity-mcp          # run over stdio
uv run --env-file .env mcp dev src/acinfinity_mcp/server.py   # MCP Inspector
uv run pytest                                  # tests (no live API calls)
uv run ruff check . && uv run ruff format .
```

The API is undocumented; everything known about it lives in [`docs/api/`](docs/api/README.md).
Writes are full read‑modify‑write round trips; standard and AI controllers use different endpoints
(see [`docs/api/endpoints.md`](docs/api/endpoints.md)).

## Security

- Your AC Infinity credentials only ever go to `www.acinfinityserver.com` (the same host the app uses) and are never logged.
- Every mutating tool requires `user_authorized: true`; the server never changes a device on its own initiative.
- Tool annotations mark reads as `readOnlyHint` so clients can auto-approve them and prompt for writes.

## Contributing

Issues and PRs are welcome — especially captures from other controller models (Outlet AI, 69 Pro+) and help
decoding the remaining `sensorModeData` fields. Run `uv run pytest` and `uv run ruff check .` before opening a PR;
never include real device ids, MAC addresses or account data in fixtures.

## Credits

API knowledge reverse-engineered from [dalinicus/homeassistant-acinfinity](https://github.com/dalinicus/homeassistant-acinfinity),
[ober37/ac-infinity-mcp](https://github.com/ober37/ac-infinity-mcp) and
[keithah/homebridge-acinfinity](https://github.com/keithah/homebridge-acinfinity).

## License

[MIT](LICENSE)

TDQS

A3.9/5.0

Scored across 18 tools

Disambiguation4/5

Most tools are clearly distinct: list_*, get_*, set_*, and backup/restore operations each target specific resources. The main potential confusion is between get_port_settings_raw and get_device_settings, which both expose raw device data, but the descriptions clarify their different scopes.

Naming Consistency5/5

Tool names follow a consistent verb_noun pattern: list_*, get_*, set_*, backup_settings, restore_settings, compare_backup. The only minor inconsistency is list_backups vs compare_backup (plural vs singular), but this does not hurt predictability.

Tool Count4/5

With 18 tools, the server is slightly above the ideal 3-15 range, but every tool addresses a distinct configuration aspect of AC Infinity controllers. The count feels justified rather than bloated.

Completeness3/5

The set covers reading and writing port modes, timers, schedules, triggers, and backups well. However, there are notable gaps: no create/update/delete operations for automation programs, and no setter for device-level settings (e.g., temperature unit, calibration), limiting full lifecycle management.

Maintenance

ActivityMaintained
ResponsivenessNo issues