spotify-mcp MCP server
mcp-name: io.github.jamiew/spotify-mcp
MCP server connecting Claude with Spotify. This fork of varunneal/spotify-mcp adds smart-batching tools and advanced playlist features that optimize API usage.
This one runs locally over stdio. If you want a remote MCP server instead — hosted, OAuth in the browser, no local install for the people connecting to it — see jamiew/spotify-mcp-cloudflare: a sibling Spotify MCP on Cloudflare Workers that you can deploy yourself in a few minutes, and a decent worked example of remote-MCP auth on Workers generally.
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 >= 0.54.
1. Get Spotify API keys
- Create an app at developer.spotify.com/dashboard.
- Add redirect URI
http://127.0.0.1:8888— it must match exactly what you set below. - 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):
{
"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
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
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:
[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):
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 withuvx spotify-mcp-jamiew, and set env varsSPOTIFY_CLIENT_ID,SPOTIFY_CLIENT_SECRET, andSPOTIFY_REDIRECT_URI=http://127.0.0.1:8888.
Run from source (local dev)
git clone https://github.com/jamiew/spotify-mcp.git
cd spotify-mcp
uv sync
Then point your client at the checkout:
{
"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:
npx @modelcontextprotocol/inspector uv --directory /path/to/spotify_mcp run spotify-mcp
Contributors
Metadata
Release files for spotify-mcp-jamiew 0.6.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| spotify_mcp_jamiew-0.6.1.tar.gz | 5.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spotify_mcp_jamiew-0.6.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.0 MB
Release files / spotify_mcp_jamiew-0.6.1.tar.gz
| Download URL | spotify_mcp_jamiew-0.6.1.tar.gz |
|---|---|
| Size | 5.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9948f1812433a445f23ef42482b7f188a256b13fbb14217943a6700bd261ef14
|
|
BLAKE2b-256 checksum How to use checksums |
3fd2774c463c145ffce88680f44f73c84d9a727f4ada3e450256451344d2a71f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / spotify_mcp_jamiew-0.6.1-py3-none-any.whl
| Download URL | spotify_mcp_jamiew-0.6.1-py3-none-any.whl |
|---|---|
| Size | 34.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a1218ab22a246a81e1cd8b9075669ffd47afc0bcecfde3418ad408df9d4a210b
|
|
BLAKE2b-256 checksum How to use checksums |
60074bb27af1188c214b6b6dbc54f46b3e7fe06b11635188eb94fa7c0c1856d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency log