---
name: lutin
description: Connect an AI agent to Lutin over MCP, then read and manage smart-home lights, rooms, houses, and saved one-tap light states with the user's approval.
version: 1.0.0
metadata:
  tags: [lutin, smart-home, lights, hue, mcp, ai-agent, home-automation]
  homepage: https://lutin.one
  app: https://app.lutin.one
  mcp_endpoint: https://app.lutin.one/mcp
---

# Lutin Agent Guide

Use this guide when a user asks you to connect to **Lutin** or gives you a link to `https://lutin.one`.

Lutin is a simple smart-home light control app. It holds named one-tap light states called **presses**, serves a PWA button board for the household, and exposes an MCP server so agents can help set up rooms, lights, and presses conversationally. Philips Hue is the first supported vendor.

Core product rules:

- Presses are saved light states for a house: a name, an icon/glyph, and one or more lamp assignments.
- A house can have multiple members. Each connected agent belongs to one member, not to the house as a shared super-user.
- Agents should be helpful but literal: read real state when available, and say clearly when a lamp, bridge, vendor, or house is unreachable.
- Reachability is an affordance, not a moral judgment. A lamp may be off at the wall, asleep, or temporarily unreachable.
- Do not invent sensors, schedules, routines, automations, scenes, or device capabilities that Lutin did not report.
- Keep wording plain and house-friendly.

## Connection

Canonical app URL:

```text
https://app.lutin.one
```

MCP endpoint:

```text
https://app.lutin.one/mcp
```

If your runtime supports remote MCP servers, configure Lutin as a remote HTTP / streamable HTTP MCP server using that endpoint.

Example generic MCP configuration:

```json
{
  "mcpServers": {
    "lutin": {
      "url": "https://app.lutin.one/mcp"
    }
  }
}
```

Example Hermes configuration:

```yaml
mcp_servers:
  lutin:
    url: "https://app.lutin.one/mcp"
```

After configuring a new MCP server, restart or reload the agent runtime if needed so it can discover the Lutin tools.

## Authentication and pairing

The user may say something like:

> Connect to Lutin. I registered with `user@example.com`.

Use that email only as the routing hint for the approval request. Do **not** ask the user for their password, one-time login code, API key, bearer token, session token, Hue credentials, or any server secret.

Lutin uses user-approved agent pairing:

1. Start a pairing request for the user's registered email, your agent name, and the minimum scope needed.
2. Give the user the returned approval link if your runtime does not open it automatically.
3. Keep the device code/private polling value out of chat and logs.
4. Poll until the user approves or denies the request.
5. Store the returned agent token only in your runtime's normal secure MCP/credential storage.
6. Verify the connection with a harmless read such as `get_app_info`, `list_houses`, or `list_presses`. Do not change a real light just to test the connection unless the user explicitly asks.

## Access levels

Lutin has two agent access levels.

**Use** access lets an agent inspect the home and press existing saved buttons/presses. Use agents can list houses, rooms, lights, and presses; read current light state; and activate or toggle a visible saved press. They cannot directly set arbitrary lights or change the setup.

**Manage** access includes Use plus direct light/room control and setup changes. Manage agents can create, capture, edit, delete, and share presses; identify and rename lights; and perform other configuration actions when the user asks.

When in doubt: Use operates the existing button board. Manage changes it or bypasses it.

Access levels:

- `use` — use when the user wants you to inspect the home and press existing saved buttons/presses. Use access can read houses, rooms, lights, current state, and presses, and can call `press` on an existing visible press. It cannot directly set arbitrary lights, create/edit/delete presses, rename lights, identify lights, or change setup.
- `manage` — use when the user wants you to directly control lights or change setup. Manage access includes Use plus direct light/room control, creating/capturing/editing/deleting presses, identifying/renaming lights, and other setup/configuration actions.

If your MCP client has its own authorization flow, prefer that. If it does not, use Lutin's device-pairing API:

```text
POST https://app.lutin.one/api/v1/auth/device/start
{
  "email": "user@example.com",
  "agentName": "Your agent name",
  "scope": "use"
}
```

or request Manage access only when appropriate:

```text
POST https://app.lutin.one/api/v1/auth/device/start
{
  "email": "user@example.com",
  "agentName": "Your agent name",
  "scope": "manage"
}
```

Then poll privately with the returned `deviceCode`:

```text
POST https://app.lutin.one/api/v1/auth/device/poll
{
  "deviceCode": "..."
}
```

When polling returns `approved`, use the returned token for the Lutin MCP connection or API calls according to your runtime's credential model. Treat it as a secret. Never show it to the user unless the user is deliberately managing credentials.

## What agents can do

Use access:

- Get app/tool information, auth scope, available houses, palette, assignment schema, and recommended workflow with `get_app_info`.
- List houses the user belongs to with light/press counts, role, Hue connection status, and reachability summary.
- List rooms in a house.
- List lights, optionally filtered by room.
- Read current live state for selected lights or a room.
- List saved presses, including whether each press is currently active.
- Validate a proposed press assignment before saving it. Validation does not save anything; saving via `define_press` requires Manage access.
- Press a saved press by id, exact name, slug, or a short unambiguous word subset of its name.

Manage access, with user intent:

- Identify a physical lamp by blinking it once.
- Rename a light after the user confirms which physical lamp it is.
- Set one lamp immediately with `set_light`.
- Set a room immediately with `set_room`.
- Define or update a saved press from explicit assignments.
- Capture current live lamp state as a saved press.
- Delete a press when the user clearly asks for it.

Routine agent access should not delete or overwrite user-created presses casually. For destructive or broad changes, identify the exact house/light/press first and get clear confirmation.

## Lutin vocabulary

Use Lutin's product words consistently:

- **House** — the shared home context where members, lights, and presses live.
- **Room** — a vendor/Hue group such as Kitchen or Master bedroom.
- **Light** or **lamp** — an individual controllable Hue light.
- **Press** — a saved one-tap light state. Do not call it a task, routine, automation, or generic scene unless the user does.
- **Shared press** — a press visible to other house members.
- **Connected agent** — an agent token approved by a member.

Preferred wording:

- "press" or "saved press" instead of "automation"
- "light state" instead of "program"
- "bridge unreachable" instead of "all lights are broken"
- "I couldn't reach that lamp" instead of "the lamp failed"
- "N lights in Lutin" rather than "all reachable" unless actual health data says so

## House selection

Most tools accept an optional `house_id`.

- If the user belongs to exactly one house, tools can usually omit `house_id`.
- If the user belongs to multiple houses, call `get_app_info` or `list_houses`, show the options, and ask which house to use.
- Never guess a house when a write would affect real lights.
- Paused memberships are intentionally not actionable for agents. If a house is unavailable because membership is paused, say that clearly rather than treating it as an empty house.

## Safe operating pattern

For first connection:

1. Call `get_app_info`.
2. Note the auth scope and whether the user has one or multiple houses.
3. If needed, ask the user which house to work in.
4. Verify with a harmless read such as `list_presses`, `list_rooms`, or `list_lights`.
5. Do not create, edit, delete, or press anything just to test write access unless the user explicitly asks.

For reads:

1. Use MCP tools when available.
2. Return a short, practical summary.
3. Preserve uncertainty: if Lutin reports unknown or unreachable state, say so.

For writes:

1. Confirm you have manage access or request it.
2. Identify the exact house, room, light, or press before mutating anything.
3. Make the smallest change that satisfies the user's request.
4. Verify by reading the relevant light/press/list back when useful.
5. Report the result briefly.

Example final responses:

```text
Done — set the bedroom lamps to warm white at 35%.
```

```text
Done — saved "Movie night" as a press for the living room.
```

```text
I found two matching presses: "Evening red" and "Bedroom evening red". Which one should I press?
```

```text
I can see the house, but Hue is currently unreachable, so I can't confirm the lamps' live state yet.
```

## Setting lights and rooms

Use `set_light` for a one-off change to a single lamp.

Use `set_room` for a one-off change to every lamp in a room.

Both can take:

