<div align="center">
# Spotify MCP Server
**A comprehensive Model Context Protocol (MCP) server for Spotify**
Provides 51 granular tools perfect for building dynamic HUDs, music visualizers, and AI-powered music control interfaces
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org)
[](https://www.typescriptlang.org/)
[](https://github.com/modelcontextprotocol/sdk)
</div>
---
<div align="center">
## Why This MCP Server?
</div>
<div align="center">
This MCP server is specifically designed for **dynamic HUD applications** where you need individual data points.
Instead of parsing large JSON responses, each tool returns exactly what you need.
</div>
<div align="center">
| Use Case | Traditional Approach | This Server |
|----------|---------------------|-------------|
| Get track name | Parse JSON → Extract `item.name` | `spotify_get_track_name` → Direct value |
| Get artist | Parse JSON → Extract `item.artists[0].name` | `spotify_get_artist_name` → Direct value |
| Show countdown timer | Parse JSON → Calculate remaining time → Format | `spotify_get_time_remaining_formatted` → "3:24" |
| Progress bar | Parse JSON → Calculate percentage | `spotify_get_track_progress_percentage` → "67" |
| Play/pause button | Parse JSON → Check `is_playing` | `spotify_is_playing` → "true" or "false" |
</div>
---
<div align="center">
## Complete Tool Coverage
**51 tools organized into 9 categories for maximum flexibility**
</div>
<div align="center">
| Category | Tool Count | Description |
|----------|------------|-------------|
| Bulk State Tools | 2 | Get complete playback state or track info in one call |
| Granular Track Info | 16 | Individual tools for artist, track name, album, duration, progress, artwork, and more |
| Granular Device Info | 6 | Get device name, type, volume, ID, and active status individually |
| Granular Playback State | 5 | Individual tools for play state, shuffle, repeat mode, and context |
| Playback Control | 7 | Play, pause, next, previous, seek, shuffle, and repeat controls |
| Volume & Device Control | 2 | Set volume and transfer playback between devices |
| Queue Management | 3 | View queue, add tracks, and see recently played |
| Search & Discovery | 5 | Search tracks, albums, artists, and get detailed information |
| Library Management | 5 | Manage saved tracks and playlists |
</div>
---
<div align="center">
## Key Features
</div>
<div align="center">
| Feature | Description |
|---------|-------------|
| Granular Data Access | 51 specialized tools for precise data retrieval |
| HUD Optimized | Returns plain text values perfect for UI components |
| Production Ready | Comprehensive error handling and automatic token refresh |
| Full Test Coverage | 94 tests covering all 51 tools and edge cases |
| Type Safe | Built with TypeScript and Zod schema validation |
| OAuth Authentication | Automatic token management and refresh |
| Zero Dependencies | Only requires Node.js 18+ and Spotify account |
</div>
---
<div align="center">
## Installation
</div>
<div align="center">
| Step | Instructions |
|:---:|:---|
| **1. Prerequisites** | • Node.js 18+ installed<br>• Spotify Account (Premium recommended)<br>• Spotify Developer App credentials |
| **2. Get Credentials** | 1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)<br>2. Create a new app<br>3. Note your **Client ID** and **Client Secret**<br>4. Add `http://localhost:8888/callback` to Redirect URIs |
| **3. Install** | `npm install` |
| **4. Configure** | Copy example env: `cp .env.example .env`<br><br>Edit `.env` with credentials:<br>`SPOTIFY_CLIENT_ID=your_id`<br>`SPOTIFY_CLIENT_SECRET=your_secret`<br>`SPOTIFY_REDIRECT_URI=http://localhost:8888/callback` |
| **5. Authenticate** | `npm run auth`<br>*(Opens browser to log in and saves tokens)* |
| **6. Build** | `npm run build` |
| **7. Configure Client** | Add to `claude_desktop_config.json`:<br><pre>{<br> "mcpServers": {<br> "spotify": {<br> "command": "node",<br> "args": ["/PATH/TO/dist/index.js"],<br> "env": { ... }<br> }<br> }<br>}</pre> |
</div>
---
<div align="center">
## Usage
Once configured, restart your MCP client and you'll have access to all 51 tools!
### Example Queries
| Category | User Query | Tool Used |
|:---:|:---|:---|
| **Dynamic HUDs** | "What's the current track name?" | `spotify_get_track_name` |
| | "Get the artist" | `spotify_get_artist_name` |
| | "What's the time remaining?" | `spotify_get_time_remaining_formatted` |
| | "What's the playback progress percentage?" | `spotify_get_track_progress_percentage` |
| | "Is music playing?" | `spotify_is_playing` |
| **Playback Control** | "Pause the music" | `spotify_pause` |
| | "Skip to the next song" | `spotify_next` |
| | "Set volume to 50%" | `spotify_set_volume` |
| | "Enable shuffle" | `spotify_set_shuffle` |
| **Discovery** | "Search for tracks by The Beatles" | `spotify_search` |
| | "Add this song to my library" | `spotify_save_track` |
</div>
---
<div align="center">
## Complete API Reference
</div>
<div align="center">
### Bulk State Tools (2)
</div>
<div align="center">
| Tool | Returns | Use Case |
|------|---------|----------|
| `spotify_get_playback_state` | Complete playback state (JSON) | Get all playback info at once |
| `spotify_get_current_track` | Complete track info (JSON) | Get all track info at once |
</div>
<div align="center">
### Granular Track Info Tools (16)
</div>
<div align="center">
| Tool | Returns | Perfect For |
|------|---------|-------------|
| `spotify_get_track_name` | Track name only | HUD track display |
| `spotify_get_artist_name` | Primary artist name | HUD artist display |
| `spotify_get_all_artists` | All artists (comma-separated) | Full artist credits |
| `spotify_get_album_name` | Album name only | HUD album display |
| `spotify_get_track_duration_ms` | Duration in milliseconds | Calculations |
| `spotify_get_track_duration_formatted` | Duration as "M:SS" | HUD duration display |
| `spotify_get_track_progress_ms` | Current position in ms | Calculations |
| `spotify_get_track_progress_formatted` | Current position as "M:SS" | HUD position display |
| `spotify_get_time_remaining_ms` | Time left in ms | Calculations |
| `spotify_get_time_remaining_formatted` | Time left as "M:SS" | HUD countdown timer |
| `spotify_get_track_progress_percentage` | Progress as 0-100 | Progress bars |
| `spotify_get_track_uri` | Spotify URI | Playback control |
| `spotify_get_track_id` | Spotify ID | API calls |
| `spotify_get_album_art_url` | Album artwork URL | HUD artwork display |
| `spotify_get_track_explicit` | "true" or "false" | Explicit content indicator |
| `spotify_get_track_popularity` | Popularity 0-100 | Track metrics |
</div>
<div align="center">
### Granular Device Tools (6)
</div>
<div align="center">
| Tool | Returns | Perfect For |
|------|---------|-------------|
| `spotify_get_device_name` | Device name | HUD device display |
| `spotify_get_device_type` | Device type | Device icons |
| `spotify_get_device_volume` | Volume 0-100 | Volume displays |
| `spotify_get_device_id` | Device ID | Device switching |
| `spotify_is_device_active` | "true" or "false" | Active device indicator |
| `spotify_get_available_devices` | All devices (JSON) | Device selection |
</div>
<div align="center">
### Granular Playback State Tools (5)
</div>
<div align="center">
| Tool | Returns | Perfect For |
|------|---------|-------------|
| `spotify_is_playing` | "true" or "false" | Play/pause button states |
| `spotify_get_shuffle_state` | "true" or "false" | Shuffle button states |
| `spotify_get_repeat_mode` | "off", "track", or "context" | Repeat button states |
| `spotify_get_context_type` | Context type | Playlist/album indicators |
| `spotify_get_context_uri` | Context URI | Context switching |
</div>
<div align="center">
### Playback Control Tools (7)
</div>
<div align="center">
| Tool | Parameters | Description |
|------|------------|-------------|
| `spotify_play` | device_id?, context_uri?, uris?, position_ms? | Start/resume playback |
| `spotify_pause` | device_id? | Pause playback |
| `spotify_next` | device_id? | Skip to next track |
| `spotify_previous` | device_id? | Skip to previous track |
| `spotify_seek` | position_ms, device_id? | Seek to position |
| `spotify_set_shuffle` | state (bool), device_id? | Toggle shuffle |
| `spotify_set_repeat` | state (track/context/off), device_id? | Set repeat mode |
</div>
<div align="center">
### Volume & Device Control Tools (2)
</div>
<div align="center">
| Tool | Parameters | Description |
|------|------------|-------------|
| `spotify_set_volume` | volume_percent (0-100), device_id? | Set playback volume |
| `spotify_transfer_playback` | device_id, play? | Transfer playback to device |
</div>
<div align="center">
### Queue Management Tools (3)
</div>
<div align="center">
| Tool | Parameters | Description |
|------|------------|-------------|
| `spotify_get_queue` | - | Get current playback queue |
| `spotify_add_to_queue` | uri, device_id? | Add track to queue |
| `spotify_get_recently_played` | limit? | Get recently played tracks |
</div>
<div align="center">
### Search & Discovery Tools (5)
</div>
<div align="center">
| Tool | Parameters | Description |
|------|------------|-------------|
| `spotify_search` | query, type[], limit? | Search for tracks/albums/artists/playlists |
| `spotify_get_track_info` | track_id | Get detailed track information |
| `spotify_get_album_info` | album_id | Get detailed album information |
| `spotify_get_artist_info` | artist_id | Get detailed artist information |
| `spotify_get_artist_top_tracks` | artist_id, market? | Get artist's top tracks |
</div>
<div align="center">
### Library Management Tools (5)
</div>
<div align="center">
| Tool | Parameters | Description |
|------|------------|-------------|
| `spotify_get_saved_tracks` | limit?, offset? | Get user's saved tracks |
| `spotify_save_track` | track_id | Save (like) a track |
| `spotify_remove_saved_track` | track_id | Remove (unlike) a track |
| `spotify_get_playlists` | limit?, offset? | Get user's playlists |
| `spotify_get_playlist` | playlist_id | Get playlist details |
</div>
---
<div align="center">
## Architecture
</div>
```
spotify-mcp-server/
├── src/
│ ├── auth/
│ │ ├── setup.ts # OAuth authentication flow
│ │ └── token-manager.ts # Token storage and refresh
│ ├── tools/
│ │ └── spotify-api.ts # Spotify API wrapper
│ └── index.ts # Main MCP server with all 51 tools
├── tests/ # Comprehensive test suite (94 tests)
├── dist/ # Compiled JavaScript (generated)
├── package.json
├── tsconfig.json
├── eslint.config.mjs
└── .env # Your credentials (not committed)
```
---
<div align="center">
## Token Management
| Token Details |
|:---|
| Tokens are stored in `spotify-tokens.json` (automatically created) |
| Access tokens are **automatically refreshed** when they expire |
| You only need to run `npm run auth` once (or if tokens are revoked) |
| Tokens persist across server restarts |
</div>
---
<div align="center">
## Error Handling
The server provides clear, actionable error messages:
| Error Code | Meaning |
|:---:|:---|
| **401 Unauthorized** | Re-run `npm run auth` |
| **403 Forbidden** | Feature may require Spotify Premium |
| **404 Not Found** | No active device or track |
| **429 Rate Limit** | Too many requests, wait a moment |
</div>
---
<div align="center">
## Development
| Task | Command |
|:---:|:---|
| **Run Tests** | `npm test` (all)<br>`npm run test:watch` (watch mode)<br>`npm run test:coverage` (report) |
| **Run Linter** | `npm run lint` |
| **Clean Build** | `npm run clean && npm run build` |
| **Debugging** | Server logs to stderr |
</div>
---
<div align="center">
## Use Cases
</div>
<div align="center">
### Dynamic HUD Applications
Perfect for creating real-time music displays:
</div>
```javascript
// Get individual values for your HUD components
const trackName = await callTool("spotify_get_track_name");
const artist = await callTool("spotify_get_artist_name");
const progress = await callTool("spotify_get_track_progress_percentage");
const timeRemaining = await callTool("spotify_get_time_remaining_formatted");
const isPlaying = await callTool("spotify_is_playing");
const albumArt = await callTool("spotify_get_album_art_url");
```
<div align="center">
### Music Visualizers
Get precise timing and state info:
</div>
```javascript
const progressMs = await callTool("spotify_get_track_progress_ms");
const durationMs = await callTool("spotify_get_track_duration_ms");
const isPlaying = await callTool("spotify_is_playing");
```
<div align="center">
### AI Music Assistants
Natural language control:
</div>
```
User: "What's playing?"
AI: Uses spotify_get_track_name and spotify_get_artist_name
User: "How much time is left?"
AI: Uses spotify_get_time_remaining_formatted
User: "Skip this song"
AI: Uses spotify_next
```
---