spotify-llm-mcp
# spotify-llm-mcp
Control Spotify and build **LLM-reasoned playlists** from any MCP client (Claude Code, Claude Desktop, Cursor, …).
It wraps the [`spotify_player`](https://github.com/aome510/spotify-player) CLI as the control plane, so it needs **no Spotify Developer app and no OAuth of its own** — it reuses the session you already logged into. The recommendation engine is the **calling LLM itself**: it reasons over your real playlist tracks and the server resolves its picks to Spotify tracks via search. (Spotify removed its `audio-features`/`recommendations` endpoints for new apps in Nov 2024 — this design sidesteps that entirely.)
## Why this design
- **Zero new credentials.** `spotify_player` already holds your session; this server just shells out to it.
- **Immune to Spotify Web-API deprecations.** Control flows through librespot, not `api.spotify.com`.
- **The LLM is the recsys.** Its music knowledge replaces Spotify's dead recommendation endpoints; the server turns song names into playable Spotify tracks.
- **Portable.** One MCP server, usable by every MCP-speaking client.
## Requirements
- [`spotify_player`](https://github.com/aome510/spotify-player) installed, authenticated once, and running as an active device. **Spotify Premium** is required for playback control.
- Python ≥ 3.10.
## Install
```bash
git clone https://github.com/rachittshah/spotify-llm-mcp
cd spotify-llm-mcp
uv pip install -e .
```
Register with Claude Code:
```bash
claude mcp add spotify -- spotify-llm-mcp
```
Or in `settings.json` / `claude_desktop_config.json`:
```jsonc
{ "mcpServers": { "spotify": { "command": "spotify-llm-mcp" } } }
```
## Tools
**Control:** `now_playing` · `control` (play/pause/next/previous/shuffle/repeat/volume/seek) · `play` · `search` · `list_devices` · `switch_device` · `get_queue`
**Recsys inputs & delivery:** `list_playlists` · `get_playlist_tracks` · `taste_profile` · `resolve_tracks` · `create_playlist_from_tracks` · `append_to_playlist`
## Features (MCP prompts / slash-commands)
- `/recommend-from-playlist <name>` — read a playlist, let the LLM extend it in-vibe, build & play the result.
- `/vibe-playlist <description>` — "late-night coding, downtempo instrumental" → a fresh playlist.
- `/more-like-this` — recommendations seeded from what's playing now.
- `/my-taste` — a summary of your listening profile.
## How the recsys works
```
LLM client ──► get_playlist_tracks("On Repeat") # real tracks, via spotify_player
│ (LLM reasons over them using its music knowledge)
└─► create_playlist_from_tracks(name, [{title, artist}, ...])
│ server resolves each name → Spotify track via search
└─► play(new_playlist_uri) # on your spotify_player device
```
## Claude Code skill
This repo also ships a Claude Code **skill** (`skill/spotify-dj/`) that teaches Claude the recsys workflows on top of the MCP tools. Install it:
```bash
cp -r skill/spotify-dj ~/.claude/skills/spotify-dj
```
Then in Claude Code: "recommend music like my On Repeat playlist" or `/spotify-dj`.
## Known limitations
- **Playback control needs Spotify Premium.** Free accounts can read state but not control it.
- **`spotify_player`'s search errors on some queries** (an upstream JSON-deserialization bug — exit 0 but non-JSON output). The recsys is resilient to this: an unresolvable pick is skipped and reported under `unresolved`, never aborting the batch.
- **Delivery is a playlist, not an ephemeral queue** — `spotify_player`'s CLI has no "add to queue" verb, so recommendations are delivered as a (revisitable) playlist.
## Development
```bash
uv pip install -e ".[dev]"
.venv/bin/python -m pytest # unit tests (no Spotify needed)
.venv/bin/python scripts/smoke_live.py # end-to-end against a live spotify_player
.venv/bin/python scripts/smoke_mcp.py # MCP-protocol smoke over stdio
```
## License
MIT © Rachitt Shah
TDQS
Scored across 14 tools
Most tools have a clear resource+action distinction, but search, play, and resolve_tracks overlap in their underlying lookup/resolution behavior, and the playlist creation/append tools both resolve track picks. Descriptions are usually enough to pick the right one.
Names are mostly readable but inconsistent: verb_noun forms like play_playlist and list_devices coexist with bare verbs like play and control, plus noun phrases like now_playing and taste_profile. The generic name control is particularly vague.
14 tools is a reasonable size for a Spotify assistant covering playback, queue, devices, search, and playlist management. Some search/resolve and playback-control functionality could be consolidated, but the count is not excessive.
Core workflows are covered: playback control, queue, devices, search, taste profile, and creating/appending playlists. However, there is no way to remove tracks or delete/replace playlists, nor any queue editing or recommendation tool, leaving notable playlist-lifecycle gaps.