Skip to main content
Glama
spotify-mcp-server

spotify-mcp-server

by freddy24-7

spotify-mcp-server

A FastMCP 3.0 server that exposes Spotify controls as Model Context Protocol (MCP) tools. Use it in two ways:

  • Claude Desktop / Claude Code — let Claude control Spotify during a conversation ("play something relaxing", "create a jazz playlist for dinner")

  • Web app — a mobile-friendly player at /app for playback control, playlist management, and AI playlist generation


Tools

Tool

Description

get_current_track

Metadata for the currently playing track

play_pause

Play, pause, or toggle playback

skip_track

Skip to next or previous track

add_to_queue

Add a track to the playback queue

get_recommendations

Fetch track recommendations from seed tracks

get_user_playlists

List the user's playlists

create_playlist

Create a new empty playlist

add_to_playlist

Add tracks to an existing playlist

search_and_add

Search for a track and add it to a playlist

play_context

Start playback of a playlist, album, or artist

get_devices

List available Spotify playback devices

transfer_playback

Transfer playback to a specific device

switch_user

Switch between pre-authenticated user profiles

generate_playlist

Generate and populate a playlist from a natural-language prompt (requires Gemini API key)


Related MCP server: Spotify MCP Server (Python)

Prerequisites

Requirement

Notes

uv ≥ 0.4

Python package manager

Python ≥ 3.10

Managed automatically by uv

Spotify account

Free or Premium

Spotify Developer App

Create one here

Gemini API key

Optional — only needed for generate_playlist


Quick Start

1. Clone the repo

git clone <repo-url> spotify-mcp-server
cd spotify-mcp-server

2. Install dependencies

uv sync

uv downloads Python 3.12, creates a virtual environment, and installs all locked dependencies automatically.

3. Create a Spotify Developer App

  1. Go to developer.spotify.com/dashboard

  2. Click Create App

  3. Add a Redirect URI — use http://127.0.0.1:8888/callback for local use, or https://your-domain/callback for Railway

  4. Note your Client ID and Client Secret

4. Configure credentials

cp .env.example .env

Edit .env:

SPOTIFY_CLIENT_ID=your_client_id_here
SPOTIFY_CLIENT_SECRET=your_client_secret_here
SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888/callback

# Optional — for AI playlist generation
GEMINI_API_KEY=your_gemini_api_key_here

.env is gitignored. Never commit it.

5. Authenticate with Spotify (one-time)

uv run python scripts/authenticate.py

This opens a browser for Spotify OAuth. After approving, the token is cached in .cache for all subsequent runs.


Option A — Claude Desktop (local, stdio)

This runs the server locally on your machine. Claude Desktop launches it automatically when you start a conversation.

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "spotify": {
      "command": "uv",
      "args": ["run", "fastmcp", "run", "src/server.py"],
      "cwd": "/absolute/path/to/spotify-mcp-server",
      "env": {
        "SPOTIFY_CLIENT_ID": "your_client_id",
        "SPOTIFY_CLIENT_SECRET": "your_client_secret",
        "SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888/callback"
      }
    }
  }
}

The config file is located at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Restart Claude Desktop after saving. The Spotify tools will appear automatically in your next conversation.

Example prompts for Claude:

  • "What's playing on Spotify?"

  • "Skip this track"

  • "Create a playlist called Dinner Jazz and add 10 tracks"

  • "Generate a playlist of 10 summer hits from 2024"


Option B — Railway (cloud, web app + MCP)

Deploy to Railway to get a persistent URL accessible from any device, including mobile.

1. Fork and connect

  1. Fork this repo to your GitHub account

  2. Create a new Railway project and connect your fork

  3. Railway will detect the Dockerfile and deploy automatically

2. Set environment variables in Railway

Variable

Value

SPOTIFY_CLIENT_ID

From Spotify Developer Dashboard

SPOTIFY_CLIENT_SECRET

From Spotify Developer Dashboard

SPOTIFY_REDIRECT_URI

https://your-railway-domain/callback

MCP_TRANSPORT

sse

GEMINI_API_KEY

Optional — for AI playlist generation

3. Add the redirect URI to Spotify

In your Spotify Developer App settings, add https://your-railway-domain/callback as an allowed Redirect URI and click Save.

4. Authenticate

Visit https://your-railway-domain/auth/login in a browser to complete the Spotify OAuth flow. The token is stored on the Railway volume at /data/.cache.

5. Access the web app

