Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
SPOTIFY_CLIENT_IDYesSpotify Client ID from your Spotify app. Required.
SPOTIFY_MCP_HISTORYNoSet to '1' to log mutations to JSONL for undo.
SPOTIFY_MCP_READONLYNoSet to '1' to hide every write tool (read-only mode).
SPOTIFY_MCP_TOOLSETSNoComma-separated list of tool groups to trim by group for hosts that cap tool counts. Example: playback,catalog

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
prompts
{
  "listChanged": true
}
resources
{
  "listChanged": true
}
completions
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
get_now_playingA

Full device/session state for what is playing right now — item, progress, plus shuffle/repeat mode, active device, and volume. For a lightweight item+progress poll use get_currently_playing instead. Also covers: get_currently_playing lightweight poll — See also: get_currently_playing.

get_currently_playingA

Lightweight poll of what is playing right now: the item and progress only. For full session state (shuffle/repeat mode, active device, volume) use get_now_playing instead. Also covers: get_now_playing full-state poll — See also: get_now_playing.

play_from_searchA

Search Spotify by name and immediately play the best match. Works for songs and podcast episodes — no URI needed.

playC

Start or resume playback. Optionally target specific content.

pauseC

Pause playback on the active device

skip_nextB

Skip to the next track in the queue or context Also covers: batch skip via skip_n — See also: skip_n, skip_previous.

skip_previousA

Skip to the previous track. If more than 3 seconds in, restarts the current track first. Also covers: batch skip via skip_n — See also: skip_n, skip_next.

seekB

Seek to a position in the current track

set_volumeC

Set playback volume (0–100)

set_shuffleC

Enable or disable shuffle mode

set_repeatA

Set repeat mode: off, context (repeat playlist/album), or track (repeat single track)

get_queueB

Get the current playback queue Also covers: enriched queue via describe_queue, snapshot via get_queue_snapshot — See also: describe_queue, get_queue_snapshot.

add_to_queueA

Add a track or episode to the end of the playback queue Also covers: bulk via batch_add_to_queue, playlist queue via queue_playlist — See also: batch_add_to_queue, queue_playlist.

get_devicesC

List available Spotify Connect devices

transfer_playbackC

Move playback to a different Spotify Connect device

handoffA

Move playback to another device preserving the current track and play position (and optionally set the target volume) — a lossless "move to the kitchen speaker"

searchA

Search Spotify's catalog for tracks, artists, albums, playlists, shows, episodes, or audiobooks. Pass types as an array (e.g. ["artist"]) to search a single kind — no track/album fallback noise. Decision guide: search (general, ≤10/type), search_deep (paginated fetch_all up to 50/type), search_fresh (tag:new last 2 weeks), search_by_isrc (exact ISRC), whats_new (personal radar from follows).

get_trackB

Get full details for a track by ID

get_artistC

Get artist info by ID

get_artist_albumsC

List an artist's albums and singles

get_albumB

Get album details and track list by ID

get_album_tracksC

List the tracks of an album with pagination

get_showB

Get full details for a podcast show

get_show_episodesA

[Deprecated] use list_show_episodes — List a podcast show's episodes with pagination. Alias kept for backward compat; forwards to same GET /shows/{id}/episodes as list_show_episodes. Resume positions require the user-read-playback-position scope. Also covers: show episode listing, paged podcast episodes.

get_episodeC

Get full details for a podcast episode

get_meA

Get the current user's Spotify profile: display name, user ID, email, country, and subscription level. Email requires the user-read-email scope; country and product require user-read-private.

get_artist_top_tracksC

Get an artist's ten most-played tracks for a market. Removed by Spotify's February 2026 Web API changes — unavailable for newer app registrations

get_available_marketsA

List the country codes of every market where Spotify is available. Removed by Spotify’s February 2026 Web API changes — unavailable for newer app registrations

get_several_tracksA

Get full details for several tracks by ID in a single call (up to 50 per request)

get_several_albumsA

Get full details for several albums by ID in a single call (up to 20 per request)

get_several_artistsB

Get full details for several artists by ID in a single call (up to 50 per request)

get_several_episodesB

Get full details for several podcast episodes by ID in a single call (up to 50 per request)

get_several_showsA

Get full details for several podcast shows by ID in a single call (up to 50 per request)

get_several_audiobooksA

Get full details for several audiobooks by ID in a single call (up to 50 per request). Audiobooks are only available in the US, UK, Canada, Ireland, New Zealand and Australia markets.

get_several_chaptersB

Get full details for several audiobook chapters by ID in a single call (up to 50 per request)

get_categoryA

Get a single Spotify browse category by ID (GET /browse/categories/{id}). Quota: 🟢 single.

search_tracksA

Search tracks only (GET /search?type=track). Quota: 🟢 single.

search_artistsA

Search artists only (GET /search?type=artist). Quota: 🟢 single.

search_albumsA

Search albums only (GET /search?type=album). Quota: 🟢 single.

search_playlistsA

Search playlists only (GET /search?type=playlist). Quota: 🟢 single.

search_showsA

Search podcast shows only (GET /search?type=show). Quota: 🟢 single.

search_episodesA

Search podcast episodes only (GET /search?type=episode). Quota: 🟢 single.

search_audiobooksA

Search audiobooks only (GET /search?type=audiobook). Audiobooks are only available in the US, UK, CA, IE, NZ and AU markets. Quota: 🟢 single.

catalog_batch_lookupA

Resolve a mixed list of Spotify URIs (tracks/albums/artists/shows/episodes/audiobooks/chapters) in partitioned batch calls. Quota: 🟡 1 per distinct type + chunking.

get_artist_singlesA

List an artist's singles only (GET /artists/{id}/albums?include_groups=single). Quota: 🟢 single.

get_artist_appearancesA

List albums an artist appears on (GET /artists/{id}/albums?include_groups=appears_on). Quota: 🟢 single.

market_validateA

Validate ISO 3166-1 market codes against GET /markets (cached) and optionally return the account market from /me. Quota: 🟢 1–2 calls.

browse_category_deepdiveA

Category → playlists → optional items peek in one call (GET /browse/categories/{id} + /playlists (+ /playlists/{id}/tracks peek)). Quota: 🟡 2–3 calls.

show_episode_searchA

Full-text search within one show's episodes (GET /shows/{id}/episodes paged + client-side q). Quota: 🟡 1–N pages (fetch_all walks).

get_top_tracksC

Get the user's most-played tracks

get_top_artistsC

Get the user's most-played artists

get_recently_playedC

Get recently played tracks with timestamps

listening_streaksB

Compute consecutive-day listening streaks from recently-played history (up to 150 items). Quota: GET /me/player/recently-played cursor walk.

top_artists_by_rangeA

Top artists for each time window with rank deltas (short vs long). Quota: up to 3× GET /me/top/artists.

taste_shift_reportB

