MCP Server Reference & Tool Schemas
homectl provides dedicated, domain-scoped Model Context Protocol (MCP) servers built with the official github.com/modelcontextprotocol/go-sdk.
1. Runtime Architecture
Section titled “1. Runtime Architecture”homectl’s MCP servers compile into single static binaries with minimal operational overhead:
- Instant Cold Starts: Boots and emits tool definitions over stdio in <5ms with zero interpreter or package resolution latency.
- Low Memory Footprint: Consumes ~12–18 MB RSS during active operation.
- Hermetic Execution: Operates without ambient environment dependencies or uncommitted runtime caches.
2. Sonos MCP Server (cmd/mcp-sonos)
Section titled “2. Sonos MCP Server (cmd/mcp-sonos)”The mcp-sonos server exposes 10 focused tools and 1 live resource.
Tool Catalog Summary
Section titled “Tool Catalog Summary”| Tool Name | Mode | Purpose | Key Parameters |
|---|---|---|---|
sonos_list_speakers |
🔒 Read-Only | Discovers or lists cached network speakers with generation (S1/S2) and renderer status | refresh?: bool |
sonos_get_now_playing |
🔒 Read-Only | Retrieves authoritative track metadata, status, play mode, shuffle, repeat, crossfade | ip: string |
sonos_get_topology |
🔒 Read-Only | Inspects zone groups, members, and stereo pairs | ip: string |
sonos_list_favorites |
🔒 Read-Only | Lists pinned cloud tracks, playlists, and radio | ip?: string |
sonos_list_services |
🔒 Read-Only | Enumerates available music services on household | ip?: string |
sonos_control |
⚡ Mutating | Playback & grouping (play, pause, stop, next, prev, seek_track, seek_time, join, leave, unjoin) |
ip: string, action: string, track?: int, target?: string |
sonos_set_volume |
⚡ Mutating | Sets absolute volume (0–100) or applies step delta | ip: string, volume?: int, delta?: int |
sonos_play_favorite |
⚡ Mutating | Launches playback of a pinned cloud favorite | ip: string, favorite_id: string |
sonos_play_stream |
⚡ Mutating | Streams an arbitrary HTTP/HTTPS audio URL | ip: string, url: string, title?: string |
sonos_add_to_queue |
⚡ Mutating | Enqueues a track URI into the active queue | ip: string, uri: string, metadata?: string, as_next?: bool |
sonos_get_queue |
🔒 Read-Only | Inspects tracks in playback queue with pagination | ip: string, start?: int, count?: int |
sonos_queue_edit |
⚡ Mutating | Edits queue (remove, clear, reorder / bump to next) or configures playback settings (shuffle, repeat, crossfade) |
ip: string, action: string, track?: int, count?: int, insert_before?: int, as_next?: bool, enabled?: bool, repeat_mode?: string |
3. Tool Definitions & Schemas
Section titled “3. Tool Definitions & Schemas”sonos_list_speakers (Read-Only)
Section titled “sonos_list_speakers (Read-Only)”Discovers all Sonos speakers on the local subnet or returns the cached topology for instant response.
- Parameters:
{"type": "object","properties": {"refresh": {"type": "boolean","description": "Whether to actively re-scan the network via mDNS/SSDP instead of loading cached devices"}}}
- Return Schema (
ListSpeakersResult):{"count": 2,"speakers": [{"Name": "Living Room","IP": "192.168.1.100","RinconID": "RINCON_000E5800000000001","ModelName": "Sonos Arc","ModelNumber": "S19","Generation": "S2","IsRenderer": true},{"Name": "Network Bridge","IP": "192.168.1.101","RinconID": "RINCON_000E5800000000002","ModelName": "Sonos Bridge","ModelNumber": "ZB100","Generation": "S1","IsRenderer": false}]}
sonos_get_now_playing (Read-Only)
Section titled “sonos_get_now_playing (Read-Only)”Returns compact, token-optimized track status, duration, volume, playback state, and queue length.
- Automatic Follower Resolution: If invoked on a speaker that is a stereo-pair or group follower (reporting an
x-rincon:URI), the tool automatically resolves the group coordinator IP, queries the coordinator, and returns authoritative metadata withis_follower: trueandcoordinator_ip. - Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" }},"required": ["ip"]}
- Return Schema (
NowPlayingResult):{"ip": "192.168.1.100","state": "PLAYING","volume": 25,"title": "Comfortably Numb","artist": "Pink Floyd","album": "The Wall","duration": "0:06:24","progress": "0:02:15","queue_length": 14,"media_uri": "x-rincon-queue:RINCON_123456#0","stream_content": "","is_follower": false}
sonos_get_topology (Read-Only)
Section titled “sonos_get_topology (Read-Only)”Exposes the zone group topology, identifying multi-room groups, bonded stereo pairs, and active coordinators.
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of any speaker in the household (required)" }},"required": ["ip"]}
- Return Schema (
TopologyResult):{"count": 1,"groups": [{"id": "RINCON_000E5800000000001:1","coordinator_uuid": "RINCON_000E5800000000001","is_pair": true,"members": [{ "uuid": "RINCON_000E5800000000001", "room_name": "Living Room (L)", "ip": "192.168.1.100", "is_coordinator": true },{ "uuid": "RINCON_000E5800000000002", "room_name": "Living Room (R)", "ip": "192.168.1.101", "is_coordinator": false }]}]}
sonos_list_favorites (Read-Only)
Section titled “sonos_list_favorites (Read-Only)”Lists pinned cloud media (Spotify playlists, Apple Music albums, radio stations) stored in the household’s “Sonos Favorites” container (FV:2).
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "Optional speaker IP. If omitted, uses first discovered speaker." }}}
- Return Schema (
ListFavoritesResult):{"count": 2,"favorites": [{ "id": "FV:2/1", "title": "Morning Jazz", "type": "playlist", "album_art_uri": "/getaa?..." },{ "id": "FV:2/2", "title": "SomaFM Groove Salad", "type": "station" }]}
sonos_control (Mutating)
Section titled “sonos_control (Mutating)”Dispatches playback and grouping actions to a speaker. If the target speaker is a follower, playback commands are automatically routed to the group coordinator. Supports transport control, queue track jumping, time seeking, and group management (join, leave, unjoin). Rejects playback on non-rendering devices (bridges) and rejects cross-generation grouping (S1 with S2).
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" },"action": {"type": "string","enum": ["play", "pause", "stop", "next", "previous", "seek_track", "seek_time", "join", "leave", "unjoin"],"description": "Playback or grouping action to execute"},"track": {"type": "integer","description": "1-based queue track number to jump to (required when action is 'seek_track')"},"target": {"type": "string","description": "Time offset for seek_time ([H:]MM:SS), or target speaker IP/room/Rincon for join action"}},"required": ["ip", "action"]}
sonos_set_volume (Mutating)
Section titled “sonos_set_volume (Mutating)”Adjusts speaker volume. Supports both absolute volume setting (0–100) and relative step adjustments (delta: +5 or -10).
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" },"volume": { "type": "integer", "description": "Target absolute volume between 0 and 100" },"delta": { "type": "integer", "description": "Relative volume delta (e.g. +5 or -10). Applied if volume is omitted." }},"required": ["ip"]}
sonos_play_favorite (Mutating)
Section titled “sonos_play_favorite (Mutating)”Loads a pinned favorite by ID and begins playback with automatic coordinator resolution.
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the target speaker (required)" },"favorite_id": { "type": "string", "description": "The favorite ID returned by sonos_list_favorites (e.g. 'FV:2/1')" }},"required": ["ip", "favorite_id"]}
sonos_play_stream (Mutating)
Section titled “sonos_play_stream (Mutating)”Loads and plays any arbitrary HTTP or HTTPS audio stream (internet radio station, podcast episode, or TTS voice announcement) directly on the target speaker.
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" },"url": { "type": "string", "description": "Direct HTTP or HTTPS stream URL (e.g. 'http://stream.somafm.com/groovesalad-128-mp3')" },"title": { "type": "string", "description": "Optional friendly stream title to display on TUI and Web UI" }},"required": ["ip", "url"]}
sonos_add_to_queue (Mutating)
Section titled “sonos_add_to_queue (Mutating)”Appends or inserts an audio URI into the speaker’s active queue without halting current playback. Supports passing stored DIDL-Lite metadata for cloud playlists and container items.
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" },"uri": { "type": "string", "description": "Track or stream URI to add" },"metadata": { "type": "string", "description": "Optional DIDL-Lite metadata for the enqueued item (required for cloud container URIs)" },"as_next": { "type": "boolean", "description": "If true, inserts track as the next song to play; otherwise appends to end" }},"required": ["ip", "uri"]}
sonos_get_queue (Read-Only)
Section titled “sonos_get_queue (Read-Only)”Inspects tracks in the Sonos playback queue on the speaker with track titles, artists, albums, durations, and positions. Supports pagination via start and count.
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" },"start": { "type": "integer", "description": "0-based starting index for pagination (default 0)" },"count": { "type": "integer", "description": "Maximum number of queue items to return (default 100)" }},"required": ["ip"]}
sonos_queue_edit (Mutating)
Section titled “sonos_queue_edit (Mutating)”Edits the local playback queue on a Sonos speaker. Supports removing tracks (action: "remove"), clearing the entire queue (action: "clear"), reordering tracks or bumping them to play next (action: "reorder"), and configuring queue playback settings (action: "shuffle", "repeat", "crossfade").
- Parameters:
{"type": "object","properties": {"ip": { "type": "string", "description": "IP address of the Sonos speaker (required)" },"action": {"type": "string","enum": ["remove", "clear", "reorder", "shuffle", "repeat", "crossfade"],"description": "Queue edit action to execute (required)"},"track": {"type": "integer","description": "1-based track position in queue (required for remove and reorder)"},"count": {"type": "integer","description": "Number of tracks to remove or reorder (default 1)"},"insert_before": {"type": "integer","description": "1-based target track position to insert before (for reorder)"},"as_next": {"type": "boolean","description": "If true, moves track(s) to play immediately after the currently playing track (for reorder)"},"enabled": {"type": "boolean","description": "Enable or disable state (used for shuffle, crossfade, and boolean repeat)"},"repeat_mode": {"type": "string","enum": ["off", "all", "one"],"description": "Repeat mode for repeat action ('off', 'all', or 'one')"}},"required": ["ip", "action"]}
4. MCP SEP-2106 Structured Output Compliance
Section titled “4. MCP SEP-2106 Structured Output Compliance”Per the Model Context Protocol specification (SEP-2106) and OpenCode client validation rules, tool outputs must be Go structs/records (JSON objects), never bare arrays.
- ❌ Invalid Schema (Bare Array):
[ { "name": "Kitchen" }, { "name": "Living Room" } ]
- ✅ Valid Schema (
homectlStandard):{"count": 2,"speakers": [ { "Name": "Kitchen" }, { "Name": "Living Room" } ]}
All homectl MCP tools wrap collections inside a top-level record, returning both a natural-language summary block and a typed payload:
return &mcp.CallToolResult{ Content: []mcp.Content{ &mcp.TextContent{Text: fmt.Sprintf("Found %d Sonos speaker(s)", len(speakers))}, &mcp.TextContent{Text: string(jsonData)}, },}, resultStruct, nil