Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,34 @@ Generic parameter shapes (which one applies is decided by the device — see the

For the complete per-device command reference, see the [SwitchBot API docs](https://github.com/OpenWonderLabs/SwitchBotAPI#send-device-control-commands).

#### `devices expand` — named flags for packed parameters

Some commands require a packed string like `"26,2,2,on"`. `devices expand` builds it from readable flags:

```bash
# Air Conditioner — setAll
switchbot devices expand <acId> setAll --temp 26 --mode cool --fan low --power on

# Curtain / Roller Shade — setPosition
switchbot devices expand <curtainId> setPosition --position 50 --mode silent

# Blind Tilt — setPosition
switchbot devices expand <blindId> setPosition --direction up --angle 50

# Relay Switch — setMode
switchbot devices expand <relayId> setMode --channel 1 --mode edge
```

Run `switchbot devices expand <id> <command> --help` to see the available flags for any device command.

#### `devices explain` — plain-language command description

```bash
switchbot devices explain <deviceId> <command> # e.g. "explain ABC123 setAll"
```

Returns a human-readable description of what the command does and what each parameter means.

### `scenes` — run manual scenes

```bash
Expand Down Expand Up @@ -327,7 +355,7 @@ Output is a stream of JSON status objects (with `--json`) or a refreshed table.
switchbot mcp serve
```

Exposes 7 MCP tools: `list_devices`, `describe_device`, `get_device_status`, `send_command`, `list_scenes`, `run_scene`, `search_catalog`.
Exposes 8 MCP tools (`list_devices`, `describe_device`, `get_device_status`, `send_command`, `list_scenes`, `run_scene`, `search_catalog`, `account_overview`) plus a `switchbot://events` resource for real-time shadow updates.
See [`docs/agent-guide.md`](./docs/agent-guide.md) for the full tool reference and safety rules (destructive-command guard).

### `cache` — inspect and clear local cache
Expand Down
34 changes: 31 additions & 3 deletions docs/agent-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,26 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
}
```

### Available tools
### Available tools (8)

| Tool | Purpose | Destructive-guard? |
|---------------------|-------------------------------------------------------------------|--------------------------|
| `list_devices` | Enumerate physical devices + IR remotes | — |
| `get_device_status` | Live status for one device | — |
| `send_command` | Dispatch a built-in or customize command | yes (`confirm: true` required) |
| `list_scenes` | Enumerate saved manual scenes | — |
| `run_scene` | Execute a saved manual scene | — |
| `search_catalog` | Look up device type by name/alias | — |
| `describe_device` | Live status **plus** catalog-derived commands + suggested actions | — |
| `account_overview` | Single cold-start snapshot — devices, scenes, quota, cache, MQTT state. Call this first in a new agent session to avoid multiple round-trips. | — |

The MCP server refuses destructive commands (Smart Lock `unlock`, Garage Door `open`, etc.) unless the tool call includes `confirm: true`. The allowed list is the `destructive: true` commands in the catalog — `switchbot schema export | jq '[.types[].commands[] | select(.destructive)]'` shows every one.
The MCP server refuses destructive commands (Smart Lock `unlock`, Garage Door `open`, etc.) unless the tool call includes `confirm: true`. The allowed list is the `destructive: true` commands in the catalog — `switchbot schema export | jq '[.data.types[].commands[] | select(.destructive)]'` shows every one.

### MCP resource: `switchbot://events`

Read-only snapshot of recent MQTT shadow-update events from the ring buffer. Returns `{state, count, events[]}`.

Enabled when `SWITCHBOT_MQTT_HOST` / `SWITCHBOT_MQTT_USERNAME` / `SWITCHBOT_MQTT_PASSWORD` env vars are set; returns `{state:"disabled", count:0, events:[]}` otherwise. To enable real-time events, add those three env vars to the MCP server config alongside `SWITCHBOT_TOKEN` / `SWITCHBOT_SECRET`.

---

Expand Down Expand Up @@ -160,6 +168,26 @@ switchbot scenes list --format id # ✓ — sceneId column present
switchbot devices status <id> --format id # ✗ — exits 2 (no ID column in status output)
```

### `devices expand` — semantic parameter flags

Some device commands require a packed string parameter (e.g., AC `setAll` takes `"26,2,2,on"`). `devices expand` accepts named flags and builds the parameter for you:

```bash
# Air Conditioner — setAll
switchbot devices expand <acId> setAll --temp 26 --mode cool --fan low --power on

# Curtain / Roller Shade — setPosition
switchbot devices expand <curtainId> setPosition --position 50 --mode silent

# Blind Tilt — setPosition
switchbot devices expand <blindId> setPosition --direction up --angle 50

# Relay Switch — setMode
switchbot devices expand <relayId> setMode --channel 1 --mode edge
```

Use `switchbot devices expand --help` or `switchbot devices expand <id> <command> --help` for the full flag list per command.

---

## Catalog: the shared contract
Expand Down Expand Up @@ -210,7 +238,7 @@ The audit format is JSONL with this shape:
"dryRun": false, "result": "ok" }
```

Pair with `switchbot devices watch --interval=30s --on-change-only` for continuous state diffs, or `switchbot events tail --local` to receive webhook pushes locally.
Pair with `switchbot devices watch --interval=30s` for continuous state diffs (add `--include-unchanged` to emit every tick even when nothing changed), or `switchbot events tail` to receive webhook pushes locally.

---

Expand Down
2 changes: 2 additions & 0 deletions src/commands/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const MCP_TOOLS = [
'list_scenes',
'run_scene',
'search_catalog',
'account_overview',
];

export function registerCapabilitiesCommand(program: Command): void {
Expand Down Expand Up @@ -69,6 +70,7 @@ export function registerCapabilitiesCommand(program: Command): void {
entry: 'mcp serve',
protocol: 'stdio (default) or --port <n> for HTTP',
tools: MCP_TOOLS,
resources: ['switchbot://events'],
},
plan: {
schemaCmd: 'plan schema',
Expand Down
10 changes: 6 additions & 4 deletions tests/commands/capabilities.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,13 @@ describe('capabilities', () => {
expect(cat.typeCount as number).toBeGreaterThan(10);
});

it('surfaces.mcp.tools has 7 entries including send_command', async () => {
it('surfaces.mcp.tools has 8 entries including send_command and account_overview', async () => {
const out = await runCapabilities();
const tools = (out.surfaces as Record<string, { tools: string[] }>).mcp.tools;
expect(tools).toHaveLength(7);
expect(tools).toContain('send_command');
const mcp = (out.surfaces as Record<string, { tools: string[]; resources: string[] }>).mcp;
expect(mcp.tools).toHaveLength(8);
expect(mcp.tools).toContain('send_command');
expect(mcp.tools).toContain('account_overview');
expect(mcp.resources).toEqual(['switchbot://events']);
});

it('version matches semver format', async () => {
Expand Down
Loading