diff --git a/README.md b/README.md index 66b9aaf..088dcd1 100644 --- a/README.md +++ b/README.md @@ -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 setAll --temp 26 --mode cool --fan low --power on + +# Curtain / Roller Shade — setPosition +switchbot devices expand setPosition --position 50 --mode silent + +# Blind Tilt — setPosition +switchbot devices expand setPosition --direction up --angle 50 + +# Relay Switch — setMode +switchbot devices expand setMode --channel 1 --mode edge +``` + +Run `switchbot devices expand --help` to see the available flags for any device command. + +#### `devices explain` — plain-language command description + +```bash +switchbot devices explain # 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 @@ -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 diff --git a/docs/agent-guide.md b/docs/agent-guide.md index 9648f7b..8d02ce4 100644 --- a/docs/agent-guide.md +++ b/docs/agent-guide.md @@ -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`. --- @@ -160,6 +168,26 @@ switchbot scenes list --format id # ✓ — sceneId column present switchbot devices status --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 setAll --temp 26 --mode cool --fan low --power on + +# Curtain / Roller Shade — setPosition +switchbot devices expand setPosition --position 50 --mode silent + +# Blind Tilt — setPosition +switchbot devices expand setPosition --direction up --angle 50 + +# Relay Switch — setMode +switchbot devices expand setMode --channel 1 --mode edge +``` + +Use `switchbot devices expand --help` or `switchbot devices expand --help` for the full flag list per command. + --- ## Catalog: the shared contract @@ -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. --- diff --git a/src/commands/capabilities.ts b/src/commands/capabilities.ts index 610f49b..cc5134f 100644 --- a/src/commands/capabilities.ts +++ b/src/commands/capabilities.ts @@ -28,6 +28,7 @@ const MCP_TOOLS = [ 'list_scenes', 'run_scene', 'search_catalog', + 'account_overview', ]; export function registerCapabilitiesCommand(program: Command): void { @@ -69,6 +70,7 @@ export function registerCapabilitiesCommand(program: Command): void { entry: 'mcp serve', protocol: 'stdio (default) or --port for HTTP', tools: MCP_TOOLS, + resources: ['switchbot://events'], }, plan: { schemaCmd: 'plan schema', diff --git a/tests/commands/capabilities.test.ts b/tests/commands/capabilities.test.ts index bd26938..6dc740b 100644 --- a/tests/commands/capabilities.test.ts +++ b/tests/commands/capabilities.test.ts @@ -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).mcp.tools; - expect(tools).toHaveLength(7); - expect(tools).toContain('send_command'); + const mcp = (out.surfaces as Record).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 () => {