Open https://your-railway-domain/app on any device — desktop or mobile.

Web app features:

  • Now Playing card with album art and progress bar

  • Play / pause / skip / queue controls

  • Device picker — switch playback between laptop, phone, Bluetooth speakers

  • Search and add tracks to playlists

  • Create playlists and browse your library

  • AI playlist generation from natural-language prompts (requires Gemini API key)

Connect Claude Desktop to the Railway server

You can also point Claude Desktop at the Railway deployment instead of running the server locally:

{
  "mcpServers": {
    "spotify": {
      "type": "http",
      "url": "https://your-railway-domain/mcp"
    }
  }
}

Multi-user / Family Accounts

The server supports multiple pre-authenticated Spotify accounts on the same deployment.

One-time setup per user:

Each family member visits:

https://your-railway-domain/auth/login?user=theirname

and logs in with their own Spotify account. Their token is stored as .cache-theirname on the Railway volume.

Switching accounts:

Call the switch_user tool with the profile name, or ask Claude:

"Switch to mum's Spotify account"

Switch back to the default account with switch_user("default").

Note: Spotify limits development apps to 25 users. Beyond that, submit your app for extended quota mode (free, requires review).


Project Structure

.
├── src/
│   └── server.py          # FastMCP server + all tool definitions
├── static/
│   └── index.html         # Mobile web app (served at /app)
├── config/
│   └── settings.py        # pydantic-settings config loader
├── scripts/
│   └── authenticate.py    # One-time local OAuth helper
├── .env.example           # Credential template
├── Dockerfile             # Railway deployment
├── railway.json           # Railway configuration
├── pyproject.toml         # Dependencies (managed by uv)
├── uv.lock                # Locked dependency graph
└── CLAUDE.md              # Project conventions

License

MIT

Available Tools

14 tools
add_to_playlistA

Add one or more tracks to an existing Spotify playlist.

Handles batching automatically (Spotify API limit: 100 tracks per request).

Parameters

playlist_id : str Spotify playlist ID or full URI. track_uris : list[str] Spotify track URIs or bare track IDs.

Returns

dict Keys: playlist_id (str), tracks_added (int).

Raises

ValueError If track_uris is empty. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: track_uris (required), playlist_id (required). Returns: object

add_to_queueA

Add a track to the user's active Spotify playback queue.

Parameters

uri : str Spotify track URI (spotify:track:<id>) or bare track ID.

Returns

dict {"status": "queued", "uri": "<full_spotify_uri>"}

Raises

spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: uri (required). Returns: object

create_playlistA

Create a new empty private playlist for the current user.

Parameters

name : str Display name for the new playlist. description : str, optional Short description shown in Spotify clients (default: empty string).

Returns

dict Keys: id, name, url.

Raises

ValueError If name is blank. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: name (required), description. Returns: object

generate_playlistA

Generate and populate a Spotify playlist from a natural-language prompt.

Uses Claude to interpret the prompt and produce a tracklist, then creates a new playlist and searches for each track on Spotify.

Parameters

prompt : str Natural-language description, e.g. "10 summer hits from 2024". playlist_name : str, optional Name for the new playlist. If omitted, Claude will suggest one.

Returns

dict Keys: playlist_id, playlist_name, playlist_url, tracks_added (int), tracks_not_found (list[str]).

Raises

EnvironmentError If GEMINI_API_KEY is not configured. ValueError If prompt is blank.

Inputs: prompt (required), playlist_name. Returns: object

get_current_trackA

Retrieve information about the track currently playing on Spotify.

Returns structured metadata including the track URI, which is needed by other tools such as add_to_queue and get_recommendations.

Returns

dict Keys: is_playing, track_name, artists, album, duration_ms, progress_ms, track_url, track_uri. Returns {"is_playing": False} when nothing is playing.

Raises

spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: no named parameters. Returns: object

get_devicesA

List all available Spotify playback devices for the current user.

Returns

dict Keys: devices (list of dicts with id, name, type, is_active, volume_percent).

Inputs: no named parameters. Returns: object

get_recommendationsA

Fetch track recommendations based on a list of seed track URIs or IDs.

Note

Spotify deprecated the public recommendations endpoint in November 2024. This tool works for apps created before that date or granted continued access.

Parameters

seed_tracks : list[str] Spotify track URIs or bare IDs (max 5 seeds; excess are truncated). limit : int, optional Number of recommendations to return (1–100, default: 5).

Returns

