Skip to main content
Glama

SpotifyMCP

CI npm version License: MIT Node

Spotify Web API MCP: playback, library, playlists, search, podcasts. Not affiliated with Spotify.

A broad Spotify Web API tool surface, plus extras most servers skip. Registration-gated wrappers are explained rather than hidden; see Registration-gated endpoints for the generated list.

What you get by default, and what to do about the rest. A server started with no environment registers a curated surface โ€” search, playback, playlists, library, following โ€” sized so the tool list does not dominate the context window before you have typed anything. SPOTIFY_MCP_TOOLSETS=all registers the entire registry instead, and the stats.fm tools are opt-in with SPOTIFY_MCP_STATSFM=1. Both are one line in docs/configuration.md.

A server started with no SPOTIFY_MCP_TOOLSETS registers 129 tools (148,378 bytes of schema) โ€” the curated default surface (#889). SPOTIFY_MCP_TOOLSETS=all registers all 560 tools, along with 17 fixed resources, 28 resource templates, and 14 prompts. Toolsets and production gates can trim a configured host further; both figures describe a real production tools/list after finalizers.

๐Ÿšง 3.0 is landing

3.0 is the release where the open issue list goes to zero โ€” every epic, every issue under it, every contradiction we turned up auditing ourselves. Most of that backlog was never "bugs" in the crashing sense; it was places where this server reported a value it had not actually checked, which is the only kind of wrong that is genuinely dangerous.

It also removes tools, because Spotify deleted the endpoints underneath them in February 2026 โ€” including artist follows, which have no migration target at all.

โ†’ Read the 3.0 roadmap


๐Ÿค– Paste this to your agent

Copy the block below into Claude Code, Cursor, OpenClaw, or any coding agent โ€” it will set SpotifyMCP up for you.

โš ๏ธ Never paste your Spotify credentials into a chat. Spotify's Developer Terms treat the Client ID as a credential: ยงVI.1.1 groups "I.D.s, client I.D.s, keys, passwords, security codes, or tokens" together as Security Codes, ยงVI.1.3 forbids disclosing them to any other party, and ยงVI.1.4 makes you responsible for their confidentiality. Anything you type into a conversation is retained by the model provider, written to shell history, and carried in the agent's context window. The Client ID is the only credential this server needs, and it is a Security Code rather than a public identifier โ€” treat it like a password.

Set up the Spotify MCP server from https://github.com/NovaLux12/spotify-mcp-server.

1. Walk me through creating a Spotify app at https://developer.spotify.com/dashboard
   with redirect URI http://127.0.0.1:8888/callback. Point me at where the dashboard
   shows the Client ID, then stop โ€” I will copy it myself.
2. Clone and build:
   git clone https://github.com/NovaLux12/spotify-mcp-server.git
   cd spotify-mcp-server && npm ci && npm run build
3. Show me which file my MCP host reads server environment from. The host's server
   config is the one that always works; a local .env is read only when you launch
   through this repo's npm run dev or npm start, which pass --env-file-if-exists
   on Node >=22.9 โ€” the published binary does not read it. Print the exact line to
   add. I will type the Client ID in myself. Do not ask me for it and never echo
   it back.
4. Start the server and run the auth command yourself, then finish the browser login
   when it opens. This server uses PKCE, so there is no client secret and no
   credential to fetch beyond the Client ID.
5. Verify with the read-only spotify_doctor tool and report its rows.

Why this one

Complete

Playback, search, catalog, library, playlists, following, plus extras like duplicate cleanup, M3U/CSV import-export, podcast sessions, snapshot diffing, listening analytics, market checks, stats.fm taste reads, and taste composite briefs, playlists, and reports.

Safe

dry_run previews on writes, receipts that prove what landed, human confirmation for bulk deletes, and READONLY to hide write-capable modules.

Honest about the surface

Tools that turn your listening history into derived metrics โ€” hourly histograms, weekday profiles, discovery ratios โ€” are off unless you ask for them with SPOTIFY_MCP_EXPERIMENTAL_ANALYTICS=1, because Spotify's Developer Policy Sec. III.13 prohibits building derived listenership metrics. The rest of the analytics surface, which re-presents your own data, is always on. See docs/compliance.md.

Honest

No tool claims to work when it cannot. Gated endpoints keep their wrappers, read replacements where one exists, and explain the 403 in plain English instead of crashing โ€” see Registration-gated endpoints, generated from src/gating.ts.

Polished

Paginated (up to 500), podcasts first-class, device-aware playback, spotify_doctor self-diagnosis, real test suite.

Related MCP server: Spotify MCP Server

Quick start

1. Create a Spotify app

Spotify Developer Dashboard โ†’ Create app โ†’ add this Redirect URI exactly:

http://127.0.0.1:8888/callback

Copy the Client ID.

2. Authenticate

SPOTIFY_CLIENT_ID=your_client_id_here npx -y @novalux12/spotify-mcp@latest auth

Opens a browser, saves tokens to ~/.spotify-mcp/tokens.json, auto-refreshes after.

Windows (Command Prompt):

set SPOTIFY_CLIENT_ID=your_client_id_here && npx -y @novalux12/spotify-mcp@latest auth

Windows (PowerShell):

$env:SPOTIFY_CLIENT_ID="your_client_id_here"; npx -y @novalux12/spotify-mcp@latest auth

Windows is supported for install and everyday use, and is not covered by CI. The commands above are the supported path, but the test suite runs on Linux only, so a Windows-specific regression would not be caught before release. See docs/platform-support.md for exactly what is and is not verified there, and what the known gaps are.

Headless / remote host:

SPOTIFY_HEADLESS=1 SPOTIFY_CLIENT_ID=your_client_id_here npx -y @novalux12/spotify-mcp@latest auth
# prints a URL โ†’ open it on any machine โ†’ paste the redirect back

Check: npx -y @novalux12/spotify-mcp@latest doctor โ€” exit 0 means you're good.

3. Add to your MCP host

{
  "mcpServers": {
    "spotify": {
      "command": "npx",
      "args": ["-y", "@novalux12/spotify-mcp@latest"],
      "env": { "SPOTIFY_CLIENT_ID": "your_client_id_here" }
    }
  }
}

Restart the host. A hammer icon in the chat input means it's connected.

Claude Code (no JSON editing):

claude mcp add spotify -- npx -y @novalux12/spotify-mcp@latest
export SPOTIFY_CLIENT_ID=your_client_id_here

OpenClaw โ€” ~/.openclaw/openclaw.json โ†’ mcp.servers:

"spotify": {
  "command": "node",
  "args": ["/path/to/spotify-mcp-server/dist/index.js"],
  "cwd": "/path/to/spotify-mcp-server",
  "env": { "SPOTIFY_CLIENT_ID": "your_client_id_here" }
}

Any spec-compliant host works โ€” same command/args/env shape under mcpServers or servers. If the host can't pass env vars, authenticate once beforehand; the token cache persists.

What you can ask

  • "What are my top tracks this month?"

  • "Make a late-night driving playlist"

  • "Add Blinding Lights to my workout playlist"

  • "What podcasts have new episodes?"

  • "Clean duplicates across all my playlists"

  • "What does my taste look like? Build a playlist from it"

  • "Do my stats.fm lifetime genres match what I've played this month?"

Configuration

All via env vars โ€” no config file. Only SPOTIFY_CLIENT_ID is required.

Variable

Example

Purpose

SPOTIFY_MCP_TOOLSETS

unset

Trim by group for hosts that cap tool counts. Unset registers the curated default surface; all registers everything. The tool count for each is in the generated census above.

SPOTIFY_MCP_STATSFM

1

Register the 50 stats.fm-backed tools across four registration keys โ€” statsfm, taste, tastecomposites and tastejukebox. Off by default: they need a separate stats.fm username. Two of them write to Spotify (taste_to_playlist and statsfm_jukebox); the rest are read-only. spotify-mcp tools counts what your environment actually registers.

SPOTIFY_MCP_READONLY

1

Hide write-capable modules; read-only resources and prompts remain available.

SPOTIFY_MCP_HISTORY

1

Log mutations to JSONL for undo and audit.

SPOTIFY_MCP_RECEIPTS

1

Persist mutation receipts so verify_receipt/undo_mutation survive a restart.

SPOTIFY_MCP_ATTRIBUTION

0

Turn off the "Music data supplied by Spotify" footer and the per-row open.spotify.com link. On unless set to 0/false/no/off; the disclosure is mandatory, so only an explicit falsy value removes it.

Full reference: docs/configuration.md

spotify_doctor (CLI + in-server tool) diagnoses token state, scope gaps, Premium gating, rate-limit cooldowns, request/quota usage (cumulative + rolling-window counts, #904), and read-cache pressure (entries held, bytes retained, responses too large to cache, #894) without extra setup.

Upgrading to 2.0

2.0 is a contract release. One tool name is gone, four things moved, and one guarantee tightened:

  1. get_show_episodes is removed. Use list_show_episodes (same endpoint, same arguments, minus the drifted alias). It was the only name that changed; everything else in the surface keeps its name. The exact registry totals are generated at the top of this file, so this sentence deliberately carries no count of its own to fall behind.

  2. Destructive writes fail closed. Any confirmation-gated bulk write now refuses when the client cannot elicit, instead of proceeding unprompted. archive_played_episodes's confirm: true no longer authorises the delete (it is still accepted, and every result says it was ignored). For headless automation, set SPOTIFY_MCP_CONFIRM=never deliberately.

  3. Playlist set-operation inputs are canonical. A/B pairs are playlist_a/playlist_b; ordered lists are playlists; playlist_subtract takes the base as base_playlist_id. This was the 2.0 contract; the old spellings it was allowed to keep alongside it were withdrawn in 3.0 (#1287). They are no longer in any tool's schema, and a call that still sends one is refused before any Spotify request with a validation error whose reason is retired_input, naming both what was sent and what to send instead. Each tool declared exactly one alias pair or one alias list, so the table below is a per-tool migration map rather than a bundle:

    family

    canonical

    the spelling that tool used to declare

    A/B pair

    playlist_a, playlist_b

    a/b, or playlist_id_a/playlist_id_b, or playlist_a_id/playlist_b_id โ€” one of them, per tool

    ordered list

    playlists

    playlist_ids, or source_playlist_ids, or sources โ€” one of them, per tool

    subtraction

    base_playlist_id + playlists

    subtract_playlist_ids, or the positional form playlists: [base, ...sources] โ€” one of them, per tool

    base_playlist_id is required again: with the positional form gone there is no longer a base for a caller to omit. A name the tool does not declare, and is not a retired spelling, is an unknown_param error โ€” a different claim from retired_input, which says the server published that name until 3.0.

  4. Numeric caps have canonical names. max_results caps what is returned; limit and scan_cap cap how much of each source is read.

  5. Unknown arguments are rejected with a typed unknown_param error rather than ignored, so a renamed parameter fails loudly instead of silently doing nothing.

Run spotify_doctor after upgrading: it reports the registered surface, the gates that hid modules, and the granted scopes in one call.

Docs

Requirements

  • Premium for playback control (play/pause/skip/seek/volume/queue). Free accounts can still use search, library & playlists.

  • Node 22.9+, Spotify app in dev mode (5 users until extended quota).

  • Audiobooks gated by Spotify to US/UK/CA/IE/NZ/AU.

  • A subset of endpoints is registration-gated โ€” 403 on current app registrations regardless of scopes or Premium. Whether a grandfathered registration still answers 200 is unverified (#1338). This is a property of your app registration, not of the tool. See Registration-gated endpoints.

Registration-gated endpoints

Some Web API endpoints are denied at the app-registration level: on current Spotify app registrations they return 403 Forbidden no matter which OAuth scopes you grant or whether the account is Premium. This is Spotify-side gating, not a misconfiguration on your end.

Nothing here is simply "removed". Three sources describe this class and they do not agree, which is why the table below states the runtime behaviour instead of a verdict:

  • Spotify's February 2026 changelog marks a batch of operations [REMOVED].

  • The live OpenAPI schema still publishes most of those same paths, carrying deprecated: true rather than deleting them โ€” /artists/{id}/top-tracks and all seven Get Several batch paths among them.

  • The runtime truth is neither document: it is what your app registration is allowed to read. A registration without the grant answers 403/404/410. Whether a grandfathered registration still answers 200 is unverified (#1338): no probe in this repository shows it, and the one probe artefact that was once cited for it records 403 on every such path.

So a 403 here is a property of the registration, not of the tool. No tool is hidden for being gated, no gated tool is a zombie: each one either reads a documented replacement and answers, or makes the call and explains the 403 in plain English. The authoritative list is the GATED_FAMILIES array in src/gating.ts โ€” GATED_PATH_PATTERNS is derived from it, so the classifier and this table cannot drift apart.

Endpoint family

Shipped tools that call it

On a current registration

browse-categories โ€” /browse/categories* (list, {id}, {id}/playlists)

get_category, browse_category_deepdive, category_resolver

403 explained

browse-new-releases โ€” /browse/new-releases

(none โ€” no shipped tool reads this path)

Replaced; no call site

markets โ€” /markets

get_available_markets, market_validate

403 explained

artist-top-tracks โ€” /artists/{id}/top-tracks

get_artist_top_tracks, queue_playlist, artist_collab_network, artist_completeness_score, batch_add_to_playlist, copy_playlist, move_items_between_playlists

403 explained

user-profile โ€” /users/{id} and /users/{id}/playlists

get_user_profile, get_user_playlists_by_id, get_playlist_followers

403 explained

me-type-contains โ€” the documented /me/{type}/contains checks (tracks, albums, shows, episodes, audiobooks, following)

(none โ€” migrated to GET /me/library/contains)

Replaced; no call site

playlist-followers-contains โ€” /playlists/{id}/followers/contains

(none โ€” migrated to GET /me/library/contains)

Replaced; no call site

batch-several โ€” the multi-id ?ids= batch endpoints (/tracks, /albums, /artists, /episodes, /shows, /audiobooks, /chapters)

get_several_tracks, get_several_albums, get_several_artists, get_several_episodes, get_several_shows, get_several_audiobooks, get_several_chapters, catalog_batch_lookup

Replaced with per-id reads

All 8 families above are operations Spotify's February 2026 changelog marks [REMOVED].

Confirm the list yourself against the source of truth:

grep -n "id: '" src/gating.ts        # the families, with tools and fallback per row

Notes:

  • A family in that list is a runtime classifier, not a promise that a tool calls it. Three families (browse-new-releases, me-type-contains, playlist-followers-contains) have no live call site left โ€” the tools that used them were migrated onto replacements โ€” and their patterns are retained so a future caller is still covered by the 403 contract rather than silently losing it.

  • GET /me/library/contains is not gated (it returned 200 on the same probe) and backs the saved-state reads behind check_playlist_following, restore_library_snapshot and receipt verification. The contains families above are the documented per-type checks, which the changelog marks removed in favour of this one. (The playlist duplicate-cleanup tools are not in that set โ€” they page /playlists/{id}/items.)

  • Batch fallback (#725). When a Get Several batch endpoint answers 403, fetchSeveral retries through per-id GET /<kind>/{id} calls on the client's existing queue/backoff. Per-id paths are not in the gated class, so the read still succeeds. The response carries degraded: true and a [degraded: batch endpoint returned 403; โ€ฆ fetched individually] footer in prose, plus degraded_reason in structuredContent, so a caller can tell a per-item round-trip from a clean batch read.

  • Endpoints Spotify lists as removed that this server does not wrap at all (no shipped tool, so nothing to explain): /recommendations, /recommendations/available-genre-seeds, /me/apps, /me/chapters, the /artists/{id}/related-artists, /audio-features, /audio-analysis and /browse/featured-playlists reads, and the /playlists/{id}/tracks family (superseded by /playlists/{id}/items). These are absent from the table above because absence of a tool is the honest answer for them โ€” there is no 403 to explain.

  • "Not authenticated" โ†’ re-run auth; check ~/.spotify-mcp/tokens.json exists and the redirect URI matches exactly (no trailing slash).

  • Auth loop / S256 error โ†’ open a private window, log into spotify.com first, then retry the auth URL there.

  • Port in use (8888) โ†’ free the port, set SPOTIFY_REDIRECT_URI to another port, or use SPOTIFY_HEADLESS=1. The message names EADDRINUSE and the port because the usual cause is a previous auth still holding it.

  • Timed out waiting for the browser callback โ†’ not a port conflict; the listener bound and has been closed. Retry, and check the redirect URI is registered exactly. Bound it with SPOTIFY_AUTH_TIMEOUT_MS (default 5 min).

  • "Premium required" on playback โ†’ expected on Free accounts; no workaround.

  • Forbidden on lookup tools (categories, markets, top-tracks, user profiles, the per-type contains checks) โ†’ these endpoints are registration-gated by Spotify; see Registration-gated endpoints. (GET /me/library/contains is not one of them, so a 403 there is a real problem, not a gated registration.)

  • Still stuck? npx -y @novalux12/spotify-mcp@latest doctor or ask your agent to run the spotify-mcp-doctor skill.

What this server is not

v2 has a written non-goals list, so a request for something outside it gets an answer rather than a maybe. Each entry below carries its reasoning in SPEC ยง1, and docs/non-goals.md is the record behind both: what each one rules out, the source it rests on, and what the server offers instead.

  • Audio streaming, audio analysis, and offline playback

  • A web UI, a dashboard, or an MCP UI surface

  • Multi-tenant or hosted operation

  • Sharing one user's credentials across users

  • Lyrics

  • The Spotify Connect SDK and native client integration

  • Voice control

  • Training a model on Spotify data, or exporting derived profiles

  • A second third-party upstream, ad-tech, or monetization egress

  • Working around Spotify's own controls

Development

git clone https://github.com/NovaLux12/spotify-mcp-server.git && cd spotify-mcp-server
npm ci && npm run build
cp .env.example .env  # add your Client ID
npm run auth          # one-time login
npm run dev           # run from source
npm test              # unit + MCP smoke tests

Not affiliated with Spotify. Use per the Spotify Developer Terms.

MIT ยฉ Carme99 and NovaLux12 contributors ยท Acknowledges calebWei/SpotifyMCP and varunneal/spotify-mcp.

Available Tools

129 tools
add_to_playlistB

Add tracks or episodes to a playlist. Max 100 URIs per call.

ParametersJSON Schema
NameRequiredDescriptionDefault
urisYesTrack or episode URIs to add
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
positionNoInsert at this index; appends if omitted. 0-based index into the playlist's current item order (0 = the first item).
playlist_idYesPlaylist ID
check_duplicatesNoSkip URIs that are already in the playlist instead of appending them (default: false)

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The only annotation is destructiveHint=false, so the safety profile is thin and the description carries most of the burden. It discloses the 100-URI ceiling, but says nothing about dedup defaults, ordering/position side effects on existing items, idempotency, or error behavior for invalid URIs. This is adequate but clearly short of full behavioral disclosure for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, the action front-loaded and the limit immediately after. Nothing wasted and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With five parameters, no output schema, and a mutation that can exceed a single-call limit, the description is thin: it omits how to handle more than 100 URIs, whether duplicates are skipped by default, and which sibling to use for bulk work. It is minimally viable but leaves a routing gap against batch_add_to_playlist.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents dry_run, position, check_duplicates, and the uris cap, so the baseline of 3 applies. The description's only parameter-relevant statement (max 100 URIs) duplicates maxItems: 100 in the schema, adding no meaning beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (add) and resource (playlist) plus the item types accepted (tracks or episodes). It does not distinguish itself from the sibling batch_add_to_playlist, which appears to serve the same purpose at a different scale, leaving the agent to guess which to call.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no exclusions, and no mention of alternatives such as batch_add_to_playlist, add_to_queue, or replace_playlist_items. The only hint is the 100-URI cap, which implies a bulk boundary but doesn't state how to route around it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

add_to_queueA

Add a track or episode to the end of the playback queue.

ParametersJSON Schema
NameRequiredDescriptionDefault
uriYesSpotify track or episode URI (e.g. spotify:track:...)
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description carries most of the burden. 'To the end of the playback queue' usefully discloses append/ordering behavior, but it omits notable traits such as the need for an active playback device and the fact that this mutation is additive-but-persistent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single well-formed sentence with the resource and the placement constraint front-loaded; every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-required-param tool with no output schema and full schema coverage, this is mostly adequate, but the device targeting (device_id) and the active-device precondition are never surfaced, leaving a real behavioral gap for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so uri, dry_run, device_id, and response_format are all already documented in the schema, including the dry_run preview semantics and the response_format enum. The description adds nothing beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb+resource ('Add a track or episode ... to the playback queue') and scopes it ('to the end'), which clearly separates it from play/pause/skip_next and get_queue siblings. It doesn't name an alternative explicitly, but the operation is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: 'to the end of the playback queue' hints at additive queuing versus immediate playback, but there is no explicit when-to-use/when-not clause and no sibling is named (e.g., play_from_search, play). An agent can infer intent but gets no routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

apply_sceneA

Apply a saved scene: resolve its device hint, transfer playback, then set volume/shuffle/repeat and start the saved context (in that order; missing targets are skipped)

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesScene name to apply
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint: false in annotations, the description adds meaningful behavioral context: it discloses the multi-step order (resolve device hint, transfer playback, set volume/shuffle/repeat, start context) and that missing targets are skipped. It does not discuss auth needs, reversibility, or rate limits, but it goes beyond the annotation without contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that states the action and execution order without wasted words. Every clause earns its place by conveying the operation or its sequencing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a multi-step mutation tool with no output schema, the description is largely sufficient: it covers the execution order and skip behavior for missing targets. It could mention dry-run behavior explicitly, but that is already fully documented in the input schema, so the remaining gap is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters (name, dry_run, response_format) are already fully documented in the schema. The description adds no parameter-level detail beyond what is in the structured input schema, making the baseline of 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Apply') and resource ('a saved scene') and immediately distinguishes the operation from siblings like save_scene, list_scenes, and delete_scene. It also spells out the execution sequence, making the tool's scope unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: the tool is for applying a saved scene, and the sequence is described. However, there is no explicit guidance on when to choose this over manually calling transfer_playback, set_volume, set_shuffle, set_repeat, or play, nor any exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

audiobook_progressA

Audiobook progress rollup: chapters total, played count, current chapter, percent complete. Walks every chapter page up to the shared fetch-all cap and reports scan coverage. Quota: 1 audiobook GET + chapter page GETs.

ParametersJSON Schema
NameRequiredDescriptionDefault
marketNoMarket, e.g. 'US'
audiobook_idYesAudiobook ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description must supply behavioral context, and it does: it walks every chapter page up to a shared fetch-all cap, reports scan coverage, and discloses the quota cost (1 audiobook GET + chapter page GETs). It does not state error/not-found behavior, which keeps it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight, front-loaded sentences with no filler; the output fields come first, then the scan behavior, then the quota cost. 'Shared fetch-all cap' is slightly jargon-y but informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by listing the returned metrics, and it covers the scanning/enumeration behavior and cost. Missing only edge-case behavior (e.g., audiobook not found) for a full 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including the response_format enum, so the parameters are fully documented structurally. The description adds no additional parameter-level meaning beyond the quota note, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (audiobook progress rollup) and enumerates the exact outputs: chapters total, played count, current chapter, percent complete. It is clearly distinguishable from all siblings, none of which report audiobook progress.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intent (fetch progress for an audiobook) is implied by the name and output list, but there is no explicit when-to-use or when-not-to-use guidance and no named alternative. Adequate but leaves routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backup_firstA

Create a pre-flight library snapshot before a destructive operation. Returns snapshot file path and counts for later restore. Read-only against Spotify.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoFree-text note for the snapshot
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide destructiveHint=false; the description adds that the tool is read-only against Spotify, returns a snapshot file path and counts, and is intended as a pre-flight safety measure. This gives useful behavioral context beyond the annotation, though storage/retention details are not disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no filler. The action and purpose are front-loaded, and each sentence adds a distinct piece of information: what it does, what it returns, and that it is safe against Spotify.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only snapshot tool with optional parameters and no output schema, the description gives enough to select and invoke it: purpose, usage timing, return shape, and safety. It could be more complete by clarifying what 'library' includes or how restore works, but that is not essential for calling this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description does not add meaning beyond the schema for the two optional parameters; it only mentions return values generally, which is already implied by the tool's purpose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Create'), resource ('pre-flight library snapshot'), and purpose ('before a destructive operation'), which clearly distinguishes it from snapshot_playlist and backup_library. Also names the key return values (snapshot file path and counts), leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use this tool: before a destructive operation and for later restore. This provides clear context for choosing it, though it does not name alternatives or give exclusions, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backup_libraryA
Read-onlyIdempotent

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 (500/category) and each playlist at SPOTIFY_MCP_PLAYLIST_ITEMS_CAP (500); the smaller wins, so a full backup of a large playlist needs both raised. Files land in SPOTIFY_MCP_BACKUP_DIR (default ~/.spotify-mcp/backups), mode 0600.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoFree-text note stored in the snapshot _meta block
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
walk_capNoCap on items per category walked for THIS call (default: SPOTIFY_MCP_FETCH_ALL_CAP). Bounds what is READ, not rows rendered โ€” use max_results to shrink the response.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, and the description adds substantive context beyond that: read-only against Spotify, the two cap env vars and the 'smaller wins' interaction, the backup directory default, and file mode 0600. It does not describe failure modes or partial-write behavior, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the essential fact (full-library snapshot to local JSON) and then packs the operational caveats into compact clauses. Dense but every clause carries information; the long cap sentence is slightly heavy but justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully explains where files land, their mode, and the cap behavior, which covers what an agent needs to invoke and reason about the result. It stops short of describing the file's internal structure or how to locate a specific backup later.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters are already documented in the schema. The description reinforces the cap mechanics (walk_cap vs the env default, playlist cap interplay) but adds little that the schema does not already say. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (snapshot) and resource (entire library) plus the destination (local JSON file), and enumerates the categories captured. It does not explicitly contrast itself with siblings like export_library_json, export_all_playlists, or backup_first, so an agent must infer the distinction from the 'ENTIRE library' scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when it applies (full-library snapshot) and gives operational context about caps and env vars, but never says when to choose it over export_library_json, backup_first, or export_all_playlists, nor when-not to use it. Usage is inferred rather than directed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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. Target the playlist by ID/URI/URL or by lane name.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
dedupeNoDeduplicate (within batch and against target). Default: true
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
source_urisYesSource URIs: spotify:track:, spotify:album:, spotify:artist:, spotify:playlist:
target_laneNoLane name from the lane registry; provide exactly one of target_playlist_id or target_lane
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
target_playlist_idNoTarget playlist ID, spotify:playlist: URI, or URL; provide exactly one of target_playlist_id or target_lane

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries most of the behavioral weight and delivers: in-batch and against-target dedupe, write batching in groups of 100, dry-run preview semantics, and an elicitation trigger at 100+ tracks. These are non-obvious operational traits an agent could not infer from the schema or annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five compact sentences, each earning its place, with the core action front-loaded and operational caveats (dedupe, batching, dry-run, elicitation) following in descending priority. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation with no output schema, the description covers the behaviors an agent most needs: dedupe semantics, batching, dry-run, and the confirmation threshold. It does not describe result shape or partial-failure behavior across batched writes, a minor gap since no output schema exists to cover it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all nine parameters, setting the baseline at 3. The description echoes dedupe and target-selection semantics but adds no syntax or format detail beyond what the schema states, so it neither compensates for nor exceeds the structured data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: 'Add tracks from multiple source URIs (tracks, albums, artists, playlists) to a target playlist in one call.' The 'multiple source URIs ... in one call' framing distinguishes it cleanly from the single-item add_to_playlist sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives targeting guidance ('by ID/URI/URL or by lane name') and mentions dry-run and elicitation thresholds, which is useful context. However, it never explicitly states when to prefer this over add_to_playlist or how it relates to bulk siblings like merge_playlists or grow_playlist; the batch intent is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_wind_downA

Cancel the in-process wind-down ramp, if one is running

ParametersJSON Schema
NameRequiredDescriptionDefault
device_idNoOnly cancel if the active wind-down targets this device id
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only include destructiveHint=false, which is minimal. The description discloses that it affects an in-process ramp and is conditional, but does not explain what happens to the ramp synchronization (e.g., devices return to original volume, whether any state is persisted) or any side effects beyond cancellation. Since annotations are sparse, the description carries more burden but still falls short of fully disclosing behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one sentence, front-loaded with the action and resource, and immediately states the condition. Every word earns its place and there is no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and minimal annotations, the description covers the essential purpose. It lacks details about scenarios (e.g., no ramp running), which might be handled by tool logic, but for a simple cancel operation it's sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are documented in the schema. The description adds no extra semantics beyond what's in the schema; device_id's purpose is already clear. For a simple tool, this is acceptable, but it doesn't add nuance like whether omitting device_id cancels all ramps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (cancel) and the resource (in-process wind-down ramp), and indicates the condition (if one is running). It differentiates from siblings like schedule_wind_down and wind_down_status, though it doesn't explicitly name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use it (when a wind-down is running and you want to stop it) and the conditionality is clear. However, it doesn't explicitly contrast with alternatives like 'wind_down_status' for checking state or 'schedule_wind_down' for starting. There is no explicit when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_following_artistsA
Read-onlyIdempotent

Check if the user follows specific artists โ€” this tests FOLLOW state, not library-saved state (for that use check_in_library). Accepts IDs or spotify:artist: URIs. Rows carry {id, uri, follows}; returns a boolean per ID. Max 50.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsYesArtist IDs, spotify:artist: URIs, or artist URLs; CSV accepted
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint and idempotentHint, so the description's added value is describing the output shape ('Rows carry {id, uri, follows}; returns a boolean per ID') and accepted URI formats. It does not mention auth or error behavior, but those are less critical for a read-only, idempotent check.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero fluff. The core purpose is front-loaded, then the distinction from check_in_library, then input formats, then output behavior, then a limit. Every phrase earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with a well-populated schema, the description covers purpose, input, output, and a key alternative. The only gap is that 'Max 50' is ambiguous (input ids vs output count) and max_results can exceed 50, but the schema clarifies ids maxItems=50 and max_results maximum=2000, so it's a minor ambiguity rather than a completeness failure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds no new parameter meaning beyond the schema โ€“ it only partially restates the ids parameter's accepted formats ('IDs or spotify:artist: URIs') which the schema already documents fully. max_results and response_format semantics are left entirely to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Check if the user follows specific artists') and explicitly distinguishes it from library-saved state by pointing to check_in_library. This clearly separates it from sibling tools like follow_artists, unfollow_artists, and check_playlist_following.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when not to use this tool ('this tests FOLLOW state, not library-saved state') and names the alternative tool (check_in_library). It also describes accepted input formats (IDs or URIs) and a practical limit, giving the agent enough to decide when to call it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_in_libraryA
Read-onlyIdempotent

Preferred. Accepts the widest URI mix (track, album, episode, show, audiobook, artist, user, playlist) in one request. Check whether items are saved in or followed by the user โ€” this tests LIBRARY-SAVED/FOLLOWED state, distinct from check_following_artists which only tests artist FOLLOW state. Returns a boolean per URI via Spotify's unified endpoint. Max 40. Following an artist is no longer expressible: Spotify's February 2026 changes removed PUT/DELETE /me/following, and this endpoint's save side does not accept spotify:artist: URIs, so there is no endpoint that can follow or unfollow an artist. This read still answers the question for artist URIs.

ParametersJSON Schema
NameRequiredDescriptionDefault
urisYesSpotify URIs to check (accepts tracks, albums, episodes, shows, audiobooks, artists, users, playlists)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint, and the description adds substantial value on top: per-URI boolean return, the 40-URI cap, the unified endpoint, and the February 2026 API change that removed artist follow/unfollow. That last point is non-obvious behavioral context an agent could not infer from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the decisive cue ('Preferred') and the capability in the first two sentences. The trailing explanation of the February 2026 following change is useful but somewhat discursive for a description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the return shape (boolean per URI), the input ceiling, and the sibling routing. Nothing needed to invoke or interpret the tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all three parameters are already documented in the schema. The description restates the accepted URI types but adds no syntax or format detail for max_results or response_format, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('check whether items are saved in or followed by the user') and explicitly scopes it against the sibling check_following_artists. An agent can distinguish it from every other check_* / get_saved_* tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Opens with 'Preferred' and says it accepts the widest URI mix in one request, then names the alternative (check_following_artists) and the exact condition that separates them (library-saved/followed state vs artist follow state). It also explains the one case where the alternative is no longer usable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

check_playlist_followingA
Read-onlyIdempotent

Check if you follow 1โ€“50 playlists. Follow state: GET /me/library/contains?uris=spotify:playlist:,โ€ฆ (40/req, 1โ€“2 GETs). Unreadable state reports unknown, never not-followed.

ParametersJSON Schema
NameRequiredDescriptionDefault
playlistsNoCanonical ordered playlists (1โ€“50)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only/idempotent, and the description adds real behavioral context beyond them: batching mechanics (40/req, 1โ€“2 GETs) and, importantly, the error semantics 'Unreadable state reports unknown, never not-followed' โ€” a valuable non-obvious contract. Lacks any note on output shape, but the key edge-case behavior is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense and front-loaded: purpose first, then the operational detail and the safety guarantee. No padding; each clause carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does explain the returned state (followed / unknown) and the batch size, which is enough for correct invocation. Minor gap: it does not describe what fields accompany each playlist in the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description reinforces the array bound ('1โ€“50 playlists') but adds no format guidance for the ID/URI/URL items or the response_format enum beyond what the schema already documents.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: 'Check if you follow 1โ€“50 playlists.' The scope (follow-state of playlists) is unambiguous and clearly distinct from the sibling check_following_artists, so an agent can select it without inspecting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The batch size (1โ€“50) implies the intended use, but there is no explicit when-to-use/when-not guidance and no named alternative (e.g., the artist counterpart or follow_playlist). Usage must be inferred from the operation itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clean_all_playlistsA
Destructive

Scan every playlist in your library for duplicate items (repeated URIs, and on opt-in same-song copies under different URIs when match_by=name_artist). Reports per-playlist findings by default; pass apply=true to remove them (keeps the first occurrence of each group). Bulk removals ask for one confirmation before anything is deleted. See the duplicate-matching vocabulary in SPEC section 4.

ParametersJSON Schema
NameRequiredDescriptionDefault
applyNoDeprecated alias for dry_run โ€” prefer dry_run. false (default): report only. true: execute the cleanup across all playlists with duplicates. If both are given, dry_run wins.
dry_runNoPreview only โ€” when true, nothing is changed; when false via dry_run=false or apply=true, executes the cleanup
match_byNoWhich rule decides that two items are the same: `uri` (exact URI, the default), `name_artist` (case-insensitive name + credited artists, catches relinks/remasters), or `name` (case-insensitive name only). The rule applied is echoed in the result as `match_by`.
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
include_relinkedNoDeprecated alias for `match_by`, kept for one release: true is `name_artist` and false is `uri`. It cannot express the `name` rule, which is why `match_by` replaced it. Sending both, where they mean different rules, is an error rather than a silent choice.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=true, so the description usefully adds that the default is non-destructive, that the first occurrence of each duplicate group is preserved, and that bulk deletions require one confirmation. It could say more about irreversibility or whether an undo/receipt applies, but the safety-relevant behavior is well covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences that front-load scope and default behavior before the mutation switch. The closing pointer to 'SPEC section 4' is an external dependency that costs a little self-containedness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does state what comes back (per-playlist findings, match_by echoed in results) and covers the confirmation flow for destructive runs. Complete enough for a library-wide cleanup tool, though return shape detail is thin.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter is already documented in the schema. The description reinforces match_by semantics and the deprecation of apply, but adds no syntax or format detail the schema lacks. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (scan/clean) plus resource (every playlist in your library) plus the object of interest (duplicate items), with the default behavior spelled out. It is clearly differentiated from single-playlist siblings like find_duplicates_in_playlist and remove_duplicate_playlist_items by the library-wide scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the default mode (report only) and the switch to mutation (apply=true), plus the confirmation gate for bulk removal. It does not explicitly name the single-playlist alternatives or say when a user should prefer them, so it falls short of a full when/when-not/alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clean_backup_artifactsA
Destructive

Delete the NON-library files sharing SPOTIFY_MCP_BACKUP_DIR with your library backups: closed listening sessions (listening-session-*.json), playlist write pre-images (playlistops-pre-*.json) and legacy or migrated playback bookmarks (playback-bookmark-*.json). Library backups and their .meta.json sidecars are never touched โ€” use delete_backup, and naming one here is refused. These files are local and gone for good once deleted. Preview by default; executing is confirmation-gated and refused when the client cannot prompt (SPOTIFY_MCP_CONFIRM=never bypasses). Ages are mtimes, and the default window is SPOTIFY_MCP_BACKUP_ARTIFACT_RETENTION_DAYS โ€” separate from the library window. Unrecognised files are listed, not deleted.

ParametersJSON Schema
NameRequiredDescriptionDefault
filesNoFile names to delete instead of a sweep. Each must be inside the backup directory and match a known family; `family` and `older_than_days` then do not apply.
familyNoWhich non-library family to act on. Default all.
dry_runNoPreview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit.
older_than_daysNoAge floor in days. 0 = no age filter. Omit to use the retention window.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=true; the description adds substantial context beyond that: files are local and irrecoverable, preview-by-default, confirmation gating, SPOTIFY_MCP_CONFIRM=never bypass, age semantics based on mtimes, and that unrecognised files are listed rather than deleted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is dense and front-loads the destructive action and target scope before the caveats, with each sentence carrying distinct information. It runs long, but almost no clause is redundant given the number of behavioral guarantees it must convey.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description explains the PLAN/preview return, the listing of unrecognised files, and all safety gates. For a destructive file-deletion tool with zero required params, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: ages are mtimes and the default retention window comes from SPOTIFY_MCP_BACKUP_ARTIFACT_RETENTION_DAYS (separate from the library window). It also clarifies that `files` overrides `family`/`older_than_days`, though the schema already states this.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

It states a precise verb (delete) plus the exact resource scope (NON-library backup artifacts), enumerating the three file families by glob pattern. It also explicitly distinguishes itself from sibling `delete_backup` and names the files that belong to that other tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use routing (non-library artifacts vs. library backups via `delete_backup`), the safe default (preview), the commit path (dry_run=false, confirmation-gated), and refusal conditions (naming a library file, clients that cannot prompt). Alternatives and exclusions are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clone_playlist_coverB

Copy cover image from source playlist to target. Quota: GET images + PUT images (plus image fetch).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
image_indexNoWhich cover image to copy. Default 0. 0-based index into the playlist's current item order (0 = the first item).
source_playlist_idYesSource playlist ID, URI, or URL
target_playlist_idYesTarget playlist ID, URI, or URL

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds genuinely useful context not present in the schema or the single destructiveHint annotation: the quota cost (GET images + PUT images, plus an image fetch). However it does not say whether the target's existing cover is overwritten or what happens on failure, so the mutation behavior stays partly opaque.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, purpose front-loaded ahead of the quota note; nothing is wasted. The parenthetical 'plus image fetch' is slightly cryptic but does not bloat the text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple copy tool with a full-coverage schema and no output schema, the essentials are covered. The remaining gap is the effect on the target's existing cover and any failure/permission behavior, which an agent would want before invoking.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including dry_run and image_index semantics, so the schema carries parameter meaning fully. The description adds nothing parameter-specific, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: copy the cover image from a source playlist to a target playlist. It is inherently distinguishable from nearby siblings like get_playlist_cover and upload_playlist_cover, though it never names them or explicitly disambiguates.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance and no alternatives referenced. The quota note is operational cost information, not routing guidance, so an agent still infers on its own when cloning a cover is preferred over uploading one.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compare_playlist_coversA
Read-onlyIdempotent

Compare two playlists covers: URL equality, dimensions. Quota: 2 GETs.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
scan_capNoMaximum rows to read from each playlist; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlist_aNoCanonical A playlist; provide with playlist_b
playlist_bNoCanonical B playlist; provide with playlist_a
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry readOnlyHint and idempotentHint, so the safety profile is covered. The description adds genuine value beyond that by disclosing the cost ('Quota: 2 GETs') and the shape of the comparison (URL equality plus dimensions), which an agent cannot read off the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the action and resource, with the cost disclosure appended. Nothing is wasted and speed of scanning is high.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and six parameters, the description carries return-shape duty and does hint at it (URL equality, dimensions). It omits edge cases such as missing covers or mismatched sizes, but for a read-only comparison tool this is close to complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters (limit, scan_cap, playlist_a/b, max_results, response_format) are already documented in the schema. The description adds no parameter-level meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('compare two playlists covers') and narrows the scope to URL equality and dimension checks, which separates it from one-cover tools like get_playlist_cover and clone_playlist_cover. It never names a sibling explicitly, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to reach for this versus get_playlist_cover or clone_playlist_cover, nor any precondition (e.g. both playlists must exist / have covers). The purpose is inferable but the selection guidance is absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

copy_playlistA

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
publicNoPublic flag for the new playlist. Default: false
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
new_nameYesName for the new playlist
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
descriptionNoDescription for the new playlist (defaults to source description)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
collaborativeNoCollaborative flag. Default: false
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
source_playlist_idYesSource playlist ID, spotify:playlist: URI, or URL

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The only annotation is destructiveHint=false, so the description carries the burden of behavioral disclosure. It adds valuable transparency by stating that the tool creates the new playlist first, adds tracks in batches of 100, and supports a dry-run mode that reports what would be created. It does not cover rate limits, auth requirements, or failure modes, but the core behavior is well disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no filler. The first sentence states the purpose, the second explains the workflow, and the third covers the dry-run behavior. Every sentence earns its place and the key information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 10 parameters and no output schema, and the description explains the main workflow well. However, it does not cover return values, response formats, or edge cases such as the interaction between limit, scan_cap, and max_results. It is adequate for a basic understanding but leaves gaps for a complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters are already fully documented. The description reinforces the 'batches of 100' behavior which relates to the limit parameter and mentions dry-run, but it does not add meaning beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Duplicate' and the resource 'existing playlist' into a new playlist, and adds a meaningful detail: preserving track order. It is specific enough to understand the tool's core function, but it does not explicitly disambiguate from sibling tools like clone_playlist_live or playlist_clone_snapshot.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to use this tool versus alternatives such as clone_playlist_live or playlist_clone_snapshot. The description implies usage for duplicating a playlist, but provides no exclusions, prerequisites, or distinguishing conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_playlistA

Create a new playlist for the current user. Set dry_run=true to preview without creating.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPlaylist name
publicNoWhether the playlist is public. Default: false
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
descriptionNoPlaylist description
collaborativeNoWhether the playlist is collaborative. Default: false

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=false, so the description need not restate safety. It adds the dry_run preview behavior, which is a useful nuance. However, it doesn't disclose other behavioral aspects like required authentication, rate limits, or the result payload on success. Since the create operation is inherently mutating but safe, the description provides moderate additional context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences convey both the primary function and a key usage tip without any filler. The description is front-loaded with the core action and includes the dry_run hint efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is a simple create operation with five documented parameters, but there is no output schema and the description doesn't mention what the tool returns (e.g., the created playlist object). Given the complexity is low and the schema covers inputs, this is adequate but leaves the return behavior unspecified. No prerequisites or side effects are described beyond dry_run.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all five parameters are documented in the schema. The description mentions dry_run, which reinforces the schema's description but doesn't add new meaning. It doesn't clarify any parameter semantics beyond what's already in the schema, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb ('Create') and resource ('a new playlist for the current user'), which clearly distinguishes it from read-only or update operations. It is concise and unambiguous, though it does not explicitly contrast with sibling playlist tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given on when to prefer this tool over alternatives like update_playlist or add_to_playlist. The only usage hint is the dry_run flag for preview, but there is no explicit condition for when to use or avoid this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_smart_playlistA

Create a playlist from rules over your own listening data: top tracks (by time range), recently played, or saved tracks โ€” with optional artist-name filtering and a one-track-per-artist toggle. When source=saved_tracks the pool is the newest N saved tracks (N=scan_cap, default fetchAllCap=500) and truncation is reported. No deprecated recommendations endpoints involved. Every source has a pool ceiling (top_tracks 100, recently_played 50, saved_tracks scan_cap), reported as pool_capped with pool_cap โ€” a capped pool is a floor, not a complete scan. dry_run previews the exact track list without creating anything.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPlaylist name
limitNoHow many tracks the playlist should hold (after filters). Default 30.
publicNoWhether the playlist is public
sourceNoWhere candidates come from: your top tracks by time_range, your recently played history, or your saved (liked) tracks.top_tracks
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoHow many saved tracks to scan when source=saved_tracks; default SPOTIFY_MCP_FETCH_ALL_CAP (500). Reports truncation when hit.
time_rangeNo~4 weeks / ~6 months / all time. Default: medium_term
descriptionNoPlaylist description
artist_filterNoOnly include tracks whose artist name contains any of these substrings (case-insensitive), e.g. ["Radiohead", "Miles Davis"].
unique_artistsNoKeep at most one track per primary artist. Default false.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry destructiveHint=false, which is thin. The description compensates by disclosing real behavioral traits: pool ceilings per source, truncation reporting, the fact that a capped pool is 'a floor, not a complete scan', and that dry_run creates nothing. It also warns about truncation for saved_tracks. The one small gap: it doesn't state what happens to an existing playlist of the same name, or whether this mutates user state (creation is implied). Still, this is well beyond the annotation floor, so a 4 is fair.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph that front-loads the core purpose and then packs in constraints. It earns its sentences; every clause adds information. It could be split for readability, but there's no waste. Slightly long for a one-liner but appropriate for the tool's complexity (11 params, 3 sources). A 4 for tight content, minor ding for lack of visual structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 11 parameters, 3 enum-based sources, no output schema, and sparse annotations, the description carries the full burden. It covers: what the tool creates, each source's behavior, pool ceilings, truncation, the dry_run preview, and the exclusion of deprecated endpoints. The parameter semantics dimension covers the rest. Nothing an agent needs to decide whether to call it or how to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaning above the schema: it explains that limit applies 'after filters', clarifies that saved_tracks pool is the 'newest N saved tracks' with scan_cap defaulting to fetchAllCap=500, and defines source-specific pool ceilings. It also frames dry_run as 'previews the exact track list'. This is genuine added value beyond the property descriptions, so a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Create') and resource ('a playlist from rules over your own listening data'), then enumerates the exact rule dimensions (source, artist filter, unique artists). It clearly differentiates from the many playlist-creation siblings (e.g. create_playlist, taste_to_playlist, playlist_template_apply) by anchoring on rule-based creation from personal listening data and explicitly ruling out deprecated recommendations endpoints. An agent can tell this apart from siblings without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit 'when to use' context by naming the three data sources and their semantics, and it adds a crucial exclusion: 'No deprecated recommendations endpoints involved,' which tells the agent this is the modern replacement for a legacy flow. It also explains when dry_run is appropriate ('previews the exact track list without creating anything'). Combined with the sibling list (save_smart_playlist_rule, refresh_smart_playlist), an agent can select this over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_backupA
Destructive

Delete one library backup file (and its metadata sidecar) from SPOTIFY_MCP_BACKUP_DIR. Irreversible โ€” the library rows in the file cannot be recovered from anywhere else. Destructive and confirmation-gated: dry_run defaults to true, and executing is refused when the client cannot prompt (SPOTIFY_MCP_CONFIRM=never bypasses). Paths outside the backup directory are refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileYesBackup file name (e.g. backup-2026-01-02-1.json) or a path inside the backup directory
dry_runNoPreview only, and the default: pass dry_run: false to delete the snapshot.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the destructiveHint annotation, disclosing irreversibility, the sidecar deletion, confirmation-gating (dry_run default true, refusal when client can't prompt, SPOTIFY_MCP_CONFIRM=never bypasses), and path restrictions. This is rich, transparent behavioral context that an agent needs for a destructive operation. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is five sentences, with the core action front-loaded in the first sentence. Every sentence adds valueโ€”sidecar deletion, irreversibility, confirmation gating, path restrictionsโ€”without redundancy. It's concise and efficiently structured for an agent to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool, the description covers the critical aspects: what is deleted, irreversibility, confirmation steps, path safeguards. It does not describe the return format or error behavior for non-existent files, but for a mutation tool with a destructiveHint and full parameter documentation, the provided context is largely sufficient. A small gap remains around response/error details, hence 4.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters (file, dry_run, response_format) are already fully documented in the schema. The description adds no new parameter-level semantics beyond what's in the schema, and the schema entries are themselves descriptive (e.g., dry_run explains default and how to override). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Delete), resource (library backup file and its metadata sidecar), and scope (from SPOTIFY_MCP_BACKUP_DIR). It clearly differentiates from list/restore/backup creation tools by emphasizing irreversibility and the sidecar. This leaves no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The purpose is clear enough that an agent would know when to use it (to delete a backup), but the description does not explicitly name alternative tools or provide conditional guidance like 'use this only when you intend permanent removal' or point to restoration tools for recovery. It focuses on behavior rather than decision context, so it falls short of strong usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_sceneA
Destructive

Delete a saved playback scene from the local sidecar

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesScene name to delete
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructiveHint=true, so the description's confirmation that this deletes a saved scene adds clarity about what is destroyed. It also specifies 'from the local sidecar', which is a useful behavioral detail not present in the annotations. There is no contradiction, and the description provides enough context for the destructive action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with zero filler. Every word contributes to the meaning, and the structure immediately conveys the action and target. Nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter delete tool with destructive annotation and full schema coverage, the description is nearly sufficient. It clearly identifies the action, target, and storage location. The only minor gap is that it does not describe the return behavior or response_format effects, but that is partially covered by the schema and is not critical for a delete operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with both 'name' and 'response_format' already documented. The tool description adds no additional meaning about the parameters or their relationships. This meets the baseline for schema-covered parameters but does not go beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'Delete' and clearly identifies the resource: 'a saved playback scene from the local sidecar'. This distinguishes it from siblings like delete_playback_bookmark and aligns with the scene-related tools (save_scene, list_scenes, apply_scene). The scope is unambiguous and immediately understandable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states the tool's function but provides no explicit guidance on when to use it versus alternatives such as delete_playback_bookmark or the other scene tools. Usage is implied by the name and resource, which is sufficient for a straightforward delete, but there is no stated exclusion or alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diff_playlistsA
Read-onlyIdempotent

Compare two playlists up to the configured source cap: tracks only in A, only in B (by track ID), and tracks present in both but at different positions. Rendered rows are capped by max_results; truncation metadata reports when source walks hit scan_cap.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlist_aNoCanonical A playlist; provide with playlist_b
playlist_bNoCanonical B playlist; provide with playlist_a
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish that this is a safe, repeatable read (readOnlyHint, idempotentHint), but the description adds real value beyond them: it discloses the source scan cap, that truncation metadata reports when source walks hit scan_cap, and that rendered rows are bounded by max_results. It stops short of describing output shape or how position comparison is computed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences, front-loaded with the operation and its result categories, followed by the capping/truncation semantics. No filler, restatement of the name, or redundant prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a comparison tool with no output schema and a fully documented parameter set, the description covers result categories, capping behavior, and truncation reporting, which is close to sufficient. It omits any note on empty/error cases or the fact that no parameters are required, but nothing critical to calling it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline is 3, but the description clarifies the non-obvious interplay between two similarly named caps: scan_cap bounds the source walk while max_results bounds rendered rows. That distinction is not obvious from the schema alone and materially helps correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Compare two playlists') and enumerates the three result classes (only in A, only in B by track ID, in both but at different positions), which is genuinely informative. However, it never distinguishes itself from the many closely related siblings such as playlist_symmetric_difference, overlap_playlists, or playlist_union, so an agent must infer which comparison tool to pick.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no named alternative despite a dense field of overlapping comparison/union/subtract/symmetric-difference siblings. Usage is only implied by the behavioral description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expand_mood_to_queriesA

Turn a free-text listening mood into search terms (genres, keywords, terms to avoid) for search. Uses the host model via MCP sampling when the host advertises the sampling capability; otherwise returns a built-in static map. Calls no Spotify endpoint and changes nothing. A model reply that cannot be parsed returns isError after one retry โ€” it is never replaced by a guess.

ParametersJSON Schema
NameRequiredDescriptionDefault
moodYesThe mood or vibe to expand, in free text (e.g. "rainy afternoon", "late night coding")
max_tokensNoToken ceiling for the sampling call. Default: 512. Ignored on the static-map path
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the lone destructiveHint=false annotation: it discloses the sampling path vs. static-map fallback, that no Spotify endpoint is called, that nothing is mutated, and the exact failure contract (isError after one retry, never a guess). This is rich, high-value behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four front-loaded sentences, each carrying distinct information (purpose, execution path, side-effect profile, error semantics). Slightly dense but no wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and a rich response_format parameter, the description carries the return-value burden and does describe the output fields. A brief note on which format actually gets returned on the static-map path would close the last gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so mood, max_tokens and response_format are fully documented in the schema. The description adds the output vocabulary but no parameter-specific semantics beyond the schema, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Turn a free-text listening mood into search terms') and enumerates the output shape (genres, keywords, terms to avoid). This is a unique utility with no equivalent among the siblings, so it is trivially distinguishable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'for search' implies it is a pre-step to searching, but the description never states when to use this versus calling search/search_deep directly, nor any exclusions. Usage is implied rather than directed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeNoowned = only playlists you ownall
formatNoOutput formatjson
output_dirNoLocal directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)
include_itemsNoInclude track items per playlist
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

destructiveHint=false is already in annotations, and the description adds meaningful behavioral detail with the quota formula: GET /me/playlists + Nร—GET /playlists/{id}/items, capped by fetchAllCap. This helps the agent reason about cost and batch size, though auth requirements and sidecar-file naming are not disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, dense sentences front-load the core action and then add the quota constraint without any filler or repetition. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given five fully documented parameters, the description covers the operation, scope choice, output format, output directory, and quota behavior. Minor ambiguity remains around the exact meaning of 'all' and the shape of the returned result, but with no output schema and strong parameter docs this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage: all five parameters already carry descriptions, defaults, and enums. The description adds tool-level context like sidecar output and quota, but does not materially refine individual parameter meaning beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The phrase 'Export every owned (or all) playlist with metadata + items to a sidecar file' names a specific verb, resource, and scope. The qualifier 'every' and the sidecar-file output clearly distinguish it from singular or JSON-specific export siblings, even though no sibling is named.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for the intended use case: bulk export of owned/all playlists, with scope selectable via the schema. It stops short of explicitly naming alternatives like export_playlist or sidecar_export_bundle or stating when not to use this tool, so the routing is left partly to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
formatNoOutput format: json or csvjson
output_dirNoLocal directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide only destructiveHint: false, so the description carries the behavioral burden. It discloses the file-writing side effect ('to a local directory'), the output field set, and โ€” most valuably โ€” that exported_at is the export time, not a follow date, because Spotify does not expose followed_at. This preempts a likely misinterpretation of the produced data, and none of it contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with the core purpose front-loaded in the first sentence and zero wasted words. The field list and the exported_at caveat each earn their place; the caveat preempts a data-interpretation error rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity tool (3 optional params, no output schema, non-destructive), the description plus schema cover purpose, destination, response mode (via response_format), field semantics, and the exported_at caveat. Minor gaps remain around overwrite behavior and directory creation, but nothing an agent needs to invoke the tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: all three parameters (format, output_dir, response_format) are documented with defaults, enums, and meaning, so the baseline is 3. The description adds marginal value by enumerating the exported fields (uri, name, genres), which clarifies what the chosen format will contain, but it doesn't deepen the meaning of any individual parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Export'), names the exact resource ('your followed artists'), the destination ('a local directory'), formats (JSON or CSV), and even the exported fields. Among the large sibling set of export_* tools, this uniquely targets followed artists, and it is clearly distinguishable from get_followed_artists by the explicit file-persistence behavior.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the phrasing signals it is for creating a local file of followed artists. There is no explicit when/when-not guidance, and with retrieval siblings like get_followed_artists and broader exports like export_library_json in the sibling set, an agent gets no direct routing help. The exported_at caveat is informative but not usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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").

ParametersJSON Schema
NameRequiredDescriptionDefault
formatNoOutput format: json (single file) or csv (one file per type)json
output_dirNoLocal directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only include destructiveHint=false, so the description carries the burden of behavioral disclosure. It explicitly discloses the SPOTIFY_MCP_FETCH_ALL_CAP behavior, reporting cap_reached, truncated, and a prose footer, which is valuable context beyond the annotation. However, it does not mention whether existing files are overwritten or how the output directory is created, but those are minor gaps given the export action is clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences that front-load the core purpose and then add the cap behavior. Every word earns its place, with no redundancy or fluff. It efficiently conveys the tool's function and a key edge case without extra text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the main export scope and the cap/truncation behavior, and the schema covers format and output details. However, it does not describe the return value for a successful export (only the cap case), and it omits details like whether the output directory is created automatically. Given the tool's complexity and lack of output schema, these are minor but notable gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides full descriptions for all three parameters (format, output_dir, response_format), including enums and defaults. The description adds no additional parameter-level meaning beyond what the schema covers. Since schema coverage is 100%, a baseline of 3 is appropriate; the description's cap explanation is not parameter-specific.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool exports the full library (saved tracks, albums, shows, episodes, audiobooks) to a local directory in JSON or CSV format, with a specific verb and resource. It also mentions the cap behavior, which distinguishes it from other export tools. The scope is explicit, making it easy to differentiate from siblings like export_playlist or export_followed_artists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus the many other export tools in the sibling list (e.g., export_all_playlists, export_followed_artists, export_profile_state). It does not mention alternatives or exclusions, leaving the agent to infer usage context. No when-not-to-use conditions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoCursor: only return items played after this timestamp (milliseconds since epoch or ISO string)
limitNoAlias for max_items
beforeNoCursor: only return items played before this timestamp (milliseconds since epoch or ISO string)
formatNoOutput format: json or csvjson
max_itemsNoMax history items to export (default: SPOTIFY_MCP_FETCH_ALL_CAP)
output_dirNoLocal directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (non-destructive only), it discloses real behavioral details: it writes a file with 0600 permissions, respects SPOTIFY_MCP_FETCH_ALL_CAP, uses before-cursor pagination, and reports path plus counts. It does not fully spell out overwrite/append or error behavior, so not a 5, but it goes well beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler; the operation, target, mechanism, environment constraint, and result are all front-loaded and compact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and only a destructiveHint annotation, the description usefully states output (path + counts), file permissions, and cap behavior. The parameter details are already in the schema, and the description fills enough operational context; a brief return-format/overwrite note would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds cross-cutting meaning that the schema lacks: the overall cap, pagination model, sidecar file behavior, and permission mode, which helps an agent understand how max_items/limit and before interact.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific operationโ€”exporting listening history (recently played) to JSON or CSVโ€”and adds the API endpoint and pagination strategy, so the tool's job is clear. It does not explicitly differentiate itself from the similar sibling listening_history_export or other export_* tools, which keeps it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies when to use it (whenever a file-based export of recently played items is needed) and clarifies the pagination/fetch-cap behavior, but it never states when to prefer a sibling such as get_recently_played or listening_history_export, nor does it give exclusions. This is adequate but leaves routing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_playlistA

Export a playlist's full item list as an M3U playlist file or a CSV spreadsheet. Pages every item; pass output_path to write a file (created with mode 0600) inside the configured output root, or omit it to get the document inline. CSV cells are formula-safe.

ParametersJSON Schema
NameRequiredDescriptionDefault
formatNoOutput format: m3u (playable playlist) or csv (spreadsheet)m3u
overwriteNoAllow replacing an existing file at output_path (refused by default)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
output_pathNoWrite the full document to this local file (relative paths resolve inside the output root, default ~/.spotify-mcp/exports) instead of returning it inline
playlist_idYesPlaylist ID
include_headersNoEmit the #EXTM3U marker / CSV header row
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It adds genuinely useful behavioral detail beyond the annotations: internal pagination, mode 0600, output-root sandboxing, inline-vs-file behavior, and formula-safe CSV. However, the claim of a 'full item list' conflicts with the schema's max_results default of 50, so the transparency is incomplete and potentially misleading.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with the purpose front-loaded and no filler. Each sentence carries a distinct, useful fact: output formats, file-vs-inline behavior, and CSV security.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The schema fills in most parameter detail and the description covers output modes well, but the description would mislead an agent about default truncation unless max_results is raised, and it does not mention sibling export formats. For a 7-parameter tool with no output schema, these are notable gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds value on top by explaining output_path semantics (mode 0600, relative to the output root, inline when omitted) and CSV cell safety. Repeating the other parameters would be redundant.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: exporting a playlist's full item list to M3U or CSV. It is clearly distinct from a generic get/list tool, but it does not explicitly differentiate itself from sibling exports like export_playlist_json, export_playlist_markdown, or export_all_playlists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear guidance on choosing between file output and inline return ('pass output_path... or omit it') and explains the output root and file mode. It stops short of naming when not to use this tool, such as pointing agents to JSON or Markdown export siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_profile_stateA

Export local sidecar stores (scenes, genre-tags, playback-ext, search-history, mutations, artist-watchlist) to a single schema-versioned JSON archive. artist-watchlist is ~/.spotify-mcp/artist-watchlist.json; SPOTIFY_MCP_DATA_DIR overrides that directory.

ParametersJSON Schema
NameRequiredDescriptionDefault
output_dirNoDirectory to write the archive into, confined to the output root (default ~/.spotify-mcp/exports, set SPOTIFY_MCP_EXPORT_DIR to move it)
include_historyNoInclude mutation history JSONL (can be large)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide destructiveHint=false, so the description carries the burden of explaining behavior. It adds that the output is a single schema-versioned JSON archive and specifies the artist-watchlist location, which is useful. However, it does not disclose overwrite behavior, directory creation, or whether the operation has any side effects beyond writing the archive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler: the first states the core action and content scope, the second adds a useful file-path detail. Information is front-loaded and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple export operation, well-documented parameters, and clear content enumeration, the description is nearly complete for correct invocation. It does not describe the return value or file-naming behavior, but no output schema exists and the operation's intent is clear enough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters (output_dir, include_history, response_format) are already fully documented. The description adds no parameter-level meaning beyond the schema, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'export local sidecar stores' to 'a single schema-versioned JSON archive', and enumerates exactly which stores are included (scenes, genre-tags, playback-ext, search-history, mutations, artist-watchlist). This clearly distinguishes it from export siblings like export_library_json or export_listening_history without needing to open the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for backing up or migrating local profile/sidecar state, but it never explicitly states when to use this tool over alternatives. With several nearby export tools (sidecar_export_bundle, export_library_json, mutation_log_export), the lack of exclusion or alternative guidance leaves some ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

filter_by_genreA
Read-onlyIdempotent

List URIs of your saved tracks or albums whose artists carry a given genre tag (case-insensitive tag-name match against your sidecar). Output is directly usable as create_playlist / add_to_playlist input. Read-only.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesWhich saved collection to filter
genreYesGenre tag to match (case-insensitive, e.g. "pop")
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the description's 'Read-only' line is redundant but not contradictory. It does add genuine beyond-annotation context: the tag match is case-insensitive and resolved against 'your sidecar' (a local data source), which tells the agent the filtering semantics differ from a live API query. It stops short of covering result limits or error behavior, but the annotation baseline is already met.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero filler, front-loading what is returned (URIs) and where they can be used before the read-only note. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description usefully explains the return value (URIs) and its downstream use, which the agent needs. It omits mention of the max_results cap behavior and result ordering, but for a filtered-list tool the essentials are covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents kind, genre, max_results, and response_format including enums and the env-var default. The description only reinforces the case-insensitive genre matching already noted in the schema, adding little beyond it. Baseline 3 applies when the schema carries the full burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List URIs of your saved tracks or albums') plus the filtering criterion (artists carrying a genre tag). The scope is narrow and clearly distinct from siblings like search_saved_tracks or library_genre_report, and it even names what the output feeds into (create_playlist / add_to_playlist).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by noting the output is 'directly usable as create_playlist / add_to_playlist input', which hints at a build-a-playlist workflow. However, it never states when to prefer this over alternatives such as search_saved_tracks or library_genre_report, leaving the routing decision to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_duplicate_saved_tracksA
Read-onlyIdempotent

Read-only duplicate detection over your saved (liked) tracks. Exact groups require the same non-null ISRC and album id with duration within ยฑ2s, and keep the oldest dated save. On opt-in, near-duplicate groups show same-title/artist tracks whose ISRC, release, or duration differs; these are distinct saved tracks and are review-only with no removals. Undated saves sort after dated saves. Optionally pass a playlist_id to cross-reference which group members also appear in that playlist. Never mutates your library.

ParametersJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idNoOptional playlist ID to cross-reference: members of each duplicate group that also appear in this playlist are flagged, so cleanup or review decisions can account for where the track is already curated.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
include_near_duplicatesNoAlso report same-title/artist groups with a different ISRC, release, or duration. Near duplicates are review-only and never recommend removal. Default false.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations by disclosing the exact-match criteria (same non-null ISRC and album id, duration ยฑ2s, keeps oldest dated save), that near-duplicates are review-only with no removals, that undated saves sort last, and that it never mutates the library.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose and then layers matching semantics efficiently; every sentence carries information. A few sentences are dense and could be tighter, but there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of explaining what comes back, and it does describe group types, exact vs. near distinction, and undated-save ordering. It stops short of describing the concise/detailed/json return shapes in depth, leaving a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: playlist_id denotes cross-referencing group members against a playlist for cleanup decisions, and include_near_duplicates is framed as an opt-in review-only mode. These enrich the parameters beyond their schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Read-only duplicate detection over your saved (liked) tracks.' The 'saved (liked) tracks' scope cleanly distinguishes it from sibling playlist duplicate tools like find_duplicates_in_playlist and find_duplicate_tracks_across_playlists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear conditions for the two modes (exact groups vs. opt-in near duplicates) and explains the optional playlist_id cross-reference use case. It never explicitly names an alternative sibling or states when NOT to use it, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_duplicates_in_playlistA
Read-onlyIdempotent

Find duplicate tracks in a playlist under one published matching rule. match_by selects the rule (uri โ€” the same track object twice; name_artist โ€” same name and credited artists, catching relinks and remasters; name โ€” same title only) and the rule is echoed back as match_by, so a group count is never unattributable. See the duplicate-matching vocabulary in SPEC section 4.

ParametersJSON Schema
NameRequiredDescriptionDefault
match_byNoWhich rule decides that two items are the same: `uri` (exact URI, the default), `name_artist` (case-insensitive name + credited artists, catches relinks/remasters), or `name` (case-insensitive name only). The rule applied is echoed in the result as `match_by`.
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idYesPlaylist ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds that the applied rule is echoed back as `match_by` so a group count is never unattributable, plus a pointer to SPEC section 4 vocabulary โ€” useful context beyond the annotations, though nothing about result shape or limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then rules; two sentences carry real information. The echo-of-`match_by` point is stated twice (once in prose, once in the schema description), a small redundancy that keeps it from being maximally tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does supply the key return-context detail (rule echoed in the result) and the matching-rule semantics. It omits result shape beyond group counts and limit behavior, but is otherwise sufficient for calling the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters including the enum semantics and the default. The description largely restates the `match_by` rules and its echo behavior, adding marginal value over the structured field, which is the expected baseline when the schema does the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (find) plus resource (duplicate tracks) and an explicit scope ('in a playlist'), which separates it from siblings like find_duplicate_tracks_across_playlists and remove_duplicate_playlist_items. An agent can classify it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly explains which matching rule each `match_by` value selects and the real-world cases they catch (relinks, remasters), which is genuine usage guidance. It does not, however, explicitly route the agent away from the removal/clone siblings, so it stops short of the top mark.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_duplicate_tracks_across_playlistsA
Read-onlyIdempotent

Find tracks that appear in more than one of the given playlists (cross-playlist dupes). Quota: N GETs (one per playlist).

ParametersJSON Schema
NameRequiredDescriptionDefault
playlistsNoCanonical ordered playlists (2โ€“20)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered. The description adds the API-quota behavior (one GET per playlist, N total), which annotations do not convey, but it says nothing about how duplicates are reported, ordering, or truncation with max_results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, with the scope definition and the quota cost front-loaded. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, idempotent tool with three fully documented parameters and no output schema, the definition covers purpose and cost adequately. It could be slightly richer about what a duplicate match looks like, but nothing essential to invoking it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: the playlist ID formats, the 2-20 bound, the max_results default, and the response_format enum are all documented in the schema. The description adds no syntax or semantic detail beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (find) and resource (tracks) plus the exact scope qualifier 'appear in more than one of the given playlists (cross-playlist dupes)'. The parenthetical explicitly disambiguates it from the within-playlist sibling find_duplicates_in_playlist/remove_duplicate_playlist_items without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives cost guidance (N GETs, one per playlist), which is genuinely useful, but never states when to prefer this over sibling overlap tools such as overlap_playlists, playlist_symmetric_difference, or playlist_union. Usage is implied by the purpose line rather than explicitly routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_toolA
Read-onlyIdempotent

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax matches to return (default 25)
queryYesCase-insensitive substring to match against tool names and descriptions
response_formatNo'concise' (default) = prose bullet list; 'detailed' = the same prose; 'json' = the result payload as parseable JSON text, identical to structuredContentconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so safety and repeatability are covered by structured data. The description adds useful operational context โ€” the registry is live, 500+ tools, and the discovery set is always available via catalog โ€” but discloses nothing about result ordering, match behavior beyond 'case-insensitive substring', or limits. Adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero padding, with the core purpose front-loaded before the routing advice. The parenthetical about the discovery set is terse but earns its place by telling the agent these tools remain callable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With annotations covering safety, an output schema covering return values, and full parameter documentation in the schema, the description only needed to supply purpose and routing โ€” both delivered. Nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with 3 parameters, each documented (query semantics, limit default/max, response_format enum meanings). The description adds no parameter guidance beyond the schema, so the baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (search) and resource (live tool registry) with the matching mechanism (name or description substring). It also quantifies scope (500+ tools), which lets an agent distinguish it immediately from the domain-specific search_* siblings that search Spotify content rather than the tool registry.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to use it first when unsure which verb applies, gives a concrete example of the ambiguity it resolves (playlist vs snapshot vs search), and names the sibling discovery tools (inspect_tool, toolset_report) plus the catalog as alternate access paths. Both the when and the alternatives are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

followed_playlists_auditB

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

ParametersJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
only_followedNoOnly followed (not owned) playlists (default false)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description must carry behavioral weight. It does add one useful operational fact โ€” the quota applies to the paged GET /me/playlists endpoint โ€” which hints at rate-limit and pagination costs. It says nothing about whether results are cached, how large the fetch can be, or how long it takes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact clauses with no filler, and the core inventory content is front-loaded before the quota note. The telegraphic list style ('counts, collab, public, follower totals') is dense but readable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden; it does list the reported dimensions, which is helpful. However it leaves the shape of the audit output, whether it covers owned playlists in the same call, and the effect of the response_format parameter unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so max_results, only_followed, and response_format are fully documented in the schema; the description adds essentially nothing parameter-specific. Baseline 3 applies when the schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource (followed vs owned playlists) and enumerates what the audit reports: counts, collaborator status, public/private, and follower totals. This distinguishes it from siblings like get_user_playlists and following_analytics, though it never names those alternatives explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No statement of when to use this tool versus get_user_playlists, get_user_playlists_by_id, or following_analytics, all of which overlap on playlist surface area. The word 'audit' and the followed/owned comparison imply a reporting use case, but the agent must infer it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

following_analyticsB

Followed-artist rollups from the tag sidecar; popularity/followers unavailable (Spotify no longer returns those fields). Quota: GET /me/following.

ParametersJSON Schema
NameRequiredDescriptionDefault
top_nNoTop N groups to show
group_byNoRollup dimension; popularity/followers report 'unavailable'genre
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in annotations, the description carries real behavioral weight: it discloses the tag-sidecar data source, that popularity/followers are structurally unavailable (Spotify API change), and that a GET /me/following quota applies. These are non-obvious constraints an agent cannot infer from the schema. It stops short of 5 only because it doesn't say what happens when the sidecar is empty or stale.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with the data-source caveat front-loaded before the quota note. No filler, though the 'Quota: GET /me/following' fragment is cryptic enough that its brevity borders on ambiguity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only rollup with no output schema, the description covers the data-source and availability caveats but never indicates the shape or grouping of results, nor how top_n interacts with max_results. Adequate but with a noticeable gap for an analytics tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four parameters including the 'unavailable' behavior for popularity/followers. The description's note about unavailable fields is largely redundant with the enum description, so it adds little beyond the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource and operation ('followed-artist rollups') plus the data source ('tag sidecar'), which is enough to distinguish it from get_followed_artists/check_following_artists. It does not explicitly name those siblings as alternatives, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use guidance or routing against the many neighboring following/export tools. The quota note hints at cost but never tells the agent when this rollup is the right call versus get_followed_artists or export_followed_artists.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

follow_playlistA

Follow a playlist โ€” save it to your Spotify library โ€” via PUT /me/library. Spotify removed the playlist-followers endpoints in Feb 2026; this is the only way to follow a playlist. Supports dry_run (default true); writes require confirmation unless SPOTIFY_MCP_CONFIRM=never.

ParametersJSON Schema
NameRequiredDescriptionDefault
publicNoMust be true or omitted; the library endpoint has no visibility parameter.
dry_runNoPreview only (default): pass dry_run: false to execute the follow.
playlist_idYesPlaylist ID to follow
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription
okNo
dry_runNo
receiptNo
cancelledNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint: false in annotations, the description adds genuinely useful behavior: dry_run defaults to true, real writes require confirmation unless SPOTIFY_MCP_CONFIRM=never, and the underlying endpoint. It does not contradict the non-destructive hint, though it omits mention of auth scopes or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the action and endpoint, followed by the rationale and safety gating. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation. Endpoint, safety mode, confirmation policy, and API-version context are all covered, leaving nothing an agent needs missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and every parameter (including the public caveat and dry_run meaning) is already documented in the schema. The description reinforces dry_run's default but adds no syntax or format detail beyond the structured fields, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Follow a playlist') plus the precise mechanism (PUT /me/library). It clearly distinguishes itself from siblings like unfollow_playlist and check_playlist_following.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains why this tool is now the only path to follow a playlist (endpoints removed Feb 2026) and notes dry_run defaults to true while writes need confirmation. No explicit when-not-to-use or sibling alternative is named, though the alternatives are largely gone by construction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_currently_playingA
Read-onlyIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
marketNoISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to SPOTIFY_MCP_MARKET
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
additional_typesNoItem types to include in the response. Default: ['track', 'episode']

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds real value beyond that by disclosing the scope of the response payload (item and progress only), letting the agent anticipate a lighter result set than the sibling. It does not mention auth or rate limits, but neither is critical for a poll.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with zero filler; the payload scope is front-loaded immediately followed by the routing instruction. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only poll with no output schema, the description covers what is needed: purpose, payload scope, and the sibling alternative. Nothing an agent requires in order to choose and call this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% โ€“ market, response_format, and additional_types are each fully documented in the schema, including defaults and enum meanings. The description adds no parameter guidance, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (poll what is playing right now) and scopes it precisely with 'lightweight' and 'the item and progress only', which distinguishes it from the richer get_now_playing sibling named in the same sentence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative tool (get_now_playing) and states the condition that selects it ('For full session state ... use get_now_playing instead'). This is textbook when-to-use/when-not-to-use routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_devicesA
Read-onlyIdempotent

List available Spotify Connect devices. The same rows are readable as a resource with no tool call at spotify://player/devices ('?format=json' returns the raw API object).

ParametersJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the description is not required to cover safety. It adds useful behavioral context by disclosing that the same rows are available as a resource without a tool call, and that the raw API object is accessible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with zero waste. Purpose is front-loaded, and the resource alternative is appended as useful supplementary context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and read-only, with a fully documented schema and annotations. The description adds the resource alternative, which is valuable; the lack of output schema means return shape need not be explained in detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema fully documents both parameters (max_results and response_format), including defaults and enum values. The description adds no additional parameter-level detail, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('Spotify Connect devices') with no ambiguity. No sibling tool covers device listing, so an agent can distinguish it immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a concrete alternative access path via the spotify://player/devices resource and notes that '?format=json' returns the raw API object. It does not explicitly state when to call the tool versus reading the resource, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_followed_artistsA
Read-onlyIdempotent

Get the artists the user follows. fetch_all=true walks every page; limit/after page manually.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoArtist ID cursor for pagination (from previous response)
limitNo1โ€“50. Default: 20
fetch_allNoWalk every page instead of one page (ignores limit)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile. The description adds pagination behavior, but this largely restates the fetch_all schema description ('Walk every page') rather than offering new behavioral context like rate limits or result-size caps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler; the primary purpose is front-loaded and the pagination note is a single compact clause. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with strong parameter documentation, the description covers the main pagination modes. However, it does not explain how fetch_all interacts with max_results, nor describe the return shape โ€” and there is no output schema to compensate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter already has documented meaning. The description mentions fetch_all, limit, and after, but adds no new semantic detail beyond the schema's own descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states the verb and resource explicitly: 'Get the artists the user follows.' The scope is clear and matches the tool name. It does not explicitly contrast with sibling tools like export_followed_artists or check_following_artists, so it lacks explicit sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear pagination guidance ('fetch_all=true walks every page; limit/after page manually'), which tells the agent when to use the fetch_all mode vs manual paging. However, it does not address when to prefer this tool over related siblings such as export_followed_artists or check_following_artists.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_now_playingA
Read-onlyIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
marketNoISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to SPOTIFY_MCP_MARKET
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
additional_typesNoItem types to include in the response. Default: ['track', 'episode']

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds real value beyond that by disclosing the breadth of state returned (shuffle/repeat mode, active device, volume) rather than just item+progress, though it says nothing about auth requirements or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler. The scope statement is front-loaded and the sibling routing note is compact and immediately actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description enumerates what is returned, covering the gap. With read-only annotations and fully documented optional params, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all three parameters (market, response_format, additional_types) carry their own descriptions, defaults, and enum semantics. The description adds no parameter-level detail, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb+resource (full device/session state for what is playing now) and enumerates the returned facets: item, progress, shuffle/repeat, active device, volume. It explicitly contrasts itself with the sibling get_currently_playing, so an agent can choose without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the alternative by name and the condition that selects it: 'For a lightweight item+progress poll use get_currently_playing instead.' This is an explicit when-to-use-this-vs-that routing rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playlistA
Read-onlyIdempotent

Get a playlist's metadata (including cover image) and items. Use market to relink tracks and flag unavailable ones, and fields/additional_types to trim the payload โ€” both are forwarded to the metadata read and the item pages.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlias for playlist_id, resolved the same way
limitNoItems per page, 1โ€“100. Default: 50
fieldsNoComma-separated list of response fields to keep, e.g. 'total,items(track(name,uri))'
marketNoISO 3166-1 alpha-2 country code, e.g. 'GB'; relinks tracks to that market and flags unavailable ones
offsetNoPagination offset for items. Default: 0
fetch_allNoFetch all items across pages (up to 500), continuing FROM offset. limit is the page size. Note: library tools' fetch_all ignores offset โ€” contracts differ between modules (#110).
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idNoPlaylist ID, spotify:playlist: URI, or open.spotify.com/playlist URL
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
additional_typesNoItem types to include beyond the default 'track', e.g. ['track', 'episode']

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds real behavioral context beyond that: market relinks tracks to a country and flags unavailable ones, and fields/additional_types trim the payload across both the metadata read and the item pages.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, purpose front-loaded, then parameter behavior. Dense but every clause carries information. The second sentence crams several parameters together, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with no output schema, the description covers identity, market and field-trimming but omits response_format (concise/detailed/json โ€” a major output-shape decision), pagination (limit/offset/fetch_all/max_results), and the id/playlist_id alias. It is adequate but leaves notable gaps for an agent to fill from the schema alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds value beyond the schema by clarifying that fields/additional_types are forwarded to both the metadata read and the item pages, and that market affects linkage/unavailability rather than simple filtering. It says nothing about response_format, limit/offset, or fetch_all semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: retrieves a playlist's metadata (including cover image) and items. This implicitly separates it from siblings like get_playlist_items and get_playlist_cover, which return only one half, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what market, fields and additional_types do and notes they are forwarded to both the metadata read and item pages, which implies when to reach for them. It never states when to prefer this tool over get_playlist_items, get_playlist_cover, or search_within_playlist, so usage remains inferred rather than guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playlist_added_datesB
Read-onlyIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
sortNoSort by added_at (default added_asc)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idYesPlaylist ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds genuine context with the pagination and quota note ('GET /playlists/{id}/items paged'), but does not say how paging interacts with max_results or what the result shape looks like.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with no filler, and the core purpose is front-loaded before the quota note. The 'Quota:' fragment is terse to the point of being slightly cryptic.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only listing tool with no output schema and fully documented parameters, the description covers what is returned and how it is fetched. It does not explain result ordering defaults or paging limits, but nothing critical to a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with sort, max_results, playlist_id and response_format all documented including defaults and enums, so the schema carries the load. The description adds no parameter syntax or format detail beyond the output fields it mentions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List when each track was added to a playlist') plus the fields returned (added_at, added_by), so the agent knows this is an added-date listing rather than a plain item listing. It stops short of explicitly naming the close sibling get_playlist_items, so it is clear but not sibling-differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use, when-not-to-use, or alternative guidance, despite several near-neighbors (get_playlist_items, get_playlist, search_within_playlist). Usage is only inferable from the phrase 'when each track was added'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playlist_coverB
Read-onlyIdempotent

Get a playlist's cover image URLs

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlias for playlist_id, matching get_playlist
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idNoPlaylist ID (or pass it as 'id')
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile, and the description is fully consistent with them (no contradiction). The description adds only the small detail that 'URLs' is plural, hinting that multiple image sizes may be returned. It does not disclose return shape, auth requirements, or rate limits, but with annotations carrying the safety burden, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single focused sentence with zero filler, front-loaded with the verb and resource. It is efficiently sized for a simple getter, though the brevity could have been leveraged to add sibling differentiation or usage context without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only getter with 100% schema coverage and safety annotations, the description is largely adequate. Gaps remain: no description of the return format despite the response_format parameter, and no routing between cover-related siblings (upload/clone/compare). The schema's note that 'id' matches get_playlist partially compensates by linking to a sibling's id format.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters (id, playlist_id, max_results, response_format) are already documented in the schema. The description adds nothing about parameters, so the baseline 3 applies. Notably, the schema's max_results and response_format parameters suggest the tool may behave more richly than the one-line description implies, but the schema itself documents them adequately.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Get') and resource ('a playlist's cover image'), and specifies the output ('URLs'). This distinguishes it from siblings like upload_playlist_cover, clone_playlist_cover, and compare_playlist_covers via the action verb. However, it doesn't explicitly name those alternatives, so differentiation is implied rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. The description never mentions the cover-related siblings (upload/clone/compare) or any condition that would select this tool over them. An agent must infer usage entirely from the tool name and the verb in the description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playlist_itemsA
Read-onlyIdempotent

List a playlist's items on a single page. Use market to relink tracks and flag unavailable ones, and fields/additional_types to trim the payload.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlias for playlist_id, matching get_playlist
limitNoItems per page, 1โ€“100. Default: 100
fieldsNoComma-separated list of response fields to keep, e.g. 'total,items(track(name,uri))'
marketNoISO 3166-1 alpha-2 country code, e.g. 'GB'; relinks tracks to that market and flags unavailable ones
offsetNoPagination offset. Default: 0
fetch_allNoFetch every item across pages (up to 500), continuing FROM offset rather than restarting at 0. limit is the page size. Note: library tools' fetch_all instead ignores offset โ€” contracts differ between modules (#110).
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idNoPlaylist ID (or pass it as 'id')
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
additional_typesNoItem types to include beyond the default 'track', e.g. ['track', 'episode']

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only and idempotent, so the safety profile is covered. The description adds real behavioral context about single-page listing and market-based relinking/flagging, but it does not disclose pagination behavior beyond the single-page claim and says nothing about the return shape or how fetch_all interacts with the stated single-page behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences front-load the core behavior and then immediately point to the most decision-relevant parameters. Every clause earns its place, with no filler or redundant restatement of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The schema is exhaustive and annotations cover safety, so the description does not need to repeat everything. Still, with no output schema and a 10-parameter tool, the description leaves the fetch_all behavior and return format unmentioned, and 'single page' could mislead an agent into ignoring the built-in multi-page fetch option.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the schema already thoroughly documents market, fields, additional_types, fetch_all, and the rest. The description essentially restates what market, fields, and additional_types do without adding new meaning, so it neither hurts nor materially improves parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('List') and resource ('a playlist's items'), and adds the scope 'on a single page' which helps set boundaries. It is not as strong as it could be because it never names a sibling like get_playlist to explicitly differentiate, but the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives useful parameter-level guidance ('Use market to relink tracks and flag unavailable ones, and fields/additional_types to trim the payload'), implying when options matter. However, it never states when to choose this over nearby alternatives like get_playlist, get_playlist_followers, or playlist_snapshot, and it omits mention of fetch_all despite saying 'a single page'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playlist_snapshotA
Read-onlyIdempotent

Expose snapshot_id + item count for optimistic concurrency. Quota: 2 GETs.

ParametersJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idYesPlaylist ID, spotify:playlist: URI, or URL
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only and idempotent behavior. The description adds useful context beyond annotations: the quota cost (2 GETs) and the concurrency reason for requesting snapshot_id, though it does not detail return shape or pagination.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences/fragments with zero filler. It front-loads the returned values and then the quota constraint, so every element earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only snapshot tool with supporting annotations and a fully described schema, the description states the core return values and quota cost. It could say more about how max_results interacts with the count or what response_format controls, but it is largely complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so playlist_id, max_results, and response_format are already documented in the schema. The description adds no parameter-specific syntax, defaults, or selection guidance, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the specific data it exposes (snapshot_id and item count) and a purpose (optimistic concurrency), which distinguishes it from playlist-item tools. However, it never says 'playlist' and does not explicitly contrast itself with siblings like get_playlist or get_playlist_items.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Mentions optimistic concurrency as a use context and quota cost, implying when it is useful. It does not give explicit when-not guidance or name alternative tools for cases where full playlist data or items are needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_queueA
Read-onlyIdempotent

Read the playback queue. Use this for queue CONTENTS (what is playing, what is up next, how long it runs, what repeats). Use peek_next for a short lookahead. Quota: 1 read; view=enriched and include=runtime add one GET /me/player, and the context label adds one catalog read.

ParametersJSON Schema
NameRequiredDescriptionDefault
viewNo'raw' (default) = the queue as returned. 'enriched' = plus the source context (playlist/album name) and total time remaining.raw
includeNoLocal analyses over the same single read, no extra request except runtime: runtime = total/avg/longest/shortest, time left on the current track, and a per-item timeline of when each row starts playing; duplicates = repeated rows and the runtime they waste; profile = unique artists/albums/shows, track-vs-episode mix, longest single-artist run.
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly and idempotent, but the description adds real non-structured context: the read-cost quota breakdown (1 read, plus one GET /me/player for enriched/runtime, plus one catalog read for the context label). It omits return-shape details, but the quota disclosure is genuinely useful cost information.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences, front-loaded with the core action, then scope, then alternative, then cost. No filler; every clause carries actionable information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description adequately conveys what comes back (contents, runtime, repeats) and the cost profile. Minor gap: it doesn't hint at pagination or max_results behavior for large queues, though the schema covers the cap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so 3 is the baseline, but the description goes beyond the schema by tying specific parameter values (view=enriched, include=runtime, context label) to their request-cost implications, which the schema does not express.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Read the playback queue') and immediately scopes it to queue contents (now playing, up next, runtime, repeat). It explicitly routes lookahead intent to a different tool, separating it from siblings like get_now_playing and skip_next.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the use case ('queue CONTENTS') and names the alternative ('Use peek_next for a short lookahead'), giving the condition that selects each. An agent can choose correctly without opening a schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_saved_albumsA
Read-onlyIdempotent

Get albums saved in the user's library. Set fetch_all=true to retrieve the entire collection. Output is capped by max_results (default: SPOTIFY_MCP_MAX_ITEMS).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo1โ€“50. Default: 20
marketNoISO 3166-1 alpha-2 country code, e.g. 'US'
offsetNoPagination offset. Default: 0
fetch_allNoFetch all pages instead of one page (ignores limit/offset)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile. The description adds behavioral detail about fetch_all ignoring limit/offset and output being capped by max_results, which is useful beyond annotations. It doesn't describe return format but that's not required here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero fluff. The core purpose is front-loaded, and the important behavioral notes about fetch_all and max_results are concise and immediately actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list retrieval with 6 well-documented parameters, the description covers the key decision points (fetch_all, max_results cap). It doesn't specify return format, but given no output schema and annotations covering safety, the description is sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter already has a clear description. The tool description adds no new parameter meaning beyond what the schema provides; it merely references fetch_all and max_results without additional detail. Baseline 3 is appropriate when the schema carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Get albums saved in the user's library.' It clearly distinguishes from sibling tools like get_saved_tracks and get_saved_shows by focusing on albums. The name and description together make the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on when to use pagination behavior: 'Set fetch_all=true to retrieve the entire collection.' It also explains the max_results cap. It does not explicitly contrast with alternatives, but the name and context make the appropriate use case obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_saved_countsA
Read-onlyIdempotent

Library size snapshot: counts for tracks/albums/shows/episodes/audiobooks/playlists via limit=1 reads โ€” no item paging. The total covers library saves only: playlists are owned and followed collections, so their count is reported alongside the library rows and excluded from the total. A collection that could not be read (rate limited, gated, or erroring) is reported as unreadable with its reason and left out of the total โ€” it is never reported as 0. One attempt per collection: a rate limit is surfaced, not retried. Quota: 6 GETs.

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover read-only/idempotent safety, yet the description discloses a wealth of behavior beyond them: a fixed quota of 6 GETs, one attempt per collection with rate limits surfaced rather than retried, unreadable collections reported with a reason and excluded from totals (never reported as 0), and playlists counted separately from the library total. This is exactly the operational context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the snapshot purpose, then layers in the edge cases. It is dense with clauses, but nearly every sentence carries decision-relevant information (total scope, unreadable handling, quota), so little is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-optional-parameter read tool with no output schema, the description fully explains what is returned (per-collection counts plus a total), how playlists relate to the total, and how failures appear. Nothing an agent needs to call or interpret it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single response_format enum is fully described in the schema, so the baseline is 3. The description adds no meaning about response_format, and its limit/quota notes are internal mechanics rather than parameter guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Library size snapshot: counts for tracks/albums/shows/episodes/audiobooks/playlists') that clearly separates it from the many sibling list/search tools (get_saved_tracks, search_saved_albums, etc.). The agent can tell this returns counts, not items, without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'no item paging' and 'limit=1 reads' phrasing implies this is the cheap-counts alternative to the listing tools, but it never explicitly names a sibling or states when to prefer this over get_saved_tracks/get_saved_albums. Usage is strongly implied rather than routed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_saved_episodesA
Read-onlyIdempotent

Get podcast episodes saved in the user's library. Set fetch_all=true to retrieve the entire collection. Output is capped by max_results (default: SPOTIFY_MCP_MAX_ITEMS).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo1โ€“50. Default: 20
marketNoISO 3166-1 alpha-2 country code, e.g. 'US'
offsetNoPagination offset. Default: 0
fetch_allNoFetch all pages instead of one page (ignores limit/offset)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, and the description adds behavioral context by explaining the fetch_all behavior and output capping via max_results with its default from SPOTIFY_MCP_MAX_ITEMS. This adds value beyond the annotations by clarifying pagination and limits, though it doesn't cover auth or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: purpose, fetch_all hint, and output cap. No redundant phrases or filler. The most important info is front-loaded in the first sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with six params and no output schema, the description covers the non-obvious behavior (fetch_all, max_results cap) while the schema fully documents the rest. It doesn't explain response_format or market, but those are in the schema, so the description is adequate for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with each parameter fully documented. The description reiterates fetch_all and max_results semantics that already exist in the schema (e.g., schema says 'Fetch all pages instead of one page (ignores limit/offset)' and max_results default), adding no new meaning. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Get podcast episodes saved in the user's library' with a specific verb and resource. It distinguishes from siblings like get_saved_tracks, get_saved_albums, and get_saved_shows by specifying 'podcast episodes' and from search_saved_episodes by indicating retrieval of the entire saved library.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers usage guidance for the fetch_all and max_results parameters, but does not say when to choose this tool over alternatives like search_saved_episodes or get_episode. There is no explicit when-to-use or when-not-to-use context relative to siblings, so it relies on implied usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_saved_showsA
Read-onlyIdempotent

Get podcast shows saved in the user's library. Set fetch_all=true to retrieve the entire collection. Output is capped by max_results (default: SPOTIFY_MCP_MAX_ITEMS).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo1โ€“50. Default: 20
offsetNoPagination offset. Default: 0
fetch_allNoFetch all pages instead of one page (ignores limit/offset)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds useful behavioral context by mentioning that output is capped by max_results and that fetch_all retrieves the entire collection, which goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no extraneous information. The purpose is stated first, followed by the most relevant options (fetch_all and max_results). Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with 5 parameters fully documented in the schema and safety covered by annotations, the description is sufficient. It explains the core behavior and key options, though it does not describe return format or pagination details, which are partially covered by the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all parameters are documented. The description reiterates fetch_all and max_results behavior but adds little beyond what the schema descriptions already provide. The baseline of 3 is appropriate given the schema carries the parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves podcast shows saved in the user's library, specifying a distinct resource ('saved shows') that separates it from siblings like get_show_details or list_show_episodes. The verb 'Get' and the resource are explicit and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for fetching saved shows but does not explicitly differentiate from list_saved_shows or other show-related tools. It offers internal guidance on fetch_all and max_results but no when-to-use vs alternatives, relying on the name to convey context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_saved_tracksA
Read-onlyIdempotent

Get tracks saved in the user's Liked Songs. Set fetch_all=true to retrieve the entire collection. Output is capped by max_results (default: SPOTIFY_MCP_MAX_ITEMS).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo1โ€“50. Default: 20
marketNoISO 3166-1 alpha-2 country code, e.g. 'US'
offsetNoPagination offset. Default: 0
fetch_allNoFetch all pages instead of one page (ignores limit/offset)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds meaningful behavioral details not in annotations: fetch_all toggles full-collection retrieval, and max_results caps output with an environment-driven default. This is exactly the kind of context that helps an agent predict cost and scope.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: the purpose comes first, followed by the two behavioral knobs that matter. No filler, no repetition of schema content. Efficient and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only collection fetch with no output schema, the description covers the main behavioral questions: what it returns, how to get everything, and how results are capped. The remaining params (limit, offset, market, response_format) are fully documented in the schema, and response_format's enum explains the return shape. Complete enough given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema descriptions cover 100% of the 6 parameters with types, defaults, ranges, and enums, so the description doesn't need to re-document them. The description does reinforce the two decision-relevant params (fetch_all, max_results) in plain language, adding a small amount beyond schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb, resource, and collection semantics: retrieves tracks saved in the user's Liked Songs. This distinguishes it from siblings like get_saved_albums, get_saved_episodes, and search_saved_tracks. Also surfaces the key options fetch_all and max_results, making the tool's scope immediately clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear operational context: how to request the full collection (fetch_all=true) and how output is bounded (max_results, defaulting to SPOTIFY_MCP_MAX_ITEMS). It does not explicitly name alternatives or exclusions, but the read-only, single-collection scope is unambiguous. No misleading guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_user_playlistsB
Read-onlyIdempotent

List the current user's playlists

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo1โ€“50. Default: 20
offsetNoPagination offset. Default: 0
fetch_allNoFetch every playlist (up to 500), continuing FROM offset rather than restarting at 0. limit is the page size. Note: library tools' fetch_all instead ignores offset โ€” contracts differ between modules (#110).
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered by structured data; 'List' is consistent with these hints. The description adds no behavioral context beyond what annotations imply, but with annotations present the bar is lower and no contradiction exists. It contributes little extra, warranting a mid score.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single clean sentence with no filler, appropriately short for a straightforward read operation whose safety is already flagged by annotations. It is front-loaded with the verb and target. Slightly more utility could be packed in, but the brevity is justified here.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich parameter descriptions in the schema and annotations covering read-only/idempotent safety, the description is largely complete for a simple list tool. The main gap is the absence of an output schema and no description-level note about return shape, but for a basic current-user playlist listing this is a minor omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3 even with no parameter info in the description. The schema itself carries detailed semantics, including fetch_all's notable contract difference versus library tools and response_format's prose-versus-JSON modes. The description adds nothing on top, but the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('List') and resource ('the current user's playlists'). It implicitly distinguishes itself from the sibling get_user_playlists_by_id by scoping to the current user rather than an arbitrary user ID. Brief but specific enough to identify the operation at a glance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. The natural sibling get_user_playlists_by_id exists for listing another user's playlists, but the description never mentions it or the condition that selects between them. There is also no note about the several pagination/response-format parameters that control behavior, leaving routing and configuration choices entirely to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_user_playlists_by_idA
Read-onlyIdempotent

List another Spotify user's public playlists (paginated). Removed by Spotify's February 2026 Web API changes โ€” unavailable for newer app registrations. Output is capped by max_results (default: SPOTIFY_MCP_MAX_ITEMS).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo1โ€“50. Default: 20
offsetNoPagination offset. Default: 0
user_idYesSpotify user ID, spotify:user: URI, or open.spotify.com/user URL
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds meaningful behavioral context beyond annotations: pagination behavior, output capping by max_results, and the deprecation/unavailability caveat. It does not describe return format, but the response_format parameter partially covers that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The primary action is front-loaded, followed by the deprecation caveat and the output cap. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list tool with full schema coverage and a response_format parameter, the description is nearly complete. It covers pagination, output capping, and the critical deprecation limitation. It does not describe the exact return structure, but no output schema exists and the response_format enum gives the agent the key options.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters. The description adds a small amount of value by clarifying that output is capped by max_results and mentioning the SPOTIFY_MCP_MAX_ITEMS default, but this largely duplicates the schema's max_results description. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List another Spotify user's public playlists (paginated).' It clearly distinguishes this tool from get_user_playlists by emphasizing 'another user's' and 'public,' and it adds a concrete deprecation caveat that further defines what the tool is.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: this is for another user's public playlists, not your own. It also provides an explicit exclusion: unavailable for newer app registrations after Spotify's February 2026 Web API changes. It does not name an alternative tool, but the context is strong enough to guide selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_user_profileA
Read-onlyIdempotent

Get any Spotify user's public profile (display name, profile image). Removed by Spotify's February 2026 Web API changes โ€” unavailable for newer app registrations. The followers field was separately removed from user profiles, so no follower count is reported

ParametersJSON Schema
NameRequiredDescriptionDefault
user_idYesSpotify user ID, spotify:user: URI, or open.spotify.com/user URL
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, but the description adds critical behavioral context: the endpoint is deprecated/removed for newer app registrations, and the followers field was separately removed so no follower count is reported. These details go well beyond the annotations and materially affect expected behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three tightly written sentences. It leads with the core purpose and then immediately provides availability caveats and missing-field details. Every sentence adds distinct value with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only profile lookup with full schema parameter coverage and annotations covering safety, the description supplies the missing operational context: deprecation status, registration limitations, returned fields, and the absence of follower counts. No output schema exists, and the description sufficiently clarifies expected output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents both user_id and response_format. The description does not add any parameter-specific syntax, constraints, or format meanings beyond what the schema provides, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Get any Spotify user's public profile (display name, profile image).' It is clear what the tool does and what data is returned, but it does not name or explicitly distinguish itself from sibling tools such as get_user_playlists_by_id or other profile-related tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides an important when-not condition: it was removed by Spotify's February 2026 Web API changes and is unavailable for newer app registrations. This helps an agent avoid calling it in unsupported contexts. However, it does not suggest alternative tools or explicitly describe when to use it versus other profile-adjacent tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

grow_playlistA

Propose tracks to grow one of your playlists using ONLY your own listening data (no recommendations): finds tracks appearing in >=2 of your OTHER playlists, boosts ones sharing an artist with the target playlist, excludes tracks already in it (and optionally your saved library), and returns top candidates with evidence. Read-only: review the proposals, then call add_to_playlist with the URIs you want.

ParametersJSON Schema
NameRequiredDescriptionDefault
sizeNoHow many candidates to propose (default 20)
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idYesTarget playlist ID to grow
exclude_savedNoSkip tracks already in your saved library (default true)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description aligns with annotations by declaring 'Read-only' consistent with destructiveHint: false, and adds useful behavioral context: the data-source constraint, deduplication rule (>=2 playlists), artist boost, and exclusion behavior. However, it leaves the dry_run parameter's implication unexplained โ€” dry_run's 'describe exactly what would change without performing it' phrasing suggests a performing mode that the read-only claim doesn't reconcile. Output format ('top candidates with evidence') is also vague.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense sentence with the core purpose front-loaded and the follow-up workflow at the end. Every clause earns its place โ€” algorithm, exclusions, and routing. It is slightly long and could be split into two sentences, but no filler or repetition exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter tool with no output schema, the description covers purpose, algorithm, and the follow-up action well. However, since no output schema exists, the vague 'returns top candidates with evidence' leaves the response shape under-specified, and the dry_run parameter's behavior is not integrated into the description. An agent could invoke it correctly but would not know what 'evidence' looks like in the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter (size, dry_run, max_results, playlist_id, exclude_saved, response_format) already carries a description. The tool description adds marginal context by explaining the algorithm that maps to exclude_saved ('and optionally your saved library') and the candidate-count notion, but it does not need to compensate for schema gaps. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Propose tracks'), resource ('one of your playlists'), and a precise algorithm: finds tracks in >=2 other playlists, boosts artist matches, excludes existing tracks. It also explicitly distinguishes itself from recommendation tools with 'using ONLY your own listening data (no recommendations)', which sets it apart from the many playlist and discovery siblings in the toolset.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit workflow: 'Read-only: review the proposals, then call add_to_playlist with the URIs you want.' This names the exact follow-up tool and clarifies that grow_playlist is an analysis/proposal step, not a mutation. It doesn't explicitly enumerate when-not-to-use alternatives, but the '(no recommendations)' qualifier and the read-only workflow assertion provide strong contextual routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_from_sidecarA

Additive restore from a library.json sidecar written by export_library_json: re-adds every missing saved item across all five collections (tracks, albums, shows, episodes, audiobooks) through the unified PUT /me/library endpoint, skipping items the library already holds. Rows whose uri is not a canonical spotify::<22-char id> URI are counted as invalid and never sent. Collections the file does not carry are named in absent_keys. The exporter's own truncated / cap_reached flags are surfaced as sidecar_truncated + truncated_collections: a capped sidecar restores only the rows it holds and says so, and a file with no flag reports completeness as UNKNOWN rather than complete. The prompt and the result both state the sidecar path, the date the file itself declares (exported_at, or the named reason it declares none โ€” never the mtime), the row count, the one use being made of it, and whether a human confirmed that use (see consent_note). dry_run=true by default. Quota: local read + contains-check + chunked writes when dry_run=false.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only, making no API calls at all. Writes happen only when explicitly set to false.
input_pathNoPath to sidecar JSON (default: <portability>/library.json)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry destructiveHint=false, so the description carries the real burden and does so thoroughly: additive semantics, skip-existing behavior, invalid-URI rows never sent, absent_keys reporting, sidecar_truncated/truncated_collections surfacing, UNKNOWN vs complete reporting, the declared-date rule, consent_note, and the quota (local read + contains-check + chunked writes only when dry_run=false). This is far beyond what the annotation provides.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence is strongly front-loaded and every subsequent sentence carries behavioral information. It is dense and clause-heavy (unsaved/absent_keys/truncation/consent bundled into few long sentences), which costs a little readability, but there is essentially no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, no-output-schema restore tool, the description covers trigger, safety, default mode, the shape of the reported result (absent_keys, sidecar_truncated, truncated_collections, exported_at, consent_note) and its cost profile. An agent has everything needed to call it correctly and interpret the outcome.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters are already documented, and the description largely repeats the dry_run default rather than adding new meaning. It does add the default sidecar path and the 'no API calls at all' nuance, but the schema does the heavy lifting, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (additive restore from a library.json sidecar) and names its counterpart, export_library_json, which wrote the file. The five collections and the underlying PUT /me/library endpoint are named, so the agent can distinguish it from restore_library_snapshot and backup_first without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly establishes the usage context: it is additive (skips items already held), it reads only sidecars written by export_library_json, and dry_run is the default preview mode. It does not explicitly contrast against siblings like restore_library_snapshot or import_profile_state, so it stops short of full when/when-not routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_playlistA

Parse an M3U or CSV document (the inverse of export_playlist) and append its Spotify URIs to a target playlist. Pass the document inline via content, or read it from input_path (a regular file inside the configured read roots). URIs already in the playlist are skipped, so a re-run adds nothing. Adds in batches of 100. Use dry_run=true to preview without writing. Result records the document source and the use made of it (consent_note); under 100 new URIs nothing is gated.

ParametersJSON Schema
NameRequiredDescriptionDefault
formatNoDocument format; auto-detected when omitted
contentNoThe M3U or CSV document body, passed inline
dry_runNoParse and report what would be added without touching the playlist
input_pathNoRead the document from this local file instead of content
playlist_idYesTarget playlist ID, spotify:playlist: URI, or share URL
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the lone destructiveHint=false annotation: discloses idempotent dedup (existing URIs skipped, re-run adds nothing), 100-URI batching, dry_run semantics, and consent_note gating behavior under 100 new URIs. This is exactly the write-safety context an agent needs for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action, then packs input modes, idempotency, batching, preview, and gating into tight sentences with no filler. Every clause carries operational value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, and the description proactively notes the result records the document source and consent_note, plus the gating threshold. Complete for a mutation tool; only failure/error behavior for malformed documents is unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3, but the description adds real meaning: input_path must be a regular file inside the configured read roots, and content is the inline alternative. It also frames dry_run as preview-only, beyond the schema's terse wording.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('parse... and append') plus resource (M3U/CSV document into a target playlist) and explicitly positions itself as the inverse of export_playlist, so an agent can distinguish it from sibling importers and exporters.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the two input modes (inline content vs input_path from read roots) and when to use dry_run=true to preview, plus the sibling relationship to export_playlist. No explicit 'when-not' or alternative-tool routing, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

import_profile_stateA

Restore local sidecar stores from a profile-state archive. merge unions each store on its own keys and de-duplicates search_history by entry id; overwrite replaces each store, keeping a 0600 .bak of what it replaced. The mutation ledger (stores.mutations_history) is export-only: it is never appended to or replaced, and an archive carrying it is reported as skipped. dry_run reports the per-store plan and writes nothing. Refuses newer schema versions.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNomerge = union on each store's own keys; overwrite = replace, keeping a .bakmerge
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
input_pathYesPath to the profile-state archive JSON file
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false available, the description carries real load: merge de-duplicates search_history by entry id, overwrite keeps a 0600 .bak of replaced stores, the mutation ledger is export-only and reported as skipped, dry_run writes nothing, and newer schema versions are refused. This is exactly the mutation/recovery context an agent cannot get from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with what the tool does, then mode semantics, then edge cases (ledger, dry_run, schema version). Every clause is operational information; there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an unannotated-in-practice mutation tool with no output schema, the description covers modes, side effects, backups, exclusions, and preview behavior well. Minor gaps remain: no statement of required permissions or what happens on partial/validation failure, and no hint at the dry_run plan's shape beyond 'per-store plan'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so 3 is the baseline; the description goes beyond the schema by spelling out the de-duplication key (entry id) that merge uses and reinforcing the dry_run/ledger rules. input_path and response_format are left to the schema, which is acceptable given how well the two enums are documented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb+resource+scope: 'Restore local sidecar stores from a profile-state archive', which an agent can act on immediately. It does not, however, differentiate itself from the closely named sibling import_from_sidecar or from restore_library_snapshot, leaving a selection ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the merge/overwrite semantics and dry_run behavior tell the agent how to call it, but there is no explicit when-to-use guidance relative to import_from_sidecar or restore_library_snapshot, and no stated prerequisites beyond the schema-version refusal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

inspect_toolA
Read-onlyIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
tool_nameYesExact registered tool name
response_formatNo'concise' (default) = prose bullet list; 'detailed' = the same prose; 'json' = the result payload as parseable JSON text, identical to structuredContentconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds only the timing guideline 'before calling it' and does not disclose further behavioral traits like response format or side effects, making a 3 appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with zero waste, stating the action and the key usage context immediately. It is appropriately sized for a simple inspection tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is low-complexity, has a rich schema with full parameter documentation, annotations covering safety, and an output schema, so return values need not be explained. The description is complete for an agent to understand and call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (tool_name and response_format) are fully documented in the schema. The description adds no additional meaning beyond what the schema provides, which is the expected baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Show') and resource ('one tool's full description and input schema'), clearly defining the tool's output. It does not explicitly differentiate from siblings like find_tool, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'before calling it' gives clear context for when to use this toolโ€”prior to invoking another tool. No exclusions or alternative tools (e.g., find_tool) are mentioned, which keeps it from a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

library_genre_reportA
Read-onlyIdempotent

Aggregate your saved library by user-declared genre tags. Scans all saved tracks and albums, joins each item's artists against your tag sidecar (see tag_management), and reports per-genre track/album counts plus the contributing artists. Genres are unavailable from Spotify itself, so only artists you have tagged appear here.

ParametersJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered. The description adds real behavioral context: it scans the entire saved library (not a filtered subset), performs an artist-level join against the tag sidecar, and returns counts plus contributing artists, with an explicit coverage limitation. It stops short of describing pagination or how max_results truncation affects the aggregates.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, all front-loaded with the operation first, then mechanism, then the important data-availability caveat. Every sentence earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does the work of explaining the return shape (per-genre track/album counts plus contributing artists) and the crucial limitation that untagged artists are excluded. It is nearly complete; only the effect of result truncation on the aggregates is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so max_results and response_format are already fully documented in the schema, including the enum values and default. The description adds nothing about either parameter, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Aggregate your saved library by user-declared genre tags') and explains the mechanism: scanning saved tracks/albums and joining artists against the tag sidecar. This clearly distinguishes it from siblings like filter_by_genre, tag_management, and library_hygiene without needing to open any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives strong contextual guidance: it points to tag_management for the sidecar and warns that only tagged artists appear because Spotify exposes no genre data. That tells the agent when output will be useful, but it never explicitly states when to prefer this over alternatives such as filter_by_genre or a plain saved-tracks listing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

library_hygieneA

Read-only album hygiene over your liked tracks: flags near-complete albums worth saving and lone singles with nothing else liked from their artist (low confidence). Album totals come from the /me/tracks walk; a width-bounded per-id GET /albums/{id} fills in the rest. Never mutates. dry_run previews cost.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview cost only.
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false provided, the description carries real extra weight: it declares read-only, 'never mutates', discloses the confidence caveat ('low confidence'), and explains that dry_run previews cost. That is meaningful behavioral context beyond the annotation. It stops at 4 because the return shape and the exact cost/preview semantics are left implicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the tool's purpose before implementation detail, and dry_run/read-only facts are packed tightly into short sentences. The implementation sentence about /me/tracks and /albums/{id} is arguably surplus for tool selection but does earn its place as transparency. Overall efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, zero-required-param tool with no output schema and fully documented params, the description covers purpose, mutation profile, confidence caveat and cost preview. Nothing critical is missing, though it never describes what a result row looks like or the ordering/limit interaction.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents dry_run, max_results and response_format with defaults and bounds. The description only reinforces that dry_run previews cost, adding little beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read-only album hygiene over your liked tracks') and enumerates the two findings it surfaces (near-complete albums, lone singles). An agent can distinguish it from siblings like unsave_orphan_tracks or find_duplicate_saved_tracks by the album-completeness angle. It does not name a sibling explicitly, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'what' is clear, so when-to-use is implied for a library-audit workflow, but there is no explicit when/when-not or reference to an alternative tool. Nothing tells the agent how this differs operationally from related hygiene tools such as unsave_orphan_tracks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

library_snapshot_diffA

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

ParametersJSON Schema
NameRequiredDescriptionDefault
after_pathYesPath to after snapshot JSON
before_pathYesPath to before snapshot JSON
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false. The description adds two genuine behavioral traits beyond that: the operation is purely local with no API/quota cost, and the output shape is added/removed counts plus samples. It does not discuss permissions or failure modes, but for a read-only diff utility this is meaningful extra context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with zero waste; the core purpose leads, followed by the quota caveat and output summary. Nothing is repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by summarizing the return (added/removed counts + samples). Combined with full schema coverage and the local-only note, an agent has almost everything needed; only the differentiation from sibling diff tools is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% โ€“ all three parameters, including the concise/detailed/json enum for response_format, are documented in the schema itself. The description adds nothing about parameter format or semantics beyond naming the file types, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (diff) and specific resources (two sidecar JSON files: library.json or playlists.json) and summarizes the payload (added/removed counts + samples). It implicitly separates itself from sibling diff_playlists by scoping to local snapshot files, though it never names that sibling to make the distinction explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Quota: local only (no API)' implies when this tool is preferable (offline snapshot comparison vs live API calls), but there is no explicit when/when-not statement or named alternative such as diff_playlists or backup_first. Usage is inferable rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_accountsA
Read-onlyIdempotent

List every local account this server can act as, and which one it is acting as now. Returns each account's account_id, profile name, display name and token file PATH โ€” never any token material. Reads the local registry and one GET /me for the acting account; no mutation requests are issued.

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it read-only and idempotent, but the description adds concrete behavior: it reads the local registry plus one GET /me for the acting account, returns account_id/profile name/display name/token file PATH, and explicitly never returns token material. This exceeds the annotation coverage and provides useful operational context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the core list action, followed by return details and safety behavior. Every sentence adds useful information without repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fills the gap by naming returned fields and clarifying that no token material is included. Annotations cover safety, and the description supplies the behavioral and return context an agent needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The sole parameter response_format has 100% schema description coverage with an enum and default, and the description does not discuss it at all. Baseline 3 applies because the schema fully documents the parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb 'List' and resource 'local accounts this server can act as', and adds the active-account distinction. This clearly separates it from sibling tools like get_user_profile and switch_account.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for discovering available local accounts and the currently active one, but does not explicitly state when to prefer it over switch_account or get_user_profile. No when-not or alternative routing is given, leaving usage to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_backupsB
Read-onlyIdempotent

List complete and partial library backups (newest first) using bounded metadata sidecar reads, with a bounded prefix fallback for legacy snapshots. Expires snapshots past SPOTIFY_MCP_BACKUP_RETENTION_DAYS (default 30, 0 disables) and reports what it removed, plus the store envelope (dir_bytes, oldest_created, oldest_retention_until).

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.3/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states 'Expires snapshots past SPOTIFY_MCP_BACKUP_RETENTION_DAYS' and 'reports what it removed', which is a mutating action. The annotations declare readOnlyHint=true, which claims the tool does not modify state. This is a direct contradiction. Per the rubric, score is 1 because the description contradicts annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but efficient, with the core listing behavior front-loaded. It includes necessary operational details (sidecar reads, retention policy, output fields) without being verbose. Could be slightly tighter, but overall well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's main actions (list, expire, report removal) and specifies the output envelope fields. It does not describe the response_format effect beyond the schema, but that field is fully documented. The only weakness is the annotation contradiction, which creates ambiguity about safety, but the description itself is fairly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for the single parameter (response_format). The description does not need to add parameter details, so the baseline of 3 applies. The schema already explains concise/detailed/json.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb and resource: 'List complete and partial library backups (newest first)'. It also lists secondary behavior (expiring old snapshots) which distinguishes it from similar tools like backup_library or delete_backup. It is unambiguous what this tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for inspecting backups and cleaning expired ones, but it does not explicitly contrast with alternatives like delete_backup (which also deletes) or backup_library (which creates backups). When to choose this over a plain delete tool is left to inference, so guidance is only moderate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_scenesB
Read-onlyIdempotent

List saved playback scenes from the local sidecar

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, covering the safety profile. The description adds the data source 'local sidecar' which is useful context, but it does not describe the return format, pagination, or any side effects. Given the annotations, the bar is lower, and the added context is minimal but not contradictory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence that front-loads the verb and resource. There is zero wasted wording, and it efficiently communicates the core function.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with one optional parameter and no output schema, the description is mostly sufficient. It tells the agent what it does and where data comes from. However, it doesn't mention that it only lists scenes from the local sidecar as opposed to elsewhere, but that is already implicit. The lack of return format details is acceptable given no output schema, and the annotations cover safety.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers the single parameter response_format with 100% description coverage, so the schema already documents it. The tool description does not mention the parameter at all, so it adds no additional meaning. Since schema coverage is high, the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'List saved playback scenes from the local sidecar'. It is specific about what it does and where the data comes from. However, it does not differentiate from siblings like apply_scene or delete_scene, so the agent must infer that this is purely a listing operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives. For example, the description doesn't mention that apply_scene is for applying a scene, or that scene_sampler_search might be used for searching. The agent is left to infer the tool's place in the workflow without explicit when-to-use or when-not-to-use instructions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_playlistsA

Merge multiple playlists into one. Deduplicates tracks across sources (first-seen order wins) and adds them in batches of 100. Pass target_playlist_id to append to an existing playlist (it is NOT cleared) or new_name to create a fresh playlist.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
publicNoVisibility of a NEW playlist. Default: false
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
new_nameNoName for a newly created target playlist
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlistsNoCanonical ordered playlists (1โ€“10)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
target_playlist_idNoExisting playlist to APPEND into (never cleared)

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false; the description carries the real behavioral burden and does so well. It discloses the dedup rule (first-seen order wins), batching (100 per request), and crucially that an existing target playlist is appended to and NOT cleared โ€“ exactly the safety-relevant fact an agent needs before a mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with zero filler. The core action is front-loaded, followed by dedup/ordering behavior and then the two target modes โ€“ a logical, scannable order.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with only a minimal annotation and no output schema, the description covers the essential operation, dedup semantics, and append-vs-create safety behavior well enough to invoke it correctly. Minor gaps remain around failure modes (e.g., duplicate IDs, exceeding source caps) and what the operation returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all nine parameters, establishing a baseline of 3. The description reinforces the target_playlist_id/new_name distinction but adds no semantics beyond what the schema fields already state (append, never cleared).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (merge multiple playlists into one) plus its distinctive semantics: cross-source deduplication with first-seen ordering and batched adds. It does not name or contrast with near-neighbours like playlist_union or copy_playlist, so an agent can't fully disambiguate from siblings without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly explains the two operating modes (append via target_playlist_id vs create via new_name) and that the target is not cleared, which is useful conditional guidance. But it never says when to prefer this tool over alternatives such as playlist_union, batch_add_to_playlist, or copy_playlist, and gives no exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_items_between_playlistsA

Bulk rehome items between playlists. Mode copy keeps the source intact; mode move removes from source after copying โ€” by playlist position, removing exactly the transferred occurrences and leaving any other copy in the source. Supports dedupe against target and optional name/artist filter. Either side may be named by lane.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNocopy = leave source intact; move = remove from source after copycopy
limitNoSource page size, 1โ€“100. Default: 100
dedupeNoSkip tracks already in target. Default: true
filterNoOptional substring filter: only transfer tracks whose name or artist name contains this string (case-insensitive)
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
source_laneNoLane name resolving to the source playlist; provide exactly one of source_playlist_id or source_lane
target_laneNoLane name resolving to the target playlist; provide exactly one of target_playlist_id or target_lane
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
source_playlist_idNoSource playlist ID, spotify:playlist: URI, or URL; provide exactly one of source_playlist_id or source_lane
target_playlist_idNoTarget playlist ID, spotify:playlist: URI, or URL; provide exactly one of target_playlist_id or target_lane

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

This description adds substantial behavioral detail beyond the single destructiveHint annotation: move removes by playlist position, removing exactly the transferred occurrences while leaving other copies in the source, dedupe against the target, and an optional filter. There is mild tension with destructiveHint=false given that move deletes items from the source, but since the copy lands in the target first and the removal semantics are fully disclosed (not hidden), the agent is not misled. It does not cover pagination/scan behavior or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences, front-loaded with the core operation and its mode distinction, then the removal nuance, then supporting options. No filler or repeated name/title text; every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter mutating tool with no output schema and only a destructiveHint annotation, the description covers the critical semantics: what copy vs move does, how removal is scoped, dedupe and filtering. What is missing is minor for correct invocation: the response_format/dry_run usage implications, paging via limit/scan_cap, and any failure conditions, though the schema documents those parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all 12 parameters are already documented in the schema (mode enum, dedupe default, filter substring semantics, lane-vs-id exclusivity). The description restates the mode and dedupe/filter ideas and adds the only novel note, that 'either side may be named by a lane,' but contributes little beyond the schema. Baseline 3 for full coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line states a specific verb and resource ('Bulk rehome items between playlists') and immediately disambiguates the two modes (copy keeps source intact, move removes after copying). It does not name or contrast itself with near-siblings like merge_playlists, copy_playlist, or playlist_union, so an agent must infer the boundary. Clear purpose, but not sibling-differentiating.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives real decision-relevant context: copy vs move semantics, dedupe-against-target, name/artist filtering, and lane-based naming of either side. However it never states when to prefer this tool over copy_playlist, merge_playlists, or batch_add_to_playlist, nor any exclusions or prerequisites. Usage is implied by capability rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

overlap_playlistsB

Find tracks shared across playlists: reports how many playlists each track appears in and lists tracks present in at least min_overlap playlists (default: all of them), most-shared first.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlistsNoCanonical ordered playlists (2โ€“10)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
min_overlapNoMinimum number of playlists a track must appear in. Default: all playlists
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The only annotation is destructiveHint=false, so the description must carry the rest. It usefully discloses the default threshold semantics and result ordering, which annotations do not cover, but says nothing about the read-only nature, the scan_cap/SPOTIFY_MCP_FETCH_ALL_CAP bounding behavior, truncation, or how dry_run interacts โ€” despite dry_run being a declared parameter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence that front-loads the core operation (shared tracks), then the report contents, the threshold default, and the sort order โ€” no filler and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter read tool with no output schema, the description adequately conveys the operation and the shape of the result (counts plus qualifying tracks, ordered). It falls short only on dry-run semantics and the scan-cap/truncation limits that an agent would want before invoking.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all seven parameters (limit, scan_cap, playlists, max_results, min_overlap, response_format, dry_run). The description adds only the min_overlap default and the ordering, which is baseline value when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource โ€” finding tracks shared across playlists โ€” and even describes the output (per-track playlist counts, tracks meeting the min_overlap threshold, sorted most-shared first). It is clear without opening the schema, though it does not name or contrast with near-neighbors like find_duplicate_tracks_across_playlists, playlist_union, or diff_playlists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what happens by default (min_overlap defaults to all playlists) but never says when to choose this over intersecting/unioning siblings or what prerequisites apply. No when-not guidance or alternative routing is present, leaving selection to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pauseB

Pause playback on the active device

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations only declare destructiveHint=false. The description adds useful scope by specifying that playback is paused on the active device, which goes slightly beyond the annotation. It does not mention authorization needs, effect on other devices, dry_run behavior, or anything about playback state changes beyond the pause itself.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no wasted words. It is appropriately sized for a simple playback control.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple pause tool with full schema coverage and no output schema, the description covers the core action. However, it omits how device_id overrides the 'active device' framing and does not mention dry_run or response_format behavior, leaving some ambiguity despite the schema documenting those parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents dry_run, device_id, and response_format. The description does not add any parameter meaning beyond what the schema provides. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource: 'Pause playback.' It is clear enough to distinguish from play, skip_next, and skip_previous. However, it does not explicitly name or differentiate itself from those sibling playback controls, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives such as 'play' or 'transfer_playback,' nor any preconditions or exclusions. The intended action is implied, but no explicit usage context is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pin_playlistA

DEPRECATED, use follow_playlist. This tool never pinned anything; it has always saved the playlist to your Spotify library via PUT /me/library.

ParametersJSON Schema
NameRequiredDescriptionDefault
publicNoMust be true or omitted; the library endpoint has no visibility parameter.
dry_runNoPreview only (default): pass dry_run: false to execute the follow.
playlist_idYesPlaylist ID to follow
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription
okNo
dry_runNo
receiptNo
cancelledNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover destructiveHint=false, and the description adds real behavioral context: the tool never actually pins, the underlying endpoint is PUT /me/library, and it is deprecated. It does not discuss auth/scopes or idempotency, but for a deprecated alias the disclosure is strong.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, deprecation and the correct behavior front-loaded, zero filler. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, and all four parameters are fully described in the schema. The description completes the picture by explaining the misleading name and the correct alternative.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and each parameter (public, dry_run, playlist_id, response_format) is documented in the schema itself. The description adds no parameter-level detail, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb+resource ('saves the playlist to your Spotify library via PUT /me/library') and explicitly corrects the misleading name, so an agent knows exactly what it does. It also names the intended replacement (follow_playlist), distinguishing it from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-not-to-use guidance ('DEPRECATED, use follow_playlist') and names the alternative tool by name. Nothing about selection is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plan_podcast_sessionA
Read-onlyIdempotent

Greedy-pack your saved podcast episodes into a listening session of a given length. Episodes play their remaining time (duration minus resume position); fully played ones are skipped. Scanning stops at the first unplayed episode that doesn't fit.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoRestrict the source: 'episodes' = your saved episodes only, 'shows' = recent episodes of your saved shows only. Omit to use saved episodes (plus saved shows when saved_only is false)
marketNoISO 3166-1 alpha-2 country code for the saved-show episode lookups, e.g. "US". Defaults to SPOTIFY_MCP_MARKET, then to the account country โ€” these lookups are market-gated, so a wrong default silently drops episode rows. Ignored for a saved-episodes-only plan.
minutesYesSession length in minutes (1โ€“480)
saved_onlyNoWhen no kind is set, include recent episodes of saved shows too. Default: true (saved episodes only)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered. The description adds genuine behavioral detail beyond that: episodes use remaining time (duration minus resume position), fully played episodes are skipped, and scanning aborts at the first non-fitting unplayed episode. Return format is not described, but the algorithm disclosure is substantive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with zero waste, front-loaded with the core action and followed by the algorithm rules that determine the output. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only planning tool with full schema coverage and no output schema, the description is essentially complete. The one meaningful gap is that it does not state it performs no playback, which matters given the start_podcast_session sibling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters (kind, market, minutes, saved_only, max_results, response_format) are already fully documented in the schema. The description's mention of resume position is algorithm context, not parameter semantics, so it adds little. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Greedy-pack your saved podcast episodes into a listening session of a given length.' The packing algorithm is clearly described. However, it never names its adjacent sibling start_podcast_session, so an agent must infer that this plans rather than plays.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the word 'plan' and 'greedy-pack' signal a non-playing computation, but there is no explicit when-to-use statement, no exclusion, and no routing to start_podcast_session, which is the most likely confusion point.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playC

Start or resume playback. Optionally target specific content.

ParametersJSON Schema
NameRequiredDescriptionDefault
urisNoUp to 100 track/episode URIs to play as an ad-hoc queue
offsetNoIndex within an album/playlist context to start from. Ignored for ad-hoc uris; not valid for artist contexts (use offset_uri instead).
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID; uses active device if omitted
offset_uriNoTrack URI inside the context to start from โ€” required for artist contexts, where a numeric index is rejected
context_uriNoSpotify URI for an album, artist, or playlist
position_msNoSeek position to start at (ms)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false. The description adds no detail about authentication needs, how existing playback or queue is affected, device state requirements, or error conditions, so it contributes little beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded and free of wasted words. The second sentence is generic but not redundant, so the structure is efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter playback control tool surrounded by many siblings, the description is extremely thin. It omits when to use it, device handling, playback behavior, and interaction with other controls; the schema covers parameters but the description does not supply necessary context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all eight parameters are fully documented in the schema. The description only vaguely refers to 'specific content' and adds no syntax or format details beyond what the schema already provides, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('start or resume') and resource ('playback'), so the basic action is clear. However, it does not differentiate from siblings like play_from_search or transfer_playback, leaving sibling selection to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The only guidance is 'Optionally target specific content,' which is vague. There is no indication of when to use this tool versus play_from_search, pause, skip_next, or other playback controls, and no conditions or exclusions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_collab_toggleB

Toggle collaborative/public flags (guards public=true && collaborative=true 400). Quota: GET + PUT.

ParametersJSON Schema
NameRequiredDescriptionDefault
publicNoTarget visibility: true makes the playlist public
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID, spotify:playlist: URI, or URL
collaborativeNoTarget collaborative state for the playlist

TDQS

B3.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false. The description adds valuable behavior: the public=true && collaborative=true 400 guard and the GET + PUT quota cost. It omits auth/permission requirements, but this is well beyond annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two terse fragments, front-loaded with the main action; no filler. The parenthetical guard and quota line are slightly cryptic but efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a flag-toggle mutation with full schema coverage and minimal annotations, the description supplies the key validation guard and quota. It lacks any routing guidance versus update_playlist, leaving a gap for tool selection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema documents all four parameters including dry_run. The description mentions the flags but adds no syntax or format beyond the schema. Baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Toggle') and resource ('collaborative/public flags'), making the action clear. It does not explicitly name or distinguish sibling tools like update_playlist, so a 4 rather than 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no alternatives, and no exclusions are provided. The guard describes a validation rule, not usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_reverseA

Reverse a playlist in one atomic replace. Quota: GET all + PUT/POST.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID, spotify:playlist: URI, or URL

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description adds real value by disclosing that the reversal happens via a single atomic replace and that the cost is GET all + PUT/POST. It is consistent with the non-destructive annotation (reordering, not deleting) and adds quota/atomicity context the annotation does not carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two very short sentences, front-loaded with the core action followed by the cost/quota note. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation with a 100%-covered two-param schema and no output schema, the description covers action, atomicity, and cost. It omits permission requirements and return behavior, but these are marginal for a tool this simple.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% โ€” both playlist_id and dry_run are fully documented in the schema, including the preview semantics of dry_run. The description adds no parameter detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("Reverse a playlist") plus the mechanism ("in one atomic replace"). It clearly distinguishes a reversal from siblings like playlist_sort or playlist_shuffle, though it never names them explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use, when-not, or alternative is stated. The description only implies usage from the verb itself and gives a quota cost note, which is not usage guidance. An agent must infer that playlist_sort or playlist_shuffle are not substitutes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_shuffleB

Fisher-Yates shuffle a playlist (seeded optional). Quota: GET all + PUT/POST.

ParametersJSON Schema
NameRequiredDescriptionDefault
seedNoDeterministic shuffle seed; omit for a random order
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID, spotify:playlist: URI, or URL

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The 'Quota: GET all + PUT/POST' note adds real operational context beyond the single destructiveHint=false annotation, implying the tool performs writes and costs a read-plus-write quota. However, it says nothing about reversibility, ownership/auth requirements, or what happens to existing ordering, which matters for a mutating operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences, algorithm stated first, quota constraint second; nothing is padded or redundant. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with only a destructiveHint annotation and no output schema, the description covers the algorithm and quota cost but omits whether the change is reversible, what the tool returns, and any auth/ownership prerequisites. Adequate but with visible gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so playlist_id, seed, and dry_run are already documented in the schema; the description only echoes the optional seed behavior and never mentions dry_run. Baseline 3 is appropriate when the schema carries the parameter burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a concrete verb ('shuffle') plus resource ('playlist') and even specifies the algorithm (Fisher-Yates), which separates it from generic siblings like playlist_sort and playlist_reverse. It stops short of explicitly contrasting itself with those siblings, so it is clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no indication of when to choose this over playlist_sort, playlist_reverse, or reorder_playlist_items, nor when to prefer the dry_run preview. The parenthetical '(seeded optional)' hints at a determinism use case but never states it as guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_sortA

Sort a playlist in place by added_at/name/artist/duration. Quota: GET all + PUT/POST. popularity is not a sort key: the API no longer returns it on playlist items.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
sort_byNoSort key applied to the playlistname_asc
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idYesPlaylist ID, spotify:playlist: URI, or URL
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description usefully adds that sorting happens in place (persistent mutation of the playlist), that it costs GET all + PUT/POST requests, and that 'popularity' is not a valid key because the API no longer returns it โ€” a real guard against a plausible wrong invocation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the operation and keys come first, followed by cost and the popularity caveat. Every clause carries information an agent can act on, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the critical behavioral facts for a mutating playlist tool (in-place edit, quota cost, invalid key) are present. Minor gaps remain: it never mentions the dry_run preview path or that sorting can invalidate existing snapshots.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all five parameters (including dry_run and response_format) are already documented. The description only reinforces the sort key families and rules out popularity, which adds marginal value over the enum and defaults in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('sort') and resource ('playlist') plus the in-place scope and the available key families (added_at/name/artist/duration). It does not differentiate itself from close siblings such as playlist_reverse, playlist_shuffle or reorder_playlist_items, so it lands at a clear-but-not-discriminating 4.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the key list; there is no statement of when to prefer this over playlist_reverse/playlist_shuffle/reorder_playlist_items, nor whether it requires an unfollowed/owned playlist or snapshot handling. The quota note hints at cost but is not a when-to-use rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_subtractB

Remove tracks of B..N from A by REWRITING A: one PUT replaces every row with the ones that survive, so any row of A absent from the union is DELETED, and the rows that remain are re-written in order. Subtracting every track empties A via one PUT with an empty uris array (Spotify's documented clear); a reply with no snapshot_id reports unconfirmed, not ok. Quota: N GETs + PUT.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlistsNoCanonical ordered playlists (1โ€“10)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
base_playlist_idYesBase playlist ID, URI, or URL. Required; list only the subtraction sources in playlists.

TDQS

B3.1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states in caps that rows of A absent from the union are DELETED and that subtracting everything empties A via a documented clear, which is destructive mutation behavior. The annotation declares destructiveHint=false, i.e. additive-only, which directly contradicts the described deletion semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core operation is front-loaded in the first clause and each sentence carries real information (rewrite semantics, empty-clear edge case, snapshot_id meaning, quota). It is dense and somewhat run-on, especially the second sentence, but there is little filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema, the description supplies the missing behavioral context: destructive rewrite semantics, empty-subtraction edge case, snapshot_id/confirmation semantics, and a quota estimate. Coverage is strong, though the contradiction with the annotation undercuts trust in the safety picture.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter (limit, scan_cap, dry_run, playlists, max_results, response_format, base_playlist_id) is already documented in the schema. The description adds only the semantics of the empty-uris clear case and does not enrich any individual parameter beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a precise verb+resource+scope: remove tracks belonging to playlists B..N from playlist A, and it spells out the rewrite mechanism that distinguishes this set-subtraction from a plain row-by-row removal. It stops short of naming sibling alternatives (e.g., playlist_union, remove_from_playlist), so it is clear rather than sibling-routing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the operation described (a set-difference edit) and the quota note hints at cost trade-offs, but there is no explicit when-to-use / when-not-to-use guidance and no alternative tool is named. The schema's dry_run field carries most of the 'preview before committing' guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_symmetric_differenceB

Tracks in exactly one of two playlists (XOR). Quota: 2 GETs.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
scan_capNoMaximum rows to read from each playlist; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlist_aNoCanonical A playlist; provide with playlist_b
playlist_bNoCanonical B playlist; provide with playlist_a
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotation destructiveHint=false already signals a non-destructive read operation. The description adds a useful behavioral detail beyond the annotation: 'Quota: 2 GETs', which tells the agent about cost before invocation. It does not cover auth requirements, pagination behavior, or output structure, so it is adequate but still thin for a playlist-comparison operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise and front-loaded: the operation is stated first, then the quota cost. Both sentences carry information that an agent can use, and there is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description states the core operation and a quota cost, which is enough to invoke the tool against a fully documented schema. However, with no output schema and no return-format guidance, it leaves gaps around what the returned result looks like, ordering, pagination behavior, and how the two playlist inputs are expected to pair. It is minimally complete rather than fully self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with all six parameters documented in the input schema, including defaults, bounds, and response_format enum values. The description adds no parameter-level syntax or semantics beyond what the schema already provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the specific operation as 'Tracks in exactly one of two playlists (XOR)', which is a clear symmetric-difference result set over playlist track resources. The XOR qualifier distinguishes it from intersection-style siblings like overlap_playlists and union-style siblings like playlist_union. It stops short of naming an explicit action verb or routing alternatives, but the purpose is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance, no exclusions, and no explicit alternatives. An agent must infer that this tool is appropriate only for symmetric-difference comparisons from the operation itself. There is no mention of related siblings such as playlist_subtract, playlist_union, or overlap_playlists.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_template_applyB

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoPlaylist name (default: "<Template> Mix")
limitNoHow many tracks (1-100, default 30)
publicNoWhether the playlist is public
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
templateYesTemplate name
descriptionNoPlaylist description override
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations are minimal (only destructiveHint: false), so the description carries much of the behavioral burden. It does state the primary side effect explicitly ('Creates a new playlist and fills it') and adds that it uses 'your existing listening data', which is useful context. However, it does not disclose behavior around name conflicts, permission requirements, or whether the dry_run parameter actually prevents side effects, leaving the agent to infer these from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with zero filler. It front-loads the core purpose and template types, then clarifies the side effect. Every word contributes to understanding what the tool does, achieving high information density without unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, no output schema, many sibling playlist tools), the description is too thin. It does not explain how this differs from similar playlist generators, what a successful response looks like, or how the dry_run mode behaves. The agent would need to inspect schemas and infer relationships to use it correctly, which is a significant gap for a mutation-oriented tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 7 parameters. The description adds only marginal value by listing template options (which are already in the enum) and mentioning the data source. It provides no extra semantics for name, limit, public, dry_run, response_format, or description beyond their schema definitions, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('create'), resource ('playlist'), and the template mechanism with concrete template names (focus, wind-down, gym, commute). It distinguishes itself from generic playlist creation by noting it composes from existing listening data. However, it does not explicitly differentiate from similar taste_* playlist-generating tools like taste_to_playlist or taste_era_playlist, so it's not a perfect sibling discriminator.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies a use case ('instant mood/vibe playlist') but provides no explicit when-to-use or when-not-to-use guidance. It does not name alternatives or conditions that would make this tool preferable over others (e.g., using create_playlist for manual control or taste_* for more personalized mixes). The dry_run parameter is also not mentioned in the description, missing an opportunity for safer usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_to_libraryA

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

ParametersJSON Schema
NameRequiredDescriptionDefault
dedupeNoSkip tracks already saved (default true)
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesSource playlist ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds operational context beyond the annotations: it discloses the underlying endpoints (GET playlist items and PUT /me/tracks) and chunking behavior (chunked 50). This helps the agent understand the write pattern and call volume, though it still omits auth scopes, error handling, and interaction with existing liked songs beyond what the schema's dedupe parameter implies.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences with zero waste: the purpose is front-loaded and the quota detail follows. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a bulk library mutation surrounded by many similar siblings, the description covers what it does and the API cost, and the schema fully documents parameters. However, it omits usage guidance and sibling differentiation, which are meaningful gaps for correct tool selection in this toolset.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters (playlist_id, dedupe, dry_run, response_format) are already documented in the schema. The description adds no parameter-level meaning beyond 'all tracks,' so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Save') and resource ('all tracks of a playlist to your Liked Songs'), making the action immediately clear. It does not explicitly distinguish itself from close siblings like save_to_library, add_to_playlist, or import_playlist, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no guidance on when to use this tool versus alternatives or what prerequisites are needed. It only describes the operation itself, leaving the agent to infer routing from the name and siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_trimB

Trim playlist to N items (keep first/last/random) by OVERWRITING the playlist: every row outside the kept set is DELETED, and the kept rows are re-written in the new order. An overwrite that deletes rows asks for confirmation first. Quota: 2 walks of the playlist items + 2 metadata GETs + PUT/POST.

ParametersJSON Schema
NameRequiredDescriptionDefault
keepYesHow many items to keep
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
keep_whichNoWhich end of the playlist to keep items from. Default firstfirst
playlist_idYesPlaylist ID, spotify:playlist: URI, or URL

TDQS

B3.3/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description explicitly says rows outside the kept set are 'DELETED' and the playlist is overwritten, but the annotation declares destructiveHint=false, which in MCP means additive-only updates. A row-deleting overwrite is not additive, so the description directly contradicts the annotation. The added confirmation and quota context would otherwise be valuable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action before the confirmation and quota details; each sentence carries distinct information. The all-caps emphasis is stylistically heavy but not padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema, the description covers the mutation mechanism, the confirmation gate, and the API quota cost, which is enough for an agent to call it correctly. Its only real deficiency is the conflict with the provided annotation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so keep, keep_which, dry_run, and playlist_id are already documented in the schema. The description restates the keep modes (first/last/random) but adds no syntax or format detail beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('trim playlist to N items') and names the three retention modes (first/last/random), letting an agent separate it from siblings like playlist_sort, split_playlist, and remove_from_playlist. The mechanism (overwrite + delete outside set) is spelled out up front.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The behavior implies when this tool is relevant (cutting a playlist down to a fixed size), and dry_run's purpose is clarified, but there is no explicit 'use this instead of X' routing against the many neighboring playlist-mutation tools. Usage is inferred rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

playlist_unionB

Union of 2โ€“10 playlists into target (deduped, first-seen order). An empty union empties the target the same way subtract does. Quota: N GETs + PUT/POST; replacing an existing target also reads its current items and its playlist metadata to measure the destructive impact.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoSource page size, 1โ€“100. Default: 100
dedupeNoDrop duplicate URIs across the merged sources. Default true
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
scan_capNoMaximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP
playlistsNoCanonical ordered playlists (2โ€“10)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
target_nameNoName for a newly created target playlist; provide exactly one of target_playlist_id or target_name
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
target_playlist_idNoExisting target playlist (ID, URI, or URL); provide exactly one of target_playlist_id or target_name

TDQS

B3.1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states that an empty union 'empties the target' and that replacing an existing target reads its items 'to measure the destructive impact' โ€” the tool's own words acknowledge data destruction, while the annotation declares destructiveHint=false. This is a direct conflict between the description and the structured safety signal, which is worse than silence for an agent deciding whether to call it unattended.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core operation, then the empty-union edge case, then cost. Nothing is repetitive, though 'N GETs + PUT/POST' and the trailing clause about reading playlist metadata are terse to the point of being cryptic.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation with full schema coverage and no output schema, the description covers the essential operational facts: merge semantics, ordering, the empty-input trap, and request cost. It omits auth/prerequisite and failure behavior, but nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter (limit, dedupe, dry_run, scan_cap, max_results, response_format, target_*) is already explained in the schema. The description adds ordering/dedupe semantics and a rough quota model but no per-parameter meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening clause gives a specific verb+resource and precise semantics ('Union of 2โ€“10 playlists into target (deduped, first-seen order)'), which cleanly separates it from shuffle/trim-ish siblings. It never names the nearest alternatives (merge_playlists, playlist_symmetric_difference, playlist_subtract) outright, so an agent must infer the routing itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the analogy 'the same way subtract does' and the quota note hint at when this set-operation is appropriate, and dry_run is available in the schema. There is no explicit when-to-use statement, no when-not-to-use, and no named alternative such as merge_playlists, so the agent gets context but no routing rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_duplicate_playlist_itemsA
Destructive

Remove duplicate items from a playlist: keeps the first occurrence of each track and removes later repeats, under the match_by rule the other duplicate tools use โ€” uri (default, exact repeats), name_artist (same name and credited artists, catching remasters and relinks under a new URI) or name (same title only). The rule applied is echoed as match_by. Supports dry_run; removals of 10+ items ask for confirmation via elicitation. See the duplicate-matching vocabulary in SPEC section 4.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
match_byNoWhich rule decides that two items are the same: `uri` (exact URI, the default), `name_artist` (case-insensitive name + credited artists, catches relinks/remasters), or `name` (case-insensitive name only). The rule applied is echoed in the result as `match_by`.
playlist_idYesPlaylist ID
include_relinkedNoDeprecated alias for `match_by`, kept for one release: true is `name_artist` and false is `uri`. It cannot express the `name` rule, which is why `match_by` replaced it. Sending both, where they mean different rules, is an error rather than a silent choice.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=true in annotations, the description carries most of the burden and does well: it discloses what is kept vs removed, that a match rule determines equality, that dry_run previews, and that removals of 10+ items trigger elicitation confirmation. It stops short of stating irreversibility or undo behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and the match_by rules, which is efficient. The sentences are long and partially duplicate the schema's match_by and include_relinked text, costing a little density.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description notes that the applied rule is echoed as match_by, covering the key return expectation. Combined with the dry_run and confirmation disclosures, it is complete enough for a moderately complex mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents every parameter, including the full match_by enum and the include_relinked deprecation error case. The description restates the match_by rules rather than adding new syntax or constraints, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Remove duplicate items from a playlist') and immediately specifies the semantics: first occurrence kept, later repeats removed. The matching-rule mechanics distinguish it from siblings like find_duplicates_in_playlist and clean_all_playlists.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context โ€” deduplicate a single playlist under a chosen match rule โ€” and mentions dry_run and the 10+ confirmation gate. It references 'the other duplicate tools use' but never explicitly says when to pick this over find_duplicates_in_playlist or clean_all_playlists.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_from_libraryA
Destructive

Preferred. Accepts the widest URI mix (track, album, episode, show, audiobook, user, playlist) in one request. Remove one or more items from the user's library via Spotify's unified library endpoint. Max 40. PREVIEWS BY DEFAULT โ€” pass dry_run=false to commit. Removals of 10+ items additionally require elicitation confirmation (or SPOTIFY_MCP_CONFIRM=never for automation).

ParametersJSON Schema
NameRequiredDescriptionDefault
urisYesSpotify URIs to remove
dry_runNoPreview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry destructiveHint=true; the description adds the critical behavior that this is a preview-first operation ('PREVIEWS BY DEFAULT โ€” pass dry_run=false to commit') and that large removals trigger elicitation confirmation with an env-var escape hatch. That is exactly the kind of operational context an agent needs to avoid an unintended destructive call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense, front-loaded sentences that each carry a distinct fact (scope, endpoint, limit, dry-run default, confirmation rule). The leading 'Preferred.' is slightly cryptic out of context, but overall there is little waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive batch tool with no output schema, the description covers scope, limits, default preview behavior, commit path, and the confirmation requirement โ€” everything needed to invoke it safely and correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents uris, dry_run and response_format, so the baseline is 3. The description still adds meaning: the max-40 batch limit, the accepted URI entity types, and the preview/commit semantics of dry_run that go beyond the schema's terse wording.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource: removes one or more items from the user's library via Spotify's unified library endpoint. It also carves out its scope against siblings ('accepts the widest URI mix (track, album, episode, show, audiobook, user, playlist) in one request'), which separates it from remove_from_playlist and remove_from_library_by_playlist.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States it is 'Preferred' and explains why (widest URI mix in one request, max 40), which implies when to choose it over narrower removal tools. It stops short of explicitly naming the alternative tools or the conditions where they would win, so it's clear context rather than full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_from_library_by_playlistA
Destructive

Remove from Liked Songs any tracks that also appear in a given playlist. Quota: 2 GETs + DELETE (chunked). PREVIEWS BY DEFAULT โ€” pass dry_run=false to commit. Removing 10+ saved tracks additionally requires elicitation confirmation (or SPOTIFY_MCP_CONFIRM=never for automation).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit.
playlist_idYesPlaylist ID whose tracks will be removed from library
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Excellent beyond annotations: quota (2 GETs + DELETE, chunked), safe-preview default, the explicit commit switch, and the elicitation/SPOTIFY_MCP_CONFIRM=never override. Annotations only note destructiveHint=true; the description carries everything else an agent needs to know before mutating.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences covering purpose, quota, safety default, and confirmation gate โ€“ front-loaded and free of padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a destructive mutation with no output schema, the description supplies the operational facts (cost, default, confirmation) that would otherwise be missing; nothing material is left unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so dry_run, playlist_id and response_format are already fully documented in the schema. The description reinforces the dry_run default/commit behavior but adds no syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (remove), resource (Liked Songs), and scope (tracks that also appear in a given playlist), which cleanly distinguishes it from siblings like remove_from_library and remove_from_playlist.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The preview-by-default and the conditions that trigger elicitation (10+ tracks) are explicit, and the dry_run commit path is named. It does not, however, route the agent to a sibling alternative for related operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_from_playlistB
Destructive

Remove tracks or episodes from a playlist. Max 100 entries per call.

ParametersJSON Schema
NameRequiredDescriptionDefault
urisYesURIs to remove; use { uri, positions } to target specific occurrences of a repeated URI
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID
snapshot_idNoApply the removal against this playlist version instead of the latest

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The destructiveHint annotation already carries the safety profile, lowering the bar. The description adds the tracks/episodes scope and the per-call volume cap, but the cap duplicates the schema's maxItems: 100 and it discloses nothing about dry_run, snapshot preconditions, or undo availability.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, action first, no filler. The second sentence repeats a schema constraint, which is mild redundancy rather than bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Adequate minimum: a destructive mutation whose parameters are fully documented by the schema and whose safety profile is covered by annotations, with no output schema needed. It stops short of useful operational context such as snapshot conflict behavior or recovery paths.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters (including the uri/positions targeting form and dry_run) are already explained. The description only restates the 100-entry ceiling, adding no semantics beyond the schema; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (remove) plus resource (tracks or episodes from a playlist), and it correctly notes both content types. It does not distinguish itself from adjacent siblings such as remove_duplicate_playlist_items or playlist_subtract, so it is clear but undifferentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use, when-not-to-use, or alternative routing is given. The description never tells the agent why it would pick this over remove_duplicate_playlist_items, playlist_subtract, or batch_add_to_playlist, leaving selection entirely to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reorder_playlist_itemsA

Move a range of items within a playlist. Spotify semantics: when insert_before > range_start, the effective destination shifts down by range_length because the moved range is lifted out first (e.g. moving [2] to insert_before=4 lands it AT index 3).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID
range_startYesIndex of the first item to move. 0-based index into the playlist's current item order (0 = the first item).
range_lengthNoNumber of items to move. Default: 1
insert_beforeYesIndex to insert the range before. 0-based index into the playlist's current item order (0 = the first item).

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries the rest, and it earns its keep by disclosing the non-obvious Spotify index-shift semantics ('when insert_before > range_start, the effective destination shifts down by range_length'), with a concrete example. That is real behavioral context beyond the annotations, though it omits side effects like snapshot changes or auth requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, action front-loaded, followed by the one piece of tricky semantics and a compact illustrative example. No filler, no repetition of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-output-schema mutation tool with full schema coverage and a destructiveHint=false annotation, the description supplies the key gotcha an agent needs to call it correctly (index shifting), plus the existence of a dry_run parameter is visible in the schema. Missing only peripheral details like confirmation/snapshot behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: it explains the conditional interaction between insert_before and range_start, clarifying what each index value actually does to the resulting order. This is parameter-level semantics beyond the field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource scoped to a single playlist ('Move a range of items within a playlist'), which implicitly separates it from cross-playlist siblings like move_items_between_playlists. It does not, however, name any sibling explicitly (e.g. playlist_sort, playlist_reverse), so an agent must infer the boundary itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the phrase 'within a playlist' hints at the in-playlist scope, but there is no explicit when-to-use, when-not-to-use, or named alternative such as playlist_sort or move_items_between_playlists. An agent gets the context but no routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

replace_playlist_itemsA
Destructive

Replace ALL items in a playlist with the supplied URIs, overwriting the current contents. Lists longer than 100 URIs are sent in chunks internally (replace + appends).

ParametersJSON Schema
NameRequiredDescriptionDefault
urisYesComplete ordered list of track or episode URIs the playlist should contain
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations include destructiveHint=true, which already signals the destructive nature. The description adds valuable behavioral context beyond that: it explicitly states that current contents are overwritten, and it discloses the internal chunking behavior for lists longer than 100 URIs. This is exactly the kind of behavioral detail that helps an agent understand side effects and limits. It doesn't mention reversibility or permissions, but the destructive annotation plus the overwrite statement cover the critical risk.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler. The first sentence states the core operation and its destructive effect. The second sentence adds the important chunking behavior. Every word earns its place, and the most critical information (replace + overwrite) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with no output schema, the description covers the essential operational facts: what it does, what it overwrites, and how it handles large inputs. The dry_run parameter is documented in the schema. The only minor gap is that it doesn't state what the response/return value is, but with no output schema and a clear operation, this is a small omission. The description is complete enough for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters. The description adds the crucial semantic that the uris array is the complete replacement set, not an incremental addition, and that the order is preserved. This adds meaning beyond the schema's 'Complete ordered list' phrasing, but the schema already carries most of the parameter documentation burden. The dry_run parameter is self-explanatory in the schema and the description doesn't add to it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Replace'), a specific resource ('ALL items in a playlist'), and the exact effect ('overwriting the current contents'). It also distinguishes itself from related playlist mutation tools by emphasizing the full-replacement semantics, which is the key differentiator among siblings like add_to_playlist, remove_from_playlist, reorder_playlist_items, and batch_add_to_playlist.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies when to use this tool: when the caller wants the playlist to contain exactly the supplied URIs and nothing else. It doesn't explicitly name alternatives or state when not to use it, but the 'Replace ALL items' phrasing makes the usage context unambiguous. It also explains the internal chunking behavior for long lists, which helps the agent understand that large inputs are handled automatically.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

restore_library_snapshotA

STRICTLY ADDITIVE restore of a library snapshot written by backup_library (see list_backups). 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 deleted, renamed, or overwritten. Truncated snapshots are previewable but refused before confirmation or writes; quota-hit, contentless or wrong-schema_version snapshots are refused outright. Prompt and result state where the stored data came from, the date the FILE declares (naming the reason when absent โ€” never the mtime), the item count, and the single use made of it; dry_run defaults to TRUE (read-only preview); setting dry_run=false requires explicit confirmation before any write, fails closed when elicitation is unavailable or errors, and allows writes when SPOTIFY_MCP_CONFIRM=never.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoDEFAULT true: read-only preview of exactly what would be added. Set false to perform the (additive) writes after explicit confirmation.
categoriesNoWhich snapshot categories to restore. Default: all
backup_pathYesSnapshot JSON path from backup_library (see list_backups)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description carries the real behavioral burden and does so richly: additive-only semantics, that existing playlists are never touched and nothing is deleted/renamed/overwritten, the 'Restored ยท <name>' naming rule, the refusal conditions, and the full dry_run/confirmation flow including the SPOTIFY_MCP_CONFIRM=never escape hatch and fail-closed elicitation. This far exceeds what the annotation conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The critical constraint ('STRICTLY ADDITIVE') is front-loaded and nearly every clause earns its place given the tool's complexity. It is, however, a single dense block with long run-on sentences, which slightly hurts scannability for an agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema and a guarded confirmation flow, the description covers everything needed to invoke it correctly: provenance, refusal preconditions, default-preview behavior, confirmation requirements, and env-var overrides. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; dry_run, categories, max_results and response_format are already documented in the schema. The description adds meaning beyond it by explaining that dry_run=false triggers explicit confirmation and fails closed, tying the parameter to an operational contract rather than restating its default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a precise verb+resource ('STRICTLY ADDITIVE restore of a library snapshot') and immediately ties its provenance to backup_library (see list_backups), which no sibling can be confused with. The additive scope is stated unambiguously, setting it apart from copy_playlist, import_profile_state and other write siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly establishes when to use it (restoring what a backup_library snapshot is missing) and states the alternatives for locating snapshots (list_backups). It also sets out when restore is refused (truncated, quota-hit, contentless, wrong schema_version). It stops short of explicitly contrasting with adjacent import tools like import_profile_state or library_snapshot_diff.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
archive_nameNoArchive playlist name (created if missing, overwritten if present)Discover Weekly Archive
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.6/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description transparently details resolution order, fallback to unverified search, dry_run behavior, idempotence, and result shape. However, it directly contradicts the annotation destructiveHint=false by saying it 'creates or overwrites the archive' and by describing overwriting as expected behavior, which is a destructive operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, each carrying distinct information: purpose, resolution/idempotence, and result. The most important action is front-loaded, and there is no filler or repetition of schema fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the key invocation concerns: what it does, how it resolves the source playlist, fallback behavior, dry-run option, idempotence, and output identity. It does not state failure behavior if resolution/search finds nothing or mention permission requirements, but those are minor gaps for a tool with no required parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the description does not need to re-document the parameters; baseline 3 applies. It adds some useful cross-context behavior such as idempotence and dry_run, but no additional per-parameter semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action and resource: 'Archive your Discover Weekly into a regular playlist (creates or overwrites the archive).' This clearly distinguishes it from the large sibling set because no other tool targets the Discover Weekly archival use case. The behavior is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to invoke the tool: to create or update the Discover Weekly archive, with dry_run for previewing and idempotence when the archive already matches. It does not explicitly name alternative tools or list situations where another sibling should be used, so it misses the top score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
archive_nameNoArchive playlist name (created if missing, overwritten if present)Release Radar Archive
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (only destructiveHint=false), the description richly discloses behavior: resolution via exact match then fallback to unverified search, dry_run preview behavior, idempotency when the archive already matches, and output echoing source identity. These are meaningful operational details an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but efficient: the primary purpose is front-loaded, and each subsequent sentence contributes a distinct behavioral fact. No filler or redundant restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the moderate complexity, full schema coverage, and lack of an output schema, the description covers the critical aspects: what happens, safety behavior via dry_run, idempotency, resolution logic, and the result format. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents dry_run, archive_name, and response_format. The description adds no new parameter-specific meaning beyond what the schema already provides, landing at the baseline score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Archive your Release Radar into a regular playlist (creates or overwrites the archive).' It clearly differentiates this tool from similar siblings by naming the exact source playlist and the archive action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the usage context: use this to archive Release Radar into a playlist. However, it does not explicitly say when to prefer this over related alternatives like save_discover_weekly, nor does it mention any when-not-to-use conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_sceneA

Save a named playback scene (device + volume + shuffle/repeat + optional context) to the local sidecar (~/.spotify-mcp/scenes.json)

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesScene name (key in the sidecar)
repeatNoRepeat mode: 'off' | 'track' | 'context'
volumeNoMaster volume percent (0โ€“100)
shuffleNoShuffle state
context_uriNoContext URI to start on apply (e.g. spotify:playlist:โ€ฆ)
device_hintNoDevice name substring (case-insensitive) or exact device id
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotation only declares destructiveHint=false. The description adds useful behavioral context by naming the exact persistence location (~/.spotify-mcp/scenes.json) and the captured playback fields. However, it does not disclose whether saving a scene with an existing name overwrites it, which is important for a persistent sidecar write operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence that packs the verb, resource, captured fields, and sidecar path with no filler. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is adequate for a moderately simple configuration-capture tool: it names the storage location and the scope of what is saved. However, it does not mention overwrite behavior, whether the scene is applied immediately, or any relationship to apply_scene, and there is no output schema to clarify return values. These gaps are notable but not crippling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all seven parameters. The description adds a high-level framing of what a scene bundles (device, volume, shuffle/repeat, optional context) but provides no parameter-level detail beyond what the schema already states. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Save') and a concrete resource ('named playback scene') while enumerating exactly what the scene consists of (device + volume + shuffle/repeat + optional context) and where it is persisted (local sidecar path). This clearly distinguishes it from sibling tools like apply_scene, list_scenes, and delete_scene.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states what the tool does but provides no explicit guidance on when to use it versus related siblings such as apply_scene, delete_scene, or list_scenes. The usage context is implied by the name and siblings, but there is no 'when to use' or 'when not to use' statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_to_libraryA

Preferred. Accepts the widest URI mix (track, album, episode, show, audiobook, user, playlist) in one request. Save one or more items to the user's library via Spotify's unified library endpoint. Max 40. PREVIEWS BY DEFAULT โ€” pass dry_run=false to commit.

ParametersJSON Schema
NameRequiredDescriptionDefault
urisYesSpotify URIs to save (e.g. ["spotify:track:abc", "spotify:user:xyz"])
dry_runNoPreview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries the real behavioral load. It discloses the critical dry-run/preview default ('PREVIEWS BY DEFAULT โ€” pass dry_run=false to commit'), which an agent would otherwise get wrong, plus the hard 40-item cap โ€” genuine value beyond the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short clauses, front-loaded with the differentiator ('Preferred') and the commit behavior. Every sentence contributes and nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does note that a preview returns a PLAN and that response_format controls output shape, which covers the main return-value concern. It stops short of describing error behavior or partial-failure handling, a minor gap for a batch mutation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters are already documented in the schema, including the dry_run preview semantics and the maxItems cap. The description restates the 40 limit and preview behavior but adds no syntax, format, or edge-case detail beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Save one or more items to the user's library'), names the underlying endpoint, and explicitly enumerates the accepted URI types. The 'Preferred' framing plus the URI-mix claim clearly distinguishes it from siblings such as remove_from_library and add_to_playlist.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Signals this is the preferred path for library saves and that it consolidates mixed URI types in one request, which routes the agent here over narrower alternatives. However, it never names the alternatives it is preferred over (e.g. add_to_playlist) or states when-not to use it, so the guidance is strong but not fully explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

schedule_wind_downA

Preview or start a volume wind-down: absolute-minute volume steps, then pause. Set dry_run to preview without replacing or cancelling an active timer.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
minutesYesTotal ramp duration in minutes (1โ€“180)
device_idNoTarget device id; defaults to the active device
floor_volumeNoVolume floor the ramp never goes below (default 10)
step_minutesNoMinutes between volume steps (default 5)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations supply only destructiveHint=false, so the description carries most of the burden and does so: it discloses that a non-preview run 'replac[es] or cancell[s] an active timer' and that the ramp terminates by pausing playback. These are consequential side effects an agent couldn't infer from the schema. It doesn't say whether the wind-down persists across sessions or what happens if minutes exceeds the remaining playback time.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the primary action and the ramp mechanism front-loaded, then the dry_run caveat. Nothing is redundant with the schema text. Slightly denser than needed but every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter mutation tool with no output schema and near-empty annotations, the description covers the essentials: what it changes, how to preview safely, and the effect on an active timer. Missing only edge-case behavior (persistence, interaction with cancel_wind_down), which keeps it from 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% (every parameter is documented, including defaults and ranges), so the baseline is 3. The phrase 'absolute-minute volume steps' adds a small interpretive cue about how minutes/step_minutes are measured, but no syntax or constraint detail beyond what the schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Preview or start a volume wind-down') plus the mechanism ('absolute-minute volume steps, then pause'), so an agent knows exactly what the tool does. It stops short of naming its siblings (wind_down_status, cancel_wind_down), so differentiation is implied rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence gives real conditional guidance: pass dry_run=true to preview, and warns that a real run replaces or cancels an active timer. That condition โ€” interaction with an already-active timer โ€” is the main selection risk, and it's stated. It doesn't explicitly route to cancel_wind_down or wind_down_status, so it's not a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_deepA
Read-onlyIdempotent

Paged catalog search that walks past the API limit of 10 results per type. Fetches up to 5 pages of 10 results per requested type server-side from a caller-supplied offset, dedupes by id, and returns compact rows. Type walks overlap (width: SPOTIFY_MCP_MAX_CONCURRENCY, else SPOTIFY_MCP_FANOUT_CONCURRENCY, else 4); same request count. Decision guide: use search_deep when you need >10 results/type or a later window; otherwise use search (single page), search_fresh (new releases), search_by_isrc (ISRC-exact), whats_new (personal follows).

ParametersJSON Schema
NameRequiredDescriptionDefault
pagesNoPages of 10 results to walk per type, 1โ€“5. Default: 1
queryYesSearch query
typesNoContent types to search. Default: ["track"]
marketNoISO 3166-1 alpha-2 country code, e.g. 'US'
offsetNoIndex of the first result to walk per type, 0โ€“1000. The next_offset a call reports is the offset to pass here to continue. Default: 0
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already mark it as read-only and idempotent, but the description goes further by disclosing server-side paging, deduplication by id, compact rows, overlap behavior, and continuation via offset. It adds substantial behavioral context beyond the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loads the purpose and then moves into mechanics and the decision guide. It is longer than average, but nearly every clause conveys useful operational or routing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex paged search tool with full parameter schema coverage and no output schema, it covers the critical missing pieces: pagination continuation, result-window behavior, and sibling routing. It does not detail return shape beyond compact rows, but the schema carries the parameter burden well.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents each parameter, including offset continuation and page limits. The description reinforces paging and offset semantics but does not add much parameter-level meaning beyond what the schema provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: paged catalog search that walks past the API limit of 10 results per type. It also explicitly distinguishes itself from close siblings such as search, search_fresh, search_by_isrc, and whats_new in the decision guide.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit when-to-use rule: use search_deep when you need more than 10 results per type or a later window. It then names each alternative and its purpose, leaving no inference needed about tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_history_statsB
Read-onlyIdempotent

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

ParametersJSON Schema
NameRequiredDescriptionDefault
top_nNoTop N queries to show (default 10)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the operation's safety profile is covered. The description adds one genuinely new behavioral fact (local-only, no API quota consumption), which is valuable, but says nothing about result format or size bounds beyond the categories listed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight clauses with zero filler, and the core purpose is front-loaded ahead of the quota note. Slightly clipped to the point of leaving the 'sidecar' concept unexplained.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only stats tool with full schema coverage and no output schema, the description is adequate but thin: it never explains what the 'sidecar' is or how recency is defined, so an agent lacks full grounding on the returned data.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters (top_n, response_format) are fully documented with defaults and enum semantics in the schema. The description adds no parameter-level detail, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('analytics over') and resource ('the local search-history sidecar'), then enumerates the three outputs it produces: top queries, type breakdown, recency. This clearly separates it from the search siblings like history_search, though it never names that alternative directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not-to-use guidance is given. The 'Quota: local only (no API)' note is useful context but does not tell the agent when to pick this over history_search or following_analytics.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_saved_albumsA
Read-onlyIdempotent

Search saved albums (client-side filter over bounded walk). Quota: GET /me/albums paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoSubstring match against album name/artist
artistNoSubstring match against album artist
scan_capNoMax albums to scan (default fetchAllCap)
added_afterNoISO date โ€” only albums added after this
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered; the description adds the non-obvious behavior that filtering happens client-side over a paged walk and notes the quota (GET /me/albums paged), which explains why scan_cap exists. It does not describe pagination limits or return shape, but the added context is genuinely useful.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact clauses with no waste and the core mechanism front-loaded. It is arguably a fragment rather than prose, but nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter read-only search with full schema coverage and annotations, the description supplies the key missing behavioral fact (client-side filtering over a bounded walk) and the endpoint quota. Only explicit sibling routing guidance is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema documents all six parameters including defaults for scan_cap and max_results. The description only obliquely supports scan_cap via 'bounded walk' and adds no syntax or format detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (search saved albums) and clarifies the mechanism (client-side filter over a bounded walk), which meaningfully separates it from get_saved_albums and search_saved_tracks/shows. It stops short of naming those siblings directly, so it is clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical 'client-side filter over bounded walk' implies this is for filtered lookup rather than full enumeration, but there is no explicit when-to-use or when-not-to-use statement versus the many sibling search_* and get_saved_* tools. Usage must be inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_saved_audiobooksA
Read-onlyIdempotent

Search saved audiobooks (bounded walk + client-side filter). Quota: GET /me/audiobooks paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoSubstring against audiobook name/author
scan_capNoMaximum saved items to scan; defaults to SPOTIFY_MCP_FETCH_ALL_CAP
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With readOnlyHint/idempotentHint already covering the safety profile, the description usefully adds that scanning is bounded and filtering is client-side, plus the underlying quota constraint ('GET /me/audiobooks paged'). This tells the agent that scan_cap governs coverage and that the operation is quota-sensitive โ€” real context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two terse sentences, fully front-loaded, with zero filler. The core purpose leads and the operational note follows.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-param, fully-documented search tool with no output schema, the description is nearly sufficient: it explains the scan-and-filter model and the quota constraint. It doesn't state the return shape, but response_format in the schema covers that, leaving only a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents query, scan_cap, max_results, and response_format. The description's 'bounded walk' loosely reinforces scan_cap semantics but adds no format, syntax, or default details beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Search saved audiobooks') and the parenthetical clarifies the mechanism (bounded walk + client-side filter). It is clearly distinguishable from siblings like search_saved_tracks or search_saved_albums, though the differentiation rests on the media noun rather than explicit contrast in the text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the name and resource type โ€” an agent can infer it searches the user's saved audiobook library. However, there is no explicit when-to-use vs when-not guidance, no mention of alternatives for other media types, and no stated prerequisites (e.g. scope requirements).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_saved_episodesB
Read-onlyIdempotent

Search saved episodes (bounded walk + client-side filter). Quota: GET /me/episodes paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
showNoSubstring against show name
queryNoSubstring against episode/show name
scan_capNoMaximum saved items to scan; defaults to SPOTIFY_MCP_FETCH_ALL_CAP
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered. The description adds genuine behavior context (bounded walk, quota against GET /me/episodes, client-side filter), but omits what happens when scan_cap is hit, whether results are truncated silently, and pagination behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded sentences with no filler; the mechanism detail leads and the quota note follows. The fragment 'Quota: GET /me/episodes paged.' is a bit clipped and would read better as a full clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Five optional params are fully schema-documented and there is no output schema to explain, so the basics are covered. However, for a search tool in a dense sibling cluster, the description leaves unresolved how it differs from get_saved_episodes and what a truncated or capped scan means for the caller.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all five parameters are already documented, including the response_format enum and the env-var defaults. The description adds no syntax or format detail beyond the schema, and the mention of client-side filtering only loosely maps to scan_cap/max_results.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (search) plus resource (saved episodes), and it adds real mechanism detail: a bounded walk with client-side filtering. It never names or contrasts the obvious siblings (get_saved_episodes, search_saved_shows), so the agent must infer the split between retrieving all vs. searching.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No statement of when to use this over get_saved_episodes or search_saved_shows, and no exclusions or preconditions. The only implied guidance comes from the word 'Search' itself, which is not enough to route between the many *_saved_*/search_* siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_saved_showsA
Read-onlyIdempotent

Search saved podcast shows (bounded walk + client-side filter). Quota: GET /me/shows paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoSubstring match against show name and publisher. Spotify removed `publisher` from show payloads in February 2026, so the publisher half can only match on an app registration created before November 2024; on a current registration this is a name search that reports 0 publisher matches rather than pretending to have searched publishers.
scan_capNoMaximum saved items to scan; defaults to SPOTIFY_MCP_FETCH_ALL_CAP
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover readOnly and idempotent, and the description adds behavior beyond them: the search is a bounded walk with client-side filtering (implies pagination/scan cost) and it is subject to a paged GET /me/shows quota. It does not state the scan default or what happens when scan_cap is exceeded, but the mechanism disclosure is genuinely useful.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with zero filler; the what and the how are front-loaded, and the quota caveat follows. Nothing is redundant with the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only search tool with no output schema, the definition supplies purpose, mechanism, and quota context. It leaves the scan/return-volume semantics and any ordering of results implicit, but the essentials for correct invocation are present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema's query parameter description is notably rich (substring match target, publisher-removal caveat). The description adds no parameter-level detail of its own, so the baseline 3 applies since the schema carries the load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Search saved podcast shows') with a scoping distinction that separates it from get_saved_shows (unfiltered listing) and from search_saved_episodes/albums/audiobooks (different media type). The parenthetical '(bounded walk + client-side filter)' further pins down what kind of search this is.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'client-side filter' implies the tool walks saved items locally rather than querying server-side, and the quota note ('GET /me/shows paged') hints at call cost, which indirectly signals when to prefer cheaper alternatives. However, no explicit when-to-use or when-not-to-use guidance or named alternative is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_saved_tracksA
Read-onlyIdempotent

Search your Liked Songs (saved tracks) by text query and optional facets โ€” client-side filter over a bounded walk of /me/tracks. For catalog-wide search use search. Reports walk truncation.

ParametersJSON Schema
NameRequiredDescriptionDefault
albumNoFilter to tracks where album name contains this substring
limitNoMax results to return
queryNoSubstring to match against track name, artist name, or album name (case-insensitive). Omit to list by facets/sort only.
artistNoFilter to tracks where any artist name contains this substring
sort_byNoSort orderadded_desc
max_itemsNoHow many saved tracks to walk (default SPOTIFY_MCP_FETCH_ALL_CAP)
added_afterNoISO date โ€” only tracks added after this date
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
added_beforeNoISO date โ€” only tracks added before this date
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile. The description adds genuinely useful behavioral context beyond those: it discloses that filtering happens client-side over a bounded walk of /me/tracks and that walk truncation is reported. This tells the agent results may be incomplete for large libraries and that this condition is signaled โ€” a meaningful operational caveat the annotations do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero waste. The core purpose is front-loaded, the client-side/bounded-walk mechanism is stated in the same breath, and the sibling disambiguation and truncation disclosure round it out. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with no output schema, the description covers the essentials: scope, mechanism, boundary condition (bounded walk), the truncation signal, and the main alternative. The response_format enum in the schema partially compensates for the missing output schema. Minor gaps: the relationship between limit and max_results is not explained in the description, and there is no guidance on how truncation affects trustworthiness of results beyond being reported.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 10 parameters โ€” baseline 3 is appropriate. The description adds a small amount of conceptual glue by framing the operation as 'text query and optional facets' and explaining the bounded-walk model, which clarifies why both max_items (walk cap) and max_results/limit (result caps) exist. But it does not go beyond the schema on parameter-level detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Search your Liked Songs (saved tracks)'), names the mechanism ('client-side filter over a bounded walk of /me/tracks'), and distinguishes itself from the catalog-wide sibling ('For catalog-wide search use search'). An agent can immediately tell this from search, search_tracks, get_saved_tracks, and the other saved-search tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the key alternative and the condition that selects it: 'For catalog-wide search use search.' This resolves the highest-risk confusion. It does not enumerate exclusions for adjacent siblings like get_saved_tracks (plain list vs. filtered search) or search_saved_albums, but the scope is clear enough from the first sentence that an agent will infer when this tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_within_playlistA
Read-onlyIdempotent

Text search inside a single playlist: a client-side filter over the rows the walk read, cheaper than paging get_playlist_items yourself for a narrow query โ€” but it can only see that window, so scanned_items/scan_cap/scan_truncated say how much of the playlist was actually read. Matches item name, artist, album and show name; kind narrows a mixed playlist to tracks only or episodes only. Quota: GET /playlists/{id}/items paged.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlias for playlist_id, matching get_playlist_items
kindNoItem kinds to match: 'track', 'episode', or 'any' (default โ€” both). Mixed playlists hold both row shapesany
queryYesSubstring to match against track/episode name, artist, album, show name
marketNoMarket for track relinking, e.g. 'US'
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
playlist_idNoPlaylist ID (or pass it as 'id')
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say readOnly/idempotent; the description goes well beyond by disclosing that the search is client-side over a partial walk, that results depend on that window, which fields report coverage (scanned_items/scan_cap/scan_truncated), and the underlying quota cost.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the alternative-tool comparison are front-loaded in the first clause, and every clause carries information; the single dense sentence with multiple em-dash asides is slightly heavy but not padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully names the scan-status fields an agent should inspect, and covers matching scope, kind filtering and quota; it is nearly complete, though it leaves market/response_format semantics entirely to the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description restates the match fields and kind semantics that the schema already documents, adding little parameter syntax or formatting detail beyond what is given there.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Text search inside a single playlist') plus the mechanism ('client-side filter over the rows the walk read'), which is enough to distinguish it from get_playlist_items and from the library-wide search siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames the use case against a named alternative ('cheaper than paging get_playlist_items yourself for a narrow query') and warns of the scan-window limitation, but it never states when NOT to use it (e.g. when a full or cross-playlist search is needed, point to search_deep/search).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

seekB

Seek to a position in the current track

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
position_msYesPosition in milliseconds
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, leaving the description to carry behavioral disclosure. It does not say whether seeking requires an active track, whether it affects the current device, how it behaves without playback, or what the dry_run preview returns โ€” none of which the terse sentence covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler; the action and target are stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter playback tool with no output schema, the definition is minimally viable but omits session prerequisites and device targeting behavior. The schema covers the parameters, but nothing explains runtime behavior an agent would want before invoking it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so position_ms, device_id, dry_run, and response_format are already documented in the schema. The description adds no extra meaning such as units, clamping behavior, or bounds beyond what the schema provides, making the baseline 3 correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (seek) and resource (position in the current track), which is unambiguous and distinct from siblings like play, pause, or skip_next. It stops short of naming an alternative or clarifying scope such as active device or track requirement, but the core action is clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No indication of when to use this versus play, play_from_search, or skip tools, nor any prerequisite such as an active playback session. Usage is only implied by the verb itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_repeatB

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

ParametersJSON Schema
NameRequiredDescriptionDefault
stateYesRepeat mode
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The only annotation is destructiveHint=false, so the description carries most of the behavioral burden. It does not disclose whether the change is immediate, whether it requires an active playback context, what happens on invalid devices, or what dry_run does. It lists the mode values but adds little behavioral context beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence that states the operation and immediately enumerates its values. Every word earns its place, and there is no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple state-setting tool with a fully described schema and no output schema. The description adequately conveys the operation and the meaning of the required enum values. It does not cover when to use it or the purpose of optional parameters like dry_run, but those gaps are minor for such a low-complexity tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaningful semantics for the state enum by explaining that 'context' repeats a playlist/album and 'track' repeats a single track, which goes beyond the schema's terse 'Repeat mode' label. The other parameters are left to the schema, which is acceptable given full coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Set repeat mode.' It also lists the three possible modes, making the operation unambiguous. However, it does not explicitly distinguish this tool from the sibling set_shuffle, which controls a related but different playback setting.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers no guidance about when to use this tool versus alternatives. It does not mention set_shuffle or any other sibling, nor does it state prerequisites such as an active playback session or device targeting. The agent must infer usage entirely from the tool name and schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_shuffleC

Enable or disable shuffle mode

ParametersJSON Schema
NameRequiredDescriptionDefault
stateYestrue = shuffle on, false = shuffle off
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations supply only destructiveHint=false, so the description carries the full burden of behavioral disclosure and does not meet it. It never says whether the change is session-only or persisted, whether it requires an active playback context, or how device targeting interacts with the setting.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short clause with the action front-loaded and zero filler. It is efficient, though the terseness contributes to the informational gaps noted elsewhere.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with no output schema, the schema and annotations cover parameters and the non-destructive hint, leaving the definition minimally adequate. Missing scope/persistence behavior and sibling differentiation keep it from being complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and each parameter (state, dry_run, device_id, response_format) is well documented in the schema itself. The description adds no parameter meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair ('Enable or disable') and resource ('shuffle mode'), so the agent knows exactly what it does. It does not distinguish itself from the sibling 'playlist_shuffle', which is a plausible confusion point given both deal with shuffling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this versus set_repeat, playlist_shuffle, or a playback-state tool, and no prerequisites stated. The agent must infer context entirely.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_volumeA

Set playback volume on one device, on a selection of devices, or across every live device. volume_percent sets an absolute level; delta_step nudges the current level by a signed step. op picks the variant: "mute" drops to 0 and remembers the level, "unmute" restores what mute remembered, "preset" applies the per-device presets stored by set_device_volume_preset, and "level" with no volume_percent copies the active device's level to the others. Quota: 1 write for a single device; 1 read + N writes when fanning out.

ParametersJSON Schema
NameRequiredDescriptionDefault
opNoVariant: "level" (default) set or copy a level, "mute", "unmute", "preset"
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoDevice ID for a single-device write (default: the active device)
delta_stepNoSigned nudge, e.g. +10 or -10, clamped to 0โ€“100. Mutually exclusive with volume_percent.
device_idsNoFor op "level" with volume_percent: fan out to these device ids or names. Mutually exclusive with all_devices.
all_devicesNoFor op "level" with volume_percent: set every volume-capable device, not a named selection.
volume_percentNoAbsolute level 0โ€“100. Mutually exclusive with delta_step.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
exclude_device_idNoFor op "level" with no volume_percent: leave this device untouched while levelling the rest

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=false in annotations, the description carries the behavioral load well: it discloses that mute remembers the prior level and unmute restores it, that level with no volume_percent copies the active device's level to others, and it states the quota cost (1 write single; 1 read + N writes fanning out). That is substantive context the annotations do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: the target scope is front-loaded, then the two level-setting modes, then op variants, then quota. No repetition of what the schema already states verbatim, and it is compact despite covering nine parameters.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a nine-parameter, no-output-schema mutation tool with thin annotations, the description covers target scope, the mode selection (absolute vs delta), each op's semantics, dry_run preview, and quota cost. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema by explaining op interactions (what 'preset' and 'level' actually do) and how volume_percent, delta_step, device_ids, all_devices and exclude_device_id combine. This is more than the schema conveys on its own.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (set) and resource (playback volume) and immediately scopes the target space: one device, a selection, or every live device. It also names the related sibling set_device_volume_preset, so an agent can distinguish preset-applying from preset-storing without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance per op variant (mute/unmute/preset/level) and clarifies the volume_percent vs delta_step choice. It references set_device_volume_preset as the tool that stores presets, implying the alternative, but stops short of an explicit 'use X instead when Y' rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

show_new_episodesA
Read-onlyIdempotent

Find new episodes across your saved podcast shows: reports episodes released within the lookback window (default 7 days), marking which are already saved in your episode library. Fetches /me/shows then each show's latest episodes, overlapping episode lookups (width: SPOTIFY_MCP_MAX_CONCURRENCY, else SPOTIFY_MCP_FANOUT_CONCURRENCY, else 4) so a 25-show scan is not 25 serial round trips. WARNING: M saved shows โ†’ M+1 requests (1 show page + M episode lookups). Use max_shows to budget and cost_preview to see the cost without making any calls. This tool is read-only: nothing is ever changed.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoLookback window in days. Default 7.
marketNoISO 3166-1 alpha-2 country code for the per-show episode lookups, e.g. "US". Defaults to SPOTIFY_MCP_MARKET, then to the account country โ€” these lookups are market-gated, so a wrong default silently drops episode rows.
max_showsNoPer-call budget for show episode lookups. Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET / SPOTIFY_MCP_SHOWRADAR_BUDGET). Scan caps at min(budget, SPOTIFY_MCP_FETCH_ALL_CAP) and reports truncation. WARNING: each lookup is an API request.
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
cost_previewNoCost preview only: make no API calls and return the request budget instead of the episode list. Use it to size a real call; it does not report any episodes. Default false.
per_show_limitNoHow many latest episodes to check per show for recency. Default 3.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only mark readOnly/idempotent, but the description discloses substantial behavior beyond them: concurrency resolution via SPOTIFY_MCP_MAX_CONCURRENCY/FANOUT_CONCURRENCY, the M saved shows โ†’ M+1 requests cost model, truncation reporting, and the warning that a wrong market default silently drops episode rows. This is exactly the operational context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose in the first clause, then layers cost model and warnings. Dense but every sentence carries information; the concurrency env-var detail is the only part bordering on excessive for a tool-selection description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter read-only tool with no output schema, the description covers purpose, cost, concurrency, market gating, and the saved-vs-new marking. It does not describe the returned structure (e.g., what the concise/detailed/json formats contain), a minor gap given response_format is exposed as a parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents each parameter and the baseline is 3. The description adds cross-parameter meaning the schema cannot: the max_shows โ†’ request-count relationship, cost_preview's 'no API calls, budget only' semantics, and the concurrency env fallback chain.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: finds new episodes across saved shows within a lookback window, marking which are already saved. Distinguishes itself from siblings like get_saved_shows and search_saved_episodes by describing a recency-scan rather than a library listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear use conditions (find episodes released within the lookback window) and routes the agent to cost_preview and max_shows for budgeting before spending requests. It does not explicitly name a sibling alternative (e.g., whats_new) or state when not to use it, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

skip_nextB

Skip to the next track in the queue or context.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Only annotation is destructiveHint=false, which is nearly uninformative for a playback control. The description adds that skipping occurs relative to queue or context, useful behavioral context, but omits what happens at the end of the queue, whether playback state must be active, and whether an active device is required.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no waste. Efficient, though it may be under-specified rather than truly concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a playback-control mutation adjacent to many stateful siblings (play, pause, seek, set_shuffle, get_queue), the description is thin. It lacks prerequisites (active playback, valid device) and edge-case behavior (end of queue), so an agent could misuse it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters (dry_run, device_id, response_format) are fully documented in the schema. The description adds no parameter detail, which is acceptable at full coverage but leaves no extra value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Skip to') and resource ('the next track in the queue or context'). An agent can distinguish it immediately from siblings like pause, seek, and play.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this vs. alternatives like play, seek, or skip_previous. The phrase 'queue or context' gestures faintly at playback-state behavior but doesn't explain prerequisites or the difference between skipping within a queue vs. a context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

skip_previousA

Skip to the previous track. If more than 3 seconds in, restarts the current track first.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoTarget device ID
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations only declare destructiveHint=false, while the description adds a key behavioral trait: playback restarts the current track when more than 3 seconds have elapsed. This is meaningful context beyond the annotation and helps the agent predict outcomes. It still does not cover authentication, rate limits, or device-state requirements, so it falls short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences, front-loaded with the primary action and followed by one important conditional behavior. Every sentence earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple playback-control tool with a fully documented schema and a non-destructive annotation, the description covers the essential purpose and the one non-obvious behavioral nuance. No output schema exists, and none is needed for this action. The definition is complete for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and all three parameters are documented in the input schema. The description adds no parameter-specific detail beyond what the schema already provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Skip to the previous track.' This clearly distinguishes the tool from sibling skip_next and from playback controls like play, pause, and seek. The added conditional restart behavior further specifies what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when the tool is useful by explaining that it restarts the current track if more than 3 seconds in. However, it does not explicitly compare this tool to alternatives like skip_next or seek, nor does it state when not to use it. Usage guidance is therefore implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

split_playlistB

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

ParametersJSON Schema
NameRequiredDescriptionDefault
partsYesNumber of parts (2โ€“10)
publicNoPublic flag for new playlists
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
name_prefixNoPrefix for new playlist names (default: source name)
playlist_idYesSource playlist ID

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description carries most of the behavioral burden. It usefully discloses the quota footprint (1 GET + N POST /me/playlists + N POST items) and that new playlists are created, but says nothing about whether the source playlist is left intact, what happens on partial failure, or how dry_run interacts with the quota.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two front-loaded sentences with no filler; the core operation comes first and the quota cost second. The '(new playlists)' parenthetical is slightly redundant but harmless, and the terse quota shorthand is efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With five parameters, no output schema, and minimal annotations, the description covers the operation and its cost but omits important context: whether the source playlist survives, ordering of items across chunks, and what a dry_run report actually returns. Adequate but with clear gaps for a mutation-style tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters including name_prefix defaults and the dry_run preview semantics. The description adds no syntax or behavioral nuance beyond what is in the schema, which is the expected baseline when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Split a playlist into N chunks') and immediately clarifies the output form ('new playlists'), which distinguishes it from siblings like merge_playlists, playlist_union, or playlist_trim. An agent can identify the operation without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no when-to-use guidance, prerequisites, or named alternatives among the many playlist-manipulation siblings (merge_playlists, playlist_trim, copy_playlist). The quota note hints at cost but does not say when splitting is the right choice over manual item manipulation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spotify_doctorA
Read-onlyIdempotent

Run read-only diagnostics: token presence/expiry, auth-time scopes vs write tools enabled by active toolsets, Premium gating, rate-limit cooldown, config state, visible account details when reachable, and the live registered-tool surface with toolset/scope/READONLY trim causes. The only live request is GET /me; no mutation requests are issued.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoInclude per-check technical detail lines when response_format is concise
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds real value beyond that by naming the specific checks performed and stating the network footprint ('The only live request is GET /me; no mutation requests are issued'), which tells the agent this cannot alter state. It stops short of describing cost, latency, or failure modes of the checks.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the verb and mode ('Run read-only diagnostics:') followed by a compact enumeration, then a closing sentence that bounds the network behavior. The enumerated list is long but each item is a distinct diagnostic, so it earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value explanation is not required, and the description covers scope, safety, and the one outbound call. The main gap is the absence of guidance on when to run it versus the other diagnostic/toolset siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters (verbose, response_format) are fully documented in the schema, including the enum semantics for response_format. The description adds nothing about how verbose or response_format interact, so the baseline 3 applies โ€” the schema carries the full burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('Run read-only diagnostics') followed by a concrete enumeration of what is checked: token expiry, scopes, Premium gating, cooldown, config, account, and registered-tool surface. An agent immediately knows this is an environment/health check rather than a data or playback tool. It does not explicitly distinguish itself from nearby diagnostic siblings like toolset_report, inspect_tool, or find_tool, which mention overlapping toolset/scope concerns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied ('diagnostics' suggests troubleshooting when auth, scopes, Premium, or rate limits are suspect), but there is no explicit when-to-use statement or 'use X instead' routing against toolset_report or inspect_tool. An agent must infer the trigger condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

start_podcast_sessionA

Plan a podcast session (see plan_podcast_session) and start it on a device. Limitation: Spotify cannot apply resume offsets when queueing โ€” only the first episode can start at its resume point (via PUT /me/player/play on its show context); later episodes are appended to the queue and play from the beginning. With dry_run, nothing is played or queued.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoRestrict the source: 'episodes' = your saved episodes only, 'shows' = recent episodes of your saved shows only. Omit to use saved episodes (plus saved shows when saved_only is false)
marketNoISO 3166-1 alpha-2 country code for the saved-show episode lookups, e.g. "US". Defaults to SPOTIFY_MCP_MARKET, then to the account country โ€” these lookups are market-gated, so a wrong default silently drops episode rows. Ignored for a saved-episodes-only plan.
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
minutesYesSession length in minutes (1โ€“480)
device_idNoTarget device ID; omit for the active device
saved_onlyNoWhen no kind is set, include recent episodes of saved shows too. Default: true (saved episodes only)
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations supply only destructiveHint=false, so the description carries most of the behavioral burden and does so well: it discloses a real, non-obvious constraint about Spotify resume offsets when queueing and clarifies that dry_run plays/queues nothing. It doesn't state whether starting a session interrupts current playback or whether a device must be active, which are relevant mutation side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the purpose, then the limitation, then the dry_run caveat. The limitation sentence is dense but each clause carries information an agent needs; nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter playback tool with full schema coverage and no output schema, the description covers purpose, sibling routing, a key platform limitation, and dry_run behavior. It omits what a session result looks like and any playback-interruption or device-state side effects, which are the remaining gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description's note that 'with dry_run, nothing is played or queued' restates the schema's dry_run description rather than adding new semantics, and no other parameter is elaborated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb+resource ('Plan a podcast session ... and start it on a device') and explicitly distinguishes itself from the sibling plan_podcast_session by the fact that it starts playback. An agent can tell the two apart without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It routes the agent to plan_podcast_session for planning-only and explains the dry_run mode as the no-playback path, giving clear context for when each behavior applies. It stops short of naming exclusions versus general playback tools like play or add_to_queue.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

switch_accountA
Destructive

Change which registered account this session acts as. Takes effect for every subsequent call in this session: the client re-points its token file, drops the previous account's cached reads and validators, and refuses to switch while a request is in flight. Asks for confirmation first, because every later write then lands in the new account's library. Changes local session state and the account registry only โ€” it issues no Spotify writes.

ParametersJSON Schema
NameRequiredDescriptionDefault
profileYesProfile name to act as โ€” the same value "--profile <name>" takes, or "default" for the account this server started as. The name must already have been authenticated with "spotify-mcp auth --profile <name>"; this tool does not run the auth flow.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavioral context beyond the annotations: it re-points the token file, drops the previous account's cached reads and validators, requests confirmation first, and refuses during in-flight requests. Critically, it resolves the ambiguity of destructiveHint=true by clarifying no Spotify writes are issued โ€” a genuinely valuable distinction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then layers effect, mechanics, and safety in dense, non-redundant sentences. It is on the longer side, but nearly every clause carries operational information an agent needs before switching accounts.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a session-state-mutating tool with no output schema, the description covers scope of effect, prerequisite auth state, cache invalidation, concurrency behavior, and confirmation handling. Nothing an agent needs to call it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both the profile parameter and its auth prerequisite, plus the response_format enum, are fully documented in the schema. The description adds no parameter-level syntax or constraints beyond that, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource โ€” 'Change which registered account this session acts as' โ€” and scopes it to the session, which cleanly separates it from list_accounts and other account-adjacent siblings. An agent can act on it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for when the tool applies (every subsequent call in the session, requires prior 'spotify-mcp auth --profile <name>') and a guard condition (refuses while a request is in flight). It stops short of naming an alternative sibling or an explicit 'don't use this when...' rule, so it lands at 4.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tag_managementA

Declare or retract genre tags for an artist in your local sidecar (~/.spotify-mcp/genre-tags.json), which library_genre_report and filter_by_genre consume. add requires at least one tag; remove drops the listed tags, or the artist entirely when none are listed. Supports dry_run preview.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoTags to add/remove; omit on remove to drop the artist entirely
actionYesadd tags to an artist, or remove tags/artist
artistYesArtist name exactly as it appears in your library
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the minimal destructiveHint annotation, the description discloses the exact sidecar file path, the persistence model, the consuming tools, the add/remove semantics, and the dry_run preview capability. It does not discuss irreversibility or edge cases like missing files, but it adds meaningful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no wasted words. The primary purpose and file location are front-loaded, followed by compact action semantics and dry-run mention. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of an output schema and minimal annotations, the description covers the essential context: what the tool does, where state lives, what consumes it, and how add/remove/dry_run behave. It omits details like whether the sidecar file is auto-created or whether tags are case-sensitive, but these are not critical for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds at least one meaningful constraint not visible in the schema: 'add requires at least one tag.' It also reinforces the distinction between removing listed tags and removing the artist entirely, adding context beyond bare parameter names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb and resource: declare or retract genre tags for an artist in a local sidecar file. It also names the consuming tools (library_genre_report and filter_by_genre), which distinguishes it from the many sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context by explaining that the tags feed library_genre_report and filter_by_genre, implying when an agent should use this tool. It also provides operational guidance (add requires at least one tag; remove can drop an artist entirely), though it does not explicitly contrast with alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
response_formatNo'concise' (default) = prose bullet list; 'detailed' = the same prose; 'json' = the result payload as parseable JSON text, identical to structuredContentconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry destructiveHint=false, so the description supplements it with the meaningful behavioral trait that this is an always-available discovery tool. A return schema exists, so return format need not be described. It stops short of explicitly confirming read-only, keeping it at 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the purpose, followed by availability context and the sibling pointer. There is no filler, and the framing question aids quick scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter, zero-required introspection tool with a full output schema and near-minimal annotations, the description covers purpose, availability, and alternatives adequately. An explicit read-only statement would complete it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single response_format parameter is fully documented in the schema, so the baseline of 3 applies. The description adds no format guidance beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Report the active toolsets and registration modules, plus the live registered tool count') and even frames it with a plain-language question it answers. It is clearly distinguishable from find_tool and inspect_tool, which it names.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives useful context ('Discovery set; always available') and points to the alternative tools find_tool / inspect_tool, but does not state explicitly when to reach for this report versus those siblings. Clear context with no exclusions, so a 4 rather than a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

transfer_playbackA

Move playback to a different Spotify Connect device, named by exact id, by the label you gave it, or by a case-insensitive name substring. A plain transfer restarts the track at 0:00 on the target; preserve_position: true carries the current track and play position across instead, and restore_shuffle_repeat: true re-applies the current shuffle and repeat modes on the target. Quota: 1 read to resolve the device, then 1โ€“4 writes depending on the flags.

ParametersJSON Schema
NameRequiredDescriptionDefault
playNoForce play (true) or arrive paused (false); omit to preserve the current play state. With preserve_position, true also resumes a session that is currently paused.
deviceYesTarget device: exact id, sidecar label, or case-insensitive name substring
volumeNoVolume to set on the target after transfer, 0โ€“100
dry_runNoPreview only: describe what would change without performing it. Default false โ€” pass true to preview.
device_idNoDEPRECATED: use `device`
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise
preserve_positionNoResume the current track at its current position on the target instead of restarting it (default: false)
restore_shuffle_repeatNoRe-apply the current shuffle and repeat modes on the target (default: false)

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=false, so the description carries real weight and delivers: it discloses that a plain transfer restarts the track at 0:00, that preserve_position carries position across, that shuffle/repeat can be re-applied, and gives an explicit write-quota cost (1 read + 1โ€“4 writes). This is exactly the behavior an agent needs before invoking a state-changing playback operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core action and then the flag semantics and cost. Every clause carries information an agent would otherwise have to guess; no filler or restatement of the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with no output schema, the description covers the risky aspects: track position, shuffle/repeat restoration, and operation cost. It omits any mention of dry_run previewing or the deprecated device_id alias, both of which an agent might want surfaced at the description level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds genuine value by describing the interplay between flags (e.g. preserve_position combined with play resumes a paused session) and by spelling out the three device-resolution modes. It does not, however, cover volume, dry_run, or the deprecated device_id, leaving those to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Move playback to a different Spotify Connect device') and immediately scopes how the target is identified. It is clearly distinguishable from siblings like play, pause, seek, and set_volume, which operate on the current session rather than relocating it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the behavioral variants (plain transfer vs preserve_position vs restore_shuffle_repeat), which implies when each flag is appropriate, but it never explicitly names an alternative tool or a when-not condition. An agent must infer the choice of flags rather than being routed to them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

undo_last_mutationA
Destructive

Undo the most recent reversible mutation (receipt FIFO). Same inversion semantics as undo_mutation: add/save โ†’ remove, removal โ†’ re-add. Executing needs confirmation and is refused when the client cannot prompt (SPOTIFY_MCP_CONFIRM=never bypasses).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only, and the default: pass dry_run: false to execute the rollback.
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructiveHint=true, yet the description adds substantial behavioral context: confirmation is required to execute, execution is refused when the client can't prompt, SPOTIFY_MCP_CONFIRM=never bypasses that gate, and the exact inversion mapping (add/save โ†’ remove, removal โ†’ re-add). This is exactly the beyond-annotation disclosure a destructive tool needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three front-loaded sentences, no filler: purpose and ordering first, semantic equivalence second, execution gating third. Every clause carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and only destructiveHint in annotations, the description carries the full burden and meets it: it covers ordering, inversion semantics, and the confirmation/refusal behavior that determines whether the call can even succeed. Nothing material is left for the agent to guess.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% (both dry_run and response_format are fully documented, including the default of dry_run=true). The description adds no parameter-level syntax or format information, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Undo the most recent reversible mutation') and pins the scope with 'receipt FIFO'. It explicitly names the sibling undo_mutation as the related-but-different operation, so an agent can route between them without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The FIFO scope makes the selection condition clear: use this for the latest mutation, and it alludes to undo_mutation for targeted rollback via 'Same inversion semantics as undo_mutation'. It stops short of an explicit 'use undo_mutation instead when you know the receipt id' sentence, so no exclusion list, but the context is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

undo_mutationA
Destructive

Undo a specific mutation by receipt ID. Inverts the recorded direction: an add/save is undone by removing, a removal by re-adding (playlist items or library). A playlist add undo removes only the rows it created, refusing when no row positions are recorded. The result reflects the refetched post-state. Non-reversible kinds return not reversible. Executing needs confirmation and is refused when the client cannot prompt (SPOTIFY_MCP_CONFIRM=never bypasses).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only, and the default: pass dry_run: false to execute the rollback.
receipt_idYesReceipt ID to undo
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations carry only destructiveHint=true, and the description goes well beyond it: it discloses the inversion semantics (add undone by remove, removal by re-add), the partial-rollback guarantee for playlist adds, the refusals, the confirmation requirement, and the SPOTIFY_MCP_CONFIRM escape hatch. That is exactly the mutation-risk context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five dense sentences, front-loaded with the core action and receipt key before the refusal and confirmation caveats. Efficient, though the clause-heavy style ('an add/save is undone by removing, a removal by re-adding') costs some readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description must cover behavior, and it does: reversibility semantics, refusal cases, confirmation gating, and the fact that results reflect the refetched post-state. Combined with a fully covered schema, an agent has what it needs to call this correctly and safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so receipt_id, dry_run, and response_format are already documented in the schema, and the description only echoes dry_run implicitly via 'Executing needs confirmation'. With the schema doing the heavy lifting, baseline 3 is appropriate; response_format is not touched by the description at all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource ('Undo a specific mutation') plus the scoping key ('by receipt ID'), which implicitly separates it from the sibling undo_last_mutation. It does not name that sibling outright, so the differentiation is inferable rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete operating conditions: non-reversible kinds return 'not reversible', playlist-add undos refuse when no row positions are recorded, and execution requires confirmation. It stops short of telling the agent when to prefer this over undo_last_mutation or verify_receipt, so alternatives are left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unfollow_playlistA
Destructive

Unfollow a playlist โ€” remove it from your Spotify library โ€” via DELETE /me/library. Always asks before writing unless SPOTIFY_MCP_CONFIRM=never.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID to unfollow
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription
okNo
dry_runNo
receiptNo
cancelledNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=true in the annotations, the description adds real behavioral context: it discloses a confirmation prompt ('Always asks before writing') and the environment variable that suppresses it (SPOTIFY_MCP_CONFIRM=never). This is meaningful beyond the annotation, though it says nothing about reversibility or whether the removal is recoverable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the core action and scope first, followed by one short clause on the confirmation behavior. No filler, nothing an agent must wade through.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. For a destructive mutation the description covers the important safety behavior (confirmation gate) and the endpoint, though it omits reversibility, which would fully round out a destructive operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so playlist_id, dry_run, and response_format are already fully documented in the schema. The description adds no parameter meaning beyond that, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb+resource ('Unfollow a playlist') and immediately clarifies the effect ('remove it from your Spotify library'), which distinguishes it from the sibling remove_from_playlist that removes tracks. Naming the underlying endpoint (DELETE /me/library) removes any residual ambiguity about scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It conveys the operation but gives no explicit when-to-use vs. alternatives guidance, e.g. it never points to follow_playlist or check_playlist_following for the reverse or verification cases. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unpin_playlistA
Destructive

DEPRECATED, use unfollow_playlist. This tool never unpinned anything; it has always removed the playlist from your Spotify library via DELETE /me/library.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
playlist_idYesPlaylist ID to unfollow
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

Output Schema

ParametersJSON Schema
NameRequiredDescription
okNo
dry_runNo
receiptNo
cancelledNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, and the description corroborates this by disclosing the actual destructive effect (library removal via DELETE /me/library). It adds genuinely useful context the annotations cannot convey: deprecation status and the mismatch between the name and real behavior. It does not cover auth or reversibility, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, deprecation warning and replacement named first, then the actual behavior. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full schema coverage, the description only needs to convey purpose, deprecation, and real effect, all of which it does. Nothing required to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with playlist_id, dry_run, and response_format all documented in the schema, so the baseline is 3. The description adds no parameter-level syntax or format detail beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States exactly what the tool does ('removed the playlist from your Spotify library via DELETE /me/library') and explicitly corrects the misleading name by noting it 'never unpinned anything.' An agent can distinguish it from unfollow_playlist and pin_playlist without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Front-loads 'DEPRECATED, use unfollow_playlist,' which is an explicit when-not-to-use directive naming the replacement sibling. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unsave_orphan_tracksA
Destructive

Find saved tracks that appear in no playlist (orphans) and optionally unsave them. Quota: walks library + all playlists (capped). PREVIEWS BY DEFAULT โ€” pass dry_run=false to commit. Removing 10+ orphans additionally requires elicitation confirmation (or SPOTIFY_MCP_CONFIRM=never for automation).

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit.
scan_capNoMax saved tracks to scan (default fetchAllCap)
max_removeNoMax orphans to remove (default 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the destructiveHint annotation by disclosing the cost profile (walks library plus all playlists, capped), the safe-by-default preview behavior, the confirmation threshold of 10+ removals, and the SPOTIFY_MCP_CONFIRM=never escape hatch for automation. These are exactly the operational details an agent needs before triggering a destructive call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the purpose, then the preview-default rule, then the edge-case confirmation. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description explains that dry_run returns a PLAN, covering the main return expectation. The detailed shape of the plan and per-track results is left unspecified, which is a minor gap for a destructive multi-item tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds value by reinforcing dry_run's default semantics, framing the plan-only return, and implying that max_remove interacts with the 10+ elicitation threshold. Quota/scoping context for scan_cap is meaningful beyond the schema text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with a precise scope: 'Find saved tracks that appear in no playlist (orphans) and optionally unsave them.' This is distinguishable from siblings like find_duplicate_saved_tracks and library_hygiene, which target different conditions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly explains the operating mode: preview by default, pass dry_run=false to commit, and that removing 10+ orphans requires elicitation. It does not name a sibling alternative (e.g., remove_from_library or library_hygiene) for a simple single-track removal, so the routing guidance is strong but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_playlistC

Update a playlist's name, description, or visibility

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlias for playlist_id
nameNoNew name
publicNoNew public state
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
descriptionNoNew description
playlist_idNoPlaylist ID
collaborativeNoNew collaborative state

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say destructiveHint=false, and the description adds no behavioral context beyond that: it does not state that changes are partial, that dry_run previews without performing, or how the API treats omitted fields. The description mostly restates the tool's name and schema fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with no filler, which is efficient. It loses a point because 'visibility' is ambiguous relative to the actual boolean fields and collaborative is omitted without any structural payoff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with seven optional parameters, no output schema, and only a destructiveHint annotation, this is under-specified. It fails to mention the dry_run preview option, leaves collaborative out, and gives no selection rule among numerous playlist mutators, so an agent gets little help beyond the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3 and the schema already documents each parameter. The description adds no new parameter meaning and even calls the public field 'visibility' while omitting collaborative; however, the schema's per-parameter descriptions carry the needed semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Begins with a specific verb ('Update') and names the resource ('a playlist') plus the affected fields (name, description, visibility), so the basic purpose is clear. It does not differentiate against sibling playlist tools such as create_playlist, playlist_sort, or add_to_playlist, and 'visibility' maps only loosely to the schema's public/collaborative booleans.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No sentence explains when to use this tool instead of the many playlist-editing siblings, and there are no exclusions or alternatives. The only guidance is implied by the verb 'Update,' which does not help choose between update_playlist, playlist_reverse, playlist_trim, or remove_from_playlist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

upload_playlist_coverA

Replace a playlist's cover image with a base64-encoded JPEG. Requires the ugc-image-upload scope on the Spotify developer dashboard app (plus playlist-modify-public/private); without it Spotify rejects the upload with 403.

ParametersJSON Schema
NameRequiredDescriptionDefault
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
jpeg_base64YesBase64-encoded JPEG file contents (max 256 KB decoded)
playlist_idYesPlaylist ID

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the sparse annotations (destructiveHint=false), the description discloses the mutation semantics ('Replace' = overwriting the existing cover), the external authorization dependency (ugc-image-upload scope), and the concrete failure behavior (Spotify rejects with 403). No contradiction with annotations. It could add what a successful response looks like, but the replace semantics and failure mode are the important behavioral facts.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, roughly 40 words, with the core action front-loaded and the scope prerequisite plus its consequence in the second sentence. Every clause earns its place; no repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter mutation with full schema coverage and no output schema, the description covers the action, input format, prerequisites, and error behavior โ€” enough for an agent to invoke it correctly and anticipate the main failure. Minor gap: it doesn't state what a successful call returns or whether the previous cover is permanently lost, but 'Replace' plus the dry_run parameter keeps this marginal.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the schema already documents playlist_id, jpeg_base64 (with max 256 KB decoded), and dry_run. The description reinforces that the image must be base64-encoded JPEG but adds nothing about the parameters that the schema doesn't already say.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource โ€” 'Replace a playlist's cover image' โ€” and adds the required input format (base64-encoded JPEG). This sharply distinguishes it from sibling cover tools like get_playlist_cover, clone_playlist_cover, and compare_playlist_covers, which read, copy, or compare covers rather than write them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear, actionable context: it names the required ugc-image-upload scope (plus playlist-modify-public/private) and predicts the exact failure mode (403) if the scope is missing, so an agent can verify prerequisites before calling. It does not explicitly name alternative tools or exclusion conditions, leaving when-versus-alternatives routing mostly implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_receiptA
Read-onlyIdempotent

Verify that a previous mutation actually landed on Spotify by looking up its receipt. Receipts are session-scoped: the 100 most recent mutations, in this process only, and lost on restart unless SPOTIFY_MCP_RECEIPTS is set. An unknown or expired id returns isError with found:false โ€” a fact about the lookup, not about the mutation.

ParametersJSON Schema
NameRequiredDescriptionDefault
receipt_idYesReceipt ID copied verbatim from a receipt-bearing mutation result (rcpt_<bootId>-<n>)

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial context beyond the readOnly/idempotent annotations: session-scoped retention (100 most recent, this process only, lost on restart unless SPOTIFY_MCP_RECEIPTS is set) and precise error semantics (isError with found:false is a fact about the lookup, not the mutation). This is exactly the operational detail annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action, then retention semantics, then error meaning. Every sentence carries non-redundant information; nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the return contract (isError with found:false) and the retention window, which are the facts an agent needs to interpret results correctly. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: the pattern and the 'rcpt_<bootId>-<n>' format are already documented in the schema. The description reinforces the id's origin ('copied verbatim from a receipt-bearing mutation result') but adds no format or syntax beyond that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: verifying that a prior mutation landed, by looking up its receipt. The operation is unambiguous and distinct from mutating siblings. It stops short of naming the nearest alternatives (undo_mutation, undo_last_mutation), so an agent must infer the boundary itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly frames the use case: confirm that a previous mutation actually landed on Spotify. It also explains the provenance of the input ('receipt-bearing mutation result'), which tells the agent when this tool is applicable. No explicit when-not-to-use or named alternative is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

whats_newA

Personal new-releases radar: derive what's new from followed artists (new albums/singles) and saved shows (new podcast episodes), replacing the removed browse/new-releases surface. WARNING: the follow list is paged 50 artists per request, so on a COLD read cache the album leg costs ceil(max_artists/50) follow pages PLUS up to max_artists album lookups (#679); a repeat scan inside the cache window re-probes the same canonical request and spends no request (#900). A large library can still exhaust small dev-account quotas in one call. Use max_artists to budget and dry_run to preview the cost before running; dry_run labels its figure a budget bound (it is arithmetic over the budget, not a measurement) and a real call reports the request count it actually issued in cost. Decision guide: whats_new for personal follows radar; search_fresh for query-scoped tag:new, search/search_deep for general catalog, search_by_isrc for ISRC-exact.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindsNoWhich sources to scan. Default: ['albums','podcasts']
sinceNoOnly include releases on/after this date (YYYY-MM-DD), or 'last-check' to resume from the stored per-kind watermark file (default path ~/.spotify-mcp/freshness.json). Tracked per kind, so a call scoped to one kind never moves the other kind's mark. An explicit date never writes this file; 'last-check' and a days_back window do.
dry_runNoPreview only: validate inputs and describe exactly what would change without performing it
days_backNoLook this many days back when `since` is omitted. Default: 30
max_artistsNoPer-call budget for artist album lookups (and show episode lookups). Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET). Walk caps at this budget and reports truncation. Independent of SPOTIFY_MCP_FETCH_ALL_CAP. WARNING: each lookup costs a request unless the read cache already holds that artist's canonical release probe (#900).
max_resultsNoMax items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry destructiveHint=false, so the description carries the real burden and does so richly: paging cost (ceil(max_artists/50) pages plus album lookups), cache-window behavior, quota exhaustion risk on small dev accounts, dry_run semantics (budget bound vs measured cost), and the cost field returned by a real call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then warnings, then a decision guide. Dense and long but each block earns its place for a quota-sensitive tool; minor redundancy around the cost/cache message and issue-number parentheticals.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, zero-required-param tool with no output schema, the description covers budgeting, dry_run vs real-run cost reporting, watermark persistence, and sibling routing - everything an agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3, but the description adds genuine interpretive context beyond the schema: how max_artists interacts with fetch caps and cache, that dry_run's figure is arithmetic not measurement, and how since/'last-check' watermarks are tracked per kind.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'derive what's new from followed artists (new albums/singles) and saved shows (new podcast episodes)'. It also names the surface it replaces and explicitly differentiates itself from four named siblings in the decision guide.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit decision guide routing between whats_new, search_fresh, search/search_deep, and search_by_isrc by scenario. Adds concrete advice on when to use max_artists to budget and dry_run to preview cost.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wind_down_statusA

Read the current or most recent wind-down progress, including per-step failures

ParametersJSON Schema
NameRequiredDescriptionDefault
device_idNoOnly return status for this device id
response_formatNo'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API objectconcise

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only indicate destructiveHint=false, but the description adds the useful detail about per-step failures and that it returns current or most recent progress. It does not describe other behavioral aspects like whether it blocks or requires active scheduling, but with limited annotations the description provides moderate value beyond them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that front-loads the main purpose and includes the critical per-step failures detail. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with only two optional parameters, no required params, and the schema covers them well. The description covers the core read operation and the availability of per-step failure info. An agent has enough to invoke it correctly without more detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameters are well documented in the schema itself. The description adds no extra semantics beyond what the schema provides, so a baseline of 3 is appropriate. It doesn't clarify how response_format affects output beyond the schema's enum descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads wind-down progress and includes per-step failures. It is specific about the resource (wind-down status) and the action (read). While it does not name a sibling, the purpose is clear and distinct from scheduling/canceling wind-down tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies it is for reading status, but does not explicitly state when to use it over siblings like schedule_wind_down or cancel_wind_down. It does not mention that it only reads and does not modify, though the annotation hints at non-destructive behavior.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 527 tool updatesv3.0.1
    • Changedadd_to_playlist1 field changed
      • changedInput schema / properties / position / description
        Previous value: -"Insert at index; appends if omitted"New value: +"Insert at this index; appends if omitted. 0-based index into the playlist's current item order (0 = the first item)."
    • Changedadd_to_queue2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedadded_on_this_day
    • Removedalbum_anniversary_check
    • Removedalbum_duration_report
    • Removedalbum_edition_lint
    • Removedalbum_focus_report
    • Removedalbum_openers_report
    • Removedalbum_representative_plan
    • Removedalbum_track_explorer
    • Removedalbum_track_stats
    • Removedalbums_runtime_batch
    • Removedapply_device_presets
    • Changedapply_scene2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedapply_snapshot_changes
    • Removedapply_volume_plan
    • Removedarchive_played_episodes
    • Removedartist_affinity
    • Removedartist_album_completeness
    • Removedartist_album_timeline
    • Removedartist_catalog_stats
    • Removedartist_collab_network
    • Removedartist_collaboration_network
    • Removedartist_collection_gaps
    • Removedartist_complete_check
    • Removedartist_completeness_score
    • Removedartist_debut_release_finder
    • Removedartist_decade_span
    • Removedartist_deep_cuts
    • Removedartist_deep_dive
    • Removedartist_discography_explorer
    • Removedartist_discography_gaps
    • Removedartist_discography_search
    • Removedartist_discography_stats
    • Removedartist_discography_timeline
    • Removedartist_era_map
    • Removedartist_era_sampler
    • Removedartist_first_release
    • Removedartist_genres_compact
    • Removedartist_latest_release_report
    • Removedartist_latest_releases
    • Removedartist_listening_clock
    • Removedartist_live_albums_finder
    • Removedartist_name_disambiguator
    • Removedartist_reissue_detector
    • Removedartist_release_digest
    • Removedartist_release_type_breakdown
    • Removedartist_representation_census
    • Removedartist_scout_from_playlists
    • Removedartist_singles_timeline
    • Removedartist_top_vs_saved
    • Removedartist_velocity_report
    • Removedartistwatch_new_additions
    • Removedaudiobook_chapter_map
    • Removedaudiobook_library_progress
    • Removedaudiobooks_by_author
    • Removedb_sides_detector
    • Removedb_sides_finder
    • Changedbackup_library2 fields changed
      • removedInput schema / properties / max_results
        Removed value: -{
        -  "description": "Per-category walk cap for THIS call (default: SPOTIFY_MCP_FETCH_ALL_CAP)",
        -  "exclusiveMinimum": 0,
        -  "maximum": 2000,
        -  "type": "integer"
        -}
      • addedInput schema / properties / walk_cap
        Added value: +{
        +  "description": "Cap on items per category walked for THIS call (default: SPOTIFY_MCP_FETCH_ALL_CAP). Bounds what is READ, not rows rendered โ€” use max_results to shrink the response.",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
    • Removedbalance_playlist_pairs
    • Changedbatch_add_to_playlist3 fields changed
      • addedInput schema / properties / target_lane
        Added value: +{
        +  "description": "Lane name from the lane registry; provide exactly one of target_playlist_id or target_lane",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Target playlist ID, spotify:playlist: URI, or URL"New value: +"Target playlist ID, spotify:playlist: URI, or URL; provide exactly one of target_playlist_id or target_lane"
      • changedInput schema / required
        Previous value: -[
        -  "target_playlist_id",
        -  "source_uris"
        -]New value: +[
        +  "source_uris"
        +]
    • Removedbatch_add_to_queue
    • Removedbinge_detector_report
    • Removedbrowse_category_deepdive
    • Removedcanonicalize_spotify_uri
    • Removedcapture_playback_position
    • Removedcatalog_batch_lookup
    • Removedcategory_resolver
    • Removedchapter_bookmarks
    • Removedcheck_artist_releases
    • Removedcheck_episode_saved
    • Changedcheck_playlist_following2 fields changed
      • removedInput schema / properties / playlist_ids
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists.",
        -  "items": {
        -    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        -    "minLength": 1,
        -    "type": "string"
        -  },
        -  "maxItems": 50,
        -  "minItems": 1,
        -  "type": "array"
        -}
      • changedInput schema / properties / playlists / description
        Previous value: -"Canonical ordered playlists (1โ€“50), or provide the complete documented legacy alias accepted by this tool"New value: +"Canonical ordered playlists (1โ€“50)"
    • Removedcheck_saved_items
    • Removedcheckpoint_playback
    • Changedclean_all_playlists3 fields changed
      • removedInput schema / properties / include_relinked / default
        Removed value: -false
      • changedInput schema / properties / include_relinked / description
        Previous value: -"Also count/collapse same-song entries under different URIs (relinks/remasters)."New value: +"Deprecated alias for `match_by`, kept for one release: true is `name_artist` and false is `uri`. It cannot express the `name` rule, which is why `match_by` replaced it. Sending both, where they mean different rules, is an error rather than a silent choice."
      • addedInput schema / properties / match_by
        Added value: +{
        +  "description": "Which rule decides that two items are the same: `uri` (exact URI, the default), `name_artist` (case-insensitive name + credited artists, catches relinks/remasters), or `name` (case-insensitive name only). The rule applied is echoed in the result as `match_by`.",
        +  "enum": [
        +    "uri",
        +    "name_artist",
        +    "name"
        +  ],
        +  "type": "string"
        +}
    • Addedclean_backup_artifacts
    • Changedclone_playlist_cover1 field changed
      • changedInput schema / properties / image_index / description
        Previous value: -"Which cover image to copy (0-based). Default 0"New value: +"Which cover image to copy. Default 0. 0-based index into the playlist's current item order (0 = the first item)."
    • Removedcollab_density_report
    • Removedcollab_mix_from_followed
    • Removedcompare_devices
    • Changedcompare_playlist_covers4 fields changed
      • changedInput schema / properties / playlist_a / description
        Previous value: -"Canonical A playlist; provide with playlist_b or one complete documented legacy pair"New value: +"Canonical A playlist; provide with playlist_b"
      • changedInput schema / properties / playlist_b / description
        Previous value: -"Canonical B playlist; provide with playlist_a or one complete documented legacy pair"New value: +"Canonical B playlist; provide with playlist_a"
      • removedInput schema / properties / playlist_id_a
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b.",
        -  "minLength": 1,
        -  "type": "string"
        -}
      • removedInput schema / properties / playlist_id_b
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b.",
        -  "minLength": 1,
        -  "type": "string"
        -}
    • Removedcontinue_last
    • Removeddaily_pick
    • Removeddead_library_finder
    • Removeddecade_sampler_plan
    • Removeddedupe_playlist_apply
    • Removeddedupe_playlist_plan
    • Removeddedupe_spotify_uris
    • Removeddeep_cuts_finder
    • Removeddeep_dive_report
    • Removeddelete_playback_bookmark
    • Removeddelete_playlist_snapshot
    • Removeddescribe_listening_session
    • Removeddescribe_queue
    • Removeddevice_health
    • Removeddevice_sync_state
    • Removeddevice_type_census
    • Removeddiff_playlist_snapshots
    • Changeddiff_playlists4 fields changed
      • removedInput schema / properties / a
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b.",
        -  "minLength": 1,
        -  "type": "string"
        -}
      • removedInput schema / properties / b
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b.",
        -  "minLength": 1,
        -  "type": "string"
        -}
      • changedInput schema / properties / playlist_a / description
        Previous value: -"Canonical A playlist; provide with playlist_b or one complete documented legacy pair"New value: +"Canonical A playlist; provide with playlist_b"
      • changedInput schema / properties / playlist_b / description
        Previous value: -"Canonical B playlist; provide with playlist_a or one complete documented legacy pair"New value: +"Canonical B playlist; provide with playlist_a"
    • Removeddiff_since_snapshot
    • Removeddiscover_weekly_diff
    • Removeddiscovery_digest
    • Removeddiscovery_ratio
    • Removedduplicate_saved_versions
    • Removedepisode_bookmark
    • Removedepisode_context_bundle
    • Removedepisode_guest_census
    • Removedepisode_resume
    • Removedepisode_runtime_report
    • Removedera_distribution_report
    • Removedera_preference_report
    • Addedexpand_mood_to_queries
    • Removedexplicit_content_ratio
    • Removedexport_playlist_json
    • Removedexport_playlist_markdown
    • Removedexport_shows_opml
    • Removedexport_snapshot_bundle
    • Removedexposure_check
    • Removedextract_playlist_range
    • Removedfeaturing_density_report
    • Removedfilter_playlist_by_artist
    • Removedfilter_playlist_by_duration
    • Removedfilter_playlist_by_era
    • Removedfind_canonical_track
    • Removedfind_collaborations
    • Removedfind_duplicate_playlists
    • Changedfind_duplicate_tracks_across_playlists2 fields changed
      • removedInput schema / properties / playlist_ids
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists.",
        -  "items": {
        -    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        -    "minLength": 1,
        -    "type": "string"
        -  },
        -  "maxItems": 20,
        -  "minItems": 2,
        -  "type": "array"
        -}
      • changedInput schema / properties / playlists / description
        Previous value: -"Canonical ordered playlists (2โ€“20), or provide the complete documented legacy alias accepted by this tool"New value: +"Canonical ordered playlists (2โ€“20)"
    • Changedfind_duplicates_in_playlist1 field changed
      • addedInput schema / properties / match_by
        Added value: +{
        +  "description": "Which rule decides that two items are the same: `uri` (exact URI, the default), `name_artist` (case-insensitive name + credited artists, catches relinks/remasters), or `name` (case-insensitive name only). The rule applied is echoed in the result as `match_by`.",
        +  "enum": [
        +    "uri",
        +    "name_artist",
        +    "name"
        +  ],
        +  "type": "string"
        +}
    • Removedfind_lost_since_snapshot
    • Removedfind_new_since_snapshot
    • Removedfind_show_by_publisher
    • Changedfind_tool2 fields changed
      • changedInput schema / properties / response_format / description
        Previous value: -"'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object"New value: +"'concise' (default) = prose bullet list; 'detailed' = the same prose; 'json' = the result payload as parseable JSON text, identical to structuredContent"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": {},
        +  "properties": {},
        +  "type": "object"
        +}
    • Removedfollow_artists
    • Addedfollow_playlist
    • Changedfollowing_analytics1 field changed
      • changedInput schema / properties / group_by / description
        Previous value: -"Rollup dimension for the report"New value: +"Rollup dimension; popularity/followers report 'unavailable'"
    • Removedforgotten_favorites
    • Removedformat_spotify_uri
    • Removedfront_to_back_plan
    • Removedgenre_dive_search
    • Removedgenre_trends_over_time
    • Removedget_album
    • Removedget_album_tracks
    • Removedget_artist
    • Removedget_artist_albums
    • Removedget_artist_appearances
    • Removedget_artist_discography
    • Removedget_artist_genres
    • Removedget_artist_singles
    • Removedget_artist_top_tracks
    • Removedget_audiobook
    • Removedget_audiobook_chapters
    • Removedget_available_markets
    • Removedget_categories
    • Removedget_category
    • Removedget_category_playlists
    • Removedget_chapter
    • Removedget_context_inspect
    • Removedget_device_volume_report
    • Removedget_episode
    • Removedget_episode_details
    • Removedget_me
    • Removedget_newly_released_episodes
    • Removedget_playback_context
    • Removedget_playback_snapshot
    • Changedget_playlist7 fields changed
      • addedInput schema / properties / additional_types
        Added value: +{
        +  "description": "Item types to include beyond the default 'track', e.g. ['track', 'episode']",
        +  "items": {
        +    "enum": [
        +      "track",
        +      "episode"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / fields
        Added value: +{
        +  "description": "Comma-separated list of response fields to keep, e.g. 'total,items(track(name,uri))'",
        +  "type": "string"
        +}
      • changedInput schema / properties / id / description
        Previous value: -"Alias for playlist_id"New value: +"Alias for playlist_id, resolved the same way"
      • addedInput schema / properties / id / minLength
        Added value: +1
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code, e.g. 'GB'; relinks tracks to that market and flags unavailable ones",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • changedInput schema / properties / playlist_id / description
        Previous value: -"Playlist ID"New value: +"Playlist ID, spotify:playlist: URI, or open.spotify.com/playlist URL"
      • addedInput schema / properties / playlist_id / minLength
        Added value: +1
    • Removedget_playlist_followers
    • Changedget_queue2 fields changed
      • addedInput schema / properties / include
        Added value: +{
        +  "default": [],
        +  "description": "Local analyses over the same single read, no extra request except runtime: runtime = total/avg/longest/shortest, time left on the current track, and a per-item timeline of when each row starts playing; duplicates = repeated rows and the runtime they waste; profile = unique artists/albums/shows, track-vs-episode mix, longest single-artist run.",
        +  "items": {
        +    "enum": [
        +      "runtime",
        +      "duplicates",
        +      "profile"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / view
        Added value: +{
        +  "default": "raw",
        +  "description": "'raw' (default) = the queue as returned. 'enriched' = plus the source context (playlist/album name) and total time remaining.",
        +  "enum": [
        +    "raw",
        +    "enriched"
        +  ],
        +  "type": "string"
        +}
    • Removedget_queue_snapshot
    • Removedget_recently_played
    • Removedget_saved_audiobooks
    • Removedget_several_albums
    • Removedget_several_artists
    • Removedget_several_audiobooks
    • Removedget_several_chapters
    • Removedget_several_episodes
    • Removedget_several_shows
    • Removedget_several_tracks
    • Removedget_show
    • Removedget_show_details
    • Removedget_show_latest_episode
    • Removedget_top_artists
    • Removedget_top_tracks
    • Removedget_track
    • Removedhandoff
    • Changedinspect_tool2 fields changed
      • changedInput schema / properties / response_format / description
        Previous value: -"'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object"New value: +"'concise' (default) = prose bullet list; 'detailed' = the same prose; 'json' = the result payload as parseable JSON text, identical to structuredContent"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": {},
        +  "properties": {},
        +  "type": "object"
        +}
    • Removedinterleave_playlists_plan
    • Removedis_local_census
    • Removedjump_to_chapter
    • Removedlabel_discography_explorer
    • Removedlabel_explorer
    • Removedlast_heard
    • Removedlibrary_coverage_report
    • Removedlibrary_growth_report
    • Removedlibrary_growth_timeline
    • Removedlibrary_to_playlist
    • Removedlibrary_value_summary
    • Addedlist_accounts
    • Removedlist_all_chapters
    • Removedlist_device_presets
    • Removedlist_playback_bookmarks
    • Removedlist_playback_states
    • Removedlist_playlist_snapshots
    • Removedlist_saved_shows
    • Removedlist_saved_snapshots
    • Removedlist_sessions
    • Removedlist_show_episodes
    • Removedlistening_clock
    • Removedlistening_clock_heatmap
    • Removedlistening_consistency_score
    • Removedlistening_eras
    • Removedlistening_gaps_report
    • Removedlistening_heatmap
    • Removedlistening_history_export
    • Removedlistening_journal_append
    • Removedlistening_recap_brief
    • Removedlistening_report
    • Removedlistening_session_close
    • Removedlistening_session_report
    • Removedlistening_session_start
    • Removedlistening_sessions
    • Removedlistening_streak_report
    • Removedlistening_streaks
    • Removedlistening_week_in_time
    • Removedlongest_saved_tracks
    • Removedlyric_snippet_search
    • Removedmark_episode_played_plan
    • Removedmarket_availability
    • Removedmarket_validate
    • Changedmerge_playlists2 fields changed
      • changedInput schema / properties / playlists / description
        Previous value: -"Canonical ordered playlists (1โ€“10), or provide the complete documented legacy alias accepted by this tool"New value: +"Canonical ordered playlists (1โ€“10)"
      • removedInput schema / properties / sources
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists.",
        -  "items": {
        -    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        -    "minLength": 1,
        -    "type": "string"
        -  },
        -  "maxItems": 10,
        -  "minItems": 1,
        -  "type": "array"
        -}
    • Removedmerge_playlists_plan
    • Removedmerge_snapshot_changes_plan
    • Removedmonthly_listening_report
    • Removedmood_bucket_report
    • Removedmorning_briefing
    • Removedmost_replayed
    • Changedmove_items_between_playlists5 fields changed
      • addedInput schema / properties / source_lane
        Added value: +{
        +  "description": "Lane name resolving to the source playlist; provide exactly one of source_playlist_id or source_lane",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / source_playlist_id / description
        Previous value: -"Source playlist ID, spotify:playlist: URI, or URL"New value: +"Source playlist ID, spotify:playlist: URI, or URL; provide exactly one of source_playlist_id or source_lane"
      • addedInput schema / properties / target_lane
        Added value: +{
        +  "description": "Lane name resolving to the target playlist; provide exactly one of target_playlist_id or target_lane",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Target playlist ID, spotify:playlist: URI, or URL"New value: +"Target playlist ID, spotify:playlist: URI, or URL; provide exactly one of target_playlist_id or target_lane"
      • removedInput schema / required
        Removed value: -[
        -  "source_playlist_id",
        -  "target_playlist_id"
        -]
    • Removedmove_tracks_between_playlists
    • Removedmutation_log_export
    • Removedmute
    • Removednever_played_saved
    • Removednew_music_from_saved_artists
    • Removednew_music_from_top_artists
    • Removednow_playing_history
    • Removedorphaned_artist_check
    • Changedoverlap_playlists1 field changed
      • changedInput schema / properties / playlists / description
        Previous value: -"Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool"New value: +"Canonical ordered playlists (2โ€“10)"
    • Removedparse_spotify_uri
    • Removedparse_spotify_uris
    • Changedpause2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedpause_everywhere
    • Removedpeek_next
    • Changedpin_playlist1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "cancelled": {
        +      "type": "boolean"
        +    },
        +    "dry_run": {
        +      "type": "boolean"
        +    },
        +    "ok": {
        +      "type": "boolean"
        +    },
        +    "receipt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedplan_podcast_session1 field changed
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code for the saved-show episode lookups, e.g. \"US\". Defaults to SPOTIFY_MCP_MARKET, then to the account country โ€” these lookups are market-gated, so a wrong default silently drops episode rows. Ignored for a saved-episodes-only plan.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
    • Removedplan_volume_level_across_devices
    • Changedplay2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedplay_at
    • Changedplay_from_search2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedplay_on
    • Removedplayback_compare_states
    • Removedplayback_health_check
    • Removedplayback_timeline
    • Removedplayback_timer_status
    • Removedplaylist_add_by_search
    • Removedplaylist_artist_heat
    • Removedplaylist_balance
    • Removedplaylist_changelog
    • Removedplaylist_chunk_preview
    • Removedplaylist_clone_live
    • Removedplaylist_clone_snapshot
    • Removedplaylist_collaboration_report
    • Removedplaylist_cover_from_track
    • Removedplaylist_dedupe_advanced
    • Removedplaylist_diff
    • Removedplaylist_difference_plan
    • Removedplaylist_edit_journal
    • Removedplaylist_era_profile
    • Removedplaylist_exclude_artists
    • Removedplaylist_expression_algebra
    • Removedplaylist_fill_from_search
    • Removedplaylist_filter_runtime
    • Removedplaylist_flip_order
    • Removedplaylist_from_tags
    • Removedplaylist_health_check
    • Removedplaylist_history
    • Removedplaylist_intersect
    • Removedplaylist_intersection
    • Removedplaylist_keep_artist
    • Removedplaylist_keep_only
    • Removedplaylist_move_block
    • Removedplaylist_move_to_top
    • Removedplaylist_names_bulk_normalize
    • Removedplaylist_overlap_matrix
    • Removedplaylist_pair_check
    • Removedplaylist_remove_artist
    • Removedplaylist_resequence
    • Removedplaylist_rotate
    • Removedplaylist_seed_shuffle
    • Removedplaylist_slice
    • Removedplaylist_snapshot_detail
    • Removedplaylist_staleness_report
    • Removedplaylist_staleness_score
    • Removedplaylist_strip_episodes
    • Changedplaylist_subtract4 fields changed
      • changedInput schema / properties / base_playlist_id / description
        Previous value: -"Base playlist ID, URI, or URL. Optional only for the deprecated positional form, where playlists[0] is the base."New value: +"Base playlist ID, URI, or URL. Required; list only the subtraction sources in playlists."
      • changedInput schema / properties / playlists / description
        Previous value: -"Canonical ordered playlists (1โ€“10), or provide the complete documented legacy alias accepted by this tool"New value: +"Canonical ordered playlists (1โ€“10)"
      • removedInput schema / properties / subtract_playlist_ids
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists.",
        -  "items": {
        -    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        -    "minLength": 1,
        -    "type": "string"
        -  },
        -  "maxItems": 10,
        -  "minItems": 1,
        -  "type": "array"
        -}
      • addedInput schema / required
        Added value: +[
        +  "base_playlist_id"
        +]
    • Removedplaylist_swap_positions
    • Changedplaylist_symmetric_difference4 fields changed
      • changedInput schema / properties / playlist_a / description
        Previous value: -"Canonical A playlist; provide with playlist_b or one complete documented legacy pair"New value: +"Canonical A playlist; provide with playlist_b"
      • changedInput schema / properties / playlist_b / description
        Previous value: -"Canonical B playlist; provide with playlist_a or one complete documented legacy pair"New value: +"Canonical B playlist; provide with playlist_a"
      • removedInput schema / properties / playlist_id_a
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b.",
        -  "minLength": 1,
        -  "type": "string"
        -}
      • removedInput schema / properties / playlist_id_b
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b.",
        -  "minLength": 1,
        -  "type": "string"
        -}
    • Removedplaylist_table_of_contents
    • Removedplaylist_trim_to_duration
    • Changedplaylist_union2 fields changed
      • changedInput schema / properties / playlists / description
        Previous value: -"Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool"New value: +"Canonical ordered playlists (2โ€“10)"
      • removedInput schema / properties / source_playlist_ids
        Removed value: -{
        -  "description": "Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists.",
        -  "items": {
        -    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        -    "minLength": 1,
        -    "type": "string"
        -  },
        -  "maxItems": 10,
        -  "minItems": 2,
        -  "type": "array"
        -}
    • Removedplaylist_union_preview
    • Removedpredict_next_tracks
    • Removedprune_old_snapshots
    • Removedpublisher_portfolio
    • Removedqueue_duplicate_check
    • Removedqueue_next
    • Removedqueue_next_episode
    • Removedqueue_playlist
    • Removedqueue_profile
    • Removedqueue_prune_plan
    • Removedqueue_replace_via_playlist
    • Removedqueue_runtime_report
    • Removedquick_save_now
    • Removedquota_probe
    • Removedread_playlist_snapshot
    • Removedreceipt_lookup
    • Removedrecord_feedback
    • Removedrefresh_smart_playlist
    • Changedremove_duplicate_playlist_items3 fields changed
      • removedInput schema / properties / include_relinked / default
        Removed value: -false
      • changedInput schema / properties / include_relinked / description
        Previous value: -"Also collapse same-song duplicates under different URIs (relinks/remasters). Default false โ€” only exact URI repeats are removed."New value: +"Deprecated alias for `match_by`, kept for one release: true is `name_artist` and false is `uri`. It cannot express the `name` rule, which is why `match_by` replaced it. Sending both, where they mean different rules, is an error rather than a silent choice."
      • addedInput schema / properties / match_by
        Added value: +{
        +  "description": "Which rule decides that two items are the same: `uri` (exact URI, the default), `name_artist` (case-insensitive name + credited artists, catches relinks/remasters), or `name` (case-insensitive name only). The rule applied is echoed in the result as `match_by`.",
        +  "enum": [
        +    "uri",
        +    "name_artist",
        +    "name"
        +  ],
        +  "type": "string"
        +}
    • Changedremove_from_library2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: show exactly which URIs would be removed without calling the API"New value: +"Preview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit."
    • Changedremove_from_library_by_playlist2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit."
    • Changedremove_from_playlist1 field changed
      • changedInput schema / properties / uris / items / anyOf
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "properties": {
        -      "positions": {
        -        "items": {
        -          "maximum": 9007199254740991,
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "uri": {
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "uri",
        -      "positions"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "properties": {
        +      "positions": {
        +        "description": "0-based index into the playlist's current item order (0 = the first item).",
        +        "items": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "uri": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "uri",
        +      "positions"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Removedremove_playlist_range
    • Removedremove_saved_episode
    • Removedremove_saved_items
    • Removedremove_saved_shows
    • Removedremove_unavailable_playlist_items
    • Removedrename_device
    • Changedreorder_playlist_items2 fields changed
      • changedInput schema / properties / insert_before / description
        Previous value: -"Index to insert the range before"New value: +"Index to insert the range before. 0-based index into the playlist's current item order (0 = the first item)."
      • changedInput schema / properties / range_start / description
        Previous value: -"Index of the first item to move"New value: +"Index of the first item to move. 0-based index into the playlist's current item order (0 = the first item)."
    • Removedrepeat_listener_report
    • Removedrepeat_queue_toggle
    • Removedreplay_session
    • Removedresolve_artist
    • Removedrestore_playback_state
    • Removedrestore_playlist_from_snapshot
    • Removedrestore_playlist_plan
    • Removedresume_playback_position
    • Removedreverse_playlist_plan
    • Removedroom_level
    • Removedrotate_playlist_plan
    • Removedsample_playlist_tracks
    • Removedsave_artist_new_releases
    • Removedsave_episode
    • Removedsave_items
    • Removedsave_playback_state
    • Removedsave_queue_as_playlist
    • Removedsave_show_digest
    • Removedsave_smart_playlist_rule
    • Changedsave_to_library2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit."
    • Removedsaved_albums_by_decade
    • Removedsaved_albums_by_label
    • Removedsaved_albums_by_type
    • Removedsaved_albums_by_year
    • Removedsaved_library_delta
    • Removedsaved_runtime_by_era
    • Removedsaved_shows_publisher_census
    • Removedsaved_track_age_report
    • Removedsaved_tracks_by_artist
    • Removedsaved_tracks_roulette
    • Removedsaved_vs_playlist_coverage
    • Removedscene_sampler_search
    • Changedschedule_wind_down2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedscope_audit
    • Removedsearch_advanced
    • Removedsearch_albums
    • Removedsearch_artists
    • Removedsearch_audiobooks
    • Removedsearch_by_isrc
    • Removedsearch_episodes
    • Removedsearch_fresh
    • Removedsearch_history
    • Removedsearch_market_diff
    • Removedsearch_playlists
    • Removedsearch_rerun
    • Changedsearch_saved_shows1 field changed
      • changedInput schema / properties / query / description
        Previous value: -"Substring match against show name/publisher"New value: +"Substring match against show name and publisher. Spotify removed `publisher` from show payloads in February 2026, so the publisher half can only match on an app registration created before November 2024; on a current registration this is a name search that reports 0 publisher matches rather than pretending to have searched publishers."
    • Removedsearch_shows
    • Removedsearch_tracks
    • Changedsearch_within_playlist6 fields changed
      • addedInput schema / properties / id
        Added value: +{
        +  "description": "Alias for playlist_id, matching get_playlist_items",
        +  "type": "string"
        +}
      • addedInput schema / properties / kind
        Added value: +{
        +  "default": "any",
        +  "description": "Item kinds to match: 'track', 'episode', or 'any' (default โ€” both). Mixed playlists hold both row shapes",
        +  "enum": [
        +    "track",
        +    "episode",
        +    "any"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / playlist_id / description
        Previous value: -"Playlist ID"New value: +"Playlist ID (or pass it as 'id')"
      • removedInput schema / properties / playlist_id / minLength
        Removed value: -1
      • changedInput schema / properties / query / description
        Previous value: -"Substring to match against track/episode name, artist, album"New value: +"Substring to match against track/episode name, artist, album, show name"
      • changedInput schema / required
        Previous value: -[
        -  "playlist_id",
        -  "query"
        -]New value: +[
        +  "query"
        +]
    • Changedseek2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedseek_relative
    • Removedsession_length_report
    • Removedsession_stats
    • Removedset_device_volume_preset
    • Changedset_repeat2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Changedset_shuffle2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Changedset_volume10 fields changed
      • addedInput schema / properties / all_devices
        Added value: +{
        +  "description": "For op \"level\" with volume_percent: set every volume-capable device, not a named selection.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / delta_step
        Added value: +{
        +  "description": "Signed nudge, e.g. +10 or -10, clamped to 0โ€“100. Mutually exclusive with volume_percent.",
        +  "maximum": 100,
        +  "minimum": -100,
        +  "type": "integer"
        +}
      • changedInput schema / properties / device_id / description
        Previous value: -"Target device ID"New value: +"Device ID for a single-device write (default: the active device)"
      • addedInput schema / properties / device_ids
        Added value: +{
        +  "description": "For op \"level\" with volume_percent: fan out to these device ids or names. Mutually exclusive with all_devices.",
        +  "items": {
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
      • addedInput schema / properties / exclude_device_id
        Added value: +{
        +  "description": "For op \"level\" with no volume_percent: leave this device untouched while levelling the rest",
        +  "type": "string"
        +}
      • addedInput schema / properties / op
        Added value: +{
        +  "description": "Variant: \"level\" (default) set or copy a level, \"mute\", \"unmute\", \"preset\"",
        +  "enum": [
        +    "level",
        +    "mute",
        +    "unmute",
        +    "preset"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / volume_percent / description
        Previous value: -"Volume level 0โ€“100"New value: +"Absolute level 0โ€“100. Mutually exclusive with delta_step."
      • removedInput schema / required
        Removed value: -[
        -  "volume_percent"
        -]
    • Removedshortest_saved_tracks
    • Removedshow_activity_feed
    • Removedshow_backlog_plan
    • Removedshow_backlog_report
    • Removedshow_episode_search
    • Removedshow_episode_timeline
    • Changedshow_new_episodes1 field changed
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code for the per-show episode lookups, e.g. \"US\". Defaults to SPOTIFY_MCP_MARKET, then to the account country โ€” these lookups are market-gated, so a wrong default silently drops episode rows.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
    • Removedshow_recommendation_brief
    • Removedshow_runtime_stats
    • Removedshows_release_calendar
    • Removedshows_without_new_episodes
    • Removedshuffle_state_report
    • Removedsidecar_export_bundle
    • Removedskip_n
    • Changedskip_next2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Changedskip_previous2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
    • Removedsleep_timer
    • Removedsleep_timer_plan
    • Removedsnapshot_added_at_report
    • Removedsnapshot_changelog
    • Removedsnapshot_diff_summary
    • Removedsnapshot_disk_usage
    • Removedsnapshot_integrity_check
    • Removedsnapshot_integrity_report
    • Removedsnapshot_new_tracks
    • Removedsnapshot_playlist
    • Removedsnapshot_registry_report
    • Removedsnapshot_removed_tracks
    • Removedsnapshot_retention_plan
    • Removedsnapshot_stats_report
    • Removedsort_playlist_apply
    • Removedsort_playlist_plan
    • Removedsplit_playlist_by_count
    • Removedsplit_playlist_by_duration
    • Removedsplit_queue_plan
    • Changedspotify_doctor1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": {},
        +  "properties": {},
        +  "type": "object"
        +}
    • Removedspotify_uri_stats
    • Removedstale_saved_shows_plan
    • Changedstart_podcast_session1 field changed
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code for the saved-show episode lookups, e.g. \"US\". Defaults to SPOTIFY_MCP_MARKET, then to the account country โ€” these lookups are market-gated, so a wrong default silently drops episode rows. Ignored for a saved-episodes-only plan.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
    • Removedstatsfm_album_date_stats
    • Removedstatsfm_album_stats
    • Removedstatsfm_artist_affinity
    • Removedstatsfm_artist_date_stats
    • Removedstatsfm_artist_stats
    • Removedstatsfm_catalog_album
    • Removedstatsfm_catalog_artist
    • Removedstatsfm_catalog_track
    • Removedstatsfm_charts_albums
    • Removedstatsfm_charts_artists
    • Removedstatsfm_charts_tracks
    • Removedstatsfm_charts_users
    • Removedstatsfm_exposure_check
    • Removedstatsfm_forgotten_favorites
    • Removedstatsfm_friend_count
    • Removedstatsfm_friends
    • Removedstatsfm_genre_artists
    • Removedstatsfm_listening_eras
    • Removedstatsfm_listening_sessions
    • Removedstatsfm_now_playing
    • Removedstatsfm_recaps
    • Removedstatsfm_recent_streams
    • Removedstatsfm_record_feedback
    • Removedstatsfm_records_artists
    • Removedstatsfm_resolve_user
    • Removedstatsfm_search
    • Removedstatsfm_streams_stats
    • Removedstatsfm_taste_profile
    • Removedstatsfm_taste_recommendations
    • Removedstatsfm_top_albums
    • Removedstatsfm_top_albums_from_artist
    • Removedstatsfm_top_artists
    • Removedstatsfm_top_genres
    • Removedstatsfm_top_tracks
    • Removedstatsfm_top_tracks_from_album
    • Removedstatsfm_top_tracks_from_artist
    • Removedstatsfm_track_date_stats
    • Removedstatsfm_track_stats
    • Removedsubscribe_to_show
    • Removedsurprise_me
    • Addedswitch_account
    • Removedswitch_device
    • Removedtag_listening_session
    • Removedtake_playlist_snapshot
    • Removedtaste_checkpoint
    • Removedtaste_checkpoint_diff
    • Removedtaste_daily_brief
    • Removedtaste_diamond_rotation
    • Removedtaste_era_playlist
    • Removedtaste_forgotten_bangers
    • Removedtaste_genre_bridge
    • Removedtaste_listening_clock
    • Removedtaste_novelty_loyalty
    • Removedtaste_obsession_ladder
    • Removedtaste_profile
    • Removedtaste_recommendations
    • Removedtaste_revival_queue
    • Removedtaste_shift_report
    • Removedtaste_to_playlist
    • Removedtaste_weekly_recap
    • Removedtitle_length_outliers
    • Changedtoolset_report2 fields changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' (default) = prose bullet list; 'detailed' = the same prose; 'json' = the result payload as parseable JSON text, identical to structuredContent",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": {},
        +  "properties": {},
        +  "type": "object"
        +}
    • Removedtop_artist_leaderboard
    • Removedtop_artist_ranking_delta
    • Removedtop_artists_by_range
    • Removedtop_genre_census
    • Removedtop_track_leaderboard
    • Removedtop_track_ranking_delta
    • Removedtrack_album_bundle
    • Removedtrack_enrichment_batch
    • Removedtrack_release_origin
    • Removedtrack_rotation_report
    • Changedtransfer_playback9 fields changed
      • addedInput schema / properties / device
        Added value: +{
        +  "description": "Target device: exact id, sidecar label, or case-insensitive name substring",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / device_id / description
        Previous value: -"Target device ID to transfer playback to"New value: +"DEPRECATED: use `device`"
      • addedInput schema / properties / dry_run / default
        Added value: +false
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: describe what would change without performing it. Default false โ€” pass true to preview."
      • changedInput schema / properties / play / description
        Previous value: -"Force play immediately (default: maintain current state)"New value: +"Force play (true) or arrive paused (false); omit to preserve the current play state. With preserve_position, true also resumes a session that is currently paused."
      • addedInput schema / properties / preserve_position
        Added value: +{
        +  "description": "Resume the current track at its current position on the target instead of restarting it (default: false)",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / restore_shuffle_repeat
        Added value: +{
        +  "description": "Re-apply the current shuffle and repeat modes on the target (default: false)",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / volume
        Added value: +{
        +  "description": "Volume to set on the target after transfer, 0โ€“100",
        +  "maximum": 100,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "device_id"
        -]New value: +[
        +  "device"
        +]
    • Removedtransfer_playback_with_state
    • Removedundo_preview
    • Removedunfollow_artists
    • Addedunfollow_playlist
    • Removedunmute
    • Changedunpin_playlist1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": {},
        +  "properties": {
        +    "cancelled": {
        +      "type": "boolean"
        +    },
        +    "dry_run": {
        +      "type": "boolean"
        +    },
        +    "ok": {
        +      "type": "boolean"
        +    },
        +    "receipt": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "type": "object"
        +}
    • Removedunplayable_saved_check
    • Changedunsave_orphan_tracks2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only: perform the read side and return a PLAN without changing anything. Default true โ€” pass dry_run=false to commit."
    • Removedunsubscribe_from_show
    • Changedverify_receipt3 fields changed
      • changedInput schema / properties / receipt_id / description
        Previous value: -"Receipt ID from a receipt-bearing mutation result"New value: +"Receipt ID copied verbatim from a receipt-bearing mutation result (rcpt_<bootId>-<n>)"
      • removedInput schema / properties / receipt_id / minLength
        Removed value: -1
      • addedInput schema / properties / receipt_id / pattern
        Added value: +"^rcpt_(?:[0-9a-z]+-)?\\d+$"
    • Removedvolume_ramp
    • Removedvolume_report
    • Removedvolume_step
    • Removedwatch_artists
    • Removedweek_in_review_playlist
    • Removedweekday_heatmap
    • Removedweekday_listening_report
    • Removedweekly_rotation_report
    • Changedwhats_new2 fields changed
      • changedInput schema / properties / max_artists / description
        Previous value: -"Per-call budget for artist album lookups (and show episode lookups). Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET). Walk caps at this budget and reports truncation. Independent of SPOTIFY_MCP_FETCH_ALL_CAP. WARNING: each lookup is an API request."New value: +"Per-call budget for artist album lookups (and show episode lookups). Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET). Walk caps at this budget and reports truncation. Independent of SPOTIFY_MCP_FETCH_ALL_CAP. WARNING: each lookup costs a request unless the read cache already holds that artist's canonical release probe (#900)."
      • changedInput schema / properties / since / description
        Previous value: -"Only include releases on/after this date (YYYY-MM-DD), or 'last-check' to resume from the stored watermark file (default path ~/.spotify-mcp/freshness.json)"New value: +"Only include releases on/after this date (YYYY-MM-DD), or 'last-check' to resume from the stored per-kind watermark file (default path ~/.spotify-mcp/freshness.json). Tracked per kind, so a call scoped to one kind never moves the other kind's mark. An explicit date never writes this file; 'last-check' and a days_back window do."
    • Removedwhere_was_i
    • Removedyear_explorer
    • Removedyear_in_review
  2. 88 tool updatesv2.1.2
    • Changedalbum_focus_report2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedalbum_representative_plan2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedalbum_track_stats2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedalbums_runtime_batch2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedartist_collab_network3 fields changed
      • addedInput schema / properties / include_track_features
        Added value: +{
        +  "description": "Opt in: also read track-level credits (1 extra GET /albums/{id}/tracks per album, up to 10 albums) so featured-artist collaborations are counted. Default: false. Albums whose credits could not be read are listed as unreadable with the reason, never counted as zero collaborators.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedartist_discography_timeline1 field changed
      • changedInput schema / properties / max_results / description
        Previous value: -"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"New value: +"Max rows to return (default: SPOTIFY_MCP_FETCH_ALL_CAP or 500)"
    • Changedartist_name_disambiguator2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedartist_release_digest1 field changed
      • changedInput schema / properties / max_artists / description
        Previous value: -"Per-call budget for artist lookups. Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET)."New value: +"Per-call artist lookup budget. Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET)."
    • Changedaudiobook_chapter_map1 field changed
      • changedInput schema / properties / max_results / description
        Previous value: -"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"New value: +"Max rows to return (default: SPOTIFY_MCP_FETCH_ALL_CAP or 500)"
    • Changedaudiobooks_by_author2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedbrowse_category_deepdive1 field changed
      • changedInput schema / properties / category_id / description
        Previous value: -"Category ID from get_categories"New value: +"Category ID"
    • Changedcheck_artist_releases1 field changed
      • changedInput schema / properties / max_artists / description
        Previous value: -"Per-call budget for artist lookups. Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET). Truncates to max_artists and reports watchlist_size / artists_scanned / truncated."New value: +"Per-call artist lookup budget. Default: 25 (or SPOTIFY_MCP_FRESHNESS_BUDGET). Reports watchlist_size / artists_scanned / truncated."
    • Changedcheck_following_artists2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify artist IDs to check"New value: +"Artist IDs, spotify:artist: URIs, or artist URLs; CSV accepted"
      • addedInput schema / properties / ids / items / minLength
        Added value: +1
    • Changeddeep_cuts_finder1 field changed
      • addedInput schema / properties / max_singles
        Added value: +{
        +  "description": "Singles to scan for the exclusion set, newest first. Default: the fetch-all cap, clamped to it.",
        +  "exclusiveMinimum": 0,
        +  "maximum": 1000,
        +  "type": "integer"
        +}
    • Addeddelete_backup
    • Changeddiscovery_digest2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedepisode_context_bundle2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedexport_all_playlists1 field changed
      • changedInput schema / properties / output_dir / description
        Previous value: -"Local directory (default: ~/.spotify-mcp/portability)"New value: +"Local directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)"
    • Changedexport_followed_artists1 field changed
      • changedInput schema / properties / output_dir / description
        Previous value: -"Local directory to write files into (default: ~/.spotify-mcp/portability)"New value: +"Local directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)"
    • Changedexport_library_json1 field changed
      • changedInput schema / properties / output_dir / description
        Previous value: -"Local directory to write files into (default: ~/.spotify-mcp/portability)"New value: +"Local directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)"
    • Changedexport_listening_history1 field changed
      • changedInput schema / properties / output_dir / description
        Previous value: -"Local directory to write files into (default: ~/.spotify-mcp/portability)"New value: +"Local directory to write into, confined to the output root (default ~/.spotify-mcp/portability, set SPOTIFY_MCP_PORTABILITY_DIR to move it)"
    • Changedexport_playlist2 fields changed
      • changedInput schema / properties / output_path / description
        Previous value: -"Write the full document to this local file instead of returning it inline"New value: +"Write the full document to this local file (relative paths resolve inside the output root, default ~/.spotify-mcp/exports) instead of returning it inline"
      • addedInput schema / properties / overwrite
        Added value: +{
        +  "default": false,
        +  "description": "Allow replacing an existing file at output_path (refused by default)",
        +  "type": "boolean"
        +}
    • Changedexport_profile_state1 field changed
      • changedInput schema / properties / output_dir / description
        Previous value: -"Directory to write the archive into (default: ~/.spotify-mcp/exports)"New value: +"Directory to write the archive into, confined to the output root (default ~/.spotify-mcp/exports, set SPOTIFY_MCP_EXPORT_DIR to move it)"
    • Changedfind_canonical_track2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedfind_collaborations2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedfind_show_by_publisher2 fields changed
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Catalogue rows fetched per request, 1-10 (Feb-2026 /search cap). Default 10",
        +  "maximum": 10,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Catalogue rows to skip before the page (Spotify /search max offset 1000). Default 0",
        +  "maximum": 1000,
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedfollow_artists2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify artist IDs to follow"New value: +"Artist IDs, spotify:artist: URIs, or artist URLs; CSV accepted"
      • addedInput schema / properties / ids / items / minLength
        Added value: +1
    • Changedfront_to_back_plan2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedgenre_dive_search2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_album3 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify album ID"New value: +"Spotify album ID, spotify:album: URI, or open.spotify.com/album URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
      • changedInput schema / properties / market / description
        Previous value: -"ISO country code; defaults to account country."New value: +"ISO country code; defaults to SPOTIFY_MCP_MARKET."
    • Changedget_album_tracks3 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify album ID"New value: +"Spotify album ID, spotify:album: URI, or open.spotify.com/album URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code. Defaults to the account country; affects track availability."New value: +"ISO 3166-1 alpha-2 country code. Defaults to SPOTIFY_MCP_MARKET; affects track availability."
    • Changedget_artist2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify artist ID"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
    • Changedget_artist_albums3 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify artist ID"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
      • changedInput schema / properties / market / description
        Previous value: -"ISO country code; defaults to account country."New value: +"ISO country code; defaults to SPOTIFY_MCP_MARKET."
    • Changedget_artist_appearances2 fields changed
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify artist ID"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / artist_id / minLength
        Added value: +1
    • Changedget_artist_singles2 fields changed
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify artist ID"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / artist_id / minLength
        Added value: +1
    • Changedget_artist_top_tracks3 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify artist ID"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code, e.g. 'US' โ€” defaults to the account country"New value: +"ISO 3166-1 alpha-2 code, e.g. 'US' โ€” defaults to SPOTIFY_MCP_MARKET"
    • Changedget_audiobook_chapters1 field changed
      • addedInput schema / properties / fetch_all
        Added value: +{
        +  "description": "When true, walk every chapter page up to the fetch-all cap (SPOTIFY_MCP_FETCH_ALL_CAP) instead of returning one page. Default: false",
        +  "type": "boolean"
        +}
    • Changedget_categories1 field changed
      • changedInput schema / properties / market / description
        Previous value: -"Canonical ISO 3166-1 alpha-2 market code, e.g. 'US'; forwarded to Spotify as market."New value: +"Canonical ISO 3166-1 alpha-2 market code, e.g. 'US'; sent as country."
    • Changedget_category1 field changed
      • changedInput schema / properties / category_id / description
        Previous value: -"Category ID from get_categories"New value: +"Category ID"
    • Changedget_category_playlists2 fields changed
      • changedInput schema / properties / category_id / description
        Previous value: -"Category ID (from get_categories)"New value: +"Category ID"
      • changedInput schema / properties / market / description
        Previous value: -"Canonical ISO 3166-1 alpha-2 market code, e.g. 'US'; forwarded to Spotify as market."New value: +"Canonical ISO 3166-1 alpha-2 market code, e.g. 'US'; sent as country."
    • Changedget_currently_playing1 field changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to the account market"New value: +"ISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to SPOTIFY_MCP_MARKET"
    • Changedget_episode2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify episode ID"New value: +"Spotify episode ID, spotify:episode: URI, or open.spotify.com/episode URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
    • Changedget_followed_artists1 field changed
      • addedInput schema / properties / fetch_all
        Added value: +{
        +  "description": "Walk every page instead of one page (ignores limit)",
        +  "type": "boolean"
        +}
    • Changedget_now_playing1 field changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to the account market"New value: +"ISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to SPOTIFY_MCP_MARKET"
    • Changedget_several_albums2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify albums IDs (1โ€“20 per request; longer lists are fetched in chunks of 20 and merged)"New value: +"Spotify album IDs, spotify:album: URIs, or open.spotify.com/album URLs (1โ€“20 per request; longer lists are fetched in chunks of 20 and merged)"
      • addedInput schema / properties / ids / items / description
        Added value: +"Spotify album ID, spotify:album: URI, or open.spotify.com/album URL"
    • Changedget_several_artists2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify artists IDs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"New value: +"Spotify artist IDs, spotify:artist: URIs, or open.spotify.com/artist URLs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"
      • addedInput schema / properties / ids / items / description
        Added value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedget_several_audiobooks2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify audiobooks IDs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"New value: +"Spotify audiobook IDs, spotify:audiobook: URIs, or open.spotify.com/audiobook URLs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"
      • addedInput schema / properties / ids / items / description
        Added value: +"Spotify audiobook ID, spotify:audiobook: URI, or open.spotify.com/audiobook URL"
    • Changedget_several_episodes2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify episodes IDs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"New value: +"Spotify episode IDs, spotify:episode: URIs, or open.spotify.com/episode URLs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"
      • addedInput schema / properties / ids / items / description
        Added value: +"Spotify episode ID, spotify:episode: URI, or open.spotify.com/episode URL"
    • Changedget_several_shows2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify shows IDs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"New value: +"Spotify show IDs, spotify:show: URIs, or open.spotify.com/show URLs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"
      • addedInput schema / properties / ids / items / description
        Added value: +"Spotify show ID, spotify:show: URI, or open.spotify.com/show URL"
    • Changedget_several_tracks2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify tracks IDs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"New value: +"Spotify track IDs, spotify:track: URIs, or open.spotify.com/track URLs (1โ€“50 per request; longer lists are fetched in chunks of 50 and merged)"
      • addedInput schema / properties / ids / items / description
        Added value: +"Spotify track ID, spotify:track: URI, or open.spotify.com/track URL"
    • Changedget_show2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify show ID"New value: +"Spotify show ID, spotify:show: URI, or open.spotify.com/show URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
    • Changedget_track2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Spotify track ID"New value: +"Spotify track ID, spotify:track: URI, or open.spotify.com/track URL"
      • addedInput schema / properties / id / minLength
        Added value: +1
    • Changedget_user_playlists_by_id1 field changed
      • changedInput schema / properties / user_id / description
        Previous value: -"Spotify user ID"New value: +"Spotify user ID, spotify:user: URI, or open.spotify.com/user URL"
    • Changedget_user_profile1 field changed
      • changedInput schema / properties / user_id / description
        Previous value: -"Spotify user ID"New value: +"Spotify user ID, spotify:user: URI, or open.spotify.com/user URL"
    • Changedhandoff1 field changed
      • addedInput schema / properties / play
        Added value: +{
        +  "description": "Resume playback on the target even if the session is currently paused (default: preserve the current play state)",
        +  "type": "boolean"
        +}
    • Changedhistory_search2 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"Substring to match (default: all)"New value: +"Substring to match"
      • addedInput schema / properties / scope
        Added value: +{
        +  "default": "all",
        +  "description": "Scope",
        +  "enum": [
        +    "portability",
        +    "backups",
        +    "history",
        +    "all"
        +  ],
        +  "type": "string"
        +}
    • Changedimport_from_sidecar1 field changed
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only when true"New value: +"Preview only, making no API calls at all. Writes happen only when explicitly set to false."
    • Changedimport_profile_state2 fields changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / mode / description
        Previous value: -"merge = add to existing stores; overwrite = replace them"New value: +"merge = union on each store's own keys; overwrite = replace, keeping a .bak"
    • Changedlibrary_hygiene1 field changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview cost only.",
        +  "type": "boolean"
        +}
    • Changedlistening_heatmap1 field changed
      • addedInput schema / properties / timezone
        Added value: +{
        +  "description": "IANA time zone for the day/hour slots, e.g. Asia/Tokyo (default SPOTIFY_MCP_TIMEZONE, else UTC). Never the host time zone.",
        +  "type": "string"
        +}
    • Changedlyric_snippet_search2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedpin_playlist2 fields changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "default": true,
        +  "description": "Preview only (default): pass dry_run: false to execute the follow.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / public / description
        Previous value: -"Whether the follow should be public (Spotify default: true)"New value: +"Must be true or omitted; the library endpoint has no visibility parameter."
    • Changedplay_from_search1 field changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code โ€” affects availability/relinking of results; defaults to the account market"New value: +"ISO 3166-1 alpha-2 country code โ€” affects availability/relinking of results; defaults to SPOTIFY_MCP_MARKET"
    • Changedplaylist_era_profile1 field changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market, e.g. 'US' โ€” when given, items are REFETCHED with this market so album release dates resolve (disclosed second GET)"New value: +"ISO 3166-1 alpha-2 market, e.g. 'US' โ€” when given, items are REFETCHED with this market and the profile is computed from THOSE rows, so album release dates resolve (disclosed second GET)"
    • Changedplaylist_sort1 field changed
      • changedInput schema / properties / sort_by / enum
        Previous value: -[
        -  "added_asc",
        -  "added_desc",
        -  "name_asc",
        -  "name_desc",
        -  "artist_asc",
        -  "duration_asc",
        -  "duration_desc",
        -  "popularity_desc"
        -]New value: +[
        +  "added_asc",
        +  "added_desc",
        +  "name_asc",
        +  "name_desc",
        +  "artist_asc",
        +  "duration_asc",
        +  "duration_desc"
        +]
    • Changedreceipt_lookup2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Exact receipt id (rcpt_N)"New value: +"Exact receipt id (rcpt_โ€ฆ-N)"
      • changedInput schema / properties / since / description
        Previous value: -"Only receipts issued... they carry no wall-clock; use id/uri filters mostly"New value: +"Only receipts issued at/after this date; receipts with no recorded issue time are always included"
    • Changedrefresh_smart_playlist1 field changed
      • changedInput schema / properties / playlist_id / description
        Previous value: -"Existing playlist id to refresh (else creates new)"New value: +"Playlist id to rebuild in place. Defaults to the id recorded by the previous refresh; otherwise the playlist is created."
    • Changedrestore_library_snapshot1 field changed
      • changedInput schema / properties / backup_path / description
        Previous value: -"Path to the snapshot JSON file from backup_library_snapshot"New value: +"Snapshot JSON path from backup_library (see list_backups)"
    • Changedsave_smart_playlist_rule1 field changed
      • changedInput schema / properties / rule / description
        Previous value: -"Rule object (source, filters, limit, etc.)"New value: +"Rule object: { source: top_tracks|recently_played|saved_tracks, time_range: short_term|medium_term|long_term, limit (1-500), artist_filter: string[], unique_artists: bool, scan_cap, description, public } โ€” defaults as create_smart_playlist, unknown keys ignored. A refresh records playlist_id/last_refreshed here."
    • Changedscene_sampler_search2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_advanced2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_by_isrc2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_deep1 field changed
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Index of the first result to walk per type, 0โ€“1000. The next_offset a call reports is the offset to pass here to continue. Default: 0",
        +  "maximum": 1000,
        +  "minimum": 0,
        +  "type": "integer"
        +}
    • Changedsearch_fresh2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_market_diff2 fields changed
      • changedInput schema / properties / types / description
        Previous value: -"Types to search (up to 2). Default: ['track']"New value: +"Type to search. Default: ['track']"
      • changedInput schema / properties / types / maxItems
        Previous value: -2New value: +1
    • Changedshow_episode_search2 fields changed
      • changedInput schema / properties / fetch_all / description
        Previous value: -"When true, walk all pages (up to cap) to find matches"New value: +"When true, walk from offset to the end (500-episode cap)"
      • changedInput schema / properties / show_id / description
        Previous value: -"Spotify show ID"New value: +"Spotify show ID, spotify:show: URI, or open.spotify.com/show URL"
    • Changedshow_episode_timeline3 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
      • changedInput schema / properties / max_results / description
        Previous value: -"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"New value: +"Max rows to return (default: SPOTIFY_MCP_FETCH_ALL_CAP or 500)"
    • Changedshow_new_episodes2 fields changed
      • addedInput schema / properties / cost_preview
        Added value: +{
        +  "description": "Cost preview only: make no API calls and return the request budget instead of the episode list. Use it to size a real call; it does not report any episodes. Default false.",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / dry_run
        Removed value: -{
        -  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        -  "type": "boolean"
        -}
    • Changedshow_recommendation_brief1 field changed
      • changedInput schema / properties / max_shows / description
        Previous value: -"Max per-show episode lookups (request budget). Default 50"New value: +"Max per-show episode lookups (request budget). Default 50; this also bounds the /me/episodes/contains calls (1 per 50 episodes found)"
    • Changedshow_runtime_stats2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedtaste_to_playlist3 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only (default true). False still only returns the list โ€” writes happen via Spotify tools."New value: +"Preview only: return the plan and write nothing. Pass false to actually create the playlist in your library and add the tracks that resolve to a Spotify id. Default true"
      • addedInput schema / properties / playlist_name
        Added value: +{
        +  "description": "Name for the playlist created when dry_run=false. Default: \"Taste: <user> (<seed>)\"",
        +  "maxLength": 100,
        +  "minLength": 1,
        +  "type": "string"
        +}
    • Changedtrack_album_bundle2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedundo_last_mutation2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only, and the default: pass dry_run: false to execute the rollback."
    • Changedundo_mutation2 fields changed
      • addedInput schema / properties / dry_run / default
        Added value: +true
      • changedInput schema / properties / dry_run / description
        Previous value: -"Preview only: validate inputs and describe exactly what would change without performing it"New value: +"Preview only, and the default: pass dry_run: false to execute the rollback."
    • Changedundo_preview1 field changed
      • changedInput schema / properties / mutation_id / description
        Previous value: -"Receipt id (rcpt_N) to preview reverting"New value: +"Receipt id (rcpt_โ€ฆ-N) to preview reverting"
    • Changedunfollow_artists2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Spotify artist IDs to unfollow"New value: +"Artist IDs, spotify:artist: URIs, or artist URLs; CSV accepted"
      • addedInput schema / properties / ids / items / minLength
        Added value: +1
    • Changedwhats_new1 field changed
      • changedInput schema / properties / since / anyOf
        Previous value: -[
        -  {
        -    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        -    "type": "string"
        -  },
        -  {
        -    "const": "last-check",
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "const": "last-check",
        +    "type": "string"
        +  },
        +  {
        +    "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +    "type": "string"
        +  }
        +]
    • Changedyear_explorer2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market code (e.g. 'US'); omit for 'from_token' behaviour"New value: +"ISO 3166-1 alpha-2 market code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
  3. 612 tool updatesv1.31.0
    • Changedadd_to_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedadd_to_queue2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedadded_on_this_day2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedalbum_anniversary_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedalbum_duration_report3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedalbum_edition_lint2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedalbum_focus_report3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / album_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify album ID, spotify:album: URI, or open.spotify.com/album URL"
    • Changedalbum_openers_report3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max album openers to return (default 100).",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
    • Changedalbum_representative_plan3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / album_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify album ID, spotify:album: URI, or open.spotify.com/album URL"
    • Changedalbum_track_explorer3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedalbum_track_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedalbums_runtime_batch2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedapply_device_presets2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedapply_scene2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedapply_snapshot_changes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedapply_volume_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedarchive_played_episodes3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / confirm / description
        Previous value: -"Confirm bulk removal when >50 fully-played episodes found"New value: +"Deprecated and ignored: it no longer authorises the write. Over 50 episodes requires elicitation confirmation, or SPOTIFY_MCP_CONFIRM=never."
    • Changedartist_affinity2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_album_completeness3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedartist_album_timeline3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_catalog_stats3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedartist_collab_network3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_collaboration_network4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_collection_gaps3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_complete_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_completeness_score2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_debut_release_finder2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_decade_span2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_deep_cuts4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_deep_dive3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedartist_discography_explorer3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max releases to return (default 40)."
    • Changedartist_discography_gaps4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_discography_search3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_discography_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_discography_timeline3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_era_map2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_era_sampler3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedartist_first_release3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedartist_genres_compact2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_latest_release_report3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedartist_latest_releases2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_listening_clock2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_live_albums_finder3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_name_disambiguator2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_reissue_detector3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max reissue groups to return (default 100)."
    • Changedartist_release_digest2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_release_type_breakdown2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_representation_census2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_scout_from_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_singles_timeline3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedartist_top_vs_saved2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartist_velocity_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedartistwatch_new_additions2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedaudiobook_chapter_map3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedaudiobook_library_progress4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_audiobooks / description
        Added value: +"How many audiobooks to scan (default 25, max 100)"
      • addedInput schema / properties / sort / description
        Added value: +"Report sort order"
    • Changedaudiobook_progress2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedaudiobooks_by_author2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedb_sides_detector3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedb_sides_finder4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedbackup_first2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedbackup_library2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedbalance_playlist_pairs7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlists to balance (2โ€“10)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Removedbase62_to_uri
    • Changedbatch_add_to_playlist6 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Target playlist ID or spotify:playlist: URI"New value: +"Target playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
    • Changedbatch_add_to_queue2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedbatch_parse_spotify_uris
    • Changedbinge_detector_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedbrowse_category_deepdive2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcancel_wind_down2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcanonicalize_spotify_uri4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / expected_kind
        Added value: +{
        +  "description": "Kind used to canonicalise bare IDs",
        +  "enum": [
        +    "track",
        +    "album",
        +    "artist",
        +    "playlist",
        +    "show",
        +    "episode",
        +    "audiobook",
        +    "user"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / uris / description
        Previous value: -"References to canonicalise"New value: +"Spotify references to canonicalise"
    • Changedcapture_playback_position2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcatalog_batch_lookup2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcategory_resolver2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedchapter_bookmarks3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / op / description
        Added value: +"Action to take: list bookmarks, save a chapter, or delete one. Default list"
    • Changedcheck_artist_releases4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / limit / description
        Previous value: -"Albums per artist to fetch, 1โ€“50. Default: 10"New value: +"Albums per artist to fetch, 1โ€“10. Default: 10"
      • changedInput schema / properties / limit / maximum
        Previous value: -50New value: +10
    • Changedcheck_episode_saved3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / episode_ids / items / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify episode ID, spotify:episode: URI, or open.spotify.com/episode URL"
    • Changedcheck_following_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcheck_in_library2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcheck_playlist_following7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_ids / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (1โ€“50), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 50,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedcheck_saved_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcheckpoint_playback2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedclassify_spotify_uris
    • Changedclean_all_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedclone_playlist_cover7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / image_index / description
        Added value: +"Which cover image to copy (0-based). Default 0"
      • addedInput schema / properties / source_playlist_id / description
        Added value: +"Source playlist ID, URI, or URL"
      • addedInput schema / properties / source_playlist_id / minLength
        Added value: +1
      • addedInput schema / properties / target_playlist_id / description
        Added value: +"Target playlist ID, URI, or URL"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
    • Changedcollab_density_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcollab_mix_from_followed2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcompare_devices2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcompare_playlist_covers11 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / playlist_a
        Added value: +{
        +  "description": "Canonical A playlist; provide with playlist_b or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / playlist_b
        Added value: +{
        +  "description": "Canonical B playlist; provide with playlist_a or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / playlist_id_a / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_id_a / minLength
        Added value: +1
      • addedInput schema / properties / playlist_id_b / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_id_b / minLength
        Added value: +1
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum rows to read from each playlist; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_id_a",
        -  "playlist_id_b"
        -]
    • Changedcontinue_last2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcopy_playlist6 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / source_playlist_id / description
        Previous value: -"Source playlist ID or spotify:playlist: URI"New value: +"Source playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / source_playlist_id / minLength
        Added value: +1
    • Removedcount_uris_by_type
    • Changedcreate_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedcreate_smart_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddaily_pick2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddead_library_finder2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddecade_sampler_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddedupe_playlist_apply2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddedupe_playlist_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddedupe_spotify_uris4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / expected_kind
        Added value: +{
        +  "description": "Kind used to interpret bare IDs; typed references retain their own kind",
        +  "enum": [
        +    "track",
        +    "album",
        +    "artist",
        +    "playlist",
        +    "show",
        +    "episode",
        +    "audiobook",
        +    "user"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / uris / description
        Previous value: -"References to dedupe"New value: +"Spotify references to deduplicate"
    • Changeddeep_cuts_finder3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changeddeep_dive_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddelete_playback_bookmark2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddelete_playlist_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddelete_scene2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddescribe_listening_session2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddescribe_queue2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddevice_health2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddevice_sync_state2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddevice_type_census2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddiff_playlist_snapshots2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddiff_playlists11 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / a / description
        Previous value: -"First playlist, as ID or spotify:playlist: URI"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / a / minLength
        Added value: +1
      • changedInput schema / properties / b / description
        Previous value: -"Second playlist, as ID or spotify:playlist: URI"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / b / minLength
        Added value: +1
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / playlist_a
        Added value: +{
        +  "description": "Canonical A playlist; provide with playlist_b or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / playlist_b
        Added value: +{
        +  "description": "Canonical B playlist; provide with playlist_a or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "a",
        -  "b"
        -]
    • Changeddiff_since_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddiscover_weekly_diff2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddiscovery_digest2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changeddiscovery_ratio2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedduplicate_saved_versions2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedepisode_bookmark2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedepisode_context_bundle2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedepisode_guest_census2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedepisode_resume2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedepisode_runtime_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedera_distribution_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedera_preference_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexplicit_content_ratio2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_all_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_followed_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_library_json2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_listening_history2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_playlist_json2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_playlist_markdown2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_profile_state2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_shows_opml2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexport_snapshot_bundle2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedexposure_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedextract_playlist_range2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedextract_spotify_id
    • Changedfeaturing_density_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfilter_by_genre2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfilter_playlist_by_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfilter_playlist_by_duration2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfilter_playlist_by_era2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_canonical_track2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_collaborations3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / artist_a / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify artist ID, spotify:artist: URI, or open.spotify.com/artist URL"
    • Changedfind_duplicate_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_duplicate_saved_tracks4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / include_near_duplicates / description
        Previous value: -"Also report same-song groups whose durations differ by more than ยฑ2s (remasters/re-recordings). Default false."New value: +"Also report same-title/artist groups with a different ISRC, release, or duration. Near duplicates are review-only and never recommend removal. Default false."
      • changedInput schema / properties / playlist_id / description
        Previous value: -"Optional playlist ID to cross-reference: members of each duplicate group that also appear in this playlist are flagged, so removal decisions can account for where the track is already curated."New value: +"Optional playlist ID to cross-reference: members of each duplicate group that also appear in this playlist are flagged, so cleanup or review decisions can account for where the track is already curated."
    • Removedfind_duplicate_spotify_uris
    • Changedfind_duplicate_tracks_across_playlists6 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlist IDs to compare (2โ€“20)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“20), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 20,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedfind_duplicates_in_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_lost_since_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_new_since_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_show_by_publisher2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfind_tool2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfollow_artists3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: show exactly which artists would be followed without calling the API",
        +  "type": "boolean"
        +}
    • Changedfollowed_playlists_audit2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedfollowing_analytics3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / group_by / description
        Added value: +"Rollup dimension for the report"
    • Changedforgotten_favorites2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedformat_spotify_uri6 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / id / description
        Previous value: -"Spotify entity ID"New value: +"Spotify ID (exactly 22 Base62 characters for catalog kinds; user IDs may be non-fixed)"
      • changedInput schema / properties / kind / description
        Previous value: -"Entity kind, e.g. track, album, artist, playlist, show, episode, audiobook, user"New value: +"Spotify entity kind"
      • addedInput schema / properties / kind / enum
        Added value: +[
        +  "track",
        +  "album",
        +  "artist",
        +  "playlist",
        +  "show",
        +  "episode",
        +  "audiobook",
        +  "user"
        +]
      • removedInput schema / properties / kind / minLength
        Removed value: -1
    • Changedfront_to_back_plan3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / album_id / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify album ID, spotify:album: URI, or open.spotify.com/album URL"
    • Changedgenre_dive_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedgenre_trends_over_time2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_album3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code. Defaults to the account country; affects track playability."New value: +"ISO country code; defaults to account country."
    • Changedget_album_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_artist_albums5 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"When true, walk all pages via getAllPages up to cap (fetch_all_cap) โ€” use for \"all\" queries. Default: false"New value: +"Fetch all pages up to cap. Default: false"
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code. Defaults to the account country; affects album availability."New value: +"ISO country code; defaults to account country."
      • changedInput schema / properties / offset / description
        Previous value: -"Index of the first album to return. Default: 0"New value: +"Album offset. Default: 0"
    • Changedget_artist_appearances2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_artist_discography4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / limit / description
        Previous value: -"Results per page, 1โ€“50. Default: 20"New value: +"Results per page, 1โ€“10. Default: 10"
      • changedInput schema / properties / limit / maximum
        Previous value: -50New value: +10
    • Changedget_artist_genres2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_artist_singles2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_artist_top_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_audiobook2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_audiobook_chapters2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_available_markets2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_categories4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code, e.g. 'US' (alias: market)"New value: +"Deprecated compatibility spelling for market. Prefer market; conflicting spellings are rejected."
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "Canonical ISO 3166-1 alpha-2 market code, e.g. 'US'; forwarded to Spotify as market.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
    • Changedget_category2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_category_playlists4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code, e.g. 'US' (alias: market)"New value: +"Deprecated compatibility spelling for market. Prefer market; conflicting spellings are rejected."
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "Canonical ISO 3166-1 alpha-2 market code, e.g. 'US'; forwarded to Spotify as market.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
    • Changedget_chapter2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_context_inspect2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_currently_playing2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_device_volume_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_devices2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_episode2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_episode_details2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_followed_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_me2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_newly_released_episodes3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / since / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedget_now_playing2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playback_context2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playback_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playlist_added_dates2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playlist_cover2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playlist_followers2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playlist_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_playlist_snapshot3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_id / description
        Added value: +"Playlist ID, spotify:playlist: URI, or URL"
    • Changedget_queue2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_queue_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_recently_played2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_saved_albums2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_saved_audiobooks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_saved_counts2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_saved_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_saved_shows2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_saved_tracks4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / fetch_all / default
        Added value: +false
      • addedInput schema / properties / offset / default
        Added value: +0
    • Changedget_several_albums2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_several_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_several_audiobooks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_several_chapters2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_several_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_several_shows2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_several_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_show2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_show_details2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedget_show_episodes
    • Changedget_show_latest_episode2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_top_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_top_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_track2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_user_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_user_playlists_by_id2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedget_user_profile2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedgrow_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedhandoff2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedhistory_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedimport_from_sidecar2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedimport_playlist3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_id / description
        Previous value: -"Target playlist ID or spotify:playlist: URI"New value: +"Target playlist ID, spotify:playlist: URI, or share URL"
    • Changedimport_profile_state2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedinspect_tool2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedinterleave_playlists_plan9 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlists to interleave (2โ€“10), in round order"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Existing playlist (ID or URI) to atomically overwrite with the interleave. Omit = read-only plan"New value: +"Existing playlist (ID, URI, or URL) to atomically overwrite with the interleave. Omit = read-only plan"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedis_local_census2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedis_valid_spotify_uri
    • Removedjoin_uri_list
    • Changedjump_to_chapter2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlabel_discography_explorer3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedlabel_explorer3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedlast_heard2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_coverage_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_genre_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_growth_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_growth_timeline2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_hygiene2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_snapshot_diff2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlibrary_to_playlist3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / limit / description
        Previous value: -"Max items to export. Default 500"New value: +"Max playable track URIs to export. Default: configured fetch-all cap"
    • Changedlibrary_value_summary2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_all_chapters2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_backups2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_device_presets2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_playback_bookmarks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_playback_states2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_playlist_snapshots2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_saved_shows2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_saved_snapshots2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_scenes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_sessions2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlist_show_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_clock2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_clock_heatmap2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_consistency_score2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_eras2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_gaps_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_heatmap2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_history_export2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_journal_append2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_recap_brief2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_session_close2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_session_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_session_start2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_sessions2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_streak_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlistening_streaks3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / max_items / description
        Previous value: -"Max history items to walk (default 150)"New value: +"Max history items to read (default 150); lower values stop the cursor walk early"
    • Changedlistening_week_in_time2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlongest_saved_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedlyric_snippet_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedmake_spotify_uri
    • Changedmark_episode_played_plan3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / episode_ids / items / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify episode ID, spotify:episode: URI, or open.spotify.com/episode URL"
    • Changedmarket_availability2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmarket_validate2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmerge_playlists12 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (1โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / sources / description
        Previous value: -"Source playlists as IDs or spotify:playlist: URIs"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / sources / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / sources / items / minLength
        Added value: +1
      • addedInput schema / properties / sources / maxItems
        Added value: +10
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Existing playlist to APPEND into (never cleared), as ID or spotify:playlist: URI"New value: +"Existing playlist to APPEND into (never cleared)"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
      • removedInput schema / required
        Removed value: -[
        -  "sources"
        -]
    • Changedmerge_playlists_plan7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlists to merge (2โ€“10), in order"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedmerge_snapshot_changes_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmonthly_listening_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmood_bucket_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmorning_briefing2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmost_replayed2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmove_items_between_playlists8 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / source_playlist_id / description
        Previous value: -"Source playlist ID or spotify:playlist: URI"New value: +"Source playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / source_playlist_id / minLength
        Added value: +1
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Target playlist ID or spotify:playlist: URI"New value: +"Target playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
    • Changedmove_tracks_between_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedmutation_log_export3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / format / description
        Added value: +"Export format. Default markdown"
    • Changedmute2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changednever_played_saved2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changednew_music_from_saved_artists3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changednew_music_from_top_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removednormalize_spotify_uri
    • Changednow_playing_history2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedopen_url_to_spotify_uri
    • Changedorphaned_artist_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedoverlap_playlists9 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / playlists / description
        Previous value: -"Two or more playlists, as IDs or spotify:playlist: URIs"New value: +"Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool"
      • addedInput schema / properties / playlists / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlists / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists / maxItems
        Added value: +10
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlists"
        -]
    • Changedparse_spotify_uri4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / expected_kind
        Added value: +{
        +  "description": "Require this entity kind",
        +  "enum": [
        +    "track",
        +    "album",
        +    "artist",
        +    "playlist",
        +    "show",
        +    "episode",
        +    "audiobook",
        +    "user"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / uri / description
        Previous value: -"Spotify URI, open.spotify.com URL, or bare ID to parse"New value: +"Spotify reference to parse"
    • Addedparse_spotify_uris
    • Changedpause2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedpause_everywhere2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedpeek_next2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedpin_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplan_podcast_session2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplan_volume_level_across_devices2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplay2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplay_at5 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / context_uri / description
        Previous value: -"Context URI (playlist/album URI) โ€” XOR uris"New value: +"Context URI (playlist/album/artist) โ€” XOR uris"
      • changedInput schema / properties / uris / description
        Previous value: -"Track/episode URIs"New value: +"Up to 100 track/episode URIs โ€” XOR context_uri"
      • addedInput schema / properties / uris / maxItems
        Added value: +100
    • Changedplay_from_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplay_on2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplayback_compare_states2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplayback_health_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplayback_timeline2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Addedplayback_timer_status
    • Changedplaylist_add_by_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_artist_heat2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_balance2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_changelog2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_chunk_preview2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_clone_live2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_clone_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_collab_toggle5 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / collaborative / description
        Added value: +"Target collaborative state for the playlist"
      • addedInput schema / properties / playlist_id / description
        Added value: +"Playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / public / description
        Added value: +"Target visibility: true makes the playlist public"
    • Changedplaylist_collaboration_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_cover_from_track2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_dedupe_advanced3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_diff9 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_a
        Added value: +{
        +  "description": "Canonical A playlist; provide with playlist_b or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / playlist_a_id / description
        Previous value: -"First playlist, as ID or spotify:playlist: URI"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_a_id / minLength
        Added value: +1
      • addedInput schema / properties / playlist_b
        Added value: +{
        +  "description": "Canonical B playlist; provide with playlist_a or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / playlist_b_id / description
        Previous value: -"Second playlist, as ID or spotify:playlist: URI"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_b_id / minLength
        Added value: +1
      • removedInput schema / required
        Removed value: -[
        -  "playlist_a_id",
        -  "playlist_b_id"
        -]
    • Changedplaylist_difference_plan11 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / base_playlist_id / description
        Previous value: -"Base playlist (ID or URI) whose survivors are kept"New value: +"Base playlist (ID, URI, or URL) whose survivors are kept"
      • addedInput schema / properties / base_playlist_id / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (1โ€“5), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 5,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / subtract_playlist_ids / description
        Previous value: -"Playlists whose tracks are removed from the base (1โ€“5)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / subtract_playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / subtract_playlist_ids / items / minLength
        Added value: +1
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Existing playlist (ID or URI) to atomically overwrite with the difference. Omit = read-only plan"New value: +"Existing playlist (ID, URI, or URL) to atomically overwrite with the difference. Omit = read-only plan"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
      • changedInput schema / required
        Previous value: -[
        -  "base_playlist_id",
        -  "subtract_playlist_ids"
        -]New value: +[
        +  "base_playlist_id"
        +]
    • Changedplaylist_edit_journal2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_era_profile2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_exclude_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_expression_algebra2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_fill_from_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_filter_runtime3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_flip_order3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_from_tags3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / mode / description
        Added value: +"create builds a new playlist; refresh rewrites the existing one. Default create"
    • Changedplaylist_health_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_history2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_intersect9 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • changedInput schema / properties / source_playlist_ids / description
        Previous value: -"Playlists to intersect, as IDs or spotify:playlist: URIs (2โ€“10)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / source_playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / source_playlist_ids / items / minLength
        Added value: +1
      • changedInput schema / properties / target_playlist_id / description
        Previous value: -"Existing playlist (ID or spotify:playlist: URI) to ATOMICALLY OVERWRITE with the result. Omit to compute read-only."New value: +"Existing playlist (ID, URI, or URL) to ATOMICALLY OVERWRITE with the result. Omit to compute read-only."
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
      • removedInput schema / required
        Removed value: -[
        -  "source_playlist_ids"
        -]
    • Changedplaylist_intersection7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlists to intersect (2โ€“10)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedplaylist_keep_artist3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_keep_only2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_move_block3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_move_to_top2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_names_bulk_normalize2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_overlap_matrix7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlists to compare (2โ€“10)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedplaylist_pair_check9 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_a
        Added value: +{
        +  "description": "Canonical A playlist; provide with playlist_b or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / playlist_a_id / description
        Previous value: -"First playlist, as ID or spotify:playlist: URI"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_a_id / minLength
        Added value: +1
      • addedInput schema / properties / playlist_b
        Added value: +{
        +  "description": "Canonical B playlist; provide with playlist_a or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / playlist_b_id / description
        Previous value: -"Second playlist, as ID or spotify:playlist: URI"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_b_id / minLength
        Added value: +1
      • removedInput schema / required
        Removed value: -[
        -  "playlist_a_id",
        -  "playlist_b_id"
        -]
    • Changedplaylist_remove_artist3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_resequence3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_reverse3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_id / description
        Added value: +"Playlist ID, spotify:playlist: URI, or URL"
    • Changedplaylist_rotate3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_seed_shuffle3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_shuffle4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_id / description
        Added value: +"Playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / seed / description
        Added value: +"Deterministic shuffle seed; omit for a random order"
    • Changedplaylist_slice2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_snapshot_detail2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_sort4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / playlist_id / description
        Added value: +"Playlist ID, spotify:playlist: URI, or URL"
      • addedInput schema / properties / sort_by / description
        Added value: +"Sort key applied to the playlist"
    • Changedplaylist_staleness_report3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / sort / description
        Added value: +"Report sort order"
    • Changedplaylist_staleness_score2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_strip_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_subtract14 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / base_playlist_id / description
        Added value: +"Base playlist ID, URI, or URL. Optional only for the deprecated positional form, where playlists[0] is the base."
      • addedInput schema / properties / base_playlist_id / minLength
        Added value: +1
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (1โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / subtract_playlist_ids / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / subtract_playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / subtract_playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / subtract_playlist_ids / maxItems
        Added value: +10
      • removedInput schema / required
        Removed value: -[
        -  "base_playlist_id",
        -  "subtract_playlist_ids"
        -]
    • Changedplaylist_swap_positions3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / include_full_order
        Added value: +{
        +  "description": "Opt in to the full planned order; otherwise structuredContent is capped",
        +  "type": "boolean"
        +}
    • Changedplaylist_symmetric_difference11 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / playlist_a
        Added value: +{
        +  "description": "Canonical A playlist; provide with playlist_b or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / playlist_b
        Added value: +{
        +  "description": "Canonical B playlist; provide with playlist_a or one complete documented legacy pair",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedInput schema / properties / playlist_id_a / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_id_a / minLength
        Added value: +1
      • addedInput schema / properties / playlist_id_b / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide a complete pair or canonical playlist_a/playlist_b."
      • addedInput schema / properties / playlist_id_b / minLength
        Added value: +1
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum rows to read from each playlist; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_id_a",
        -  "playlist_id_b"
        -]
    • Changedplaylist_table_of_contents2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_template_apply2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_to_library2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_trim5 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / keep / description
        Added value: +"How many items to keep"
      • addedInput schema / properties / keep_which / description
        Added value: +"Which end of the playlist to keep items from. Default first"
      • addedInput schema / properties / playlist_id / description
        Added value: +"Playlist ID, spotify:playlist: URI, or URL"
    • Changedplaylist_trim_to_duration2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedplaylist_union15 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / dedupe / description
        Added value: +"Drop duplicate URIs across the merged sources. Default true"
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "Source page size, 1โ€“100. Default: 100",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / scan_cap
        Added value: +{
        +  "description": "Maximum source rows to scan; bounded by SPOTIFY_MCP_FETCH_ALL_CAP",
        +  "maximum": 10000,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / source_playlist_ids / description
        Added value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / source_playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / source_playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / target_name / description
        Added value: +"Name for a newly created target playlist; provide exactly one of target_playlist_id or target_name"
      • addedInput schema / properties / target_playlist_id / description
        Added value: +"Existing target playlist (ID, URI, or URL); provide exactly one of target_playlist_id or target_name"
      • addedInput schema / properties / target_playlist_id / minLength
        Added value: +1
      • removedInput schema / required
        Removed value: -[
        -  "source_playlist_ids"
        -]
    • Changedplaylist_union_preview7 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / playlist_ids / description
        Previous value: -"Playlists to union (2โ€“10)"New value: +"Deprecated one-release alias supported through v2.0; removed in v2.1. Provide this complete alias or canonical playlists."
      • addedInput schema / properties / playlist_ids / items / description
        Added value: +"Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field"
      • addedInput schema / properties / playlist_ids / items / minLength
        Added value: +1
      • addedInput schema / properties / playlists
        Added value: +{
        +  "description": "Canonical ordered playlists (2โ€“10), or provide the complete documented legacy alias accepted by this tool",
        +  "items": {
        +    "description": "Playlist ID, spotify:playlist: URI, or Spotify playlist URL; use this reference in the canonical or documented legacy field",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 10,
        +  "minItems": 2,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_ids"
        -]
    • Changedpredict_next_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedprune_old_snapshots2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedpublisher_portfolio3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_shows
        Added value: +{
        +  "description": "Max per-show episode lookups (request budget). Default 20",
        +  "maximum": 200,
        +  "minimum": 1,
        +  "type": "integer"
        +}
    • Changedqueue_duplicate_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_next2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_next_episode2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_profile2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_prune_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_replace_via_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedqueue_runtime_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedquick_save_now2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedquota_probe2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedread_playlist_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedreceipt_lookup2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrecord_feedback2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrefresh_smart_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_duplicate_playlist_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_from_library2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_from_library_by_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_from_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_playlist_range2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_saved_episode3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / episode_ids / items / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify episode ID, spotify:episode: URI, or open.spotify.com/episode URL"
    • Changedremove_saved_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedremove_saved_shows3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / show_ids / items / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify show ID, spotify:show: URI, or open.spotify.com/show URL"
    • Changedremove_unavailable_playlist_items4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_removals
        Added value: +{
        +  "description": "Destructive cap: maximum unavailable playlist rows to remove; defaults to all detected unavailable rows",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • removedInput schema / properties / max_results
        Removed value: -{
        -  "description": "Max unavailable items to remove (default 100)",
        -  "maximum": 100,
        -  "minimum": 1,
        -  "type": "integer"
        -}
    • Changedrename_device2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedreorder_playlist_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrepeat_listener_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrepeat_queue_toggle2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedreplace_playlist_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedreplay_session2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedresolve_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrestore_library_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrestore_playback_state2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrestore_playlist_from_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrestore_playlist_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedresume_playback_position2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedreverse_playlist_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedroom_level2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedrotate_playlist_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsample_playlist_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_artist_new_releases4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / limit / description
        Previous value: -"Albums to fetch, 1โ€“50. Default: 20"New value: +"Albums to fetch, 1โ€“10. Default: 10"
      • changedInput schema / properties / limit / maximum
        Previous value: -50New value: +10
    • Changedsave_discover_weekly2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_episode3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / episode_ids / items / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify episode ID, spotify:episode: URI, or open.spotify.com/episode URL"
    • Changedsave_items2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_playback_state2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_queue_as_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_release_radar2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_scene2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_show_digest2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_smart_playlist_rule2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsave_to_library2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_albums_by_decade2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_albums_by_label2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_albums_by_type2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_albums_by_year2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_library_delta2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_runtime_by_era2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_shows_publisher_census2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_track_age_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_tracks_by_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_tracks_roulette2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsaved_vs_playlist_coverage2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedscene_sampler_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedschedule_wind_down3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Changedscope_audit2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / offset / default
        Added value: +0
    • Changedsearch_advanced3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedsearch_albums2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_audiobooks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_by_isrc2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_deep2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_fresh3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedsearch_history2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_history_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_market_diff2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_playlists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_rerun2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_saved_albums2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_saved_audiobooks3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / scan_cap / description
        Added value: +"Maximum saved items to scan; defaults to SPOTIFY_MCP_FETCH_ALL_CAP"
    • Changedsearch_saved_episodes3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / scan_cap / description
        Added value: +"Maximum saved items to scan; defaults to SPOTIFY_MCP_FETCH_ALL_CAP"
    • Changedsearch_saved_shows3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / scan_cap / description
        Added value: +"Maximum saved items to scan; defaults to SPOTIFY_MCP_FETCH_ALL_CAP"
    • Changedsearch_saved_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_shows2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_within_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedseek2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedseek_relative2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsession_length_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsession_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedset_device_volume_preset2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedset_repeat2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedset_shuffle2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedset_volume2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshortest_saved_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshow_activity_feed2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshow_backlog_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshow_backlog_report3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / sort / description
        Added value: +"Report sort order"
    • Changedshow_episode_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshow_episode_timeline3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedshow_new_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshow_recommendation_brief3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / since / pattern
        Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • Changedshow_runtime_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshows_release_calendar2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshows_without_new_episodes2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedshuffle_state_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsidecar_export_bundle2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedskip_n2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedskip_next2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedskip_previous2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsleep_timer2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsleep_timer_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_added_at_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_changelog2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_diff_summary2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_disk_usage2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_integrity_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_integrity_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_new_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_registry_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_removed_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_retention_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsnapshot_stats_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsort_playlist_apply2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsort_playlist_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedsort_uris_by_kind
    • Changedsplit_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsplit_playlist_by_count2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsplit_playlist_by_duration2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsplit_queue_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removedsplit_uri_list
    • Changedspotify_doctor5 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / response_format / default
        Added value: +"concise"
      • changedInput schema / properties / response_format / description
        Previous value: -"Response format: concise (default) returns human-readable text, detailed adds metadata, json returns structured data"New value: +"'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object"
      • changedInput schema / properties / verbose / description
        Previous value: -"Include per-check technical detail lines in the prose output"New value: +"Include per-check technical detail lines when response_format is concise"
    • Removedspotify_uri_kind
    • Addedspotify_uri_stats
    • Removedspotify_uri_to_open_url
    • Changedstale_saved_shows_plan2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstart_podcast_session2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_album_date_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_album_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_artist_affinity2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_artist_date_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_artist_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_catalog_album2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_catalog_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_catalog_track2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_charts_albums2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_charts_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_charts_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_charts_users2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_exposure_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_forgotten_favorites2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_friend_count2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_friends2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_genre_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_listening_eras2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_listening_sessions2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_now_playing2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_recaps2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_recent_streams2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_record_feedback2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_records_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_resolve_user2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_search2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_streams_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_taste_profile2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_taste_recommendations2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_albums2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_albums_from_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_genres2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_tracks_from_album2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_top_tracks_from_artist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_track_date_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedstatsfm_track_stats2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsubscribe_to_show3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedInput schema / properties / show_ids / items / description
        Previous value: -"Spotify ID, URI (spotify:...), or open.spotify.com URL โ€” all resolve to the same entity"New value: +"Spotify show ID, spotify:show: URI, or open.spotify.com/show URL"
    • Changedsurprise_me2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedswitch_device2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtag_listening_session2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtag_management2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtake_playlist_snapshot2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_checkpoint2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_checkpoint_diff2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_daily_brief2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_diamond_rotation2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_era_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_forgotten_bangers2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_genre_bridge2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_listening_clock2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_novelty_loyalty2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_obsession_ladder2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_profile2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_recommendations2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_revival_queue2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_shift_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_to_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtaste_weekly_recap2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtitle_length_outliers2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtoolset_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtop_artist_leaderboard2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtop_artist_ranking_delta2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtop_artists_by_range2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtop_genre_census2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtop_track_leaderboard2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtop_track_ranking_delta2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtrack_album_bundle2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtrack_enrichment_batch3 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / max_results / description
        Added value: +"Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)"
    • Changedtrack_release_origin2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtrack_rotation_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtransfer_playback2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedtransfer_playback_with_state2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedundo_last_mutation2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedundo_mutation2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedundo_preview2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedunfollow_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedunmute2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedunpin_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedunplayable_saved_check2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedunsave_orphan_tracks2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedunsubscribe_from_show2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedupdate_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedupload_playlist_cover2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Removeduri_kind_stats
    • Removeduri_namespace_census
    • Removeduri_shorthand_expand
    • Removeduri_to_base62
    • Removedvalidate_spotify_uri
    • Changedverify_receipt2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedvolume_ramp2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedvolume_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedvolume_step2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedwatch_artists2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedweek_in_review_playlist2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedweekday_heatmap2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedweekday_listening_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedweekly_rotation_report2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedwhats_new2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedwhere_was_i2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Addedwind_down_status
    • Changedyear_explorer2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedyear_in_review2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • addedInput schema / additionalProperties
        Added value: +false
  4. 19 tool updatesv1.30.0
    • Addedstatsfm_artist_affinity
    • Addedstatsfm_exposure_check
    • Addedstatsfm_forgotten_favorites
    • Addedstatsfm_listening_eras
    • Addedstatsfm_listening_sessions
    • Addedstatsfm_record_feedback
    • Addedstatsfm_taste_profile
    • Addedstatsfm_taste_recommendations
    • Addedtaste_daily_brief
    • Addedtaste_diamond_rotation
    • Addedtaste_era_playlist
    • Addedtaste_forgotten_bangers
    • Addedtaste_genre_bridge
    • Addedtaste_listening_clock
    • Addedtaste_novelty_loyalty
    • Addedtaste_obsession_ladder
    • Addedtaste_revival_queue
    • Addedtaste_to_playlist
    • Addedtaste_weekly_recap
  5. 38 tool updatesv1.29.0
    • Addedartist_affinity
    • Addedexposure_check
    • Addedforgotten_favorites
    • Addedlistening_eras
    • Addedlistening_sessions
    • Addedrecord_feedback
    • Addedstatsfm_album_date_stats
    • Addedstatsfm_album_stats
    • Addedstatsfm_artist_date_stats
    • Addedstatsfm_artist_stats
    • Addedstatsfm_catalog_album
    • Addedstatsfm_catalog_artist
    • Addedstatsfm_catalog_track
    • Addedstatsfm_charts_albums
    • Addedstatsfm_charts_artists
    • Addedstatsfm_charts_tracks
    • Addedstatsfm_charts_users
    • Addedstatsfm_friend_count
    • Addedstatsfm_friends
    • Addedstatsfm_genre_artists
    • Addedstatsfm_now_playing
    • Addedstatsfm_recaps
    • Addedstatsfm_recent_streams
    • Addedstatsfm_records_artists
    • Addedstatsfm_resolve_user
    • Addedstatsfm_search
    • Addedstatsfm_streams_stats
    • Addedstatsfm_top_albums
    • Addedstatsfm_top_albums_from_artist
    • Addedstatsfm_top_artists
    • Addedstatsfm_top_genres
    • Addedstatsfm_top_tracks
    • Addedstatsfm_top_tracks_from_album
    • Addedstatsfm_top_tracks_from_artist
    • Addedstatsfm_track_date_stats
    • Addedstatsfm_track_stats
    • Addedtaste_profile
    • Addedtaste_recommendations
  6. 64 tool updatesv1.28.0
    • Changedaudiobook_progress2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"Market"New value: +"Market, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedbackup_first1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedbatch_add_to_queue
    • Changedbrowse_category_deepdive2 fields changed
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / country / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedcategory_resolver2 fields changed
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / country / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedclean_all_playlists2 fields changed
      • changedInput schema / properties / apply / description
        Previous value: -"false (default): report only โ€” nothing is changed. true: execute the cleanup across all playlists with duplicates."New value: +"Deprecated alias for dry_run โ€” prefer dry_run. false (default): report only. true: execute the cleanup across all playlists with duplicates. If both are given, dry_run wins."
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only โ€” when true, nothing is changed; when false via dry_run=false or apply=true, executes the cleanup",
        +  "type": "boolean"
        +}
    • Changedcreate_smart_playlist1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changeddiff_since_snapshot1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedfind_duplicate_playlists1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedfind_show_by_publisher2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for the search"New value: +"ISO 3166-1 alpha-2 market for the search, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedfind_tool1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_album_tracks1 field changed
      • addedInput schema / properties / fetch_all
        Added value: +{
        +  "description": "When true, walk all pages via getAllPages up to cap (fetch_all_cap) โ€” use for \"all\" queries. Default: false",
        +  "type": "boolean"
        +}
    • Changedget_artist_albums1 field changed
      • addedInput schema / properties / fetch_all
        Added value: +{
        +  "description": "When true, walk all pages via getAllPages up to cap (fetch_all_cap) โ€” use for \"all\" queries. Default: false",
        +  "type": "boolean"
        +}
    • Changedget_artist_discography2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_artist_top_tracks2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code. Defaults to the account country."New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US' โ€” defaults to the account country"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_categories2 fields changed
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US' (alias: market)"
      • addedInput schema / properties / country / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_category2 fields changed
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / country / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_category_playlists2 fields changed
      • changedInput schema / properties / country / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US' (alias: market)"
      • addedInput schema / properties / country / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_episode2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_episode_details2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for availability"New value: +"ISO 3166-1 alpha-2 market for availability, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_playlist_followers1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_playlist_items1 field changed
      • addedInput schema / properties / fetch_all
        Added value: +{
        +  "description": "Fetch every item across pages (up to 500), continuing FROM offset rather than restarting at 0. limit is the page size. Note: library tools' fetch_all instead ignores offset โ€” contracts differ between modules (#110).",
        +  "type": "boolean"
        +}
    • Changedget_saved_albums2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_saved_episodes2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_saved_tracks2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_show_details2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for availability"New value: +"ISO 3166-1 alpha-2 market for availability, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedget_show_episodes1 field changed
      • addedInput schema / properties / fetch_all
        Added value: +{
        +  "description": "When true, walk all pages via getAllPages up to cap (fetch_all_cap) โ€” use for \"all\" queries. Default: false",
        +  "type": "boolean"
        +}
    • Changedget_show_latest_episode2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for availability"New value: +"ISO 3166-1 alpha-2 market for availability, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedimport_playlist1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedinspect_tool1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedlist_playlist_snapshots1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedlist_show_episodes2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for availability"New value: +"ISO 3166-1 alpha-2 market for availability, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedmarket_availability3 fields changed
      • removedInput schema / properties / markets / items / maxLength
        Removed value: -5
      • removedInput schema / properties / markets / items / minLength
        Removed value: -2
      • addedInput schema / properties / markets / items / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedmarket_validate3 fields changed
      • removedInput schema / properties / markets / items / maxLength
        Removed value: -2
      • removedInput schema / properties / markets / items / minLength
        Removed value: -2
      • addedInput schema / properties / markets / items / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedpause1 field changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Changedplaylist_collaboration_report1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedplaylist_era_profile2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market. When given, items are REFETCHED with this market so album release dates resolve (disclosed second GET)."New value: +"ISO 3166-1 alpha-2 market, e.g. 'US' โ€” when given, items are REFETCHED with this market so album release dates resolve (disclosed second GET)"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedplaylist_fill_from_search4 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for search"New value: +"ISO 3166-1 alpha-2 market for search, e.g. 'US'"
      • removedInput schema / properties / market / maxLength
        Removed value: -2
      • removedInput schema / properties / market / minLength
        Removed value: -2
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedplaylist_health_check1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedplaylist_staleness_score2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for availability"New value: +"ISO 3166-1 alpha-2 market for availability, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedquick_save_now2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO-3166 market code passed on the player read"New value: +"ISO-3166 market code passed on the player read, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedremove_unavailable_playlist_items1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedsave_artist_new_releases2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsaved_tracks_by_artist2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 market for the artist search"New value: +"ISO 3166-1 alpha-2 market for the artist search, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US' โ€” uppercased automatically"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_albums2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_artists2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_audiobooks2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_deep2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_episodes2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_market_diff6 fields changed
      • removedInput schema / properties / market_a / maxLength
        Removed value: -2
      • removedInput schema / properties / market_a / minLength
        Removed value: -2
      • addedInput schema / properties / market_a / pattern
        Added value: +"^[A-Za-z]{2}$"
      • removedInput schema / properties / market_b / maxLength
        Removed value: -2
      • removedInput schema / properties / market_b / minLength
        Removed value: -2
      • addedInput schema / properties / market_b / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_playlists2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_shows2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_tracks2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsearch_within_playlist2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"Market for track relinking"New value: +"Market for track relinking, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedseek1 field changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Changedset_repeat1 field changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Changedset_shuffle1 field changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Changedset_volume1 field changed
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Changedshow_episode_search2 fields changed
      • changedInput schema / properties / market / description
        Previous value: -"ISO 3166-1 alpha-2 country code"New value: +"ISO 3166-1 alpha-2 country code, e.g. 'US'"
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
    • Changedsnapshot_playlist1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedspotify_doctor1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "description": "Response format: concise (default) returns human-readable text, detailed adds metadata, json returns structured data",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedundo_last_mutation1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedundo_mutation1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
  7. 550 tool updatesv1.26.1
    • Changedadd_to_playlist4 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / check_duplicates
        Added value: +{
        +  "description": "Skip URIs that are already in the playlist instead of appending them (default: false)",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / position / maximum
        Added value: +9007199254740991
    • Changedadd_to_queue3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedadded_on_this_day
    • Addedalbum_anniversary_check
    • Addedalbum_duration_report
    • Addedalbum_edition_lint
    • Addedalbum_focus_report
    • Addedalbum_openers_report
    • Addedalbum_representative_plan
    • Addedalbum_track_explorer
    • Addedalbum_track_stats
    • Addedalbums_runtime_batch
    • Addedapply_device_presets
    • Addedapply_scene
    • Addedapply_snapshot_changes
    • Addedapply_volume_plan
    • Addedarchive_played_episodes
    • Addedartist_album_completeness
    • Addedartist_album_timeline
    • Addedartist_catalog_stats
    • Addedartist_collab_network
    • Addedartist_collaboration_network
    • Addedartist_collection_gaps
    • Addedartist_complete_check
    • Addedartist_completeness_score
    • Addedartist_debut_release_finder
    • Addedartist_decade_span
    • Addedartist_deep_cuts
    • Addedartist_deep_dive
    • Addedartist_discography_explorer
    • Addedartist_discography_gaps
    • Addedartist_discography_search
    • Addedartist_discography_stats
    • Addedartist_discography_timeline
    • Addedartist_era_map
    • Addedartist_era_sampler
    • Addedartist_first_release
    • Addedartist_genres_compact
    • Addedartist_latest_release_report
    • Addedartist_latest_releases
    • Addedartist_listening_clock
    • Addedartist_live_albums_finder
    • Addedartist_name_disambiguator
    • Addedartist_reissue_detector
    • Addedartist_release_digest
    • Addedartist_release_type_breakdown
    • Addedartist_representation_census
    • Addedartist_scout_from_playlists
    • Addedartist_singles_timeline
    • Addedartist_top_vs_saved
    • Addedartist_velocity_report
    • Addedartistwatch_new_additions
    • Addedaudiobook_chapter_map
    • Addedaudiobook_library_progress
    • Addedaudiobook_progress
    • Addedaudiobooks_by_author
    • Addedb_sides_detector
    • Addedb_sides_finder
    • Addedbackup_first
    • Addedbackup_library
    • Addedbalance_playlist_pairs
    • Addedbase62_to_uri
    • Addedbatch_add_to_playlist
    • Addedbatch_parse_spotify_uris
    • Addedbinge_detector_report
    • Addedbrowse_category_deepdive
    • Addedcancel_wind_down
    • Addedcanonicalize_spotify_uri
    • Addedcapture_playback_position
    • Addedcatalog_batch_lookup
    • Addedcategory_resolver
    • Addedchapter_bookmarks
    • Addedcheck_artist_releases
    • Addedcheck_episode_saved
    • Changedcheck_following_artists3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedcheck_in_library
    • Addedcheck_playlist_following
    • Changedcheck_saved_items5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / uris / description
        Previous value: -"Spotify URIs to check (accepts tracks, albums, shows, episodes, artists, playlists)"New value: +"Spotify URIs to check (accepts tracks, albums, shows, episodes, audiobooks)"
      • changedInput schema / properties / uris / maxItems
        Previous value: -40New value: +50
    • Addedcheckpoint_playback
    • Addedclassify_spotify_uris
    • Addedclean_all_playlists
    • Addedclone_playlist_cover
    • Addedcollab_density_report
    • Addedcollab_mix_from_followed
    • Addedcompare_devices
    • Addedcompare_playlist_covers
    • Addedcontinue_last
    • Addedcopy_playlist
    • Addedcount_uris_by_type
    • Changedcreate_playlist2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Addedcreate_smart_playlist
    • Addeddaily_pick
    • Addeddead_library_finder
    • Addeddecade_sampler_plan
    • Addeddedupe_playlist_apply
    • Addeddedupe_playlist_plan
    • Addeddedupe_spotify_uris
    • Addeddeep_cuts_finder
    • Addeddeep_dive_report
    • Addeddelete_playback_bookmark
    • Addeddelete_playlist_snapshot
    • Addeddelete_scene
    • Addeddescribe_listening_session
    • Addeddescribe_queue
    • Addeddevice_health
    • Addeddevice_sync_state
    • Addeddevice_type_census
    • Addeddiff_playlist_snapshots
    • Addeddiff_playlists
    • Addeddiff_since_snapshot
    • Addeddiscover_weekly_diff
    • Addeddiscovery_digest
    • Addeddiscovery_ratio
    • Addedduplicate_saved_versions
    • Addedepisode_bookmark
    • Addedepisode_context_bundle
    • Addedepisode_guest_census
    • Addedepisode_resume
    • Addedepisode_runtime_report
    • Addedera_distribution_report
    • Addedera_preference_report
    • Addedexplicit_content_ratio
    • Addedexport_all_playlists
    • Addedexport_followed_artists
    • Addedexport_library_json
    • Addedexport_listening_history
    • Addedexport_playlist
    • Addedexport_playlist_json
    • Addedexport_playlist_markdown
    • Addedexport_profile_state
    • Addedexport_shows_opml
    • Addedexport_snapshot_bundle
    • Addedextract_playlist_range
    • Addedextract_spotify_id
    • Addedfeaturing_density_report
    • Addedfilter_by_genre
    • Addedfilter_playlist_by_artist
    • Addedfilter_playlist_by_duration
    • Addedfilter_playlist_by_era
    • Addedfind_canonical_track
    • Addedfind_collaborations
    • Addedfind_duplicate_playlists
    • Addedfind_duplicate_saved_tracks
    • Addedfind_duplicate_spotify_uris
    • Addedfind_duplicate_tracks_across_playlists
    • Addedfind_duplicates_in_playlist
    • Addedfind_lost_since_snapshot
    • Addedfind_new_since_snapshot
    • Addedfind_show_by_publisher
    • Addedfind_tool
    • Addedfollow_artists
    • Addedfollowed_playlists_audit
    • Addedfollowing_analytics
    • Addedformat_spotify_uri
    • Addedfront_to_back_plan
    • Addedgenre_dive_search
    • Addedgenre_trends_over_time
    • Changedget_album4 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code. Defaults to the account country; affects track playability.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_album_tracks5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code. Defaults to the account country; affects track availability.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_artist2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_artist_albums7 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / limit / description
        Previous value: -"Results per page, 1โ€“50. Default: 20"New value: +"Results per page, 1โ€“10. Default: 10"
      • changedInput schema / properties / limit / maximum
        Previous value: -50New value: +10
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code. Defaults to the account country; affects album availability.",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Index of the first album to return. Default: 0",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_artist_appearances
    • Addedget_artist_discography
    • Addedget_artist_genres
    • Addedget_artist_singles
    • Addedget_artist_top_tracks
    • Changedget_audiobook3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_audiobook_chapters5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_available_markets
    • Addedget_categories
    • Addedget_category
    • Addedget_category_playlists
    • Changedget_chapter3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_context_inspect
    • Changedget_currently_playing3 fields changed
      • addedInput schema / properties / additional_types
        Added value: +{
        +  "default": [
        +    "track",
        +    "episode"
        +  ],
        +  "description": "Item types to include in the response. Default: ['track', 'episode']",
        +  "items": {
        +    "enum": [
        +      "track",
        +      "episode"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to the account market",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_device_volume_report
    • Changedget_devices2 fields changed
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_episode2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_episode_details
    • Changedget_followed_artists3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_me1 field changed
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_newly_released_episodes
    • Changedget_now_playing3 fields changed
      • addedInput schema / properties / additional_types
        Added value: +{
        +  "default": [
        +    "track",
        +    "episode"
        +  ],
        +  "description": "Item types to include in the response. Default: ['track', 'episode']",
        +  "items": {
        +    "enum": [
        +      "track",
        +      "episode"
        +    ],
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code โ€” localises item names; lowercase input is uppercased; defaults to the account market",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_playback_context
    • Addedget_playback_snapshot
    • Changedget_playlist8 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"Fetch all items across pages (up to 500) instead of a single page"New value: +"Fetch all items across pages (up to 500), continuing FROM offset. limit is the page size. Note: library tools' fetch_all ignores offset โ€” contracts differ between modules (#110)."
      • changedInput schema / properties / id / description
        Previous value: -"Playlist ID"New value: +"Alias for playlist_id"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / playlist_id
        Added value: +{
        +  "description": "Playlist ID",
        +  "type": "string"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "id"
        -]
    • Addedget_playlist_added_dates
    • Changedget_playlist_cover6 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / id
        Added value: +{
        +  "description": "Alias for playlist_id, matching get_playlist",
        +  "type": "string"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • changedInput schema / properties / playlist_id / description
        Previous value: -"Playlist ID"New value: +"Playlist ID (or pass it as 'id')"
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "playlist_id"
        -]
    • Addedget_playlist_followers
    • Addedget_playlist_items
    • Addedget_playlist_snapshot
    • Changedget_queue2 fields changed
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_queue_snapshot
    • Changedget_recently_played7 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / after / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / after / minimum
        Added value: +-9007199254740991
      • addedInput schema / properties / before / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / before / minimum
        Added value: +-9007199254740991
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_saved_albums5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"Fetch all pages instead of one page (ignores limit/offset; capped at 500 items)"New value: +"Fetch all pages instead of one page (ignores limit/offset)"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_saved_audiobooks4 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_saved_counts
    • Changedget_saved_episodes5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"Fetch all pages instead of one page (ignores limit/offset; capped at 500 items)"New value: +"Fetch all pages instead of one page (ignores limit/offset)"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_saved_shows5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"Fetch all pages instead of one page (ignores limit/offset; capped at 500 items)"New value: +"Fetch all pages instead of one page (ignores limit/offset)"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_saved_tracks5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"Fetch all pages instead of one page (ignores limit/offset; capped at 500 items)"New value: +"Fetch all pages instead of one page (ignores limit/offset)"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_several_albums
    • Addedget_several_artists
    • Addedget_several_audiobooks
    • Addedget_several_chapters
    • Addedget_several_episodes
    • Addedget_several_shows
    • Addedget_several_tracks
    • Changedget_show3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_show_details
    • Changedget_show_episodes5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / market / pattern
        Added value: +"^[A-Za-z]{2}$"
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_show_latest_episode
    • Changedget_top_artists4 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Start position (0-based). Default: 0",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_top_tracks4 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Start position (0-based). Default: 0",
        +  "maximum": 9007199254740991,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_track2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedget_user_playlists5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • changedInput schema / properties / fetch_all / description
        Previous value: -"Fetch every page (up to 500 playlists) instead of a single page"New value: +"Fetch every playlist (up to 500), continuing FROM offset rather than restarting at 0. limit is the page size. Note: library tools' fetch_all instead ignores offset โ€” contracts differ between modules (#110)."
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedget_user_playlists_by_id
    • Addedget_user_profile
    • Addedgrow_playlist
    • Addedhandoff
    • Addedhistory_search
    • Addedimport_from_sidecar
    • Addedimport_playlist
    • Addedimport_profile_state
    • Addedinspect_tool
    • Addedinterleave_playlists_plan
    • Addedis_local_census
    • Addedis_valid_spotify_uri
    • Addedjoin_uri_list
    • Addedjump_to_chapter
    • Addedlabel_discography_explorer
    • Addedlabel_explorer
    • Addedlast_heard
    • Addedlibrary_coverage_report
    • Addedlibrary_genre_report
    • Addedlibrary_growth_report
    • Addedlibrary_growth_timeline
    • Addedlibrary_hygiene
    • Addedlibrary_snapshot_diff
    • Addedlibrary_to_playlist
    • Addedlibrary_value_summary
    • Addedlist_all_chapters
    • Addedlist_backups
    • Addedlist_device_presets
    • Addedlist_playback_bookmarks
    • Addedlist_playback_states
    • Addedlist_playlist_snapshots
    • Addedlist_saved_shows
    • Addedlist_saved_snapshots
    • Addedlist_scenes
    • Addedlist_sessions
    • Addedlist_show_episodes
    • Addedlistening_clock
    • Addedlistening_clock_heatmap
    • Addedlistening_consistency_score
    • Addedlistening_gaps_report
    • Addedlistening_heatmap
    • Addedlistening_history_export
    • Addedlistening_journal_append
    • Addedlistening_recap_brief
    • Addedlistening_report
    • Addedlistening_session_close
    • Addedlistening_session_report
    • Addedlistening_session_start
    • Addedlistening_streak_report
    • Addedlistening_streaks
    • Addedlistening_week_in_time
    • Addedlongest_saved_tracks
    • Addedlyric_snippet_search
    • Addedmake_spotify_uri
    • Addedmark_episode_played_plan
    • Addedmarket_availability
    • Addedmarket_validate
    • Addedmerge_playlists
    • Addedmerge_playlists_plan
    • Addedmerge_snapshot_changes_plan
    • Addedmonthly_listening_report
    • Addedmood_bucket_report
    • Addedmorning_briefing
    • Addedmost_replayed
    • Addedmove_items_between_playlists
    • Addedmove_tracks_between_playlists
    • Addedmutation_log_export
    • Addedmute
    • Addednever_played_saved
    • Addednew_music_from_saved_artists
    • Addednew_music_from_top_artists
    • Addednormalize_spotify_uri
    • Addednow_playing_history
    • Addedopen_url_to_spotify_uri
    • Addedorphaned_artist_check
    • Addedoverlap_playlists
    • Addedparse_spotify_uri
    • Changedpause2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedpause_everywhere
    • Addedpeek_next
    • Addedpin_playlist
    • Addedplan_podcast_session
    • Addedplan_volume_level_across_devices
    • Changedplay8 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / offset / description
        Previous value: -"Index within context to start from"New value: +"Index within an album/playlist context to start from. Ignored for ad-hoc uris; not valid for artist contexts (use offset_uri instead)."
      • addedInput schema / properties / offset / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / offset_uri
        Added value: +{
        +  "description": "Track URI inside the context to start from โ€” required for artist contexts, where a numeric index is rejected",
        +  "type": "string"
        +}
      • addedInput schema / properties / position_ms / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / uris / maxItems
        Added value: +100
    • Addedplay_at
    • Changedplay_from_search4 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / market
        Added value: +{
        +  "description": "ISO 3166-1 alpha-2 country code โ€” affects availability/relinking of results; defaults to the account market",
        +  "pattern": "^[A-Za-z]{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedplay_on
    • Addedplayback_compare_states
    • Addedplayback_health_check
    • Addedplayback_timeline
    • Addedplaylist_add_by_search
    • Addedplaylist_artist_heat
    • Addedplaylist_balance
    • Addedplaylist_changelog
    • Addedplaylist_chunk_preview
    • Addedplaylist_clone_live
    • Addedplaylist_clone_snapshot
    • Addedplaylist_collab_toggle
    • Addedplaylist_collaboration_report
    • Addedplaylist_cover_from_track
    • Addedplaylist_dedupe_advanced
    • Addedplaylist_diff
    • Addedplaylist_difference_plan
    • Addedplaylist_edit_journal
    • Addedplaylist_era_profile
    • Addedplaylist_exclude_artists
    • Addedplaylist_expression_algebra
    • Addedplaylist_fill_from_search
    • Addedplaylist_filter_runtime
    • Addedplaylist_flip_order
    • Addedplaylist_from_tags
    • Addedplaylist_health_check
    • Addedplaylist_history
    • Addedplaylist_intersect
    • Addedplaylist_intersection
    • Addedplaylist_keep_artist
    • Addedplaylist_keep_only
    • Addedplaylist_move_block
    • Addedplaylist_move_to_top
    • Addedplaylist_names_bulk_normalize
    • Addedplaylist_overlap_matrix
    • Addedplaylist_pair_check
    • Addedplaylist_remove_artist
    • Addedplaylist_resequence
    • Addedplaylist_reverse
    • Addedplaylist_rotate
    • Addedplaylist_seed_shuffle
    • Addedplaylist_shuffle
    • Addedplaylist_slice
    • Addedplaylist_snapshot_detail
    • Addedplaylist_sort
    • Addedplaylist_staleness_report
    • Addedplaylist_staleness_score
    • Addedplaylist_strip_episodes
    • Addedplaylist_subtract
    • Addedplaylist_swap_positions
    • Addedplaylist_symmetric_difference
    • Addedplaylist_table_of_contents
    • Addedplaylist_template_apply
    • Addedplaylist_to_library
    • Addedplaylist_trim
    • Addedplaylist_trim_to_duration
    • Addedplaylist_union
    • Addedplaylist_union_preview
    • Addedpredict_next_tracks
    • Addedprune_old_snapshots
    • Addedpublisher_portfolio
    • Addedqueue_duplicate_check
    • Addedqueue_next
    • Addedqueue_next_episode
    • Addedqueue_playlist
    • Addedqueue_profile
    • Addedqueue_prune_plan
    • Addedqueue_replace_via_playlist
    • Addedqueue_runtime_report
    • Addedquick_save_now
    • Addedquota_probe
    • Addedread_playlist_snapshot
    • Addedreceipt_lookup
    • Addedrefresh_smart_playlist
    • Addedremove_duplicate_playlist_items
    • Addedremove_from_library
    • Addedremove_from_library_by_playlist
    • Changedremove_from_playlist7 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / snapshot_id
        Added value: +{
        +  "description": "Apply the removal against this playlist version instead of the latest",
        +  "type": "string"
        +}
      • changedInput schema / properties / uris / description
        Previous value: -"URIs to remove"New value: +"URIs to remove; use { uri, positions } to target specific occurrences of a repeated URI"
      • addedInput schema / properties / uris / items / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "properties": {
        +      "positions": {
        +        "items": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "uri": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "uri",
        +      "positions"
        +    ],
        +    "type": "object"
        +  }
        +]
      • removedInput schema / properties / uris / items / type
        Removed value: -"string"
      • addedInput schema / properties / uris / maxItems
        Added value: +100
    • Addedremove_playlist_range
    • Addedremove_saved_episode
    • Changedremove_saved_items3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: show exactly which URIs would be removed without calling the API",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedremove_saved_shows
    • Addedremove_unavailable_playlist_items
    • Addedrename_device
    • Changedreorder_playlist_items5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / insert_before / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / range_length / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / range_start / maximum
        Added value: +9007199254740991
    • Addedrepeat_listener_report
    • Addedrepeat_queue_toggle
    • Addedreplace_playlist_items
    • Addedreplay_session
    • Addedresolve_artist
    • Addedrestore_library_snapshot
    • Addedrestore_playback_state
    • Addedrestore_playlist_from_snapshot
    • Addedrestore_playlist_plan
    • Addedresume_playback_position
    • Addedreverse_playlist_plan
    • Addedroom_level
    • Addedrotate_playlist_plan
    • Addedsample_playlist_tracks
    • Addedsave_artist_new_releases
    • Addedsave_discover_weekly
    • Addedsave_episode
    • Changedsave_items3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedsave_playback_state
    • Addedsave_queue_as_playlist
    • Addedsave_release_radar
    • Addedsave_scene
    • Addedsave_show_digest
    • Addedsave_smart_playlist_rule
    • Addedsave_to_library
    • Addedsaved_albums_by_decade
    • Addedsaved_albums_by_label
    • Addedsaved_albums_by_type
    • Addedsaved_albums_by_year
    • Addedsaved_library_delta
    • Addedsaved_runtime_by_era
    • Addedsaved_shows_publisher_census
    • Addedsaved_track_age_report
    • Addedsaved_tracks_by_artist
    • Addedsaved_tracks_roulette
    • Addedsaved_vs_playlist_coverage
    • Addedscene_sampler_search
    • Addedschedule_wind_down
    • Addedscope_audit
    • Changedsearch7 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / include_external
        Added value: +{
        +  "description": "Pass \"audio\" to include externally-hosted audio items marked as playable",
        +  "enum": [
        +    "audio"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / max_results
        Added value: +{
        +  "description": "Max items to return (default: SPOTIFY_MCP_MAX_ITEMS env or 50)",
        +  "exclusiveMinimum": 0,
        +  "maximum": 2000,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "Index of the first result to return, 0โ€“1000. Use with limit to page through results",
        +  "maximum": 1000,
        +  "minimum": 0,
        +  "type": "integer"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / types / description
        Previous value: -"Content types to search, as an array. Default: [\"track\",\"artist\",\"album\"]. Pass e.g. [\"artist\"] for an artist-only search."New value: +"Content types to search, as an array. Default: [\"track\",\"artist\",\"album\"]. Pass e.g. [\"artist\"] for an artist-only search. \"audiobook\" is only available in the US, UK, CA, IE, NZ and AU markets."
      • changedInput schema / properties / types / items / enum
        Previous value: -[
        -  "track",
        -  "artist",
        -  "album",
        -  "playlist",
        -  "show",
        -  "episode"
        -]New value: +[
        +  "track",
        +  "artist",
        +  "album",
        +  "playlist",
        +  "show",
        +  "episode",
        +  "audiobook"
        +]
    • Addedsearch_advanced
    • Addedsearch_albums
    • Addedsearch_artists
    • Addedsearch_audiobooks
    • Addedsearch_by_isrc
    • Addedsearch_deep
    • Addedsearch_episodes
    • Addedsearch_fresh
    • Addedsearch_history
    • Addedsearch_history_stats
    • Addedsearch_market_diff
    • Addedsearch_playlists
    • Addedsearch_rerun
    • Addedsearch_saved_albums
    • Addedsearch_saved_audiobooks
    • Addedsearch_saved_episodes
    • Addedsearch_saved_shows
    • Addedsearch_saved_tracks
    • Addedsearch_shows
    • Addedsearch_tracks
    • Addedsearch_within_playlist
    • Changedseek3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / position_ms / maximum
        Added value: +9007199254740991
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedseek_relative
    • Addedsession_length_report
    • Addedsession_stats
    • Addedset_device_volume_preset
    • Changedset_repeat2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedset_shuffle2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedset_volume2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedshortest_saved_tracks
    • Addedshow_activity_feed
    • Addedshow_backlog_plan
    • Addedshow_backlog_report
    • Addedshow_episode_search
    • Addedshow_episode_timeline
    • Addedshow_new_episodes
    • Addedshow_recommendation_brief
    • Addedshow_runtime_stats
    • Addedshows_release_calendar
    • Addedshows_without_new_episodes
    • Addedshuffle_state_report
    • Addedsidecar_export_bundle
    • Addedskip_n
    • Changedskip_next3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Changedskip_previous3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedsleep_timer
    • Addedsleep_timer_plan
    • Addedsnapshot_added_at_report
    • Addedsnapshot_changelog
    • Addedsnapshot_diff_summary
    • Addedsnapshot_disk_usage
    • Addedsnapshot_integrity_check
    • Addedsnapshot_integrity_report
    • Addedsnapshot_new_tracks
    • Addedsnapshot_playlist
    • Addedsnapshot_registry_report
    • Addedsnapshot_removed_tracks
    • Addedsnapshot_retention_plan
    • Addedsnapshot_stats_report
    • Addedsort_playlist_apply
    • Addedsort_playlist_plan
    • Addedsort_uris_by_kind
    • Addedsplit_playlist
    • Addedsplit_playlist_by_count
    • Addedsplit_playlist_by_duration
    • Addedsplit_queue_plan
    • Addedsplit_uri_list
    • Addedspotify_doctor
    • Addedspotify_uri_kind
    • Addedspotify_uri_to_open_url
    • Addedstale_saved_shows_plan
    • Addedstart_podcast_session
    • Addedsubscribe_to_show
    • Addedsurprise_me
    • Addedswitch_device
    • Addedtag_listening_session
    • Addedtag_management
    • Addedtake_playlist_snapshot
    • Addedtaste_checkpoint
    • Addedtaste_checkpoint_diff
    • Addedtaste_shift_report
    • Addedtitle_length_outliers
    • Addedtoolset_report
    • Addedtop_artist_leaderboard
    • Addedtop_artist_ranking_delta
    • Addedtop_artists_by_range
    • Addedtop_genre_census
    • Addedtop_track_leaderboard
    • Addedtop_track_ranking_delta
    • Addedtrack_album_bundle
    • Addedtrack_enrichment_batch
    • Addedtrack_release_origin
    • Addedtrack_rotation_report
    • Changedtransfer_playback3 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / response_format
        Added value: +{
        +  "default": "concise",
        +  "description": "'concise' = human prose, 'detailed' = more fields in prose, 'json' = raw API object",
        +  "enum": [
        +    "concise",
        +    "detailed",
        +    "json"
        +  ],
        +  "type": "string"
        +}
    • Addedtransfer_playback_with_state
    • Addedundo_last_mutation
    • Addedundo_mutation
    • Addedundo_preview
    • Addedunfollow_artists
    • Addedunmute
    • Addedunpin_playlist
    • Addedunplayable_saved_check
    • Addedunsave_orphan_tracks
    • Addedunsubscribe_from_show
    • Changedupdate_playlist5 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / id / description
        Previous value: -"Playlist ID"New value: +"Alias for playlist_id"
      • addedInput schema / properties / playlist_id
        Added value: +{
        +  "description": "Playlist ID",
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "id"
        -]
    • Changedupload_playlist_cover2 fields changed
      • removedInput schema / additionalProperties
        Removed value: -false
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "description": "Preview only: validate inputs and describe exactly what would change without performing it",
        +  "type": "boolean"
        +}
    • Addeduri_kind_stats
    • Addeduri_namespace_census
    • Addeduri_shorthand_expand
    • Addeduri_to_base62
    • Addedvalidate_spotify_uri
    • Addedverify_receipt
    • Addedvolume_ramp
    • Addedvolume_report
    • Addedvolume_step
    • Addedwatch_artists
    • Addedweek_in_review_playlist
    • Addedweekday_heatmap
    • Addedweekday_listening_report
    • Addedweekly_rotation_report
    • Addedwhats_new
    • Addedwhere_was_i
    • Addedyear_explorer
    • Addedyear_in_review
  8. 50 tool updatesv1.0.1
    • First observedadd_to_playlist
    • First observedadd_to_queue
    • First observedcheck_following_artists
    • First observedcheck_saved_items
    • First observedcreate_playlist
    • First observedget_album
    • First observedget_album_tracks
    • First observedget_artist
    • First observedget_artist_albums
    • First observedget_audiobook
    • First observedget_audiobook_chapters
    • First observedget_chapter
    • First observedget_currently_playing
    • First observedget_devices
    • First observedget_episode
    • First observedget_followed_artists
    • First observedget_me
    • First observedget_now_playing
    • First observedget_playlist
    • First observedget_playlist_cover
    • First observedget_queue
    • First observedget_recently_played
    • First observedget_saved_albums
    • First observedget_saved_audiobooks
    • First observedget_saved_episodes
    • First observedget_saved_shows
    • First observedget_saved_tracks
    • First observedget_show
    • First observedget_show_episodes
    • First observedget_top_artists
    • First observedget_top_tracks
    • First observedget_track
    • First observedget_user_playlists
    • First observedpause
    • First observedplay
    • First observedplay_from_search
    • First observedremove_from_playlist
    • First observedremove_saved_items
    • First observedreorder_playlist_items
    • First observedsave_items
    • First observedsearch
    • First observedseek
    • First observedset_repeat
    • First observedset_shuffle
    • First observedset_volume
    • First observedskip_next
    • First observedskip_previous
    • First observedtransfer_playback
    • First observedupdate_playlist
    • First observedupload_playlist_cover

TDQS

B3.3/5.0

Scored across 129 tools

Disambiguation2/5

129 tools with massive overlap: at least four search variants (search, search_deep, search_fresh, search_by_isrc) plus wow search helpers; five duplicate detectors (find_duplicates_in_playlist, find_duplicate_saved_tracks, find_duplicate_tracks_across_playlists, clean_all_playlists, remove_duplicate_playlist_items); multiple playlist export/import/backup tools (export_playlist, export_all_playlists, import_playlist, backup_library, backup_first, import_from_sidecar / backup_library / restore_library_snapshot, backup_library / export_library_json, backup_library / export_profile_state); get_now_playing vs get_currently_playing; follow_playlist vs pin_playlist (deprecated); follow/unfollow vs check_following_artists vs check_in_library. The descriptions do contain decision guides and cross-references, which helps, but the volume of overlapping purpose makes misselection highly probable.

Naming Consistency4/5

Names are overwhelmingly snake_case verb_noun (get_devices, create_playlist, remove_from_library, add_to_queue), with occasional noun_verb constructions (playlist_shuffle, library_genre_report) but consistently readable. No camelCase mixing except the deprecated processV2-style naming is absent. One or two oddballs (whats_new, wind_down_status, spotify_doctor) but not enough to break the pattern.

Tool Count1/5

129 tools for a music/podcast control server vastly exceeds a manageable surface. Even accounting for discovery helpers (find_tool, inspect_tool, toolset_report), the set is huge and many tools have narrow, heavily qualified purposes, making it effectively unusable without a meta-discovery layer. This is an extreme count mismatch.

Completeness4/5

The surface covers core playback, library CRUD, playlist manipulation, podcast/audiobook, search, export/import/backup, and account management extremely thoroughly. Notable gaps are around artist follow/unfollow (explicitly unavailable in API) and playlist reordering by drag-and-drop, but those are external limitations or edge cases. For the apparent domain, the coverage is nearly exhaustive.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to control Spotify playback, search for music, manage playlists, and access library information through the Spotify API. Requires Spotify Premium for playback control features.
    4
    -
  • F
    license
    B
    quality
    B
    maintenance
    Enables AI assistants to control Spotify playback, search the catalog, and manage playlists and liked songs through natural language. Supports reading currently playing tracks, queues and devices, plus play, pause, skip, queueing, volume control, and playlist creation and editing.
    30
    -