Skip to content

MCP Server Reference & Tool Schemas

homectl provides dedicated, domain-scoped Model Context Protocol (MCP) servers built with the official github.com/modelcontextprotocol/go-sdk.


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.

The mcp-sonos server exposes 10 focused tools and 1 live resource.

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

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
    }
    ]
    }

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 with is_follower: true and coordinator_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
    }

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 }
    ]
    }
    ]
    }

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" }
    ]
    }

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"]
    }

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"]
    }

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"]
    }

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"]
    }

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"]
    }

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"]
    }

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 (homectl Standard):
    {
    "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