Skip to main content
Glama
README.md
# otolawn-mcp

A Model Context Protocol (MCP) server for [OtO Lawn](https://otolawn.com) smart sprinkler
devices. Control your OtO zones from any MCP client (Claude, Cursor, etc.):

- List devices, zones, and schedules
- Start / stop watering on demand, with a water depth or runtime you choose
- Enable/disable zones, rename them, change their scheduled water amounts
- Browse irrigation event history (what ran, when, how much water, errors)
- Enable/disable watering schedules
- Read the weather data OtO uses for rain/wind skipping, device diagnostics, battery
  history and notification messages

The protocol was reverse-engineered from the OtO mobile app (v4.0.8, Android build
`com.oto`). See [docs/API.md](docs/API.md) for the full API reference. This is an
independent personal-use interoperability project - it is not affiliated with or
endorsed by OtO Inc. Trademarks belong to their owners.

```text
This project talks to YOUR devices with YOUR credentials.
```

## How it works

```text
MCP client (Claude, etc.)
    |  (stdio JSON-RPC)
    v
otolawn-mcp server  ──► Firebase Auth (email/password sign-in)  ─► ID token
    |                  https://oto-cloud-service-ems-prod-*.run.app API
    v                  (Bearer ID-token auth)
OtO sprinkler device(s), polled by OtO's cloud
```

- Authentication uses the same Firebase auth endpoint the app uses, with an embedded
  app API key (public information, shipped inside the distributed app).
- The ID token is cached in memory and refreshed automatically (tokens last ~1 hour).
- Manual start/stop are executed via the same schedule-execution endpoints the app
  uses; the physical device picks up the change within ~1-2 minutes.

## Install

Requires Python 3.11+.

```bash
git clone https://github.com/DmitriyAlergant/otolawn-mcp
cd otolawn-mcp
python -m venv .venv
uv pip install -e .        # or: .venv/bin/pip install -e .
```

## Configure credentials

```bash
export OTO_EMAIL="you@example.com"
export OTO_PASSWORD="your-oto-app-password"
```

These are the same email/password you use in the OtO mobile app.

## Tool call contract

All tools return flat JSON blobs:

```json
{"ok": true , "...": "payload"}
{"ok": false, "error": "description on failure"}
```

Water depths are millimetres (`wateringQuantity` at the API level). Runtimes and
water depth are related by a per-zone calibration curve (`timeToWater_form`);
`water_zone` accepts either.

## Available tools

| Tool | Description |
|---|---|
| `list_devices` | Devices with name + winter mode |
| `get_device_status` | Live hardware status: battery mA/V, charge state, comm info |
| `get_battery_history` | Daily battery level history |
| `get_device_logs` | Device event log (watering starts/stops, errors) |
| `list_zones` / `get_zone` | Zones with water amount, enabled, days, rain/wind skips |
| `set_zone_enabled` | Enable / disable a zone |
| `rename_zone` | Rename a zone |
| `set_zone_watering` | Change a zone's scheduled water depth or runtime |
| `water_zone` | **Start watering now** (returns `scheduleId`) |
| `stop_watering` | Stop a manual run by `scheduleId` |
| `list_events` | Irrigation events (scheduled run instances) with statuses |
| `cancel_event` | Cancel an event, or un-cancel a rain-skipped one |
| `list_routines` / `set_routine_enabled` | Watering schedules (routines) |
| `get_weather` | Weather used by the rain/wind intelligence |
| `list_messages` | Account messages |
| `add_zone` | Create an unconfigured zone (path calibration still needs the app) |
| `delete_zone` | Delete a zone |

## Example

```text
You:    "Water the Front Lawn Far zone about 3 mm, then tell me how much it ran."
Claude: calls list_zones() ─► finds zone "Front Lawn Far"
        calls water_zone(device_id, zone_id, water_depth_mm=3)
        calls list_events(only_active=true) ...
        calls stop_watering(scheduleId) when done (or lets it finish)
```

## Registering with Claude Code / other clients

`claude mcp add otolawn -- <repo>/venv/bin/otolawn-mcp` (with creds in env), or
in `mcp.json`:

```json
{
  "mcpServers": {
    "otolawn": {
      "command": "/path/to/otolawn-mcp/.venv/bin/otolawn-mcp",
      "env": { "OTO_EMAIL": "you@example.com", "OTO_PASSWORD": "..." }
    }
  }
}
```

## Safety notes

- `water_zone` triggers real watering within a minute or so.
- A stopped `water_zone` run may still have briefly spawned a run - the device
  applies commands on its next poll, so stopping immediately after starting is
  also handled (event ends up `USER_STOPPED`).
- Rain/wind intelligence is not bypassed by manual starts; use large-enough depth
  if you expect the forecast to interfere.
- Deleting zones or devices cannot easily be undone.

## Repo contents

- `src/otolawn_mcp/client.py` - OtO cloud API client (auth, zones, events, control)
- `src/otolawn_mcp/server.py` - MCP tool surface
- `docs/API.md` - the full reverse-engineered API reference

## Disclaimer

This is an unofficial, independent interoperability implementation, not affiliated
with OtO Inc. Endpoints may change without notice. Use at your own risk. Be mindful
of local water-use rules and of what you commit to a public repo :).

MIT licensed. See [LICENSE](LICENSE).

TDQS

A3.5/5.0

Scored across 19 tools

Disambiguation4/5

Most tools target clearly distinct resources and actions (zones vs routines vs events vs devices). A few pairs could be momentarily confused—cancel_event vs stop_watering, and water_zone (manual) vs set_zone_watering (scheduled amount)—but the descriptions explicitly clarify the manual/scheduled distinction.

Naming Consistency5/5

Every tool follows a consistent snake_case verb_noun pattern (list_zones, get_zone, set_zone_enabled, water_zone, cancel_event, etc.). No mixed conventions or vague verbs appear.

Tool Count4/5

19 tools is on the heavier side but the domain is genuinely broad (zones, routines, events, devices, weather, messages), and each tool maps to a distinct operation. Slightly heavy but not bloated.

Completeness4/5

Zones have full lifecycle coverage (add/get/list/rename/enable/delete/set-watering) and devices/events are well covered. The main gap is routines: they can only be listed and enabled/disabled, with no create/edit, though zone-level scheduling partially compensates.

Maintenance

ActivityMaintained
ResponsivenessNo issues