dict Keys: seeds (list[str]), tracks (list[dict]).

Raises

ValueError If seed_tracks is empty or limit is out of range. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: seed_tracks (required), limit. Returns: object

get_user_playlistsA

Fetch a paginated list of the current user's Spotify playlists.

Parameters

limit : int, optional Maximum number of playlists to return (1–50, default: 20). offset : int, optional Zero-based index of the first playlist to return (default: 0).

Returns

dict Keys: total, limit, offset, playlists.

Raises

ValueError If limit is outside [1, 50]. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: limit, offset. Returns: object

play_contextA

Start playback of a Spotify context (playlist, album, or artist).

Parameters

context_uri : str Spotify URI (e.g. spotify:playlist:<id>) or bare playlist ID.

Returns

dict {"status": "playing", "context_uri": str}

Raises

spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: context_uri (required). Returns: object

play_pauseA

Control Spotify playback – play, pause, or toggle the current state.

Parameters

action : str, optional One of "play", "pause", or "toggle" (default).

Returns

dict {"status": "playing" | "paused" | "no_active_device"}

Raises

ValueError If action is not one of the accepted values. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: action. Returns: object

search_and_addA

Search for a track and add the top result to a playlist in one step.

Parameters

query : str Free-text search query (e.g. "Shape of You Ed Sheeran"). playlist_id : str Spotify playlist ID or full URI to add the track to.

Returns

dict Keys: track_name, artists, track_uri, playlist_id.

Raises

ValueError If query is blank or the search returns no results. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: query (required), playlist_id (required). Returns: object

skip_trackA

Skip to the next or previous track on the active Spotify device.

Parameters

direction : str, optional "next" (default) to skip forward, "previous" to go back.

Returns

dict {"status": "skipped_next" | "skipped_previous" | "no_active_device"}

Raises

ValueError If direction is not "next" or "previous". spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: direction. Returns: object

switch_userA

Switch the active Spotify user profile.

Updates the server's internal state so all subsequent tool calls use the token cache for name. Each user's token lives in .cache-<name> in the project root; pass "default" to return to the primary account.

Parameters

name : str User profile name. Must have a corresponding cache file or be "default".

Returns

dict {"previous_user": str, "current_user": str}

Raises

ValueError If name is blank or no token cache exists for that profile.

Inputs: name (required). Returns: object

transfer_playbackA

Transfer Spotify playback to a specific device.

Parameters

device_id : str The Spotify device ID to transfer playback to.

Returns

dict {"status": "transferred", "device_id": str}

Raises

ValueError If device_id is blank. spotipy.SpotifyException Propagated if the Spotify API returns a non-2xx response.

Inputs: device_id (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.3/5.0

    Scored across 14 tools

    Disambiguation5/5

    Every tool serves a distinct resource or action: playback control (play_pause, skip_track, transfer_playback), queue management (add_to_queue), context playback (play_context), and playlist operations (create, list, add, search_and_add, generate). No two tools have overlapping purposes, and the descriptions make each tool's role clear.

    Naming Consistency5/5

    All tool names follow a consistent lowercase snake_case pattern with a verb-first structure (e.g., get_devices, create_playlist, add_to_queue). Compound names like play_pause and search_and_add remain readable and do not break the overall convention.

    Tool Count5/5

    With 14 tools, the server is well-scoped for its purpose: it provides essential playback controls, playlist management, and a few convenience functions like generate_playlist and switch_user. The count feels appropriate for a Spotify MCP server without being bloated or too thin.

    Completeness3/5

    Core workflows are covered: playback (play/pause/skip/queue/devices) and playlist creation/listing/adding tracks. However, notable gaps exist, such as removing tracks from a playlist, deleting/updating playlists, and missing playback features like seek, volume, or shuffle. These would require external workarounds.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables interaction with Spotify through MCP, providing tools for searching tracks, artists, albums, playlists, and accessing user data like top tracks and recently played.
      -
    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables controlling Spotify playback, managing playlists, searching music, and accessing library features through any MCP-compatible AI client. Provides 34 tools for full Spotify integration.
      -
    • A
      license
      Not graded
      quality
      B
      maintenance
      Exposes Spotify search, playlist, library, discovery, and playback tools to AI assistants over MCP Streamable HTTP. Supports Spotify OAuth, multi-client MCP OAuth with PKCE and dynamic client registration, encrypted token storage, and self-hosted Docker deployment.
      1
      AGPL 3.0