Skip to main content
Glama
README.md
# sonos-mcp

MCP server for controlling Sonos speakers.

## Using it

Connect the server to an MCP client (see [Connecting to Claude](#connecting-to-claude) below) and ask for music in plain language — "play some jazz in the kitchen", "turn the living room down to 20", "DJ a party then wind down with chill vibes". The server exposes these tools:

- `topology` — list speakers on the network, or the current room groupings (run this first to learn valid room names)
- `search` — search the Sonos-linked Spotify account for tracks, albums, playlists, or artists
- `play_media` — play a Spotify URI on a speaker/group (replace the queue, or enqueue)
- `transport` — play, pause, stop, skip, and playback status
- `volume` — get/set volume for a room or a whole bonded group
- `queue` — list, jump to, remove, or clear queue entries
- `grouping` — join, unjoin, or dissolve speaker groups
- `dj` — turn free-form vibe strings (e.g. `["party", "focus", "chill"]`) into a playlist queue: each vibe resolves to the first matching Spotify playlist, played in order
- `status` — check that the underlying `sonos` CLI is installed and reachable

You'll need Sonos speakers on your local network, the [`sonos` CLI](https://github.com/steipete/sonoscli) on your `PATH`, and a Spotify account linked to your Sonos system.

Prefer skipping the server entirely? [`skills/sonos`](skills/sonos/SKILL.md) is a Claude skill that teaches Claude to drive the `sonos` CLI directly — copy it into `~/.claude/skills/` and it covers the same discover/search/play/queue/volume/grouping workflows from the terminal.

## Requirements

- Node.js 20+
- The [`sonos` CLI](https://github.com/steipete/sonoscli) installed and on `PATH`

## Development

Install dependencies:

```sh
npm install
```

Generate a self-signed TLS cert for local dev (once, or whenever it expires):

```sh
npm run certs
```

This writes `certs/key.pem` and `certs/cert.pem`, which are gitignored.

Run the server (TypeScript, no build step):

```sh
npm run dev
```

The server listens on `https://localhost:3000/mcp` (override with `PORT`).

Build and run the compiled output:

```sh
npm run build
npm start
```

## Connecting to Claude

The dev server uses a self-signed cert, which Claude's HTTP client rejects by default
(`DEPTH_ZERO_SELF_SIGNED_CERT`). `curl -k` bypasses this, but Claude has no such flag, so
each client needs to be told to trust `certs/cert.pem` explicitly.

### Claude Code

Set `NODE_EXTRA_CA_CERTS` to the cert's path whenever you launch `claude`:

```sh
export NODE_EXTRA_CA_CERTS="$(pwd)/certs/cert.pem"
claude mcp add --transport http sonos-mcp https://localhost:3000/mcp
```

Add the `export` to your shell profile if you want it to persist — note it's a global env
var that affects every Node/Bun process you launch from that shell, not just this project,
so it's opt-in rather than something this repo sets for you.

### Claude Desktop

Desktop's Settings → Connectors → "Add custom connector" doesn't work for a local dev
server: that flow goes through `claude.ai`'s cloud connector setup, which can't reach
`localhost` on your machine at all — clicking Add just silently does nothing.

Desktop's local `claude_desktop_config.json` also can't reference a URL directly; it only
supports spawning local stdio commands. The fix is to bridge HTTP to stdio with
[`mcp-remote`](https://www.npmjs.com/package/mcp-remote), passing the CA cert via that
process's own `env` (no global/shell env var needed). Add this to
`~/Library/Application Support/Claude/claude_desktop_config.json`, under `mcpServers`:

```json
"sonos-mcp": {
  "command": "npx",
  "args": ["-y", "mcp-remote", "https://localhost:3000/mcp"],
  "env": {
    "NODE_EXTRA_CA_CERTS": "/absolute/path/to/sonos-mcp/certs/cert.pem"
  }
}
```

Then fully quit (Cmd+Q) and reopen Claude Desktop to pick up the config change.

## Manually testing

The server speaks MCP over Streamable HTTP. With the dev server running, exercise it with `curl` (the `-k` flag skips validation of the self-signed cert):

```sh
# initialize a session
curl -sk -X POST https://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"manual-test","version":"1.0.0"}}}'

# list tools
curl -sk -X POST https://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# call the topology tool to list speakers
curl -sk -X POST https://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"topology","arguments":{"action":"discover"}}}'
```