# spotify-mcp MCP server mcp-name: io.github.jamiew/spotify-mcp MCP server connecting Claude with Spotify. This fork of [varunneal/spotify-mcp](https://github.com/varunneal/spotify-mcp) adds smart-batching tools and advanced playlist features that optimize API usage. This server runs locally over stdio. Want a hosted MCP instead? The sister project [spotify-mcp-cloudflare](https://github.com/jamiew/spotify-mcp-cloudflare) deploys to Cloudflare Workers in a few minutes, with OAuth in the browser and no local install for anyone connecting. ## Features ### Core Functionality - **Playback Control**: Start, pause, skip tracks, manage queue - **Search & Discovery**: Find tracks, albums, artists, playlists with pagination - **Real-time State**: Live user profile and playback status - **Resources**: Read user, playback, track, playlist, artist, and album state by URI ### Modern MCP Protocol - **Server instructions**: whole-surface guidance ships once per session instead of per tool - **Structured output**: every tool returns a typed schema, not a bare dict - **Tool annotations & icons**: read-only/destructive hints, titles, and a Spotify glyph - **Progress notifications**: live updates while paginating large playlists - **Elicitation**: destructive playlist removals ask for confirmation on clients that support it ### Enhanced Playlist Tools (New in this fork) - **Smart Batch Operations**: Add/remove up to 100 tracks in single API calls - **Large Playlist Support**: Efficiently handle playlists with 1000+ tracks using pagination - **Advanced Playlist Management**: Create, modify details, reorder tracks, bulk track operations - **API-Optimized Workflows**: Intelligent batching reduces API calls by 60-80% ### Tools | Tool | Does | | --- | --- | | `get_me` | The signed-in user's profile | | `search_music` | Search tracks, albums, artists or playlists, with filters and regime-aware page limits | | `get_tracks` | Details for up to 50 tracks in one request; individual reads when batching is unavailable | | `get_artist` | Details for up to 50 artists in one request; top tracks when you ask for a single artist | | `get_album` | Details for up to 20 albums in one request; the track list when you ask for a single album | | `get_playback_state` | What's playing now: track, device, progress, shuffle, repeat | | `control_playback` | Play, pause, next, previous, seek, volume, shuffle, repeat; best-effort state confirmation | | `list_devices` | Available Spotify Connect devices | | `transfer_playback` | Move playback to another device | | `get_queue` | Now playing plus the upcoming queue | | `add_to_queue` | Queue a track | | `list_playlists` | The user's playlists, paginated | | `get_playlist` | Playlist metadata without its tracks; track count when available | | `get_playlist_tracks` | Playlist tracks, paginated to any size | | `create_playlist` | Create a playlist | | `update_playlist_details` | Rename a playlist or change its description/visibility | | `add_tracks_to_playlist` | Add up to 100 tracks in one call | | `remove_tracks_from_playlist` | Remove tracks (confirms first where the client supports it) | | `reorder_playlist` | Move a block of tracks to a new position | | `unfollow_playlist` | Unfollow a playlist — how Spotify deletes your own | | `get_saved_tracks` | Liked Songs, paginated | | `save_tracks` | Like tracks | | `remove_saved_tracks` | Unlike tracks | | `check_saved_tracks` | Which of up to 50 tracks are already liked, without paging the library | | `check_saved_albums` | Which of up to 20 albums are already saved | | `check_following_artists` | Which of up to 50 artists the user follows | | `get_top_items` | Top artists or tracks over a time range | | `get_recently_played` | Recently played tracks with timestamps | `tests/test_tool_metadata.py` fails if this table drifts from the code, or if a tool ships without a title, icon and behaviour annotations. Restricted apps cap search pages at 10 results. Advance with the returned `offset + limit`, not the requested page size. Individual track fallbacks can require up to 50 Spotify requests. Playlist `limit`/`offset` count positions, so a page includes any unresolved rows at those positions. Local files and unresolved rows come back with `id: null`, local files also set `is_local`, and they keep their position so `reorder_playlist` indices stay correct. ## Installation Requires a Spotify **Premium** account and [`uv`](https://docs.astral.sh/uv/) >= 0.54. ### 1. Get Spotify API keys 1. Create an app at [developer.spotify.com/dashboard](https://developer.spotify.com/dashboard). 2. Add redirect URI `http://127.0.0.1:8888` — it must match exactly what you set below. 3. Copy the **Client ID** and **Client Secret**. ### 2. Add the server to your MCP client Every client runs the same command — `uvx spotify-mcp-jamiew` — with your three Spotify env vars. No clone, no local path. **Standard config** (works in most clients): ```json { "mcpServers": { "spotify": { "command": "uvx", "args": ["spotify-mcp-jamiew"], "env": { "SPOTIFY_CLIENT_ID": "your_client_id", "SPOTIFY_CLIENT_SECRET": "your_client_secret", "SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888" } } } } ```
Claude Code ```bash claude mcp add spotify \ -e SPOTIFY_CLIENT_ID=your_client_id \ -e SPOTIFY_CLIENT_SECRET=your_client_secret \ -e SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888 \ -- uvx spotify-mcp-jamiew ``` Add `-s user` to install it globally across all projects. Verify with `claude mcp list`.
Claude Desktop Add the **standard config** above to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows), then fully restart Claude Desktop.
Codex CLI ```bash codex mcp add spotify \ --env SPOTIFY_CLIENT_ID=your_client_id \ --env SPOTIFY_CLIENT_SECRET=your_client_secret \ --env SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888 \ -- uvx spotify-mcp-jamiew ``` Or add to `~/.codex/config.toml`: ```toml [mcp_servers.spotify] command = "uvx" args = ["spotify-mcp-jamiew"] [mcp_servers.spotify.env] SPOTIFY_CLIENT_ID = "your_client_id" SPOTIFY_CLIENT_SECRET = "your_client_secret" SPOTIFY_REDIRECT_URI = "http://127.0.0.1:8888" ```
Hermes Add to `~/.hermes/config.yaml`, then run `/reload-mcp` (or restart Hermes): ```yaml mcp_servers: spotify: command: uvx args: [spotify-mcp-jamiew] env: SPOTIFY_CLIENT_ID: your_client_id SPOTIFY_CLIENT_SECRET: your_client_secret SPOTIFY_REDIRECT_URI: http://127.0.0.1:8888 ```
OpenClaw Add the **standard config** above to `~/.openclaw/openclaw.json` (under `mcpServers`), then `openclaw gateway restart`.
Other clients (mcp.json) Most MCP clients read a JSON file with an `mcpServers` block — drop the **standard config** above into it. Using something else? Paste this to your agent: > Install the spotify-mcp MCP server from https://github.com/jamiew/spotify-mcp — it's on PyPI as `spotify-mcp-jamiew`, run it with `uvx spotify-mcp-jamiew`, and set env vars `SPOTIFY_CLIENT_ID`, `SPOTIFY_CLIENT_SECRET`, and `SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888`.
Run from source (local dev) ```bash git clone https://github.com/jamiew/spotify-mcp.git cd spotify-mcp uv sync ``` Then point your client at the checkout: ```json { "mcpServers": { "spotify": { "command": "uv", "args": ["--directory", "/path/to/spotify-mcp", "run", "spotify-mcp"], "env": { "SPOTIFY_CLIENT_ID": "your_client_id", "SPOTIFY_CLIENT_SECRET": "your_client_secret", "SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888" } } } } ``` To run the latest unpublished commit without cloning: `uvx --from git+https://github.com/jamiew/spotify-mcp.git spotify-mcp`.
On first use the server opens a browser for Spotify OAuth; the token is cached locally for later runs. ## Usage Examples - **"Create a chill study playlist with 20 tracks"** → Search + playlist creation + bulk track addition - **"Show me the first 50 tracks from my 'Liked Songs'"** → Pagination for large playlists - **"Find similar artists to Radiohead and add their top tracks to my queue"** → Search + artist info + queue management ## Development Built with the **FastMCP framework** — focused single-purpose tools spanning playback, search, queue, and playlist management, with type-safe APIs and comprehensive test coverage. **Debug with MCP Inspector:** ```bash npx @modelcontextprotocol/inspector uv --directory /path/to/spotify_mcp run spotify-mcp ``` ## Contributors - [@jamiew](https://github.com/jamiew) - [@varunneal](https://github.com/varunneal) — original [varunneal/spotify-mcp](https://github.com/varunneal/spotify-mcp) - [@jonico](https://github.com/jonico) - [@tedeuxx](https://github.com/tedeuxx) - [@karimStekelenburg](https://github.com/karimStekelenburg)