- `on`: `true` or `false`
- `brightness`: number from `0` to `100`
- `color`: a palette name string, or a structured color object such as `{ "name": "warm white" }`, `{ "hex": "#ff3300" }`, `{ "mirek": 250 }`, or `{ "xy": { "x": 0.5, "y": 0.4 } }`

Important:

- `set_light` and `set_room` are live preview/tuning operations. They do **not** save a press.
- The response includes an `assignment` object. Reuse that assignment in `define_press` if the user wants to save the look.
- If the user asks for a vague color such as "nice evening light," use `get_app_info` to inspect the palette and choose a conservative named color.
- Do not claim the room is in a saved press state just because you used `set_light` or `set_room`.

## Presses

A press is a saved light state.

Use `list_presses` before pressing or editing if you do not already have a precise id/name.

Use `press` to activate or toggle a saved press. It accepts:

- exact press id
- exact press name, case-insensitive
- slug form such as `bedroom-day`
- an unambiguous subset of name words, such as `evening red`

If multiple presses match, do not guess. Present candidates and ask the user.

Use `validate_press` before `define_press` when constructing a press from scratch. It catches invalid targets, colors, brightness values, no-light groups, overlapping lamp coverage, and likely capability mismatches.

Use `define_press` when you are building a press from explicit assignments.

Use `capture_press` when the user has already tuned the lights and wants to save the current live state.

Use `delete_press` only when the user clearly identifies the press and asks to remove it.

## Reachability and live state

Treat live state and reachability honestly.

- A light can be unreachable because it is off at the wall, asleep, disconnected, or because the bridge/vendor path is unavailable.
- If Lutin returns unknown state, say "unknown" or "I couldn't read it," not a guessed color or brightness.
- If only some lamps respond, say that it was partial and which part failed if the tool gives details.
- A stale command memory must not be described as real current state. Prefer live state tools when the user asks what the lights are actually showing.
- When checking whether a press is active, remember Lutin now derives board highlights from live lamp state when warm, with command memory only as a fallback.

## Good agent behaviour

Be direct, careful, and house-friendly.

Do not:

- Invent rooms, lamps, Hue bridges, scenes, sensors, schedules, or automations.
- Use raw vendor ids in the final answer unless the user asks for diagnostics.
- Fire lights just to prove write access.
- Rename lights without human confirmation.
- Delete presses or change shared house setup from ambiguous wording.
- Treat "unreachable" as "off."

Do:

- Start with `get_app_info` in a new conversation.
- Use friendly lamp names when available.
- Ask a short clarification when a write is ambiguous.
- Say exactly what changed.
- Keep responses short unless the user asks for detail.

## Common user requests

Interpret common wording like this:

- "Connect to Lutin" → configure MCP / start pairing.
- "What can you see?" → `get_app_info`, then summarize houses, scope, light/press counts, and Hue status.
- "What lights are in the bedroom?" → `list_lights` filtered by room.
- "Turn the kitchen warm" → `set_room` for Kitchen with a warm white palette color.
- "Make the left lamp red" → identify the exact light, then `set_light` with a red color.
- "Save this as movie night" → `capture_press` if the lights are already set, otherwise validate/define explicit assignments.
- "Press movie night" → `press("movie night")`; if ambiguous, ask.
- "What presses do I have?" → `list_presses`.
- "Rename this lamp" → use `identify_light` first if "this" is not already tied to a known light id.
- "Share this with the house" → use `define_press` with `shared: true` when creating/updating a press, after confirming which press/look.

## First connection check

After connecting, verify with harmless reads:

```text
get_app_info
list_houses
list_presses
```

Do not create a dummy press, rename a real lamp, or blink a lamp unless the user explicitly asks you to test write access.

## If connection fails

Common causes:

- The MCP server was added but the agent runtime was not restarted/reloaded.
- The user has not approved the pairing request yet.
- The pairing request expired; start a fresh one.
- The requested scope is too narrow for the action.
- The user registered with a different email address.
- The user is a paused member of the target house.
- Hue is not connected, or the Hue bridge/vendor path is unreachable.

Explain the problem plainly and ask for only the minimum next step, such as approving a fresh link, confirming the registered email, selecting the correct house, reconnecting Hue, or requesting Manage access.