Compare short_term vs long_term top artists+tracks: rising/falling + Jaccard similarity. Quota: 4× GET /me/top/*.

listening_reportB

Aggregate listening report: compares your top tracks between two time windows (rising / constant / fading), plus era histogram, discovery ratio, repeat overlap with recently played, and hour-of-day buckets

statsfm_taste_profileA

Taste snapshot from stats.fm: core artists, top genres, loyalty-vs-novelty balance, and day-parting (when you listen). Read-only, no auth.

taste_profileA

Taste snapshot from stats.fm: core artists, top genres, loyalty-vs-novelty balance, and day-parting (when you listen). Read-only, no auth. (Legacy alias of statsfm_taste_profile — prefer the canonical name.)

statsfm_artist_affinityA

How deep does an artist run? Lifetime intensity (share of top-artist streams) plus a recency half-life fitted to recent stream ages. Read-only, no auth.

artist_affinityA

How deep does an artist run? Lifetime intensity (share of top-artist streams) plus a recency half-life fitted to recent stream ages. Read-only, no auth. (Legacy alias of statsfm_artist_affinity — prefer the canonical name.)

statsfm_exposure_checkA

Where does a subject sit on the exposure ladder — unheard / sampled / explored / established / favorite? Evidence cites lifetime + recent counts. Read-only, no auth.

exposure_checkA

Where does a subject sit on the exposure ladder — unheard / sampled / explored / established / favorite? Evidence cites lifetime + recent counts. Read-only, no auth. (Legacy alias of statsfm_exposure_check — prefer the canonical name.)

statsfm_listening_erasA

Change points in monthly listening: groups months into eras split on top-artist turnover or >60% volume shifts. Read-only, no auth.

listening_erasA

Change points in monthly listening: groups months into eras split on top-artist turnover or >60% volume shifts. Read-only, no auth. (Legacy alias of statsfm_listening_eras — prefer the canonical name.)

statsfm_listening_sessionsA

Group recent streams into sessions: a gap longer than gap_minutes starts a new session (default 30). Read-only, no auth.

listening_sessionsA

Group recent streams into sessions: a gap longer than gap_minutes starts a new session (default 30). Read-only, no auth. (Legacy alias of statsfm_listening_sessions — prefer the canonical name.)

statsfm_forgotten_favoritesB

High-lifetime tracks with zero recent plays — favorites that fell off. Ranked by lifetime streams. Read-only, no auth.

forgotten_favoritesA

High-lifetime tracks with zero recent plays — favorites that fell off. Ranked by lifetime streams. Read-only, no auth. (Legacy alias of statsfm_forgotten_favorites — prefer the canonical name.)

statsfm_taste_recommendationsA

Bridge-mode recommendations: adjacent genres/artists between the listener’s core and the unexplored, each with evidence and a risk note. Heuristic over stats.fm tops — read-only, no auth.

taste_recommendationsA

Bridge-mode recommendations: adjacent genres/artists between the listener’s core and the unexplored, each with evidence and a risk note. Heuristic over stats.fm tops — read-only, no auth. (Legacy alias of statsfm_taste_recommendations — prefer the canonical name.)

statsfm_record_feedbackA

Record a local-only taste verdict (love/like/mixed/boring/dislike) or list stored verdicts. Never touches the network — memory for future recommendations.

record_feedbackA

Record a local-only taste verdict (love/like/mixed/boring/dislike) or list stored verdicts. Never touches the network — memory for future recommendations. (Legacy alias of statsfm_record_feedback — prefer the canonical name.)

taste_to_playlistA

Taste profile → playlist track list (DRY RUN first): blend lifetime tops with recent streams into a copy-pasteable track list. Read-only — never writes to Spotify.

taste_daily_briefA

Yesterday (or a given date) in brief: top-3 tracks, 2 revival picks, novelty share vs the lifetime core. Read-only, no auth.

taste_era_playlistA

Era window → representative track list: pick a listening era and get its playlist spec. Read-only, no auth.

taste_forgotten_bangersA

Forgotten-bangers playlist spec: lifetime tops missing from the recent sample, ranked with a revival pick. Read-only, no auth.

taste_obsession_ladderB

Obsession ladder: artists ranked by stream share, each with an exposure tier. Read-only, no auth.

taste_diamond_rotationA

Diamond-mining rotation: mid-tier lifetime tracks (rank ~20–60) absent from recent streams — deep cuts to re-polish. Read-only, no auth.

taste_weekly_recapA

Week-in-review brief: stream count, top artists/tracks of the window, busiest day, novelty share. Read-only, no auth.

taste_genre_bridgeA

Genre-bridge playlist spec: picks spanning two genres with evidence + risk per pick. Read-only, no auth.

taste_novelty_loyaltyA

Loyalty-vs-novelty report: top-5 share, recent-outside-core share, and a verdict (comfort / balanced / explorer). Read-only, no auth.

taste_listening_clockA

Listening-clock summary: day-part split (UTC), peak window, and a sequencing note for playlist order. Read-only, no auth.

taste_revival_queueA

Revival queue builder: ordered re-listen queue from forgotten favorites + dormant-affinity artists, each with a search_tracks fallback line. Read-only, no auth.

library_hygieneA

Read-only album completion & consolidation analysis over your liked tracks: flags near-complete albums worth saving in full and lone singles with nothing else liked from their artist (low confidence). Suggests only — never mutates your library.

restore_library_snapshotA

STRICTLY ADDITIVE restore of a library snapshot written by backup_library_snapshot. Adds only what is missing: saves absent tracks/albums/shows/episodes/audiobooks, follows unfollowed artists, and creates NEW playlists named 'Restored · ()' — existing playlists are never touched and nothing is ever deleted, renamed, or overwritten. dry_run defaults to TRUE (read-only preview); setting dry_run=false requires explicit interactive confirmation before any write, and restores are refused entirely in environments without confirmation support.

backup_libraryA

Snapshot your ENTIRE library to a local JSON file (read-only against Spotify): liked tracks, saved albums/shows/episodes/audiobooks, followed artists, and every playlist with its items. Walks capped at SPOTIFY_MCP_FETCH_ALL_CAP (default 500 per category). Files land in SPOTIFY_MCP_BACKUP_DIR (default ~/.spotify-mcp/backups), mode 0600.

list_backupsA

List previous library backups (newest first) with path, creation date, size, and the _meta.counts summary from each snapshot

get_artist_genresA

Get genres for an artist (focused view of GET /artists/{id})

get_categoriesB

List Spotify browse categories (GET /browse/categories)

get_category_playlistsB

Get playlists for a browse category (GET /browse/categories/{id}/playlists)

get_artist_discographyC

Get filtered discography for an artist (GET /artists/{id}/albums with album-type filtering)

resolve_artistC

Resolve an artist name or URI to a Spotify artist ID via search

save_artist_new_releasesA

Find new releases for an artist and save unsaved albums to Your Library (diffs against /me/library/contains)

watch_artistsA

Add artists to a local watchlist sidecar for new-release polling

check_artist_releasesA

Check watched artists for new releases since last check (or within lookback_days). WARNING: N artists in watchlist = N API requests. Use max_artists to budget and dry_run to preview cost.

artist_release_digestA

Show a digest of new releases since the last check for a watchlist. WARNING: N artists = N requests. Use max_artists to budget and dry_run to preview.

search_historyB

Recall past searches (local sidecar, 90-day expiry). Optionally filter by query substring.

search_rerunA

Re-execute a stored search by history id via GET /search.

search_within_playlistA

Text search inside a single playlist (client-side filter over full item walk). Quota: 🟢 GET /playlists/{id}/items paged.

search_history_statsA

Analytics over the local search-history sidecar: top queries, type breakdown, recency. Quota: 🟢 local only (no API).

audiobook_progressA

Audiobook progress rollup: chapters total, played count, current chapter, percent complete. Quota: 🟡 2 GETs (audiobook + chapters).

unsave_orphan_tracksA

Find saved tracks that appear in no playlist (orphans) and optionally unsave them. Quota: 🟡 walks library + all playlists (capped). Destructive when dry_run=false.

playlist_to_libraryB

Save all tracks of a playlist to your Liked Songs (library). Quota: 🟢 GET playlist items + PUT /me/tracks (chunked 50).

followed_playlists_auditB

Inventory of followed vs owned playlists: counts, collab, public, follower totals. Quota: 🟢 GET /me/playlists paged.

get_playlist_added_datesA

List when each track was added to a playlist (added_at + added_by). Quota: 🟢 GET /playlists/{id}/items paged.

split_playlistB

Split a playlist into N chunks (new playlists). Quota: 🟡 GET all + N POST /me/playlists + N POST items.

find_duplicate_tracks_across_playlistsA

Find tracks that appear in more than one of the given playlists (cross-playlist dupes). Quota: 🟡 N GETs (one per playlist). Also covers: find_duplicates_in_playlist (single-playlist), find_duplicate_playlists — See also: find_duplicates_in_playlist, find_duplicate_playlists.

remove_from_library_by_playlistA

Remove from Liked Songs any tracks that also appear in a given playlist. Quota: 🟡 2 GETs + DELETE (chunked).

search_advancedA

Structured advanced-search composer: builds a valid Spotify filter query from typed fields and runs it. Supported filter syntax: track:"name" artist:"name" album:"name" year:1984 year:1980-1989 genre:"pop" tag:new (last ~2 weeks) tag:hipster (lowest-popularity) isrc:CCXXXNNNNNNN upc:NNNNNNNNNNNNN. Pass whichever fields you have; they are quoted and composed for you. Quota: 🟢 one GET /search call.

track_album_bundleA

Context card for one track: the track plus its full album metadata and the album's remaining track listing (the "what am I listening to" card). Quota: 🟡 2 API calls (GET /tracks/{id} + GET /albums/{id}/tracks).

artist_discography_timelineA

[local-compute] Chronological release table (year · type · name · tracks) built from a paginated /artists/{id}/albums walk. Sorted newest first; since_year trims older rows client-side. Quota: 🟡 one paginated walk (typically several API calls on the rate-limited queue).

search_freshA

Query-scoped newness: runs your query with Spotify's tag:new filter (last ~2 weeks of releases) — per-artist/genre "what just dropped" without the dead browse/new-releases endpoint. Quota: 🟢 one GET /search call. Decision guide: search_fresh for newness-filtered hits; search (general), search_deep (paginated), search_by_isrc (ISRC-exact), whats_new (personal follows).

track_enrichment_batchA

Up to 50 track IDs → enriched rows: album release date, label and artist genres joined back onto each track via chunked several-tracks + several-albums + several-artists fan-in. Quota: 🟡 ~3 chunked API calls (one per several-* endpoint, more when chunking splits).

albums_runtime_batchA

[local-compute] Runtime per album — total and mean track length — for up to 20 albums in one pass (album objects embed the first 50 tracks, so totals are exact for albums up to 50 tracks and flagged as partial above that). Quota: 🟢 one GET /albums?ids= call.

album_track_statsA

[local-compute] Track-length statistics for one album: min/max/mean/median plus a longest-track callout, built from a paged /albums/{id}/tracks walk. Quota: 🟡 one paginated walk (usually a single call).

artist_discography_statsA

[local-compute] Discography shape for one artist: release counts by album/single/compilation, first and latest release, releases-per-year rate and the longest silence gap between releases. Quota: 🟡 one paginated /artists/{id}/albums walk (typically several API calls).

show_runtime_statsA

[local-compute] Runtime profile for one show: total and average episode runtime plus release cadence (days between episodes), built from a paged /shows/{id}/episodes walk. Quota: 🟡 one paginated walk (typically several API calls).

show_episode_timelineA

[local-compute] One show's episodes chronologically with hiatus-gap detection — any gap between consecutive release dates larger than the threshold is called out ("no episode in N days"). Quota: 🟡 one paginated /shows/{id}/episodes walk (typically several API calls).

category_resolverA

Free-text genre/vibe → best-matching browse category ID via local fuzzy match over GET /browse/categories results. REGISTRATION GATE: /browse/categories is on the #329 app-registration gated surface — on fresh registrations this short-circuits with a clear disclosure instead of a raw 403. Quota: 🟡 1–4 API calls (paged category walk).

search_by_isrcA

Exact track resolution from an ISRC via the isrc: search filter — the dedupe/relink anchor for catalog work. Quota: 🟢 one GET /search call. Decision guide: search_by_isrc for ISRC-only exact match; search/search_deep for general text, search_fresh for tag:new newness.

find_canonical_trackA

[local-compute] Given a title + artist, search all versions, group by (artist, title) and rank them — studio > album > live/remaster — to return the canonical URI plus a variant table. Quota: 🟡 1–2 GET /search calls (fallback broad search when the precise filter comes back empty).

audiobook_chapter_mapB

[local-compute] Chapter-by-chapter duration map, total runtime and the mid-point chapter for one audiobook. MARKET GATE: audiobooks are US/UK/CA/IE/NZ/AU only. Quota: 🟡 2+ API calls (GET /audiobooks/{id} + paged GET /audiobooks/{id}/chapters).

artist_collab_networkA

[local-compute] Featured/collab artists extracted from an artist's top tracks and recent albums with co-appearance counts — computed from real payloads, not the dead related-artists endpoint. NOTE: /artists/{id}/top-tracks is on the #329 registration-gated surface; if it 403s the network is computed from recent albums only, with an explicit disclosure. Quota: 🟡 1 + paginated API calls.

search_market_diffA

Same query run in two markets with the result sets diffed — availability/regional insight in one card. Quota: 🟡 2 GET /search calls (one per market).

episode_context_bundleA

Episode + parent show + neighbouring episodes (prev/next by release date) in one card. Quota: 🟡 2 API calls (GET /episodes/{id} + GET /shows/{id}/episodes).

audiobooks_by_authorA

Author catalogue via the author: search filter with client-side sorting — sort=release orders by release date (when Spotify exposes one; unknown dates sort last) and sort=length orders by chapter count as the length proxy. MARKET GATE: audiobooks are US/UK/CA/IE/NZ/AU only. Quota: 🟢 one GET /search call.

artist_genres_compactA

Up to 50 artist IDs → name·genres two-column projection (compact roster view over several-artists). Quota: 🟢 one GET /artists?ids= call.

sleep_timerA

Keep music playing and auto-pause after N minutes: registers an in-process timer (cancel-safe; calling again replaces it) that fires PUT /me/player/pause on expiry. No fade — distinct from stepped schedule_wind_down. Quota: 🟢 1 read now; 1 pause on expiry. Timer lives in this MCP server process only.

muteA

Set volume to 0 while remembering the previous level in the sidecar — one word beats volume_step ×N. unmute restores it. Quota: 🟢 1 read + 1 write.

unmuteA

Restore the volume level remembered by mute (falls back to 50% if nothing remembered). Quota: 🟢 1 write (sidecar read is local).

switch_deviceA

Transfer playback to a device by fuzzy name or sidecar label — pure handoff, no content args (complements play_on which plays content, and handoff which is pos-preserving id-only). Quota: 🟢 1 read + 1 write.

surprise_meA

"Surprise me": picks a random saved track, saved album, or owned playlist and plays it. Randomness seedable via seed for reproducible picks. Quota: 🟡 1-3 reads + 1 write (PUT /me/player/play).

skip_nA

Advance N tracks at once via N sequential POST /me/player/next calls. Quota: 🔴 N writes (1-20, one call per skip — Spotify has no batch-skip endpoint). Also covers: single skip via skip_next / skip_previous — See also: skip_next, skip_previous.

pause_everywhereA

Pause every live Connect device (attempts PUT /me/player/pause per non-restricted device) — kills the "which speaker is still playing" hunt. Quota: 🟡 1 read + N writes (one pause per live device).

volume_rampA

Generic volume ramp to a target percent over N minutes (up OR down, step-controlled, optional end-state pause/play) — a superset of schedule_wind_down (which is down-only with floor+pause). Quota: 🟢 stepped PUT /me/player/volume writes (ceil(minutes/step_minutes) calls), in-process, cancel-safe (restart replaces).

episode_bookmarkA

Bookmark the current podcast-episode position to the sidecar (title, show, progress, optional note) — where_was_i is audiobooks-only today. Quota: 🟢 1 read (GET /me/player).

episode_resumeA

Jump straight back to the newest (or a named) episode bookmark: transfer + play with position + seek (2-3 writes). Pairs with episode_bookmark. Quota: 🟡 2-3 writes.

queue_next_episodeA

Find the next unplayed episode of a show (not in recently-played and not fully played) within an episodes_back lookahead and queue it — podcast binge glue. Quota: 🟡 2-3 reads + 1 write (POST /me/player/queue).

queue_replace_via_playlistA

Honest no-clear-endpoint workaround to replace the live queue: snapshot it, optionally filter (drop dupes / keep only given artists), build a playlist, and start it as the playback context — the live queue is replaced via context switch (Spotify has no queue-clear endpoint). Quota: 🟡 1 read + 2-3 writes.

session_statsA

Session-size distribution from recently-played via detectSessions (30-min gap): session count, median/mean tracks per session, longest session, avg session length. Quota: 🟢 1-2 reads, local compute.

most_replayedA

Most-replayed tracks in the recent window: play counts per track from recently-played, deduped — "on repeat" computed locally (complements window-based listening_report). Quota: 🟢 1-2 reads, local compute.

last_heardA

For 1-10 artists: when did you last actually play them (recently-played cursor walk) + the gap — answers "when did I last listen to X?" without guessing. Quota: 🟡 2-10 pages walked (max_pages, disclosed; stops early once all found).

weekday_heatmapA

Plays bucketed by weekday × daypart (morning/afternoon/evening/night) — listening_heatmap is hour-of-day; this adds the weekly dimension. Quota: 🟢 1-2 reads, local compute.

queue_profileA

Composition profile of the current queue: unique artists, albums, track-vs-episode mix, longest consecutive block by one artist. Quota: 🟢 1 read (GET /me/player/queue), local compute.

checkpoint_playbackA

One-shot timestamped auto-named playback checkpoint (cp-2026-08-27T21:05 style) — saves you naming slots for save_playback_state. Quota: 🟢 1 read + local sidecar write.

continue_lastA

Resume the most recent checkpoint without knowing its name (sidecar lookup by saved_at). Pairs with checkpoint_playback. Quota: 🟡 2-3 writes (play + shuffle/repeat best-effort).

room_levelA

Level the room: read the active device volume and apply the same percent to every other live device. Quota: 🟡 1 read + N writes (one volume PUT per target device).

volume_reportA

Read-only volume snapshot across all devices, including sidecar presets vs live deltas — "what's the volume everywhere right now?". Quota: 🟢 1 read (GET /me/player/devices).

daily_pickA

Deterministic "banger of the day": date-seeded pick from recently-played highlights (most-played pool + seeded tiebreak) — same date, same pick. Quota: 🟢 1-2 reads, local compute.

playlist_intersectA

Keep only the tracks present in ALL of 2–10 playlists, written as one atomic replace — the missing set op (union/subtract/XOR exist). Without a target it reports the intersection read-only. Quota: 🟢 N GETs + 1 PUT when committing. Also covers: playlist_intersection (same op, unified) — See also: playlist_intersection.

playlist_add_by_searchA

"Add Radiohead Paranoid Android to Chill Mix" in one shot: search the catalog, pick the top result(s), and add the URI(s) to a playlist. Highest-traffic curation gesture. Quota: 🟡 1 search + 1 add call.

playlist_trim_to_durationA

Fit a playlist to a target runtime (e.g. "exactly 30 min for the commute"): greedy keep-first/last/random selection within ±tolerance seconds, written as one atomic replace. Complements item-count playlist_trim. Quota: 🟢 GET + 1 PUT.

saved_tracks_rouletteA

Deal N random cards from your saved tracks into a FRESH playlist — an instant rediscovery sampler. Quota: 🟡 getAllPages + 1 create + chunked adds.

playlist_sliceA

Copy a slice of one playlist — positions start..end, first/last N, or an added-at date range — into a NEW playlist. Era snapshots, side A/B, decadal splits. Quota: 🟢 GET + create + chunked adds.

playlist_names_bulk_normalizeA

One-shot name hygiene across your library: strip "(Official Copy)"-style noise, trailing "2" duplicates, apply a prefix/suffix, or renumber. Preview → commit. Quota: 🟡 GET + N PUTs (N = renamed only).

playlist_keep_onlyA

Inverse removal: keep only matching items (by uri / artist / type / query) and drop everything else — one atomic replace, no N+1 deletes. Quota: 🟢 GET + 1 PUT.

playlist_strip_episodesA

Purify a playlist after collab drift: strip every podcast EPISODE (or every TRACK) with one client-side filter + atomic replace. Quota: 🟢 GET + 1 PUT.

playlist_move_to_topA

Bring matching items (uris / artist / query) to the FRONT of a playlist in one atomic replace. Deliberately avoids Spotify reorder N+1 for large moves. Quota: 🟢 GET + 1 PUT.

playlist_exclude_artistsB

Remove every track by one or more artist IDs from a playlist — the "purge the artist" one-shot. Quota: 🟢 GET + chunked deletes.

playlist_staleness_scoreA

Local staleness check: days since the most-recent / median added_at in a playlist, a fresh/aging/stale/fossil grade, and refresh suggestions. Read-only. Quota: 🟢 1–2 GETs.

playlist_artist_heatA

Local artist-concentration check: top-artist share, an HHI concentration index, and the repeat-offender list with track counts. "Is this mix just one band?" Quota: 🟢 1 GET.

playlist_era_profileA

Local release-era profile: decade histogram, median track age, and a time-capsule verdict. Pairs with playlist_era slices. Quota: 🟢 1 GET (market refetch disclosed).

playlist_overlap_matrixB

Pairwise Jaccard overlap for 2–10 playlists — which of your mixes have drifted into the same set. Quota: 🟢 N GETs.

saved_tracks_by_artistA

List your SAVED tracks for one artist ("everything I've saved by X"): resolves the artist ID when given a name, then filters the liked shelf. Quota: 🟡 getAllPages + 1 search (name input).

saved_library_deltaA

Diff your current saved tracks/albums against a local backup snapshot (from backup_now): added since / removed since. Quota: 🟡 getAllPages walks + local file read.

library_to_playlistA

Export your saved tracks (or saved albums' first tracks) into a NEW playlist — sort by save order, cap at N, chunked adds. Quota: 🟡 getAllPages + create + chunked adds.

collab_mix_from_followedA

Build a collaborative-style mix playlist from your FOLLOWED artists' recent releases: walks /me/following (cursor-paged, capped by artists_cap), fans out one albums GET per artist plus one album GET per picked album (concurrency 5 — disclosed fan-out), takes ≤per_artist newest tracks per artist, then round-robin-merges them into a new playlist. dry_run=true (default) previews the mix. Quota: 🔴 ~artists_cap×(1+per_artist) GETs + create/adds.

quick_save_nowA

One-call "like this song": saves the currently-playing track (or the last recent recently-played tracks) straight to your library. Collapses get_currently_playing → save_to_library into a single step. 1 player read + 1 library write. dry_run previews.

morning_briefingA

Daily digest in one call: new releases from followed artists + new episodes from saved shows + per-show backlog + today's listening so far. Superset of whats_new + show_new_episodes. Quota: roughly 2 + artists + shows reads (budgeted).

monthly_listening_reportA

Calendar-month listening report: top tracks/artists, estimated minutes, active days and session count, rendered as markdown; optionally archives a sidecar snapshot for month-over-month diffs. Local compute over recently-played (90-day window — older months cannot be fully reconstructed) + /me/top short-term data. ~6 reads.

year_in_reviewA

Spotify-Wrapped substitute: top tracks/artists across all top-list time ranges, decade mix, library growth and discovery ratio, rendered as a markdown review. Local compute. Quota: ~9 reads (3 top ranges × 2 lists + library + history).

taste_checkpointA

Save a snapshot of your current top artists/tracks/genres to a dated sidecar slot for longitudinal taste tracking (pair with taste_checkpoint_diff). 2 reads, sidecar write only.

taste_checkpoint_diffA

Diff two saved taste checkpoints: new entrants, drop-offs, genre drift and Jaccard similarity. Pure local sidecar — zero API calls. List slots with from="?" or omit.

discover_weekly_diffA

This week's Discover Weekly vs the last copy in your archive playlist: what is new, what overlapped, and which tracks you already liked. 2-3 reads (+1 write only with save_after). Resolves both playlists by exact name.

dead_library_finderA

Find saved tracks that never appear in your recent history AND sit in none of your playlists — unsave candidates. Local compute over /me/tracks + playlists + history. dry_run defaults to true; disabling it actually removes the candidates.

week_in_review_playlistA

Create a "Week of " playlist from the last 7 days of plays: deduped, ordered by recency. Rerunning replaces the same playlist's content — your weekly ritual in one call. Quota: 1-3 reads + 1-3 writes. dry_run previews the tracklist.

scope_auditA

Decode the current token's granted OAuth scopes and classify every registered tool module: callable, scope-gated, or read-only. Optional probe fires one lightweight read for actionable evidence. Supports the #329 gating audit.

quota_probeA

Fire 2-3 lightweight authenticated reads and report Retry-After / quota state plus a per-endpoint 403 gating map — actionable evidence for the #330 gauntlet. Quota: 2-3 reads.

playlist_staleness_reportA

Per-playlist staleness report: newest/oldest added_at, median item age and count added in the last 90 days — find playlists rotting in place. Quota: 1 + N reads (N = playlists scanned), page-capped.

show_backlog_reportA

Per saved podcast show: unplayed episodes (resume_point), hours of backlog and newest-episode age — decide what to unsubscribe from. Quota: 1 + N reads (budgeted).

audiobook_library_progressA

All saved audiobooks with % complete and estimated time remaining, sorted by progress — what am I actually reading. Quota: 1 + N reads. NOTE: audiobook endpoints are market-gated (US/UK/CA/IE/NZ/AU) — outside these a clear error is returned.

chapter_bookmarksA

Named chapter+position bookmarks per audiobook, stored in the local sidecar (jump later via jump_to_chapter). save/list/delete. Zero API calls — pure sidecar.

artist_complete_checkB

Collector completeness: the artist's full album list vs your saved albums — what's missing, with album/single/compilation breakdown. Quota: 2 reads (artist albums + your saved albums, page-capped).

playlist_from_tagsA

Create or refresh a playlist from saved library items whose artists carry the given genre tags (the write side of tag_management — uses the same sidecar rule pattern). Quota: 2+ reads + 1-3 writes. dry_run previews the match list.

listening_journal_appendA

Attach a timestamped note to today's journal, optionally tagged with a session id or tag — makes tag_listening_session actually useful for recall. Sidecar only, zero API calls.

export_playlist_markdownA

Export one playlist as a paste-ready markdown table (the doc-friendly variant of export_playlist). 1 read.

export_shows_opmlA

Export your saved shows as OPML XML — the interchange format podcast apps speak. DISCLOSURE: the Spotify API does not expose publishers' underlying RSS feed URLs, so each OPML entry links to the Spotify show page (some apps import it, some ignore it).

sidecar_export_bundleA

One-call export of ALL local sidecar state (scenes, device presets, tags, smart rules, playback states, bookmarks, checkpoints, journal) as a single JSON for machine migration, plus a restore checklist. Zero API calls.

listening_week_in_timeB

Charts for any specific past week within the ~90-day recently-played window, via a before/after cursor walk — retro "what was I playing then". Quota: 2-6 reads.

mutation_log_exportA

Render the JSONL mutation history as a CSV or markdown report, date/uri-filtered — an audit trail you can actually read. Local file only, zero API calls.

undo_previewA

Dry-run for undo_mutation: shows exactly what a receipt-driven revert WOULD do (diff of before/after, target inversion calls) without executing. 0-2 reads.

receipt_lookupA

Find mutation receipts by id, date range or affected URI — closes the receipts loop (issue → lookup). Local, zero API calls.

export_playlist_jsonA

Full-fidelity JSON export of one playlist: items + added_at + added_by + URIs (the fields CSV/M3U lose). 1 read.

device_sync_stateC

Reconcile sidecar device labels/volume presets (and scene device hints) against the live device list; flags dead labels and can prune them. 1 read + sidecar. dry_run plans.

playlist_fill_from_searchA

Grow a playlist to N items from search queries you supply: round-robin one pick per query per pass, first unseen track match wins, chunked adds. Complements listening-data grow_playlist. Quota: 🟡 len(queries) searches + chunked adds.

playlist_expression_algebraA

Mini set-algebra over playlists: REF ∪ (REF ∩ REF) − REF → NEW playlist. Operators: ∩ (binds tightest), then ∪ and − left-assoc; ASCII aliases | + for union, & for intersection. Refs are playlist IDs or spotify:playlist: URIs; results dedupe preserving first-seen order. Quota: 🟢 N GETs + 1 write.

playlist_cover_from_trackA

Set the playlist cover from a track album art: pick by position in the playlist, pass any track URI, or default to the first track with art. Fetches the image (largest JPEG candidate ≤ 256 KB) and PUTs /playlists/{id}/images. Quota: 🟢 GET + PUT (+1 image fetch, disclosed).

library_coverage_reportA

Report coverage between your saved tracks and playlists: orphan saved tracks (liked but not in any playlist) and unsaved playlist items. Read-only.

listening_heatmapA

When do you listen? Buckets recently-played tracks into 168 hourly slots (24h x 7d) and reports peak/quiet windows. Read-only.

library_growth_reportA

How fast your library is growing — buckets saved tracks/albums/shows/episodes by added_at period (weekly/monthly/yearly). Read-only.

genre_trends_over_timeB

How your taste shifts — per-period top genres via artist genres/tags, with deltas and emerging/declining tags. Read-only.

save_discover_weeklyA

Archive your Discover Weekly into a regular playlist (creates or overwrites the archive). Resolves Discover Weekly via /me/playlists exact match first, falling back to search (unverified); dry_run previews; idempotent if archive already matches. Result echoes source identity (owner, url, verified).

save_release_radarA

Archive your Release Radar into a regular playlist (creates or overwrites the archive). Resolves Release Radar via /me/playlists exact match first, falling back to search (unverified); dry_run previews; idempotent if archive already matches. Result echoes source identity (owner, url, verified).

export_library_jsonA

Export your full library (saved tracks, albums, shows, episodes, audiobooks) to a local directory as JSON or CSV sidecar files. Respects SPOTIFY_MCP_FETCH_ALL_CAP per type; when capped, reports cap_reached + truncated and a prose footer ("first N of … — raise SPOTIFY_MCP_FETCH_ALL_CAP").

export_followed_artistsA

Export your followed artists to a local directory as JSON or CSV. Fields: uri, name, genres. The file's exported_at is the export time, not a per-artist follow date (Spotify does not expose followed_at).

export_profile_stateA

Export local sidecar stores (scenes, genre-tags, playback-ext, search-history, mutations, artist-watchlist) to a single schema-versioned JSON archive. Note: artist-watchlist defaults to ./data/artist-watchlist.json (cwd-relative, not ~/.spotify-mcp/) — a quirk flagged for future alignment.

import_profile_stateA

Restore local sidecar stores from a profile-state archive. Merge adds to existing stores; overwrite replaces them. Refuses archives newer than this server's schema version.

export_listening_historyA

Export your listening history (recently played) to a JSON or CSV sidecar by walking /me/player/recently-played with before-cursor pagination. Respects SPOTIFY_MCP_FETCH_ALL_CAP; writes file 0600 and reports path + counts. Analogous to export_library_json.

export_all_playlistsA

Export every owned (or all) playlist with metadata + items to a sidecar file. Quota: GET /me/playlists + N×GET /playlists/{id}/items; capped by fetchAllCap.

library_snapshot_diffA

Diff two portability/library sidecar JSON files (library.json or playlists.json): added/removed counts + samples. Quota: 🟢 local only (no API).

history_searchA

Search local portability/backups for files matching a query (filename substring). Quota: 🟢 local only (no API).

import_from_sidecarA

Additive restore from a portability sidecar (library.json / playlists.json): re-adds missing saved items and creates missing playlists. Skips existing. dry_run=true by default. Quota: 🟢 local read + 🟡 contains-check + writes when dry_run=false (chunked).

archive_played_episodesA

Remove fully-played episodes from your episode library in bulk (checks resume_point.fully_played). Batch DELETE /me/episodes; elicitation >50; dry_run supported.

playlist_health_checkA

Audit a playlist for unavailable, local, duplicate, and empty issues (read-only)

get_playlist_followersA

Get follower count for a playlist, optionally including public owner profile

playlist_collaboration_reportA

Report who added what to a playlist (counts + first/last timestamps, most-active)

snapshot_playlistA

Snapshot a playlist's current URIs+positions+timestamp to a sidecar JSON file (legacy, simple path playlistId→file). For transactional local snapshots with plsnapi naming, diff, and bundle tooling, use take_playlist_snapshot instead. Also covers: playlist snapshot (legacy).

diff_since_snapshotC

Compare current playlist state to a stored snapshot

remove_unavailable_playlist_itemsA

Remove unavailable (null track) items from a playlist — actionable companion to playlist_health_check. Targets only unavailable occurrences by position so healthy copies are preserved. Read-only dry_run preview available.

find_duplicate_playlistsA

Scan your playlists for exact and near-duplicate track sets. Exact = identical URI sets (order-insensitive); near = Jaccard overlap >= threshold. Read-only. Also covers: find_duplicates_in_playlist, find_duplicate_tracks_across_playlists — See also: find_duplicates_in_playlist, find_duplicate_tracks_across_playlists.

list_playlist_snapshotsB

List stored snapshots (optionally filtered by playlist_id)

batch_add_to_playlistA

Add tracks from multiple source URIs (tracks, albums, artists, playlists) to a target playlist in one call. Dedupes within the batch and optionally against the existing playlist. Batches writes in groups of 100. Dry-run previews without writing. Elicitation for 100+ tracks.

copy_playlistB

Duplicate an existing playlist into a new playlist, preserving track order. Creates the new playlist then adds tracks in batches of 100. Dry-run reports what would be created.

move_items_between_playlistsA

Bulk rehome items between playlists. Mode copy keeps the source intact; mode move removes from source after copying. Supports dedupe against target and optional name/artist filter.

pin_playlistC

Follow (pin) a playlist to your library. PUT /playlists/{id}/followers.

unpin_playlistB

Unfollow (unpin) a playlist. DELETE /playlists/{id}/followers. Supports dry_run and elicitation for bulk use.

playlist_template_applyA

Create an instant mood/vibe playlist from a template (focus, wind-down, gym, commute) composed from your existing listening data. Creates a new playlist and fills it.

queue_playlistA

Queue all tracks from a playlist/album/artist URI in order (cap 200). mode=append adds to end; mode=replace is not supported — Spotify has no queue-clear endpoint. Also covers: single add via add_to_queue, bulk via batch_add_to_queue — See also: add_to_queue, batch_add_to_queue.

save_queue_as_playlistA

Capture the current playback queue as a durable playlist. Reads GET /me/player/queue, creates (or appends to) a playlist, adds URIs in batches of 100 preserving order. Handles mixed track/episode URIs.

batch_add_to_queueA

Add multiple URIs to the playback queue in one shot. POSTs each URI to /me/player/queue and returns a summary of queued/failed counts. Quota: 🟡 N writes (one POST per URI). Also covers: single add via add_to_queue, playlist queue via queue_playlist — See also: add_to_queue, queue_playlist.

save_playback_stateB

Snapshot current playback state to a named local slot (sidecar JSON).

restore_playback_stateA

Restore a saved playback state snapshot (seeks, shuffle/repeat, queue context) to a device.

list_playback_statesA

List saved playback state snapshots from the local sidecar.

rename_deviceA

Rename a device locally (sidecar label — Spotify has no rename endpoint).

set_device_volume_presetB

Store a per-device volume preset (0–100) in the local sidecar.

apply_device_presetsB

Apply all stored per-device volume presets via PUT /me/player/volume.

list_device_presetsA

List stored device name labels and volume presets.

tag_listening_sessionB

Tag a listening session (auto-detected 30-min gaps from recently-played) with labels.

replay_sessionC

Replay a tagged listening session: queue its tracks or create a playlist.

list_sessionsB

List tagged listening sessions (optionally filter by tag). Auto-detect mode can also scan recently-played gaps.

save_smart_playlist_ruleA

Persist a smart-playlist rule to the local sidecar for later refresh (mirrors backup sidecar pattern).

refresh_smart_playlistA

Refresh a persisted smart playlist: rebuild candidates from the stored rule and recreate the playlist content.

save_show_digestA

Create or update a digest playlist from the latest show_new_episodes radar (auto-save helper).

play_onA

Play a context/uris/search query on a named device (resolves device name → id via GET /me/player/devices, then PUT /me/player/play). 🟡 (1 read + 1 write; +1 if volume/shuffle). Supports device name substring or exact id.

queue_nextB

Queue a track/episode to play next (tail insert with honest disclosure — Spotify has no insert-next API; tail placement is the API reality). Optionally notes temp-playlist workaround. 🟢 (1 write)

describe_queueA

Enriched queue view: currently playing + up-next with durations, total remaining, and source context label. 🟢 (1 read) or 🟡 (2 if include_context resolves playlist/album name). Also covers: raw queue via get_queue, snapshot via get_queue_snapshot — See also: get_queue, get_queue_snapshot.

describe_listening_sessionA

Playback history timeline from recently-played, optionally grouped into sessions (30-min gap via detectSessions). 🟢 (1 page) / 🟡 (2 pages). Read-only.

play_atB

Start playback at a specific position — accepts H:MM:SS / MM:SS / seconds string or position_ms. Wraps PUT /me/player/play with offset/position_ms. 🟢 (1 write).

device_healthA

Device availability & capability report — merges GET /me/player/devices + GET /me/player active id + sidecar labels/presets. 🟢 (1-2 reads, local merge). Read-only.

seek_relativeA

Relative seek — forward/back by delta_ms from current progress (GET /me/player then PUT /me/player/seek, clamped to [0, duration]). 🟢 (1 read + 1 write).

playback_timelineA

Progress forecast — elapsed/remaining for current track and optional queue runway, plus ETA wall-clock. 🟢/🟡 (1 read; +1 if include_queue). Read-only.

repeat_queue_toggleB

One-call queue-repeat helper — sets repeat=context/off and optionally shuffle in 1-2 writes. 🟢.

now_playing_historyA

Merged listening stream — recently-played plus currently-playing item on top (deduped). 🟡 (2 reads). Read-only.

playback_compare_statesA

Diff two saved playback snapshots (sidecar only, no API). Shows item/shuffle/repeat/progress/device/context changes. 🟢 (0 API calls).

peek_nextA

Queue lookahead — next N tracks with durations and total runway. Right-sized via max_results. 🟢 (1 read). Read-only.

get_playback_contextB

Resolve the current playback context URI (from GET /me/player) to catalog metadata — playlist/album/artist/show name, owner, track count. 🟢/🟡 (1-2 reads). Read-only.

volume_stepA

Nudge volume up/down by a step (reads current volume via GET /me/player, then PUT /me/player/volume clamped 0-100). 🟡 (1 read + 1 write).

market_availabilityA

Per-entity multi-market preview — checks if a track/episode/album is playable in each of 1-10 given markets (N× GET /{type}/{id}?market=X). Reports per-market available/404 plus full available_markets. 🟡 (N reads, 1-10). Read-only.

spotify_doctorA

Run local diagnostics: token presence/expiry, auth-time scopes vs write tools enabled by active toolsets, Premium gating notes, rate-limit cooldown, and a config snapshot. Read-only, best-effort live account probe for product/country when network available.

get_playback_snapshotA

Return the full current playback state compactly: device, track/episode, position, shuffle/repeat and context. Read-only.

capture_playback_positionA

Bookmark the current track, playback position and device to a local JSON file under the backup dir so it can be resumed later with resume_playback_position. Writes only a local sidecar file, never touches Spotify.

resume_playback_positionA

Resume a captured playback bookmark: transfer playback to the bookmarked device and seek to the bookmarked position. Preview by default — pass dry_run=false to execute.

list_playback_bookmarksA

List all captured playback bookmarks stored locally under the backup dir, newest last. Read-only.

delete_playback_bookmarkA

Delete one captured playback bookmark file from the local backup dir. Preview by default — pass dry_run=false to delete.

compare_devicesA

List every available Spotify device ranked by active state, then device type (Computer > Smartphone > Tablet > TV > Speaker), then volume. Read-only.

get_device_volume_reportA

Report volume_percent, supports_volume and active state for every Spotify device, highlighting the currently active device. Read-only.

plan_volume_level_across_devicesA

Plan setting every (volume-capable) Spotify device to one target volume level — returns the exact per-device PUT calls without executing anything. Read-only planner.

apply_volume_planA

Set one target volume level across all (or selected) Spotify devices via per-device PUT /me/player/volume. Preview by default — pass dry_run=false to apply.

get_queue_snapshotA

Return the full upcoming queue with per-track runtime and the total queue runtime. Read-only. Also covers: raw queue via get_queue, enriched view via describe_queue — See also: get_queue, describe_queue.

queue_runtime_reportA

Compute runtime statistics for the upcoming queue: total, average, longest and shortest items plus time remaining on the current track. Read-only.

split_queue_planA

Plan splitting the upcoming queue into runtime-bounded playlist chunks (default 30 minutes each). Preview by default — pass dry_run=false to actually create the playlists and fill them.

queue_duplicate_checkA

Check the upcoming queue for duplicate tracks/episodes and report each duplicate group with its positions and wasted runtime. Read-only.

queue_prune_planA

Plan pruning the upcoming queue: identify redundant duplicate entries (and optionally podcast episodes) to drop, and emit a clean re-queue list. Spotify has no queue-removal endpoint, so this is a plan you act on with queue playback. Read-only planner.

get_context_inspectA

Inspect the currently-playing context (playlist/album/artist) in detail, including the position of the current track within that context when it is enumerable. Read-only.

predict_next_tracksB

Predict the next N tracks that will play from the queue, each with its own runtime and the cumulative time until it plays. Read-only.

shuffle_state_reportA

Report the current shuffle and repeat state, the device they apply to and the active context. Read-only.

playback_health_checkA

Probe the playback stack end to end: token validity, available devices, current playback state and queue readability — reporting pass/fail per probe. Read-only.

listening_session_startA

Start a local listening-session log: captures the current playback snapshot into a session file under the backup dir; close it later with listening_session_close. Writes only a local sidecar file.

listening_session_closeA

Close a listening session: captures an end-of-session playback snapshot, stamps the duration and marks the session log closed. Writes only a local sidecar file.

listening_session_reportB

Report a listening session (or the most recent one when no id is given): duration, start/end snapshots and closed status. Read-only.

transfer_playback_with_stateA

Transfer playback to another device while restoring the full state: same track, position, shuffle and repeat. Preview by default — pass dry_run=false to execute the transfer.

sleep_timer_planA

Plan a sleep timer: pick the leading queue items whose cumulative runtime best approximates a target duration, then a final pause call. Read-only planner.

device_type_censusA

Census of available Spotify devices grouped by type, with counts, names and volume range per group. Read-only.

sort_playlist_planA

Plan a sort of a playlist by name, artist, album, duration, added-at date or release era and preview the exact resulting order — read-only, commits nothing (use sort_playlist_apply to commit). Quota: 🟢 1–2 GETs.

sort_playlist_applyA

Sort a playlist in place by name, artist, album, duration, added-at date or release era: backs up the current items to a local file first, then rewrites via one atomic replace. dry_run=true (default) previews only. Quota: 🟢 GET + 1 local write + 1 PUT.

reverse_playlist_planA

Plan (and optionally commit) reversing a playlist's entire order via one atomic replace — dry_run defaults to TRUE so it returns the reversed PLAN read-only. Quota: 🟢 GET + 1 PUT when committing. Also covers: playlist_reverse variant — See also: playlist_reverse.

rotate_playlist_planA

Plan (and optionally commit) rotating a playlist by N positions — positive moves the first N items to the end, negative moves the last |N| to the front; dry_run defaults to TRUE so it returns the rotated PLAN read-only. Quota: 🟢 GET + 1 PUT when committing.

interleave_playlists_planA

Plan (and optionally commit) interleaving 2–10 playlists — round-robin one track each or in N-track chunks. Without a target it returns the interleaved PLAN read-only; with target_playlist_id and dry_run=false it atomically overwrites the target. Quota: 🟢 N GETs + 1 PUT when committing.

merge_playlists_planA

Plan (and optionally commit) merging 2–10 playlists in order into a NEW playlist (optional first/last dedupe) — dry_run defaults to TRUE so it returns the merged PLAN read-only. Quota: 🟡 N GETs + create + chunked adds when committing.

playlist_difference_planA

Plan (and optionally commit) the set difference "base minus subtrahends": keep the base playlist's tracks that appear in NONE of up to 5 others. Without a target it returns the PLAN read-only; with target_playlist_id and dry_run=false it atomically overwrites the target. Quota: 🟢 ≤7 GETs + 1 PUT when committing.

playlist_intersectionA

Report the tracks present in ALL of 2–10 playlists, including which of the source playlists each common track appears in — the read-only intersection analysis (commit variants live in the set-op plan tools). Quota: 🟢 N GETs.

playlist_union_previewA

Preview the union of 2–10 playlists as a first-seen-ordered sequence, with per-playlist counts and how many tracks are unique to each — read-only, no writes. Quota: 🟢 N GETs.

extract_playlist_rangeA

Extract a positional range of a playlist (0-based start, EXCLUSIVE end; negative values count from the end) into a NEW playlist, reporting the original→new position map — dry_run defaults to TRUE. Quota: 🟢 GET + create + chunked adds when committing.

remove_playlist_rangeA

Delete a positional range of a playlist (0-based start, EXCLUSIVE end; negative values count from the end): backs up the current items to a local file first, then removes by positions + uris. dry_run defaults to TRUE. Quota: 🟢 GET + chunked deletes when committing.

dedupe_playlist_planA

Census every duplicate uri in a playlist — groups, all positions, and the exact keep-first/keep-last removal plan — read-only (commit with dedupe_playlist_apply). Quota: 🟢 1–2 GETs.

dedupe_playlist_applyA

Remove duplicate uris from a playlist keeping the first (or last) occurrence: backs up the current items to a local file first, then rewrites via one atomic replace. dry_run defaults to TRUE. Quota: 🟢 GET + 1 local write + 1 PUT when committing.

split_playlist_by_countA

Split a playlist into N roughly-equal parts, each written to a NEW playlist named " 1..N" — dry_run defaults to TRUE so it returns the part plan read-only. Quota: 🟡 GET + N creates + chunked adds when committing.

split_playlist_by_durationA

Split a playlist greedily into consecutive parts of a target runtime (e.g. 60-minute commute blocks), each written to a NEW playlist — dry_run defaults to TRUE. Quota: 🟡 GET + N creates + chunked adds when committing.

filter_playlist_by_eraA

Filter a playlist by album release era (decade and/or year window) and either report the matches read-only or — with a name and dry_run=false — write them to a NEW playlist. Quota: 🟢 GET (+ create/adds when committing).

filter_playlist_by_artistA

Filter a playlist by artist (IDs/URIs or names, matched on id or exact name) and either report the matches read-only or — with a name and dry_run=false — write them to a NEW playlist. Quota: 🟢 GET (+ create/adds when committing).

filter_playlist_by_durationA

Filter a playlist by track duration (min/max seconds) and either report the matches read-only or — with a name and dry_run=false — write them to a NEW playlist. Quota: 🟢 GET (+ create/adds when committing).

sample_playlist_tracksA

Draw a uniform random sample of N tracks from a playlist — deterministic when a seed is given (same seed + same playlist = same sample), read-only. Quota: 🟢 1–2 GETs.

playlist_table_of_contentsA

Build a table of contents for a playlist: totals, runtime, and "chapters" — contiguous position ranges grouped by the month each block was added — plus contributor counts. Read-only. Quota: 🟢 1–2 GETs.

playlist_edit_journalA

Journal a playlist's live edit history from added_at/added_by metadata: add-batches by date with who added them, collab contributors, and drift verdict — read-only, no local snapshot needed. Quota: 🟢 1–2 GETs.

move_tracks_between_playlistsA

Move matching tracks (by uris, name substring, or artist) from one playlist to another: backs up the source to a local file first, deletes the matched positions from the source, then appends them to the destination. dry_run defaults to TRUE. Quota: 🟡 GETs + chunked deletes + chunked adds when committing.

balance_playlist_pairsA

Plan (and optionally commit) rebalancing 2–10 playlists to similar track counts or runtimes: computes surplus moves from the larger to the smaller. dry_run defaults to TRUE so it returns the move PLAN read-only. Quota: 🟡 N GETs + moves when committing.

playlist_clone_liveA

Clone a playlist AS IT IS RIGHT NOW into a NEW playlist (name, optional description and publicity) — works on the live playlist, not a local snapshot; dry_run defaults to TRUE. Quota: 🟡 GET + create + chunked adds when committing.

artist_deep_diveB

Builds a one-artist dossier from the artist object plus a full discography walk: genres, release counts by group, active span, most prolific year, first/latest releases and most frequent collaborators. Quota: 1 + one paginated /artists/{id}/albums walk.

artist_discography_gapsA

Chronological discography table (oldest to newest by default) with per-release gap-in-days versus the previous release, built from a paginated /artists/{id}/albums walk. Quota: one paginated walk (several queued calls on long discographies).

artist_era_samplerA

Splits an artist discography into equal year-span eras and deterministically picks representative releases per era (albums first, earliest and fullest first) as a sampling plan. Quota: one paginated /artists/{id}/albums walk.

artist_deep_cutsA

Finds an artist's deep cuts: tracks whose (normalized) title appears on exactly one release across the artist's recent albums and singles, ranked longest-first. Quota: 2 walks + one chunked /albums?ids= fan-in (1 call per 20 releases).

artist_first_releaseB

Locates an artist's earliest release across all album groups and returns a full card for it: label, copyright, track listing and runtime via the full album payload. Quota: one paginated walk + 1 GET /albums/{id}.

artist_latest_release_reportB

Reports on an artist's most recent release: full metadata (label, copyright, track listing, runtime), days since release and the gap to the release before it. Quota: one paginated walk + 1-2 GET /albums/{id}.

artist_album_completenessA

Checks how complete your saved-album library is for one artist: canonical studio-album titles from the discography walk matched (edition-insensitively) against your /me/albums walk, with a missing list. Quota: 2 paginated walks (artist albums + saved albums).

artist_top_vs_savedA

Compares your top artists (from /me/top/artists) against your own library: saved-album and saved-track counts per top artist, ranked by library presence. Read-only; no popularity fields used. Quota: 1 /me/top/artists + 2 capped library walks.

find_collaborationsA

Finds tracks where two artists appear together: walks artist A's releases, matches artist B (name or ID) on release-level credits, then pinpoints the exact shared tracks via full-album payloads. Quota: 1-2 walks/searches + chunked /albums?ids= fan-in.

artist_collaboration_networkB

Builds a depth-2 collaboration web for one artist from discography walks alone: first-degree collaborators with co-appearance counts, then each top collaborator's recent releases to surface second-degree links and mutual connections. Quota: 1 + up to first_degree_cap additional small walks.

label_explorerB

Census of record labels across your saved albums (label comes from chunked full-album fan-in); pass a label name to list just that label's albums in your library. Quota: 1 walk + 1 /albums?ids= call per 20 albums.

year_explorerA

Time-machine view of one release year built from your own library plus a small catalog supplement: saved albums and saved tracks originally released in that year, plus top catalog matches via a year: search. Quota: 2 capped library walks + 1 /search call.

decade_sampler_planA

Read-only sampling plan across decades: groups your saved albums by release decade and deterministically picks evenly spaced representatives per decade (spread across the decade, longest-held tiebreak). Quota: 1 capped /me/albums walk.

artist_name_disambiguatorA

Resolves an ambiguous artist name: runs a typed artist search and profiles each candidate (genres, active year span and a sample release from a small discography probe) so you can pick the right ID. Quota: 1 /search + 1 small albums call per candidate.

artistwatch_new_additionsA

Watches your FOLLOWED artists for new material: walks /me/following, probes each artist's latest release and flags those released within the last N days. Quota: 1 cursor walk + 1 small albums call per followed artist.

album_representative_planA

Builds a deterministic "sample this album" plan: opener, mid-point, closer and the longest track, ordered by original position with cumulative offsets, from the full album payload. Quota: 1 GET /albums/{id} (+1 paged tracks walk above 50 tracks).

front_to_back_planA

Full front-to-back listening plan for one album: ordered track listing with cumulative start times and vinyl-style side breaks at a configurable minutes-per-side budget. Read-only. Quota: 1 GET /albums/{id} (+1 paged tracks walk above 50 tracks).

b_sides_finderB

Surfaces an artist's b-sides: tracks on singles/compilation releases whose normalized titles never appear on the artist's core album-group releases, found via discography walks + chunked full-album fan-in. Quota: 2 walks + 1 /albums?ids= call per 20 releases per group. Also covers: b_sides_detector — See also: b_sides_detector.

album_focus_reportA

Deep focus report on one album: track-by-track listing with cumulative runtime, duration statistics, edition detection (same base title elsewhere in the artist discography) and label/copyright capture. Quota: 1 GET /albums/{id} + 1 paginated discography walk.

artist_catalog_statsB

Numbers-only catalog profile for one artist: release totals by group, summed track counts, average tracks per release, active span, busiest year and median release gap, from one paginated discography walk. Quota: one paginated /artists/{id}/albums walk.

lyric_snippet_searchA

Finds candidate tracks for a remembered lyric or title fragment: runs quoted-phrase /search over tracks and ranks exact title matches first. DISCLOSURE: Spotify's public API has no lyrics endpoint, so matching is title/album-based; verify the snippet against the returned candidates. Quota: 1-2 /search calls.

new_music_from_top_artistsA

Fresh-music digest from YOUR listening: probes the latest release of each of your top artists (from /me/top/artists) and flags those released within the last N days. Quota: 1 /me/top/artists + 1 small albums call per top artist.

discovery_digestB

One combined discovery digest from your own data: latest releases from your top artists with freshness flags, a tag:new catalog search seeded with your most common top-artist genre, and a followed-artist count. Quota: ~2 + N small API calls (top artists, per-artist probes, 1 search, 1 followed walk).

era_distribution_reportA

Histogram of releases across eras: pass artist_id for that artist's discography in 5-year buckets, or omit it for your own saved-album library in decade buckets, with percentages and peak-era callouts. Quota: 1 walk (discography or saved albums).

artist_discography_explorerA

Overview stats for one artist's discography: release counts by type, first and latest releases, active span and releases per active year. Accepts an artist ID, URI, URL or name (name → closest search match). Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_album_timelineB

[local-compute] Chronological release table (oldest → newest) with inter-release gap days, median gap and the longest drought highlighted. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_era_mapA

Cluster an artist's releases into eras separated by quiet periods longer than gap_years, with one representative album per era and era spans. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_release_type_breakdownA

Break an artist's discography down by album type (album · single · compilation · appears_on): counts, first and latest per type, and sample titles. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_latest_releasesA

Fetch the most recent N releases from an artist's catalog with age in days — a quick "what's new here" read. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_reissue_detectorA

Detect alternate versions (live/deluxe/remaster/expanded editions) in an artist's release titles and group them by base title — spot the canonical release vs its variants. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_debut_release_finderA

Dig up an artist's earliest release with full detail plus everything else they released in that same year — the origin story view. Quota: 🟡 one paginated /artists/{id}/albums walk.

label_discography_explorerA

Group an artist's albums and singles by record label (via batched /albums?ids= payloads) and rank labels by release count with year ranges. Quota: 🔴 paginated walk + batched /albums lookups.

artist_discography_searchA

Full-text filter over an artist's release titles — find that live album, deluxe edition or collaboration without scrolling the whole catalog. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_decade_spanA

Histogram of an artist's releases per decade with the dominant decade called out — instantly see which era carries the catalog. Quota: 🟡 one paginated /artists/{id}/albums walk.

album_track_explorerA

Full track listing for one album with per-track cross-album duplicate counts — spot which songs are unique to this release vs recycled across the discography. Quota: 🔴 one album fetch + one paginated discography walk.

album_openers_reportA

List track 1 (the side-A opener) of every studio album by an artist, chronologically — the "how each record begins" view. Quota: 🔴 paginated walk + batched /albums lookups.

deep_cuts_finderA

Surface deep cuts: album tracks past position 2 that are neither the title track nor released as singles — the forgotten album material, per album. Quota: 🔴 paginated walk + batched /albums lookups.

b_sides_detectorB

Detect B-sides: tracks that appear on an artist's singles but never on any album — the non-LP catalogue. Also covers: b_sides_finder (same discography scan) — See also: b_sides_finder. Quota: 🔴 paginated walks + batched /albums lookups.

track_release_originA

Find where a track first appeared: walks an artist's releases chronologically and reports the earliest album/single/compilation containing the track, plus later re-appearances. Quota: 🔴 paginated walk + batched /albums lookups.

album_anniversary_checkA

Upcoming album anniversaries for an artist within the next window_days, with milestone years (5/10/15/…) flagged — plan re-listens or anniversary posts. Quota: 🟡 one paginated /artists/{id}/albums walk.

album_duration_reportB

Runtime profile for an artist's studio albums: total length, track count and longest track per album, ranked by runtime — find the epics and the EPs. Quota: 🔴 paginated walk + batched /albums lookups.

new_music_from_saved_artistsA

Newest releases across the artists you follow (and optionally those in your saved albums), sorted by release date — your personal new-release feed. Quota: 🔴 followed-artist walk + per-artist album peeks.

artist_scout_from_playlistsA

Find new-to-you artists: pull the artist roster from one of your playlists and rank the ones you have NOT saved any tracks of — discovery from your own rotation. Quota: 🔴 playlist walk + saved-tracks membership check.

artist_live_albums_finderA

List an artist's live releases (titles matching live/unplugged/live-at patterns) chronologically — the concert-record shelf. Quota: 🟡 one paginated /artists/{id}/albums walk.

artist_collection_gapsA

List an artist's studio albums missing from your saved collection — the exact records to add next. Quota: 🔴 paginated walk + saved-albums membership check.

artist_singles_timelineA

Chronological singles timeline for an artist (date · title · track count) — the 45-rpm history in one table. Quota: 🟡 one paginated /artists/{id}/albums walk (singles group).

genre_dive_searchA

Search artists by genre keyword (e.g. "britpop", "afrobeat") and list the matching profiles with their genre tags — the entry point for a genre dive. Quota: 🟢 one GET /search call.

scene_sampler_searchA

Build a scene sampler: search artists by a scene/genre keyword, then fetch each act's newest release as a one-track-per-artist listening plan. Quota: 🟡 one /search call + one album peek per artist.

saved_albums_by_decadeB

Group your saved albums by release decade (from each album release_date) and show a histogram. Read-only.

saved_albums_by_labelB

Group your saved albums by record label (from each album payload) and rank labels by count. Read-only.

saved_albums_by_typeA

Group your saved albums by album_type (album / single / compilation / EP). Read-only.

artist_representation_censusA

Census of your saved tracks by credited artist: rank the top N artists by how many saved tracks they appear on. Read-only.

orphaned_artist_checkA

Find asymmetries in your library: artists you saved tracks from but never saved an album of, and vice versa. Read-only.

saved_track_age_reportB

Histogram of when you saved each liked track (added_at): age buckets plus a per-year add histogram. Read-only.

added_on_this_dayA

Show tracks you saved on this calendar day (month + day) in previous years — your library "on this day". Read-only.

library_growth_timelineB

Show how fast your saved-track library grew: adds per month, busiest month, and your longest/current monthly add streaks. Read-only.

duplicate_saved_versionsA

Find songs you saved more than once from different albums (same normalised track name + primary artist, distinct album IDs). Read-only.

album_edition_lintA

Lint your saved albums for the same record kept across multiple editions (same name after edition-noise stripping + primary artist, distinct album IDs). Read-only.

never_played_savedA

List saved tracks absent from your recently-played window. Honest bounds: recently-played only covers roughly your last 50 plays, so this is "not played lately", not "never played". Read-only.

saved_vs_playlist_coverageA

Report which of your saved tracks appear in none of your owned/followed playlists, with a coverage ratio. Read-only.

artist_completeness_scoreA

For your top N saved-track artists, fetch each artist’s top tracks and score how many of them you have saved (0–100%). Read-only, capped at 25 artists.

saved_runtime_by_eraB

Total listening runtime of your saved tracks grouped by the release decade of each track’s album. Read-only.

longest_saved_tracksA

Rank your saved tracks by duration, longest first. Read-only.

shortest_saved_tracksA

Rank your saved tracks by duration, shortest first. Read-only.

saved_albums_by_yearB

Histogram of your saved albums by release year. Read-only.

collab_density_reportC

Measure collaboration density: how many of your saved tracks credit 2+ artists, with the top collaborations ranked. Read-only.

featuring_density_reportA

Measure how many of your saved track titles carry a "feat." / "featuring" marker, with examples ranked. Read-only.

title_length_outliersB

Statistical outliers in saved-track title length (characters): mean/median plus the longest and shortest titles. Read-only.

explicit_content_ratioB

Share of your saved tracks flagged explicit, with the top explicit artists. Read-only.

is_local_censusA

Count your saved tracks flagged as local files (is_local true) and list them — these often fail to play on other devices. Read-only.

unplayable_saved_checkA

Audit your saved library for tracks the API marks unplayable (is_playable false or a restrictions block) and show why. Read-only.

library_value_summaryA

One mega-report over your saved library: totals, runtime, explicit/local/unplayable counts, collab + featuring density, growth streaks, era histogram, duplicate-version and edition-lint counts, and top artists. Read-only.

list_saved_showsB

List the shows saved in your library with publisher, episode count, and saved date — truncated to max_results with a fetch-all hint when longer. Default 20 rows, 'concise' prose.

get_show_detailsB

Fetch full metadata for one show (description, publisher, episode count, languages, media type). Defaults to 'concise' prose.

list_show_episodesA

Page one show's episode list newest-first with duration and release date — the browse view for a single podcast. Default limit 20, 'concise' prose. Canonical for GET /shows/{id}/episodes; get_show_episodes is a deprecated alias. Also covers: paged podcast episodes.

get_show_latest_episodeA

Return the single newest episode of a show with duration, description, and resume point — 'what dropped last?' in one GET. Defaults to 'concise' prose.

saved_shows_publisher_censusA

Count your saved shows by publisher and rank the biggest presses in your subscriptions — read-only census over the whole shelf. Defaults to top 10 publishers, 'concise' prose.

shows_without_new_episodesA

Find saved shows with no episode released inside the lookback window ("which pods went quiet?") — pages /me/shows then the latest episode per show. Defaults to 30 days, 50 show lookups.

stale_saved_shows_planA

Build a PLAN for pruning saved shows that have published nothing within the staleness threshold — read-only by design, it never unfollows anything; pair with remove_saved_shows to commit. Defaults to 90 days, 50 show lookups.

subscribe_to_showA

Save one or more shows to your library (PUT /me/shows) — previews a deterministic PLAN by default; pass dry_run=false to commit.

unsubscribe_from_showA

Remove ONE saved show from your library (DELETE /me/shows) — removal verb: also see remove_saved_shows (bulk), delete_playlist_snapshot (local snapshots). After confirming what it is — previews a PLAN naming the show by default; pass dry_run=false to commit.

remove_saved_showsA

Bulk-remove shows from your library (DELETE /me/shows) — removal verb family: also see unsubscribe_from_show (single), remove_saved_episode (episodes). After cross-checking which of the given IDs are actually saved — previews a PLAN by default; pass dry_run=false to commit.

get_episode_detailsA

Fetch full metadata for one episode (duration, release date, resume point, show, description). Defaults to 'concise' prose.

check_episode_savedA

Check which episodes are already saved in your library (GET /me/episodes/contains) — batch yes/no, no guessing. Read-only.

save_episodeA

Save episodes to your library (PUT /me/episodes) — previews a PLAN with episode names by default; pass dry_run=false to commit.

remove_saved_episodeA

Remove episodes from your library (DELETE /me/episodes) — removal verb: also see remove_saved_shows (shows), delete_playlist_snapshot (local). After cross-checking which are actually saved — previews a PLAN by default; pass dry_run=false to commit.

mark_episode_played_planA

Plan (never execute — Spotify removed the mark-played API, issue #230) which episodes to mark fully played: fetches current resume points and outputs the target positions the player would seek to. Read-only by design.

get_newly_released_episodesA

Collect episodes released since a date across ALL saved shows, merged newest-first and tagged with their show — the unified new-episode inbox. Defaults to the last 7 days.

shows_release_calendarA

Estimate each saved show's next expected release from its recent publish cadence (median interval between the latest publishes) — a forward calendar for your subscriptions. Defaults to 30 show lookups.

episode_runtime_reportA

Runtime statistics for one show's episodes — count, total/min/median/max duration, and the longest and shortest episodes — to plan listening time. Defaults to the 100 newest episodes.

publisher_portfolioA

Per-publisher portfolio across your saved shows: show count, listed episode totals, and sampled runtime of their recent episodes — who owns your listening time. Defaults to 10 recent episodes per show.

show_activity_feedA

Chronological feed of the most recent episodes across ALL your saved shows, merged and sorted newest-first — one scroll instead of N show visits. Defaults to 3 episodes per show, newest first.

show_backlog_planA

Plan (dry-run only, never mutates) your podcast backlog: unlistened episodes across saved shows ordered SHORTEST-FIRST, so the queue clears with quick wins. Defaults to 20 recent episodes per show, 20 shows.

find_show_by_publisherA

Search the catalog and match shows whose PUBLISHER (network) matches your query — the missing publisher facet on show search. Defaults to 10 search results.

episode_guest_censusA

Census recurring GUESTS across a show's recent episodes by mining description credits ("with X", "featuring X", "guest X") — who keeps coming back. Defaults to the 20 newest episodes.

show_recommendation_briefA

Cross-reference newly released episodes against your saved-episode and recently-played history: which new drops are NOT yet saved or played — a listen-next brief. Defaults to the last 14 days.

top_artist_ranking_deltaA

Show how each top artist’s rank moved between two time windows (climbers first; default compares short_term against medium_term). Quota: 2× GET /me/top/artists.

top_track_ranking_deltaA

Show how each top track’s rank moved between two time windows (climbers first; default compares short_term against medium_term). Quota: 2× GET /me/top/tracks.

top_artist_leaderboardA

Score top artists across all three time windows with recency-weighted points (short×3, medium×2, long×1) and rank the combined leaderboard. Quota: 3× GET /me/top/artists.

top_track_leaderboardA

Score top tracks across all three time windows with recency-weighted points (short×3, medium×2, long×1) and rank the combined leaderboard. Quota: 3× GET /me/top/tracks.

artist_velocity_reportB

Classify each top artist’s momentum by comparing short_term and long_term ranks (surging / climbing / steady / slipping / falling / new_entry). Quota: 2× GET /me/top/artists.

track_rotation_reportA

Report how many times each track appears in recently-played history and bucket them into heavy/regular/light rotation (default 150 history items). Quota: GET /me/player/recently-played cursor walk.

discovery_ratioA

Measure what share of your recently-played tracks are NOT in your top tracks (discovery vs staple listening; default compares against medium_term). Quota: GET /me/player/recently-played + 1× GET /me/top/tracks.

listening_clockB

Profile when you listen by local hour (24-bucket histogram plus daypart totals and peak hour) from recently-played history (default 150 items). Quota: GET /me/player/recently-played cursor walk.

weekday_listening_reportA

Break recently-played history down by weekday (plays, unique tracks, unique artists, busiest day; Mon→Sun ordering, default 150 items). Quota: GET /me/player/recently-played cursor walk.

binge_detector_reportA

Flag artists whose recently-played counts exceed a play threshold (default ≥5 plays) with span and track coverage, sorted by intensity. Quota: GET /me/player/recently-played cursor walk.

repeat_listener_reportA

Quantify repeat listening in recently-played history: share of plays going to tracks heard more than once plus consecutive same-track replays (default 150 items). Quota: GET /me/player/recently-played cursor walk.

listening_streak_reportA

Compute consecutive-day listening streaks from recently-played history, including the longest streak and whether it is still alive (default 150 items). Quota: GET /me/player/recently-played cursor walk.

top_genre_censusA

Build a weighted genre census from your top artists (rank-weighted across the three windows; genres resolved via the batch /artists endpoint, default 40 artists per window). Quota: 3× GET /me/top/artists + 1× GET /artists?ids=.

mood_bucket_reportA

Segment recently-played plays into daypart × familiarity buckets (fresh tracks vs staples from your top tracks, default medium_term) as a lightweight listening-mood proxy. Quota: GET /me/player/recently-played + 1× GET /me/top/tracks.

deep_dive_reportB

Deep-dive one artist: recently-played counts, which of their tracks rotate, and their rank in each top-artists window (accepts ID, URI, or URL). Quota: GET /me/player/recently-played + 3× GET /me/top/artists.

listening_clock_heatmapB

Render a weekday × hour listening heatmap from recently-played history with the peak cell highlighted (default 150 items). Quota: GET /me/player/recently-played cursor walk.

artist_listening_clockA

Profile WHEN you play one specific artist (hour-of-day histogram plus daypart split; defaults to your most-played artist in the history window). Quota: GET /me/player/recently-played cursor walk.

session_length_reportA

Split recently-played history into listening sessions by inactivity gap (default 30 minutes) and report size/duration stats plus a distribution (default 150 items). Quota: GET /me/player/recently-played cursor walk.

listening_gaps_reportA

Find the quiet stretches in your recently-played history: every inactivity gap above a threshold (default ≥120 minutes) with the longest gaps listed (default 150 items). Quota: GET /me/player/recently-played cursor walk.

weekly_rotation_reportA

Track day-by-day rotation from recently-played history: plays, unique tracks/artists, and first-heard-this-window tracks per day (oldest→newest, default 150 items). Quota: GET /me/player/recently-played cursor walk.

listening_consistency_scoreA

Score how consistent your listening is (0-100) from recently-played history: active-day coverage, hour spread, and weekday balance with each component shown (default 150 items). Quota: GET /me/player/recently-played cursor walk.

era_preference_reportA

Compare the decade mix (album release eras) of your recently-played tracks against a top-tracks window, highlighting where recent listening skews older or newer (default medium_term). Quota: GET /me/player/recently-played + 1× GET /me/top/tracks.

listening_recap_briefA

Produce a one-call recap of your recent listening: headline plays, top artist/track, leaderboard leaders, peak hour, busiest weekday, discovery ratio, and streak status (default 200 history items). Quota: GET /me/player/recently-played + 4× GET /me/top/*.

listening_history_exportB

Export your recently-played history as a paginated chronological table (oldest→newest; supports offset continuation; default walks up to 500 items). Quota: GET /me/player/recently-played cursor walk.

parse_spotify_uriA

Parse a single spotify: URI into its entity kind and ID parts without any network call; reports validity and a parse error when malformed.

format_spotify_uriA

Format an entity kind + ID pair into a canonical spotify: URI locally; validates the ID shape and returns null when the pair is malformed.

spotify_uri_to_open_urlA

Convert a spotify: URI (or bare ID + kind) into its https://open.spotify.com share URL locally, stripping nothing else.

open_url_to_spotify_uriB

Convert an open.spotify.com URL (including /embed/ forms with ?si= tracking params) into a canonical spotify: URI locally.

extract_spotify_idA

Extract the bare 22-char entity ID from any Spotify reference — URI, open.spotify.com URL (embed/intl forms ok), or bare ID — with zero network calls.

validate_spotify_uriA

Validate a Spotify reference against the URI grammar and 22-char base62 ID rule locally, returning a field-by-field validity report.

normalize_spotify_uriA

Normalise any accepted Spotify reference form (URI with extra segments, URL with tracking params, bare ID) into its canonical lowercase spotify: URI, offline.

spotify_uri_kindA

Report the entity kind of a single Spotify reference (uri/url/bare ID) locally, or null when the kind segment is missing or unknown.

batch_parse_spotify_urisA

Parse a batch of Spotify references into kind/ID parts in one local pass — no network calls; one result row per input.

is_valid_spotify_uriA

Boolean validity check for a single Spotify reference — true only for well-formed spotify: URIs with a 22-char base62 ID; evaluated locally.

uri_namespace_censusA

Census of a batch of Spotify references grouped by reference form (uri/url/id/invalid) and by entity kind — a local frequency table, no network calls.

base62_to_uriA

Reinterpret a base62 ID string as a Spotify entity ID and build the full spotify: URI for a given kind, offline.

uri_to_base62A

Strip a spotify: URI (or URL) down to its raw base62 ID string, locally; null when the reference has no extractable ID.

make_spotify_uriA

Construct a spotify: URI from kind + ID with strict validation — rejects wrong-length IDs and unknown kinds before anything is built.

split_uri_listA

Split a delimited string of Spotify references into a clean array — accepts comma, semicolon, whitespace, or newline separators; local only.

join_uri_listA

Join an array of Spotify references into a single delimited string — comma, semicolon, newline, or a custom glue; local only.

dedupe_spotify_urisA

Remove duplicate Spotify references from a list, preserving first-seen order, comparing canonical URI forms where possible — local, no network.

find_duplicate_spotify_urisA

List duplicate Spotify references in a batch with counts and positions, comparing canonical URI forms — computed locally with no network calls.

sort_uris_by_kindA

Sort Spotify references into deterministic groups by entity kind (track, album, artist, playlist, show, episode, audiobook, user) and return them labelled per group — offline.

count_uris_by_typeA

Count how many references in a batch belong to each entity kind (track, album, artist, …) — a local tally, no network calls.

canonicalize_spotify_uriA

Canonicalise a batch of Spotify references in one local pass: *** scheme, known kind, 22-char base62 ID, tracking params stripped — no network.

uri_kind_statsB

Aggregate statistics over a batch of Spotify references: counts per form, per kind, share percentages, and the modal kind — all computed locally.

classify_spotify_urisA

Classify each reference in a batch: reference form, entity kind, canonical-form verdict, and per-row issues — one local pass, no network calls.

uri_shorthand_expandA

Expand shorthand Spotify refs like "t:", "pl/", or "track:" into canonical spotify: URIs. Codes: t/tr=track, al=album, ar=artist, pl/p=playlist, sh=show, ep=episode, ab=audiobook, u=user — local only.

take_playlist_snapshotA

Capture a live playlist’s items (uri, name, added_at) into a timestamped local JSON snapshot file; dry_run=true previews the walk and target filename without writing. Newest, transactional snapshot (swarm) — preferred over legacy snapshot_playlist. See also list_saved_snapshots, read_playlist_snapshot, diff_playlist_snapshots. Also covers: playlist snapshot (swarm). Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

list_saved_snapshotsA

List local playlist snapshots (newest first) with path, creation time, size, and the _meta summary; optionally filtered to one playlist Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

read_playlist_snapshotA

Read one local playlist snapshot and return its meta plus the captured track rows (truncated by max_results) Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

delete_playlist_snapshotA

Delete one local playlist snapshot file; dry_run=true (default) only reports what would be removed Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

diff_playlist_snapshotsB

Diff two local snapshots of a playlist and report every added and removed track between them Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_new_tracksA

List only the tracks added between an older and a newer snapshot of a playlist Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_removed_tracksA

List only the tracks removed between an older and a newer snapshot of a playlist Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_added_at_reportA

Report when the tracks in a snapshot were added to the playlist, bucketed by month (YYYY-MM) Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_changelogB

Build a chronological changelog of a playlist from every local snapshot, describing the changes between consecutive snapshots Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_stats_reportA

Compute stats for one snapshot: track count, unique URIs, duplicates, and the oldest/newest added_at dates Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_integrity_checkB

Validate one snapshot (or all of them): JSON parses, required _meta keys exist, and the declared track_count matches the tracks array Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

prune_old_snapshotsB

Delete old local snapshots, keeping the newest N per playlist and optionally dropping those older than a cutoff; dry_run=true (default) only reports what would go Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

restore_playlist_from_snapshotA

Make a live playlist match a snapshot (add missing, remove extra tracks); dry_run=true (default) returns the deterministic PLAN without touching Spotify Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

restore_playlist_planA

Read-only plan of exactly which tracks would be added/removed to make a live playlist match a snapshot — never mutates Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_diff_summaryA

One-paragraph summary of the differences between two snapshots: counts plus the first few changed tracks Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

find_new_since_snapshotA

Compare a live playlist against a snapshot and list tracks added to the playlist since it was taken Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

find_lost_since_snapshotA

Compare a live playlist against a snapshot and list snapshot tracks that have since disappeared from the playlist Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

merge_snapshot_changes_planA

Read-only plan to replay the changes between two snapshots onto the live playlist (add new and/or remove lost tracks) Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

apply_snapshot_changesB

Execute a merge plan on the live playlist (replay the changes between two snapshots); dry_run=true (default) only returns the plan Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_retention_planA

Report which snapshots a keep-last-N (+ optional age cutoff) retention policy would keep or delete — never deletes anything Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_disk_usageB

Report disk usage of the snapshot directory: total size, file count, per-playlist breakdown, and the largest files Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_integrity_reportA

Aggregate health report over all local snapshots: valid vs corrupt files, per-playlist coverage, and the age of each playlist’s newest snapshot Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

export_snapshot_bundleA

Bundle selected snapshots (all of one playlist, or explicit ids) into a single portable JSON export file locally; dry_run=true (default) previews the bundle Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

snapshot_registry_reportA

Registry view of every local snapshot: per playlist, all snapshot ids with taken_at and track counts, plus naming anomalies in the snapshot directory Snapshot guide: take_playlist_snapshot (create), list_saved_snapshots (list), read_playlist_snapshot (read), diff_playlist_snapshots / snapshot_new_tracks / snapshot_removed_tracks (diff), restore_playlist_from_snapshot / restore_playlist_plan (restore).

find_toolA

Search the live tool registry by name or description substring — the fastest way to discover which of the 500+ tools handles a job. Discovery set: find_tool/inspect_tool/toolset_report are always available (also via catalog). Use this first when unsure which verb to use (e.g., playlist vs snapshot vs search).

inspect_toolA

Show one tool's full description and input schema before calling it

toolset_reportA

Report the active toolsets and registration modules, plus the live registered tool count — answers "how much surface is exposed right now". Discovery set; always available. Also see find_tool / inspect_tool.

playlist_resequenceA

Sort a playlist in place — by track name, artist, album, duration, or date added — written back as one atomic replace. Episodes sort last (no artist/album key). Quota: 🟢 2 GETs + 1 PUT. Also covers: reorder_playlist_items (range-based), playlist_move_block — See also: reorder_playlist_items, playlist_move_block.

playlist_rotateB

Rotate a playlist by N positions: positive N moves the first N items to the end, negative N moves the last |N| to the front (wraps around). Written as one atomic replace. Quota: 🟢 2 GETs + 1 PUT.

playlist_seed_shuffleA

Shuffle a playlist in place (Fisher–Yates) with an optional deterministic seed — same seed, same order, so you can preview and commit the exact same shuffle. Unavailable items are kept, pinned at the end. Quota: 🟢 2 GETs + 1 PUT.

playlist_flip_orderB

Reverse a playlist: last item becomes first, written as one atomic replace. The standard fix for imports that arrived backwards. Quota: 🟢 2 GETs + 1 PUT.

playlist_move_blockA

Move a contiguous block of items (1-based start + count) so its first item lands at a target position expressed in the ORIGINAL numbering. The rest of the playlist closes up around it. Written as one atomic replace. Quota: 🟢 2 GETs + 1 PUT. Also covers: reorder_playlist_items, playlist_resequence — See also: reorder_playlist_items, playlist_resequence.

playlist_swap_positionsA

Swap the items at two 1-based positions — e.g. flip tracks 3 and 7. Positions may be any two distinct slots in the playlist. Written as one atomic replace. Quota: 🟢 2 GETs + 1 PUT.

playlist_dedupe_advancedA

Remove duplicate items from a playlist, matching by URI (exact copies) OR by track name (catches re-adds of the same song from different albums/singles when combined with dedupe by uri). Choose keep-first or keep-last. Written as one atomic replace. Quota: 🟢 2 GETs + 1 PUT.

playlist_remove_artistA

Remove every track by one artist from a playlist (match by artist name, case-insensitive, or by artist ID / spotify:artist: URI). Shows exactly what would go. Quota: 🟢 2 GETs + 1 PUT when committing.

playlist_keep_artistA

Inverse filter: keep ONLY tracks by one artist in a playlist and drop everything else. Optionally keep podcast episodes too (they have no artist). One atomic replace. Quota: 🟢 2 GETs + 1 PUT.

playlist_filter_runtimeA

Keep only items whose duration falls inside a window (e.g. min_sec 120 → drop intros/interludes; max_sec 360 → drop 6-minute epics). At least one bound required. One atomic replace. Quota: 🟢 2 GETs + 1 PUT.

playlist_chunk_previewA

Read-only pagination preview: how a playlist splits into write-sized chunks (the 100-URI replace limit) or any custom size — per-chunk position ranges, first/last items, and item counts. Plan batched edits before running them. Quota: 🟢 2 GETs.

playlist_diffA

Compare two playlists: what is only in A, only in B, and in both — plus whether the shared tracks appear in the same relative order. Read-only. Quota: 🟢 4 GETs. Also covers: diff_playlists (live playlist diff), playlist_difference_plan (subtract plan) — See also: diff_playlists, playlist_difference_plan.

playlist_historyA

List your local backup snapshots (from backup_now): file name, created timestamp, and the counts each snapshot carries. The entry point for snapshot_detail / changelog / clone_snapshot. Read-only, no API calls.

playlist_snapshot_detailA

Inspect one playlist inside a local backup snapshot: its item_count as recorded plus the full item list (truncated by max_results). Read-only, no API calls.

playlist_clone_snapshotA

Restore a playlist from a local backup snapshot as a NEW playlist (never overwrites the live one — clone, don't clobber). Items restore by URI; catalog-removed items are skipped by Spotify automatically. Quota: 🟡 0 GETs + create + chunked adds.

playlist_changelogA

Diff ONE playlist across two backup snapshots (older → newer): tracks added, removed, and kept — plus whether the kept tracks were reordered. The "what changed since last week" view. Read-only, no API calls.

playlist_pair_checkA

Pairwise relationship report for two playlists: sizes, overlap, Jaccard similarity, and sampled candidates from each side that the other lacks (for merging or splitting decisions). Read-only. Quota: 🟢 4 GETs.

playlist_balanceA

Split a playlist into N balanced new playlists: sequential chunks (part 1 = first third, …) or interleave (round-robin deal, so every part samples the whole span). Creates N new playlists; the source is left untouched. Quota: 🟡 2 GETs + N creates + chunked adds.

statsfm_resolve_userA

Resolve a stats.fm user id or customId to their profile (falls back to user search)

statsfm_top_tracksC

A stats.fm user's most-streamed tracks

statsfm_top_artistsC

A stats.fm user's most-streamed artists

statsfm_top_albumsC

A stats.fm user's most-streamed albums

Prompts

Interactive templates invoked by user choice

NameDescription
djAct as a DJ. Based on my top artists and current mood, queue up a set of songs.
playlist_from_moodCreate a playlist for a given mood. Searches for tracks and adds them to a new playlist.
music_taste_summarySummarize the user's music taste based on their top tracks and artists.
discover_weekly_alternativeBased on my top tracks and recently played songs, find lesser-known songs I probably haven't heard.
playlist_auditAudit a playlist for duplicate tracks and unplayable ('dead') entries, with cleanup suggestions.
listening_recapWrite a recap of recent listening: top tracks/artists plus recently-played context.
migrate_libraryCollect tracks from your saved albums into a single playlist.
podcast_catchupList new podcast episodes published since a date across your saved shows, and queue them if asked.
artist_deep_diveTour an artist's discography: profile, albums, standout tracks.
music_briefingDaily or weekly music briefing: new podcast episodes, new releases from followed artists, catalog freshness, and recently played — composed from radar tools.
morning_briefingMorning briefing: new releases + listening streak + top track.
weekly_digestWeekly digest: taste shift + streaks + recommendations.
crate_diggingCrate dig deep cuts for your top artists.
triage_liked_songsTriage your Liked Songs backlog into era- or genre-bucket playlists.

Resources

Contextual data attached and managed by the client

NameDescription
meCurrent user profile ('?format=json' returns the raw API object)
player-stateCurrent Spotify playback state (live; '?format=json' returns the raw API object)
player-queueCurrent playback queue ('?format=json' returns the raw API object)
top-tracksUser's top tracks (medium term; '?format=json' returns the raw API object)
top-artistsUser's top artists (medium term; '?format=json' returns the raw API object)
recently-playedLast 20 recently played tracks ('?format=json' returns the raw API object)
playlistsAll user playlists, names and IDs ('?format=json' returns the raw items)
saved-albumsAlbums saved in your library
saved-showsPodcast shows saved in your library
saved-episodesPodcast episodes saved in your library
saved-tracksTracks saved in your library, paginated via ?offset&limit ('?format=json' returns raw paged object)
followed-artistsArtists you follow ('?format=json' returns the raw items)
saved-audiobooksAudiobooks saved in your library ('?format=json' returns the raw items)
listening-historyRecent listening history (last 20, live; '?format=json' returns raw API object)
genre-heatmapGenre heatmap from followed_artists sidecar ('?format=json' returns raw counts)
rate-limitLast rate-limit event: Retry-After/wait or 'never throttled'

TDQS

C2.8/5.0

Scored across 608 tools

Disambiguation1/5

With 608 tools, the surface is saturated with near-duplicates: get_now_playing vs get_currently_playing vs get_playback_snapshot, listening_streaks vs listening_streak_report, playlist_intersect vs playlist_intersection, b_sides_finder vs b_sides_detector, plus roughly 20 URI-parsing utilities and 30+ snapshot tools. Explicit legacy aliases help at the margins, but an agent cannot reliably disambiguate such overlapping clusters.

Naming Consistency1/5

Names mix verb_noun (get_track, create_playlist), noun_verb (playlist_sort, playlist_intersect), bare verbs (play, pause, mute, seek), and there is no consistent preview/commit pattern (sort_playlist_plan vs playlist_sort vs sort_playlist_apply; reverse_playlist_plan vs playlist_reverse). Arbitrary aliasing like get_show_episodes/list_show_episodes and statsfm_taste_profile/taste_profile adds further chaos.

Tool Count1/5

608 tools is an extreme count for any MCP server, far beyond the 50+ threshold for a failing score. The scope could be served by a small fraction of these tools; dozens of report tools, snapshot variants, and URI helpers are redundant.

Completeness4/5

The server covers the full Spotify API surface plus stats.fm and local sidecar features: playback, library, playlists, search, podcasts, audiobooks, analytics, snapshots, and mutation tracking. Missing features are mostly removed API endpoints (artist top tracks, user profile) with explicit disclosures, and genuine gaps (queue clear, insert-next) have documented workarounds.

Maintenance

ActivityActive
ResponsivenessResponsive