From greenhouse
Talk to a running greenhouse-server over MCP to read sensors (soil moisture, temperature, humidity, light), drive irrigators (start, stop, log manual, emergency stop-all), review typed irrigation decisions, manage the alert inbox, inspect plant health, and tune per-cluster config. Use this skill whenever the user asks anything about their plants, soil, watering, irrigation schedule, sensor readings, irrigator status, blocked drips, leaks, alerts, or plant health — even when they don't say "greenhouse" or "irrigation". Example triggers: "is my monstera thirsty?", "water the living room cluster", "why did it skip the last cycle?", "did anything irrigate last night?", "check my plants", "what's the moisture in the kitchen".
How this skill is triggered — by the user, by Claude, or both
Slash command
/greenhouse:greenhouseThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A smart plant irrigation system. **Tuya Cloud is the live source for sensor data; the local SQLite archive is the permanent record. Actuation is local-only over Tuya protocol v3.5 — never via the Cloud.** This plugin gives you MCP tools that hit the user's running greenhouse-server.
A smart plant irrigation system. Tuya Cloud is the live source for sensor data; the local SQLite archive is the permanent record. Actuation is local-only over Tuya protocol v3.5 — never via the Cloud. This plugin gives you MCP tools that hit the user's running greenhouse-server.
Cluster ─┬─ Plants (1..N) ← species-specific care data drives targets
├─ Sensors (0..N) ← soil moisture / temp / humidity / light
└─ Irrigators (0..1) ← Tuya device, local protocol
│
▼
Decision engine ─→ IrrigationDecision (typed) ─→ DecisionLog (persisted, every eval)
Every check produces one IrrigationDecision with a reasons: list[Reason] trail. Each Reason carries a stable TriggerCode enum (e.g. cooldown, sensor_dry, weather_skip, conflict). The decision is persisted whether or not it actuated — that audit trail is your friend when the user asks "why didn't anything happen?".
Every /api/v1 endpoint on the server is exposed as an MCP tool by fastapi-mcp. You don't need to memorize names — list the tools at the start of the session if you're unsure. Common moves:
| User intent | What to call |
|---|---|
| "Is my plant thirsty?" / "Check status" | clusters/{id}/status or clusters/{id}/monitor |
| "Water cluster X" | clusters/{id}/irrigate (smart pipeline) or irrigators/{id}/start (manual) |
| "Why did it skip / why didn't anything run?" | clusters/{id}/decisions — read primary_code and reason_text |
| "Did the schedule fire?" | clusters/{id}/history + clusters/{id}/decisions |
| "What's wrong?" | alerts inbox (filter by status=open) |
| "I just watered by hand" | irrigators/{id}/log-manual |
| "Show me trends" | clusters/{id}/chart-data or plants/{id}/chart-data |
| "I'll be away next week" | Create a vacation window |
| "How healthy is my monstera?" | plants/{id}/health |
| "Emergency — stop everything" | bulk/stop-all |
For the full surface, list the MCP tools at the start of the session — every /api/v1 endpoint is exposed as one. If you need the raw OpenAPI, the server publishes it at /docs.
The engine enforces several rules. Respect them when reasoning; don't try to bypass them on the user's behalf.
cooldown, that's working as designed. Don't suggest forcing it unless they ask explicitly — and even then, the right move is a manual irrigators/{id}/start call (which the user is consciously taking responsibility for), not a workaround.min_soil_moisture, not the average). When the user has a multi-plant cluster and asks "is the cluster wet?", look at the minimum, not the mean.conflict reason → short 1-minute burst, not a normal cycle. Don't surprised when duration is small in this case.weather_skip and that's correct.alerts to see why.blocked_drip or chronic_underwatering inform; they do not block irrigation.When summarizing decisions, lead with the primary_code and the human-readable reason_text. Don't paraphrase — those codes are stable identifiers the user can search for and the developer documents.
The MCP server is bearer-token authenticated. The plugin's .mcp.json reads two env vars:
GREENHOUSE_SERVER_URL — base URL of the running server, e.g. http://192.168.1.50:8000 or http://localhost:8000.GREENHOUSE_MCP_TOKEN — the bearer token (matches the server's GREENHOUSE_MCP_TOKEN).If tools fail with 401 or 503, the most likely cause is a missing/mismatched token. If the user hasn't set these, point them at the plugin README — don't try to guess the URL.
The bearer token grants physical actuation authority (the server can start/stop real solenoid valves). Treat it like a root credential and never log it.
TriggerCode enum, trust layer, learning engine, confidence scoring, threshold constants. Load when the user asks why the engine did or didn't do something, or when interpreting a DecisionLog. The TriggerCode values returned by MCP tools are stable identifiers — this file is how you turn them into human explanations.greenhouse CLI surface, server URL resolution, JSON-stdout + exit-code contract, common shell workflows. Load when the user asks for a shell command, wants to write a cron / bash script, or when MCP isn't reachable and the CLI is the fallback transport.Don't preload these. The endpoint catalogue isn't here on purpose — the MCP tool list is the source of truth and won't drift, so consult that for "does the server have an endpoint for X?" questions.
clusters/{id}/decisions for the latest evaluation — the engine writes a log row even when it skips. If there's no row in the expected window, the scheduler didn't fire — check health/system and scheduler/jobs.clusters/{id}/stats/export endpoint returns a file, not JSON. If you call it through MCP, expect a blob you'll need to save and tell the user where it landed.Creates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.
npx claudepluginhub giocaizzi/greenhouse --plugin greenhouse