4.7 KiB
Spotify MCP Server — Design Spec
Date: 2026-05-22
Overview
A Python MCP server that exposes Spotify library and playlist management as tools for Claude. Connects via stdio transport (Claude launches it as a subprocess). Authentication uses the OAuth PKCE flow via spotipy; tokens are cached locally and auto-refreshed.
Project Structure
mcp-spotify/
├── server.py # MCP server entry point, tool registrations
├── spotify_client.py # Thin wrapper around spotipy (auth + API calls)
├── pyproject.toml # Dependencies: mcp, spotipy, python-dotenv
├── .env.example # SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET, SPOTIPY_REDIRECT_URI
└── README.md # Setup instructions (creating a Spotify Developer app, registering with Claude Code)
Dependencies
mcp— official MCP Python SDK (stdio server)spotipy— Spotify Web API client with built-in OAuth and token cachingpython-dotenv— load.envat startup
MCP Tools
| Tool | Description | Parameters |
|---|---|---|
list_playlists |
List the authenticated user's playlists | — |
get_playlist_tracks |
Get all tracks in a playlist with full metadata | playlist_id: str |
list_saved_tracks |
Get the user's liked/saved tracks | limit: int = 50 |
search_tracks |
Search Spotify for tracks | query: str, limit: int = 10 |
create_playlist |
Create a new playlist | name: str, description: str = "", public: bool = False |
add_tracks_to_playlist |
Add tracks to a playlist by URI | playlist_id: str, track_uris: list[str] |
Track data returned by get_playlist_tracks
Each track entry includes:
name— track titleartists— list of artist namesalbum— album nameduration_ms— duration in millisecondsduration— duration formatted asmm:sspopularity— Spotify popularity score (0–100)uri— Spotify track URI (used to add tracks to playlists)added_at— ISO timestamp of when the track was added to the playlist
All fields come from a single paginated API call (playlist_items); no additional requests needed.
Authentication
Setup (once per user)
- Create a Spotify Developer app at developer.spotify.com
- Set the redirect URI to
http://localhost:8888/callback - Copy
.env.exampleto.envand fill in:SPOTIPY_CLIENT_ID=<your_client_id> SPOTIPY_CLIENT_SECRET=<your_client_secret> SPOTIPY_REDIRECT_URI=http://localhost:8888/callback
First run
spotify_client.py initializes spotipy.Spotify with SpotifyOAuth. spotipy opens the browser to Spotify's auth page. After login, Spotify redirects to localhost:8888/callback. spotipy exchanges the code for tokens and caches them to ~/.cache/spotipy/<username>.cache.
Subsequent runs
spotipy reads the cached token. If expired, it silently refreshes using the stored refresh token. No browser interaction needed.
OAuth scopes
playlist-read-private
playlist-read-collaborative
playlist-modify-public
playlist-modify-private
user-library-read
Architecture & Data Flow
Claude (MCP client)
│ stdio (JSON-RPC)
▼
server.py (mcp SDK — tool definitions + request routing)
│ Python function calls
▼
spotify_client.py (spotipy wrapper)
│ HTTPS
▼
Spotify Web API
server.py owns all MCP concerns: tool schemas, request parsing, response formatting.
spotify_client.py owns all Spotify concerns: auth, API calls, pagination, data shaping.
Error Handling
- Startup: If required env vars are missing, raise immediately with a descriptive message before the server accepts any connections.
- API errors:
spotipyraisesSpotifyExceptionfor all API-level errors. These are caught inserver.pyand returned as MCP error responses containing the HTTP status code and Spotify error message. - Token expiry: Handled transparently by spotipy's
SpotifyOAuth— no special handling needed.
Claude Code Registration
Add to ~/.claude/settings.json (or project .claude/settings.json):
{
"mcpServers": {
"spotify": {
"command": "python",
"args": ["/path/to/mcp-spotify/server.py"],
"env": {
"SPOTIPY_CLIENT_ID": "<your_client_id>",
"SPOTIPY_CLIENT_SECRET": "<your_client_secret>",
"SPOTIPY_REDIRECT_URI": "http://localhost:8888/callback"
}
}
}
}
Alternatively, env vars can be loaded from .env by python-dotenv and the env block omitted.
Testing
No automated tests. The server is a thin adapter over spotipy and the Spotify Web API; mocking the API would test the wrong thing. Verification is done by running the server and calling tools from Claude.