spotify-mcp-service-gateway
A framework component for external AI agents to orchestrate Spotify media control, library administration, and user experience enrichment via Model Context Protocol (MCP). Facilitates music retrieval, playback initiation, and custom playlist curation through an integrated API surface.
Author

marcelmarais
Quick Info
Actions
Tags
Spotify MCP Service Gateway
This is a specialized, low-footprint Model Context Protocol (MCP) endpoint designed to permit sophisticated conversational agents (such as Claude, Cursor, or other compatible systems) granular command over the user's Spotify environment.
Detailed Contents
- [Illustrative Use Cases](#illustrative-use-cases) - [Exposed API Functions](#exposed-api-functions) - [Data Retrieval Endpoints](#data-retrieval-endpoints) - [Media Collection Management](#media-collection-management) - [Playback Control & Content Generation](#playback-control--content-generation) - [Deployment & Configuration](#deployment--configuration) - [Prerequisites Checklist](#prerequisites-checklist) - [Installation Steps](#installation-steps) - [Spotify Application Credentialing](#spotify-application-credentialing) - [API Credential Initialization](#api-credential-initialization) - [Authorization Flow Summary](#authorization-flow-summary)Illustrative Use Cases
- _"Commence playback of the debut single by the artist Elvis."
- _"Fabricate a new compilation named 'Swift/Slipknot Hybrid' featuring tracks from both artists."
- _"Duplicate every track from my 'Intense Workouts' list into my 'Focus Music' list, maintaining original ordering."
Exposed API Functions
Data Retrieval Endpoints
-
searchCatalogue
-
Purpose: Query the Spotify catalog for music items.
- Arguments:
query(string): Search term.type(string): Target entity type (track, album, artist, playlist).limit(number, optional): Maximum result count (constrained between 10 and 50).
- Returns: A collection of matching entities, including unique identifiers and metadata.
-
Invocation Example:
searchCatalogue("Rhapsody in Blue", "album", 15) -
getPlaybackStatus
-
Purpose: Fetch metadata for the currently active audio stream.
- Arguments: None required.
- Returns: An object detailing the current track's title, primary artist, associated album, current position, total duration, and playback state (playing/paused).
-
Invocation Example:
getPlaybackStatus() -
listUserPlaylists
-
Purpose: Retrieve the authenticated user's owned or subscribed playlists.
- Arguments:
limit(number, optional): Pagination limit (defaults to 20).offset(number, optional): Starting index for results (defaults to 0).
- Returns: An array detailing each playlist's unique identifier, nomenclature, track count, and visibility setting.
-
Invocation Example:
listUserPlaylists(50, 0) -
fetchPlaylistContents
-
Purpose: Extract the track listings from a specified playlist.
- Arguments:
playlistId(string): The Spotify unique identifier for the target playlist.limit(number, optional): Max tracks to return per call (default: 100).offset(number, optional): Index offset for fetching subsequent batches (default: 0).
- Returns: A sequence of track objects, each containing identifiers, titles, contributing artists, album association, length, and timestamp of addition.
-
Invocation Example:
fetchPlaylistContents("4o7h3gPjA9oz9GiPac4AsH4n") -
queryRecentActivity
-
Purpose: Access the history of recently played audio content.
- Arguments:
limit(number, optional): Specifies the maximum volume of historical tracks to retrieve.
- Returns: A structured list of recently consumed tracks, or a default message if no history exists.
-
Invocation Example:
queryRecentActivity({ limit: 25 }) -
retrieveUserFavorites
-
Purpose: Obtain the collection of tracks marked as 'Liked Songs' by the user.
- Arguments:
limit(number, optional): Maximum items returned (range 1 to 50, default 50).offset(number, optional): Pagination starting point (0-indexed, default 0).
- Returns: A structured readout of favorited tracks, noting names, artists, duration, unique IDs, and the date they were added to the liked collection. Includes pagination status.
- Invocation Example:
retrieveUserFavorites({ limit: 50, offset: 100 })
Playback Control & Content Generation
-
initiatePlayback
-
Purpose: Command Spotify to begin playing content (track, album, artist, or playlist).
- Arguments:
uri(string, optional): Direct Spotify Uniform Resource Identifier (takes precedence).type(string, optional): Content category to play.id(string, optional): Spotify unique identifier for the content.deviceId(string, optional): Target playback device identifier.
- Returns: Operation confirmation status.
- Invocation Example:
initiatePlayback({ uri: "spotify:album:1bT2L9i6mQ1j2m0d2x0S7s" }) -
Alternative:
initiatePlayback({ type: "artist", id: "5U6b3k4p5z2l8w7c2f5d1e" }) -
haltPlayback
-
Purpose: Temporarily suspend the current audio stream.
- Arguments:
deviceId(string, optional): Device context for the pause command.
- Returns: Operation confirmation status.
-
Invocation Example:
haltPlayback() -
advanceTrack
-
Purpose: Jump forward to the subsequent item in the current queue or context.
- Arguments:
deviceId(string, optional): Target device context.
- Returns: Operation confirmation status.
-
Invocation Example:
advanceTrack() -
revertTrack
-
Purpose: Rewind to the preceding track in the sequence.
- Arguments:
deviceId(string, optional): Target device context.
- Returns: Operation confirmation status.
-
Invocation Example:
revertTrack() -
constructPlaylist
-
Purpose: Provision a brand new playlist container within the user's library.
- Arguments:
name(string): Required title for the new list.description(string, optional): Narrative context for the playlist.public(boolean, optional): Visibility setting (defaults to private/false).
- Returns: Details of the newly created playlist, including its ID and web link.
-
Invocation Example:
constructPlaylist({ name: "Chill Coding Beats", public: true }) -
injectTracksIntoPlaylist
-
Purpose: Append specified tracks to an existing playlist entity.
- Arguments:
playlistId(string): Identifier of the destination playlist.trackUris(array): A list of track URIs or IDs slated for insertion.position(number, optional): The index at which to insert the tracks.
- Returns: Confirmation of success and the resulting playlist snapshot identifier.
-
Invocation Example:
injectTracksIntoPlaylist({ playlistId: "7xT8yXpA9oz9GiPac4AsH4n", trackUris: ["spotify:track:1aB2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q"] }) -
enqueueContent
-
Purpose: Add specified content to the immediate playback queue.
-
- Arguments:
uri(string, optional): Spotify URI of the queued item (overrides type/id).type(string, optional): Content classification (track, album, etc.).id(string, optional): Spotify ID for the item.deviceId(string, optional): Target device for queuing.
- Returns: Operation confirmation status.
- Invocation Example:
enqueueContent({ type: "playlist", id: "37i9dQZF1DXcBWIGoYBM5M" }) - Alternative:
enqueueContent({ uri: "spotify:track:6rqhFgbbKwnb9MLmUQDhG6" })
Media Collection Management
-
fetchAlbumDetails
-
Purpose: Retrieve comprehensive metadata for one or multiple Spotify Album identifiers.
- Arguments:
albumIds(string|array): One or several album identifiers (maximum batch size of 20).
- Returns: Detailed album object(s) including creators, launch date, taxonomy, track count, and ID. Returns a summary list for multiple IDs, detailed view for one.
-
Invocation Example:
fetchAlbumDetails(["5g4xW3Sj3l8j7w9p1s4e8t", "2rT3xW4y5z6a7b8c9d0e1f2g3h4i5j6k"]) -
getAlbumTracklist
-
Purpose: Access the songs comprising a specific album, supporting offset-based retrieval.
- Arguments:
albumId(string): The Spotify identifier for the album.limit(number, optional): Maximum tracks fetched per request (1-50).offset(number, optional): Pagination index (starting at 0).
- Returns: A list of tracks specific to that album, showing titles, primary artists, runtimes, and internal IDs. Pagination metadata is included.
-
Invocation Example:
getAlbumTracklist("5g4xW3Sj3l8j7w9p1s4e8t", 20, 0) -
modifySavedAlbums
-
Purpose: Persist or discard albums from the user's primary music collection ("Your Music").
- Arguments:
albumIds(array): List of Spotify album identifiers (max 20).action(string): Operation: must be either "save" or "remove".
- Returns: Status confirmation message for the batch operation.
-
Invocation Example:
modifySavedAlbums({ albumIds: ["4aawyAB9vmqN3uQ7FjRGTy"], action: "save" }) -
verifySavedAlbumStatus
-
Purpose: Determine the saved status of provided albums within the user's library.
- Arguments:
albumIds(array): Identifiers for the albums to verify (max 20).
- Returns: A mapping indicating the saved/unsaved status for each submitted ID.
- Invocation Example:
verifySavedAlbumStatus(["4aawyAB9vmqN3uQ7FjRGTy", "1DFixLWuPkv3KT3TnV35m3"])
Deployment & Configuration
Prerequisites Checklist
- Runtime Environment: Node.js version 16 or greater installed.
- Account Requirement: Active Spotify Premium subscription.
- API Credentials: A previously registered Spotify Developer Application.
Installation Steps
bash git clone https://github.com/marcelmarais/spotify-mcp-server.git cd spotify-mcp-server npm install npm run build
Spotify Application Credentialing
- Navigate to the Spotify Developer Portal.
- Authenticate using your Spotify credentials.
- Initiate the creation of a new application instance.
- Provide required nomenclature (Name/Description).
- Confirm acceptance of the usage agreements and finalize creation.
- Your Client ID will be displayed on the summary page.
- Reveal and record your Client Secret.
- Edit the application settings ('Edit Settings') to stipulate a functional Redirect URI (e.g.,
http://127.0.0.1:8888/callback). - Commit the updated configuration.
API Credential Initialization
Generate a spotify-config.json file in the root directory, derived from the provided template:
bash
Clone the example template
cp spotify-config.example.json spotify-config.json
Populate the file with your secrets:
{ "clientId": "your-client-id-here", "clientSecret": "your-client-secret-here", "redirectUri": "http://127.0.0.1:8888/callback" }
Authorization Flow Summary
The service utilizes the OAuth 2.0 standard for securing access. Follow the procedure below:
- Execute the dedicated authorization routine:
bash npm run auth
-
The execution will output a URL; open this URL within any web browser.
-
Log in to your Spotify account and grant the necessary permissions to the application.
-
Spotify redirects the browser to your configured URI, embedding an authorization code in the query parameters.
-
The initiated script intercepts this code and immediately performs a back-channel exchange to obtain valid access and refresh tokens.
-
These sensitive tokens, along with expiry metadata, are persisted in
spotify-config.json, which will then resemble:
{ "clientId": "...", "clientSecret": "...", "redirectUri": "...", "accessToken": "BQAi9Pn...kKQ", "refreshToken": "AQDQcj...7w", "expiresAt": 1677889354671 }
- The server is configured to proactively use the refresh token to renew the access token prior to expiration.
Integration with Conversational Environments (Claude Desktop, Cursor, and VsCode Cline)
To enable Claude Desktop to utilize this gateway, augment your Claude configuration file:
{ "mcpServers": { "spotify": { "command": "node", "args": ["spotify-mcp-server/build/index.js"] } } }
For the Cursor IDE, access the MCP configuration panel via Command + Shift + J within Settings. Introduce a new server entry using the execution path:
bash node /full/path/to/spotify-mcp-server/build/index.js
For Cline integration, ensure your specific MCP configuration file (cline_mcp_settings.json) includes the definition, optionally specifying tools that require no user confirmation for execution:
{ "mcpServers": { "spotify": { "command": "node", "args": ["~/../spotify-mcp-server/build/index.js"], "autoApprove": ["getPlaybackStatus", "queryRecentActivity"] } } }
Adding functions to the autoApprove list bypasses the need for manual agent confirmation when invoking those specific read operations.
