Skip to main content
Glama
Spotify MCP Server

Spotify MCP Server

by jamiew

Spotify MCP, Python local server

spotify-mcp

mcp-name: io.github.jamiew/spotify-mcp

A local Python MCP server for searching Spotify, controlling playback, and managing playlists and Liked Songs from your MCP client. Runs over stdio with your Spotify account. This is a supported fork of varunneal/spotify-mcp.

The TypeScript edition supports local and hosted use, with a different MCP surface.

Setup

Requires Python 3.12+, uv, and Spotify Premium for playback.

  1. Create an app in the Spotify developer dashboard.

  2. Register http://127.0.0.1:8888 as its redirect URI, exactly as written.

  3. Copy the app's Client ID and Client Secret into your MCP client's configuration:

{
  "mcpServers": {
    "spotify": {
      "command": "uvx",
      "args": ["spotify-mcp-jamiew"],
      "env": {
        "SPOTIFY_CLIENT_ID": "your_client_id",
        "SPOTIFY_CLIENT_SECRET": "your_client_secret",
        "SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888"
      }
    }
  }
}

Restart the client. On first use, a browser opens for Spotify authorization; the token is cached locally. Keep the client secret and token cache private. Playback needs an available Spotify Connect device, so open Spotify on the device you want to control.

Client-specific setup: Claude Desktop, Claude Code, and Codex. Use the same command and environment variables in each client's format.

Run from source

The package command above uses the published package, which may lag this README's source changes. To run the current checkout:

git clone https://github.com/jamiew/spotify-mcp.git
cd spotify-mcp
uv sync

In the config above, change command to uv and args to ["--directory", "/absolute/path/to/spotify-mcp", "run", "spotify-mcp"]. Keep the same environment variables. Without cloning, use uvx --from git+https://github.com/jamiew/spotify-mcp.git spotify-mcp.

Reauthorization: artist-follow checks need user-follow-read, and following or unfollowing artists and playlists needs user-follow-modify. Existing grants do not receive new scopes automatically. Restart and complete Spotify authorization when prompted; if access is still denied, review the app's grant in your Spotify account and reauthorize. Do not automatically delete the auth cache.

Related MCP server: Spotify MCP Server

Features

48 tools, six resources (user, playback, track, playlist, artist, album), and five prompts. Tools provide typed outputs and behavior annotations; large playlist reads report progress. Playlist removal asks for confirmation where supported, reordering uses snapshot guards, and playback control attempts best-effort read-after-write confirmation, not guaranteed success.

Tools

Tool

Does

get_me

Read your profile

search_music

Search tracks, albums, artists, or playlists with filters and pagination

get_tracks

Read up to 50 tracks; individual reads when batching is unavailable

get_artist

Read up to 50 artists; top tracks for a single artist

get_album

Read up to 20 albums; track list for a single album

get_playback_state

Read current track or episode, device, progress, shuffle, and repeat

control_playback

Play tracks, episodes or a context; pause, skip, seek, volume, shuffle, repeat

list_devices

List Spotify Connect devices

transfer_playback

Move playback to another device

get_queue

Read now playing and upcoming tracks and episodes

add_to_queue

Queue a track or podcast episode

list_playlists

List your playlists with pagination

get_playlist

Read playlist metadata without tracks

get_playlist_tracks

Read playlist tracks with pagination

create_playlist

Create a private playlist; set public=true to publish

update_playlist_details

Change name, description, or visibility

add_tracks_to_playlist

Add up to 100 tracks or episodes

remove_tracks_from_playlist

Remove tracks or episodes with confirmation where supported

reorder_playlist

Move a block of tracks

follow_playlist

Follow (save) a playlist

unfollow_playlist

Unfollow a playlist, including your own

get_saved_tracks

Read Liked Songs with pagination

save_tracks

Like tracks

remove_saved_tracks

Unlike tracks

check_saved_tracks

Check up to 50 tracks against Liked Songs

check_saved_albums

Check up to 20 saved albums

check_following_artists

Check up to 50 followed artists

get_saved_albums

Read saved albums with pagination

save_albums

Save up to 20 albums

remove_saved_albums

Remove up to 20 saved albums

get_followed_artists

Read followed artists with cursor pagination

follow_artists

Follow up to 50 artists

unfollow_artists

Unfollow up to 50 artists

get_saved_shows

Read saved podcast shows with pagination

save_shows

Save up to 50 podcast shows

remove_saved_shows

Remove up to 50 saved podcast shows

check_saved_shows

Check up to 50 saved podcast shows

get_show_episodes

Read a show's episodes with resume points and pagination

get_saved_episodes

Read saved podcast episodes with pagination

check_saved_episodes

Check up to 50 saved podcast episodes

save_episodes

Save up to 50 podcast episodes

remove_saved_episodes

Remove up to 50 saved podcast episodes

get_saved_audiobooks

Read saved audiobooks with pagination

check_saved_audiobooks

Check up to 50 saved audiobooks

save_audiobooks

Save up to 50 audiobooks

remove_saved_audiobooks

Remove up to 50 saved audiobooks

get_top_items

Read top artists or tracks over a time range

get_recently_played

Read recently played tracks with timestamps

Behavior to know

  • New playlists default to private. Existing playlists are unchanged. Spotify can report unexpected visibility, so confirm sensitive playlists in the Spotify app.

  • Library writes (tracks, artists, shows, episodes, audiobooks) and membership checks accept 50 items, sent upstream in batches of 40. Album saves, removals and checks accept 20. Membership results preserve input alignment; incomplete chunks fail. Writes are not atomic across chunks: earlier changes may remain after an error. Check membership before retrying.

  • Restricted apps cap search pages at 10. Advance by the returned offset + limit, not the requested size. Individual-track fallback can make up to 50 Spotify requests.

  • Playlist pagination counts positions, including unresolved rows and local files with id: null. Local files also set is_local; positions remain valid for reordering.

Spotify access and policy

  • Permissions and app access mode determine available endpoints and playlist access. A 403 may mean missing permission, not a retired endpoint. Existing integrations' February restrictions were postponed; restricted apps use the February 2026 API routes.

  • Development Mode normally allows five allowlisted users and requires a Premium app owner; older larger allowlists may be grandfathered. Extended access is not routine hobby-project approval: criteria include an organization, a legal entity, a launched service, and 250,000 monthly active users. A public URL does not remove these limits.

  • All Development Mode apps on a developer account share one quota, even with the 25 permitted Client IDs. This server surfaces 429 errors without retries, including QUOTA_EXCEEDED and ordinary rate limits with Retry-After when provided. No guaranteed quota reset time is specified.

  • This server uses one local identity. Do not share its token cache or expose it as an unauthenticated public service. Other users should self-host and authorize their own accounts.

  • AI policy is a separate constraint. Spotify Developer Policy III.14 restricts training or otherwise ingesting Spotify Content into AI/ML models; "no training" or "metadata only" is not automatic clearance. III.13 restricts analysis and derived metrics; III.3 restricts voice-control assistants. Seek Spotify clarification or approval before public AI access. This is a risk notice, not legal advice or permission.

Moving between implementations

Shared versions and tool names do not imply drop-in compatibility with other implementations. Check arguments, limits, and result shapes before switching. Preserve any workflow that relies on this server's resources, five prompts, snapshot guards, removal confirmation, or playback confirmation; those behaviors are not universal.

Credits

MIT license, copyright 2025 Varun Neal Srivastava. Thanks to @varunneal for the original project, @jamiew, @jonico, @tedeuxx, and @karimStekelenburg.

Banner made with Glif.

Available Tools

48 tools
add_to_queueAdd to QueueB

Add a track or podcast episode to the playback queue.

Args:
    track_id: Track ID, or a spotify:track:/spotify:episode: URI or
        open.spotify.com URL. A bare ID is taken as a track.
Returns:
    Status and message
NameRequiredDescriptionDefault
track_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=false, destructiveHint=false and openWorldHint=true, so the mutation profile is covered by structured data. The description adds useful input-flexibility context (bare IDs, Spotify URIs, open.spotify.com URLs), but it omits the important behavioral precondition that Spotify requires an active device and that repeat calls enqueue duplicates.

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 purpose sentence is front-loaded and the arg explanation is tight and specific. The 'Returns: Status and message' line is low-value boilerplate given an output schema exists, but overall there is little waste.

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 an output schema present, the return-value line is unnecessary, and the real gaps are behavioral: no mention of requiring an active device, no note on deduplication, and no contrast with sibling tools. For a single-parameter mutation tool this is adequate but leaves out context 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 0% and the single property 'track_id' carries no description, so the description must compensate — and it does, explaining accepted forms (bare ID, spotify:track:/spotify:episode: URI, open.spotify.com URL) and the default that a bare ID is treated as a track. That is a meaningful addition 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 states a specific verb and resource — 'Add a track or podcast episode to the playback queue' — so an agent knows exactly what is created and where. It does not distinguish itself from plausible siblings like add_tracks_to_playlist or control_playback, which is the only thing keeping 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 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 and no exclusion of alternatives; the phrase 'playback queue' only implicitly contrasts with playlist tools. An agent must infer on its own whether queueing a track differs from adding it to a playlist, and nothing is said about prerequisites such as an active playback device.

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

add_tracks_to_playlistAdd Tracks to PlaylistB

Add tracks or podcast episodes to a playlist.

Args:
    playlist_id: Playlist ID
    track_uris: Track or episode URIs/URLs (up to 100). Bare IDs are tracks;
        pass spotify:episode: URIs or episode URLs for episodes.
NameRequiredDescriptionDefault
track_urisYes
playlist_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare the mutation profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false), so the safety bar is low. The description adds one useful behavioral fact – a hard cap of 100 items per call – but says nothing about append position, duplicate handling, or how the playlist must be accessible to the caller.

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-line purpose statement front-loaded, followed by a compact Args block with no filler. The size is appropriate for a two-parameter tool; only the redundant 'Playlist ID' restatement wastes a line.

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 an output schema present, return values needn't be explained, and the URI/episode semantics are covered. However, an agent still has to guess about append ordering, duplicates, and playlist editability, which matters for a non-idempotent write.

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 0%, so the description must carry the load; it explains that track_uris accepts bare track IDs, spotify:episode: URIs, or episode URLs, which is meaningful format guidance. playlist_id is only restated ('Playlist ID') with no format or ownership detail, leaving half the contract thin.

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 uses a specific verb+resource ('Add tracks or podcast episodes to a playlist') and clarifies that episodes, not just tracks, can be added. It doesn't differentiate itself from close siblings like add_to_queue, save_tracks, or remove_tracks_from_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?

There is no explicit when-to-use guidance: nothing says to prefer this over add_to_queue, reorder_playlist, or save_tracks, nor any prerequisite such as needing to own or collaborate on the playlist. The only usable routing hint is the episode-vs-track URI convention, which is parameter-level rather than usage-level.

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

check_following_artistsCheck Followed ArtistsA
Read-onlyIdempotent

Check up to 50 artist follows in upstream chunks of at most 40.

Uses artist URIs on the consolidated library route, with a legacy fallback.
Requires user-follow-read; reauthorize if your existing grant lacks it.

Args:
    artist_ids: Artist IDs or URIs (up to 50)
Returns:
    MembershipStatus.results maps each Spotify artist id to true if followed
NameRequiredDescriptionDefault
artist_idsYes

Output Schema

NameRequiredDescription
checkedYes
resultsYes

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint. The description adds meaningful behavioral context beyond these: chunking into at most 40 per call, a legacy fallback, and the auth scope requirement (user-follow-read). This goes beyond the annotations and provides useful operational details 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.

Conciseness4/5

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

The description is well-structured with a brief intro, then dedicated Args and Returns sections. It is concise and front-loaded with the core purpose. The technical details (chunking, route, fallback) are relevant and not excessive, though the phrasing 'consolidated library route' might be opaque to some agents.

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 description covers purpose, auth scope, input format, limits, and return mapping (MembershipStatus.results). An output schema exists, so the description needn't fully explain return structure, but it does anyway. For a simple read-only check with one parameter, it is nearly complete, covering the essential context 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?

The schema only defines artist_ids as an array of strings with no description (0% coverage). The description compensates by clarifying that artist_ids can be either IDs or URIs and that up to 50 are accepted. This adds essential meaning beyond the raw schema, though it doesn't specify format details like URI syntax.

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 checks up to 50 artist follows, using the verb 'check' and the resource 'artist follows'. It is specific about the action and resource, but it does not explicitly contrast with similar sibling tools like check_saved_tracks or check_saved_albums, 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 Guidelines2/5

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

The description provides implementation details such as the consolidated library route, legacy fallback, and the required user-follow-read scope, but it does not explain when to use this tool versus alternatives. There is no explicit when/when-not guidance or mention of preferred conditions, leaving usage context to inference.

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

check_saved_albumsCheck Saved AlbumsA
Read-onlyIdempotent

Check which albums are already saved to the library.

Up to 20 albums per tool call, preserving this tool's existing album cap.

Args:
    album_ids: Album IDs or URIs (up to 20)
Returns:
    MembershipStatus.results maps each Spotify album id to true if saved
NameRequiredDescriptionDefault
album_idsYes

Output Schema

NameRequiredDescription
checkedYes
resultsYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description adds value beyond these by disclosing the 20-album cap, the acceptance of URIs in addition to IDs, and the return shape (MembershipStatus.results mapping each album id to a boolean). No contradiction with the read-only 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?

The purpose is front-loaded in the first line, and the Args/Returns block is compact and structured. Every sentence earns its place with no filler. It's slightly verbose with the repetition of the cap across the intro and the Args line, but that's minor.

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 (one required parameter) and has an output schema, so the description needn't explain return values in depth—yet it still names the return type. Annotations cover safety. The description is adequate for a single-param read tool; a small gap is the lack of any note about failure/error behavior when an invalid album ID is passed.

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 0%, so the description must compensate, and it does: 'Album IDs or URIs (up to 20)' adds the critical facts that URIs are accepted (not just bare IDs) and that the array is capped at 20. This goes meaningfully beyond what the bare schema (array of strings) conveys.

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?

'Check which albums are already saved to the library' states a specific verb and resource, and the resource type (albums vs tracks) implicitly differentiates it from the sibling check_saved_tracks. However, it doesn't explicitly name that sibling or any other alternative, so it falls short of the top tier that explicitly distinguishes 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 Guidelines3/5

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

The purpose line implies when to use it (when you need to verify album save status), and the 20-album cap conveys a usage constraint. But there is no explicit when-to-use vs alternatives guidance, no exclusions, and no mention of check_saved_tracks or get_saved_albums as related tools an agent might choose instead.

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

check_saved_audiobooksCheck Saved AudiobooksA
Read-onlyIdempotent

Check which audiobooks are already saved, in upstream chunks of 40.

Args:
    audiobook_ids: Audiobook IDs or URIs (up to 50)
Returns:
    MembershipStatus.results maps each Spotify audiobook id to true if saved
NameRequiredDescriptionDefault
audiobook_idsYes

Output Schema

NameRequiredDescription
checkedYes
resultsYes

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds real behavioral context beyond that: upstream batching in chunks of 40 and a 50-ID request cap, which tells the agent to expect batched network behavior. It stops short of saying what happens when more than 50 IDs are supplied (error, truncation, or split).

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 front-loaded sentence carries the action and the batching detail, followed by compact Args/Returns lines. No filler, and the key constraint appears before supporting detail.

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 the description need not detail the response, yet it still clarifies that results map each audiobook ID to a boolean. Combined with annotations and the input format/limit disclosure, this is nearly complete; the only gap is the unspecified behavior when the cap is exceeded.

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 0%, so the description must carry the load, and it does: the single argument accepts 'Audiobook IDs or URIs' (the URI form is not evident from the bare string-array schema) and is bounded at up to 50 entries. That is meaningful added semantics for the only parameter.

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 pair ('Check which audiobooks are already saved'), which clearly reads as a membership/batch lookup rather than a full listing. It is distinguishable from siblings like get_saved_audiobooks, save_audiobooks and remove_saved_audiobooks by implication, but the description never names an alternative 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?

Usage is implied by the name and the 'check' wording: use it to test membership before saving/removing. There is no explicit when-to-use vs get_saved_audiobooks (which would list everything) or vs check_saved_tracks/check_saved_shows, so the agent must infer the routing.

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

check_saved_episodesCheck Saved EpisodesA
Read-onlyIdempotent

Check which podcast episodes are already saved, in upstream chunks of 40.

Args:
    episode_ids: Episode IDs or URIs (up to 50)
Returns:
    MembershipStatus.results maps each Spotify episode id to true if saved
NameRequiredDescriptionDefault
episode_idsYes

Output Schema

NameRequiredDescription
checkedYes
resultsYes

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already establish read-only and idempotent behavior, so the description's real contribution is the upstream chunking of 40 and the up-to-50 input ceiling — genuine behavioral detail an agent can't get elsewhere. It does not state error or partial-failure behavior, keeping it below 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-loaded purpose statement followed by compact Args/Returns blocks; every sentence carries information. The Returns line is somewhat redundant given an output schema exists.

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 single-parameter read tool with annotations and an output schema, the description supplies the purpose, the input types, the batch limit, and the chunking model. Remaining gaps (result ordering, behavior on invalid IDs) are 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 coverage is 0%, so the description carries the burden. It does add two important facts: the parameter accepts episode IDs or URIs, and it is capped at 50 items. However, it says nothing about the array item format beyond 'URIs' or what happens when the list exceeds a chunk.

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: check which podcast episodes are already saved. An agent can distinguish it from get_saved_episodes and save_episodes, though it never names those siblings 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 'already saved' framing implies the use case (membership testing before save/remove), but there is no explicit when-to-use or when-not guidance, and no routing to the related get_saved_episodes / save_episodes / remove_saved_episodes tools.

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

check_saved_showsCheck Saved ShowsA
Read-onlyIdempotent

Check which podcast shows are already saved, in upstream chunks of 40.

Args:
    show_ids: Show IDs or URIs (up to 50)
Returns:
    MembershipStatus.results maps each Spotify show id to true if saved
NameRequiredDescriptionDefault
show_idsYes

Output Schema

NameRequiredDescription
checkedYes
resultsYes

TDQS

A3.9/5.0
Behavior4/5

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

The annotations already cover the safety profile (readOnly, idempotent, openWorld), so the description's job is to add operational detail -- and it does, disclosing that requests are split 'in upstream chunks of 40' and that the return maps each show id to a boolean. It stops short of saying what happens on partial failures or invalid IDs within a chunk.

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 plus a compact Args/Returns block, front-loaded with the core action. Every line contributes either purpose, input contract, or return shape; 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 one-parameter read tool with an output schema, the definition covers purpose, input format, batch limit, and the shape of the result mapping. The only gap is behavioral edge cases (invalid IDs, partial chunk failures), which the output schema may partially resolve.

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 0%, so the description carries the burden and largely meets it: it names the parameter, states that both IDs and URIs are accepted, and caps input at 50. The relationship between the 50-item cap and the 40-item internal chunking is left unexplained, which is the only real ambiguity.

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 -- 'Check which podcast shows are already saved' -- which distinguishes it from the sibling mutations save_shows/remove_saved_shows and from the episode/audiobook check variants. It never explicitly contrasts itself with get_saved_shows, which returns the saved set rather than testing membership, so routing between those two still requires inference.

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: passing a list of IDs to test membership suggests batch verification scenarios, but the description never says when to prefer this over get_saved_shows or what to do when more than 50 IDs are known. No prerequisites or exclusions are stated.

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

check_saved_tracksCheck Liked SongsA
Read-onlyIdempotent

Check which tracks are already liked, without paging the whole library.

Up to 50 tracks per tool call, split into upstream chunks of at most 40.
Use this before save_tracks rather than paging through get_saved_tracks.

Args:
    track_ids: Track IDs or URIs (up to 50)
Returns:
    MembershipStatus.results maps each Spotify track id to true if liked
NameRequiredDescriptionDefault
track_idsYes

Output Schema

NameRequiredDescription
checkedYes
resultsYes

TDQS

A4.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the description doesn't need to restate them. It adds behavioral context: no paging of the whole library, a 50-track cap with upstream chunking of 40, and a result mapping. This is exactly the type of operational behavior beyond annotation flags.

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 followed by a minimal Args/Returns block. The main purpose is front-loaded, usage guidance in second sentence, and the parameter note completes it. 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?

With one required parameter, a clear output schema (present), and annotations covering safety, the description covers everything an agent needs: what to pass, how many, and what to expect in the response (summarized even though output schema exists). No critical gap.

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

Parameters5/5

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

The schema only says 'track_ids' is an array of strings with no description (coverage 0%). The description compensates fully: it defines accepted value types ('Track IDs or URIs') and a bound ('up to 50'). This is essential for correct invocation.

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 ('check'), resource ('tracks'), and scope ('already liked' without paging the whole library). Explicitly contrasts with get_saved_tracks in the same domain, and sibling tools like check_saved_albums are distinguishable by resource. This 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 Guidelines5/5

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

Explicitly instructs when to use: 'before save_tracks' and not as an alternative to paging get_saved_tracks. Also notes the 50-track limit and chunking pattern, so an agent knows to split inputs. No other sibling is needed.

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

control_playbackControl PlaybackA

Control Spotify playback. Requires Premium and an active device.

Args:
    action: 'play', 'pause', 'next', 'previous', 'seek', 'volume', 'shuffle' or 'repeat'
    track_ids: Tracks or episodes to play (action='play'; ignored when
        context_uri is set). Bare IDs are tracks; pass spotify:episode: URIs
        or episode share URLs for podcast episodes.
    context_uri: Album, playlist, artist or show URI to play (action='play')
    position_ms: Position in milliseconds (required for action='seek')
    volume_percent: Volume 0-100 (required for action='volume')
    state: 'on'/'off' for shuffle; 'track'/'context'/'off' for repeat
    device_id: Target device (default: the currently active one)

Returns:
    Last observed PlaybackState, possibly unconfirmed.

Confirmation is best effort: at most five post-action reads with brief waits.
Stale state or a later read failure returns the last observation. Checks do not
verify every requested track, context or device transition.
NameRequiredDescriptionDefault
stateNo
actionYes
device_idNo
track_idsNo
context_uriNo
position_msNo
volume_percentNo

Output Schema

NameRequiredDescription
trackNo
deviceNo
repeatNo
volumeNo
shuffleNo
is_playingYes
progress_msNo
currently_playing_typeNo

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare this is a mutating, non-idempotent, open-world but non-destructive call; the description adds real context beyond that — the Premium and active-device preconditions, and that confirmation is best-effort with at most five post-action reads. It also discloses the important limitation that the returned state may be stale or unconfirmed and that not every requested track/context/device transition is verified, which is exactly the kind of caveat annotations cannot express. Only the plain return-type mention is redundant with the existing output 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?

Purpose and prereqs are front-loaded, then a structured Args/Returns layout with one line per parameter; there is little filler. The Returns paragraph is slightly long given an output schema exists, but the confirmation caveat it carries justifies most of that length.

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 a polymorphic action, the definition covers prerequisites, all parameters, conditional relationships, and verification semantics, and it correctly leans on the output schema for return shape. What is missing is failure behavior — what the caller sees when no active device exists, when Premium is absent, or when a supplied URI is invalid.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the entire burden, and it does: it enumerates the legal action values, defines state values per action, explains that track_ids is ignored when context_uri is set, distinguishes bare track IDs from episode URIs/share URLs, and documents the unit and range for position_ms and volume_percent plus the device_id default. This adds meaning well beyond the bare JSON types.

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 sentence states a specific verb and resource ('Control Spotify playback') and the action list enumerates exactly which playback operations are covered, which implicitly separates it from read-only siblings like get_playback_state and from transfer_playback. It stops short of naming those siblings explicitly, so an agent must infer the boundary rather than read 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?

Prerequisites are stated clearly ('Requires Premium and an active device'), and per-action requirements are called out (position_ms for seek, volume_percent for volume), which is genuine when-to-use guidance for the action variants. There is no guidance on when to prefer this over get_playback_state, transfer_playback, or add_to_queue, and no statement of what happens when no device is active.

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

create_playlistCreate PlaylistB

Create a new Spotify playlist.

Args:
    name: Playlist name
    description: Playlist description (default: empty)
    public: Whether playlist is public (default: False)

Returns:
    The created Playlist
NameRequiredDescriptionDefault
nameYes
publicNo
descriptionNo

Output Schema

NameRequiredDescription
idYes
nameYes
ownerNo
publicNo
tracksNo
descriptionNo
total_tracksNo

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare the write semantics (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true), so the safety profile is covered. The description adds that the call returns the created Playlist, but says nothing about authentication requirements, whether duplicate names are allowed, or what happens on quota/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.

Conciseness4/5

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

The purpose sentence is front-loaded and the Args/Returns block is easy to scan. The Args block does restate schema defaults, so it is slightly redundant for a three-parameter tool, but nothing is bloated.

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?

An output schema exists, so the Returns line is a bonus rather than a necessity, and all three inputs are mentioned. What is missing for a mutating, open-world tool is the surrounding context: auth/scope needs and the follow-up step of adding tracks to the newly created (empty) 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 0%, so the description carries the burden, and it does name all three parameters and their roles plus defaults. However, the defaults (false, "") are already in the schema and the one-line glosses ("Playlist name", "Whether playlist is public") barely add meaning beyond the property titles — no note on whether public means search-visible or collaborator-visible.

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?

"Create a new Spotify playlist" gives a specific verb plus resource, which cleanly separates it from read siblings like get_playlist, list_playlists and mutators like update_playlist_details or add_tracks_to_playlist. It stops short of naming an alternative, but the create verb alone 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 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 and no prerequisites: nothing says the new playlist starts empty and needs add_tracks_to_playlist to populate it, nor that a user-authenticated account is required. The agent must infer the whole workflow from sibling names.

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

follow_artistsFollow ArtistsA
Idempotent

Follow artists. Requires user-follow-modify; reauthorize if it is missing.

Args:
    artist_ids: Artist IDs or URIs (up to 50)
NameRequiredDescriptionDefault
artist_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false, so the write/safety profile is covered. The description adds genuinely new behavioral context: the required OAuth scope and the reauthorization fallback if the scope is missing — information an agent cannot get from the 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?

The definition is short and front-loaded with the operation, then the auth requirement, then the parameter note. The opening 'Follow artists' mildly restates the tool name, but every other clause (scope, reauthorize, ID formats, cap) 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 single-parameter tool with an output schema and full annotation coverage, the description supplies the auth prerequisite, input formats, and batch limit — essentially everything needed to invoke it correctly. Only edge-case behavior (partial failures, behavior for already-followed artists beyond the idempotent hint) 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 description coverage is 0%, so the description carries the full burden, and it does add meaning: 'Artist IDs or URIs' broadens the accepted input format beyond a bare array of strings, and 'up to 50' supplies a batch-size limit absent from the schema. It still does not say what happens on exceeding 50 or whether invalid IDs fail the whole call.

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 uses a specific verb+resource pair ('Follow artists') that maps directly to the tool name and is unambiguous against siblings like unfollow_artists and check_following_artists. It does not explicitly name or differentiate itself from those siblings, 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 states a concrete prerequisite ('Requires user-follow-modify; reauthorize if it is missing'), which tells the agent about an auth gate. However, it never says when to use this versus unfollow_artists (to remove) or check_following_artists (to verify), so the choice between siblings is left to inference from names.

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

follow_playlistFollow PlaylistA
Idempotent

Follow (save) a playlist so it appears in the user's library.

Args:
    playlist_id: Playlist ID, URI or open.spotify.com URL
NameRequiredDescriptionDefault
playlist_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare non-read-only, idempotent, non-destructive, open-world behavior, so the safety burden is light. The description adds that the result is the playlist appearing in the user's library, which is useful persistent-effect context, but says nothing about auth requirements, what happens on repeat calls, or whether anything is modified server-side beyond the follow relation.

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 lines with no wasted wording, and the essential scope statement comes first. The 'Args:' block formatting is slightly mechanical but appropriate for a one-parameter tool.

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, and the single parameter's accepted formats are covered. The main remaining gaps are authentication context and repeat-call semantics, which are minor for a simple one-argument follow operation.

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 0% and the schema only says 'Playlist Id' as a string, so the description meaningfully adds that a URI or open.spotify.com URL is also accepted. That format guidance is exactly the value the schema fails to provide for this single required parameter.

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 a specific verb and resource ('Follow (save) a playlist') and clarifies the effect ('appears in the user's library'), which makes it distinguishable from sibling unfollow_playlist. It does not explicitly name that sibling, so it falls just short of full 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?

The parenthetical 'save' and 'appears in the user's library' imply the use case, but the description never says when to choose this over unfollow_playlist, nor what conditions apply (e.g. already-followed playlists, authentication requirement). Usage is inferable but not guided.

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

get_albumGet AlbumA
Read-onlyIdempotent

Get details for one or more Spotify albums, batched into a single request.

Args:
    album_ids: One album ID/URI, or a list of up to 20 — Spotify's own cap
        for album batches, which is lower than the 50 for tracks and artists.

Returns:
    AlbumInfo whose `albums` follows the order requested. `tracks` holds the
    album's track list only when a single album was requested.
NameRequiredDescriptionDefault
album_idsYes

Output Schema

NameRequiredDescription
albumsYes
tracksYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, and open-world behavior, and the description adds real value on top: the batch cap of 20 (and why it differs from tracks/artists) and the ordering guarantee. It stops short of noting auth/rate-limit 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 one-line purpose followed by compact Args/Returns blocks, with no filler sentences. The parenthetical comparison to track/artist caps is slightly extraneous but aids correct batching.

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 single-parameter read tool with an output schema, the description covers the input constraint and the key return nuance (tracks only populated for a single album), which is what an agent needs. Nothing critical 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 0% and the schema only says 'Album Ids' with an anyOf of string or array, so the description carries the load: it clarifies a single ID/URI vs a list, the hard maximum of 20, and that URI form is accepted. That is meaningful beyond the schema but doesn't spell out exact URI syntax.

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 ('Get details for one or more Spotify albums') plus the batching behavior, which lets an agent separate it from library-oriented siblings like get_saved_albums or check_saved_albums. It does not name any 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?

Usage is only implied: pass album IDs to fetch their details. There is no statement of when to prefer this over get_saved_albums/get_tracks or any exclusion, so the agent must infer the routing.

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

get_artistGet ArtistA
Read-onlyIdempotent

Get details for one or more Spotify artists, batched into a single request.

Args:
    artist_ids: One artist ID/URI, or a list of up to 50. A list costs one
        Spotify request rather than one per artist.
Returns:
    ArtistInfo whose `artists` follows the order requested. `top_tracks` is
    filled only when a single artist was requested, and is empty rather than
    an error when Spotify withholds that endpoint.
NameRequiredDescriptionDefault
artist_idsYes

Output Schema

NameRequiredDescription
artistsYes
top_tracksYes

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent and openWorld, so safety is covered. The description adds real behavioral detail beyond them: batching collapses N lookups into one request, results preserve requested order, and `top_tracks` is populated only for single-artist calls and returns empty instead of erroring when Spotify withholds it.

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 one-line purpose, then Args/Returns sections that are scannable and free of filler. The Returns text partially restates what the output schema already encodes, but the conditional `top_tracks` behavior justifies its presence.

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 single-parameter read tool with an output schema and safety annotations already in place, nothing an agent needs is missing: input forms, batch limit, ordering guarantee, and the conditional/empty-result behavior of `top_tracks` are all covered.

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 0%, so the description must carry parameter meaning, and it does: it accepts a single ID or URI as well as a list, and caps the list at 50. It does not describe ID format validity or behavior when some IDs are invalid, which keeps it below the top score.

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 ('Get details for one or more Spotify artists') plus the batching scope, which is more precise than the title alone. It does not explicitly name a sibling such as get_followed_artists or search_music to disambiguate, so differentiation is left implicit in the ID-based input.

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 agent can infer this is the tool for looking up artists when IDs/URIs are already known, and the note that 'a list costs one Spotify request rather than one per artist' gives useful cost context. There is no explicit when-not guidance or named alternative for discovery-by-name.

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

get_followed_artistsGet Followed ArtistsA
Read-onlyIdempotent

Get the artists the user follows. Paged by cursor, not offset.

Args:
    limit: Max artists to return per page (1-50, default 20)
    after: The `after` cursor from the previous page (omit for the first page)

Returns:
    FollowedArtists; pass its `after` back for the next page (None on the last)
NameRequiredDescriptionDefault
afterNo
limitNo

Output Schema

NameRequiredDescription
nextNo
afterNo
itemsYes
limitYes
totalNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so safety is covered. The description adds genuinely useful behavior beyond that: paging is cursor-based rather than offset-based, the cursor comes from the previous response, and None signals the last page. It does not mention rate limits or ordering of results, which keeps it at a 4 rather than 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?

The definition is front-loaded with the purpose, then cleanly separated into Args and Returns sections, and every line conveys information. The docstring-style Args/Returns scaffolding is slightly heavier than needed given the schema and output schema already list these fields, but no sentence 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 two-parameter read tool with an output schema and full annotation coverage, this is complete: it explains what the tool returns conceptually, how to paginate, and what terminates iteration. Nothing an agent needs in order to call it correctly and drive the pagination loop is missing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden and does: limit is bounded to 1-50 with default 20, and after is defined as the cursor from the previous page that must be omitted on the first call. These constraints and semantics exist nowhere in the schema, which only shows types and defaults.

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: "Get the artists the user follows." That is unambiguous and clearly distinct from sibling mutators like follow_artists/unfollow_artists. It stops short of naming a near-neighbor such as check_following_artists or get_artist, so it is clear but not sibling-differentiating at the top level.

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 artists the user follows" and the paging note, but there is no explicit when-to-use/when-not guidance and no mention of the alternatives in the sibling set (check_following_artists for a boolean check, get_artist for a single artist). An agent can infer the right context, but nothing steers it away from the wrong sibling.

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

get_meSpotify ProfileA
Read-onlyIdempotent

Get the signed-in user's Spotify profile.

Returns:
    UserProfile. email/country/product are unavailable on newer Spotify apps
    and come back empty rather than erroring.
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
idYes
emailNo
countryNo
productNo
followersNo
display_nameNo

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, openWorldHint=true, and idempotentHint=true, so the safety profile is known. The description adds a valuable behavioral nuance: email/country/product may be unavailable on newer apps and return empty instead of erroring. This goes beyond the annotations and helps the agent handle potential empty fields gracefully.

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 fluff. The core purpose is front-loaded in the first sentence, and the second sentence adds a critical caveat about return values. Every word earns its place; it is both concise and structured effectively.

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 parameterless GET that returns a user profile, the description covers everything an agent needs: the purpose and a key behavioral caveat about potentially empty fields. The output schema likely details the return structure, and the annotations cover safety, so no additional context is necessary.

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?

The tool has zero parameters, so the description has no parameter semantics to explain. Per the rubric, a baseline of 4 is appropriate for 0-parameter tools; the description correctly focuses on the output behavior rather than parameters.

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 clear verb-resource pair: 'Get the signed-in user's Spotify profile.' It is specific and unambiguous, and it differentiates from sibling tools by focusing on the user profile rather than playback, tracks, or playlists. No ambiguity about what the tool returns.

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 the tool: whenever the agent needs the signed-in user's profile. It does not explicitly name alternatives or exclusions, but given the unique purpose, the context is self-evident. A 4 is appropriate because the usage context is clear without needing to contrast with siblings.

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

get_playback_stateNow PlayingA
Read-onlyIdempotent

Get the current playback state: track, device, progress, shuffle and repeat.

Returns:
    PlaybackState (is_playing is False when nothing is playing)
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
trackNo
deviceNo
repeatNo
volumeNo
shuffleNo
is_playingYes
progress_msNo
currently_playing_typeNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds a genuinely useful behavioral detail beyond that: is_playing is False when nothing is playing, which tells the agent how to interpret the empty/none state. It stops short of noting auth or active-device requirements, keeping it from 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?

One sentence for purpose, one line for the return edge case, nothing else. The field list is front-loaded and every phrase carries information the agent needs; no restatement of the title or 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 a zero-parameter read tool with an output schema present, the definition covers purpose, returned fields and the empty-state semantics, which is nearly everything needed to call it correctly. The remaining gap is environmental context (active device / account tier) that determines whether playback state is even available.

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?

The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. The schema is an empty object, consistent with the description's parameterless framing.

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 ("Get the current playback state") and enumerates exactly what comes back: track, device, progress, shuffle, repeat. That enumeration distinguishes it cleanly from control_playback (mutation) and get_queue (upcoming items) without either sibling being named.

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: an agent can infer this answers "what is playing right now." There is no explicit guidance on when to prefer it over get_queue or list_devices, and no mention of prerequisites such as an active device or premium account, which materially affect whether this call returns useful data.

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

get_playlistGet PlaylistA
Read-onlyIdempotent

Get basic information about a Spotify playlist.

Args:
    playlist_id: Spotify playlist ID

Returns:
    Playlist metadata (no tracks - use get_playlist_tracks for tracks)

Note: This returns playlist info only. For tracks, use get_playlist_tracks
which supports full pagination for large playlists.
NameRequiredDescriptionDefault
playlist_idYes

Output Schema

NameRequiredDescription
idYes
nameYes
ownerNo
publicNo
tracksNo
descriptionNo
total_tracksNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true and openWorldHint=true, so safety is covered; the description adds real value by stating the response omits tracks and that pagination lives in a different tool. It does not mention error behavior for invalid IDs or auth requirements, which keeps it from 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.

Conciseness3/5

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

The Args/Returns/Note scaffolding plus a closing note repeats the same fact three times: no tracks, use get_playlist_tracks. The message is front-loaded and understandable, but redundant sentences dilute it and the Returns block duplicates what the output schema already provides.

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 one required parameter, an output schema present, and annotations covering the safety profile, the description supplies what is needed to select and call the tool. The one residual gap is the playlist_id format, which neither schema nor description pins down.

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 0%, so the description carries the full burden for the single parameter. It states 'playlist_id: Spotify playlist ID', which identifies the parameter's meaning but does not specify the expected format (e.g., base-62 ID versus URI/URL), leaving an ambiguity an agent could hit.

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 verb and resource ('Get basic information about a Spotify playlist') and explicitly differentiates itself from the sibling get_playlist_tracks by stating it returns 'Playlist metadata (no tracks)'. The phrase 'basic information' is slightly vague about which metadata fields are returned, keeping it just 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?

It gives clear routing guidance: for tracks, use get_playlist_tracks, and it notes that tool 'supports full pagination for large playlists', which is a useful selection criterion. It does not address cases like when to use list_playlists versus get_playlist, but the primary alternative is handled well.

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

get_playlist_tracksGet Playlist TracksA
Read-onlyIdempotent

Get tracks from a playlist with full pagination support.

Args:
    playlist_id: Playlist ID
    limit: Max tracks to return (None for all tracks, up to 10,000 safety limit)
    offset: Number of tracks to skip for pagination (default 0)

Returns:
    PlaylistTracks with 'items' (list of tracks), 'total', 'limit', 'offset'

Note: Large playlists require pagination. Use limit/offset to get specific ranges:
- Get first 100: limit=100, offset=0
- Get next 100: limit=100, offset=100
- Get all tracks: limit=None (use with caution on very large playlists)
NameRequiredDescriptionDefault
limitNo
offsetNo
playlist_idYes

Output Schema

NameRequiredDescription
itemsYes
limitNo
totalYes
offsetYes
returnedYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds genuinely new behavior: a 10,000-item safety cap when limit is None, and the pagination model of successive limit/offset windows. It does not describe auth requirements for private playlists, which is the main remaining gap.

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 purpose is front-loaded in one sentence and the pagination examples are actionable. The Returns block partially duplicates the existing output schema, which is mild waste, but the Args block earns its place because the schema has no parameter descriptions.

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 3-parameter read tool with annotations and an output schema already in place, the description covers purpose, parameter semantics, pagination strategy, and the safety limit. Only edge-case behavior (invalid or inaccessible playlist_id, error responses) is unaddressed, which is minor given the output schema handles return shape.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden and does so: it explains that limit=None means all tracks subject to a 10,000 safety limit, that offset is the number of tracks to skip with default 0, and gives worked pagination examples. This is meaning the schema alone does not convey.

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 first sentence gives a specific verb and resource ("Get tracks from a playlist") plus a scope qualifier ("with full pagination support"), which clearly separates it from metadata tools like get_playlist. It never names a sibling tool explicitly, 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 Guidelines4/5

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

The Note section gives concrete when-to-use guidance: large playlists require pagination, use limit/offset for ranges, and use limit=None with caution on very large playlists. It lacks explicit routing to alternatives (e.g., get_playlist for metadata vs this tool for track listings), but the operational 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_queueGet QueueB
Read-onlyIdempotent

Get the current playback queue. Returns: Currently playing track and queue of upcoming tracks

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
queueYes
currently_playingNo

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds useful context about the shape of the response (currently playing track and upcoming tracks), but says nothing about behavior when no device is active or when the queue is empty, which is the main failure mode an agent would want to anticipate.

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 lines with the core action front-loaded and the return contents immediately after. The awkward 'Returns:' indentation adds a little noise but nothing is wasted or 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?

With zero parameters and an output schema present, the definition covers nearly everything an agent needs to invoke it correctly. The one gap is the lack of any note about authentication scope or behavior without an active device, which matters for an open-world playback 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?

The tool takes zero parameters, so the baseline of 4 applies; there is nothing for the description to disambiguate. No parameter-level meaning is missing because no parameters exist.

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 ("Get the current playback queue") and clarifies scope by listing what is returned: the currently playing track plus upcoming tracks. It does not differentiate from the close sibling get_playback_state, which returns overlapping playback information, so an agent must still infer the boundary.

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 versus alternatives such as get_playback_state (current track/device/progress) or add_to_queue, nor any note on prerequisites like an active playback session. The only implicit signal is that it returns upcoming tracks, which is left for the agent to interpret.

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

get_recently_playedRecently PlayedB
Read-onlyIdempotent

Get recently played tracks, most recent first.

Args:
    limit: Max tracks to return (1-50, default 20)

Returns:
    RecentlyPlayed with each track's played_at timestamp
NameRequiredDescriptionDefault
limitNo

Output Schema

NameRequiredDescription
itemsYes

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so safety and idempotency are covered. The description adds useful behavior beyond that: the result ordering and the presence of a played_at timestamp per track. It is silent on auth requirements and on whether only the current user's history is returned, which would matter for an open-world read.

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?

Short and front-loaded: the core behavior is in the first sentence, with Args/Returns following in a scannable structure. The docstring-style formatting is slightly verbose for one parameter but nothing 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 one-parameter read tool with an output schema, most of the essentials are present — scope, ordering, parameter bounds. The gaps are the lack of any routing guidance among the many sibling read tools and no mention of whose history is returned or whether results are capped by a time window.

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 0% and the schema only supplies a default of 20, so the description carries the burden — and it does, documenting the range (1-50) and the default explicitly. Only a single parameter, and it is fully characterized.

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 ("Get recently played tracks") plus an ordering guarantee ("most recent first"), which an agent can distinguish from list/get tools. It does not explicitly differentiate itself from near-neighbors like get_top_items or get_playback_state, so it falls short of 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 when-to-use guidance at all — nothing says whether this is for building a history view versus get_top_items (aggregate favorites) or get_playback_state (currently playing). The agent must infer the selection rule from the names alone.

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

get_saved_albumsGet Saved AlbumsB
Read-onlyIdempotent

Get albums saved in the user's library.

Args:
    limit: Max albums to return per page (1-50, default 20)
    offset: Number of albums to skip for pagination (default 0)

Returns:
    SavedAlbums with 'items' (albums with added_at) and pagination info
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds useful behavior beyond that by disclosing pagination mechanics (limit/offset) and the shape of the response ('items' with added_at), but says nothing about authentication scope requirements or result-size limits at the account level.

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 purpose statement is front-loaded and the Args/Returns structure is scannable with no filler. The Returns block is partly redundant with the existing output schema, a minor waste, but the rest 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 two-parameter read tool with annotations and an output schema, the description covers purpose, both parameters, and pagination adequately. The remaining gap is routing guidance relative to the many saved-library siblings (save_albums, check_saved_albums, remove_saved_albums).

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 0%, so the description must carry the parameter burden, and it does: it gives limit a valid range (1-50) and default 20, and explains offset as 'Number of albums to skip for pagination'. This meaningfully exceeds the bare integer properties in the schema, though it omits edge-case behavior for out-of-range values.

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 ('Get albums saved in the user's library'), which is unambiguous on its own. However, it does not distinguish itself from close siblings like check_saved_albums, save_albums, or get_album, so the agent must infer the boundary from names alone.

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 is given: nothing says to call this instead of get_album (single album) or check_saved_albums (existence check), nor when to page through the library versus search. The 'saved in the user's library' phrasing implies scope but offers no explicit exclusions or alternatives.

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

get_saved_audiobooksGet Saved AudiobooksB
Read-onlyIdempotent

Get the audiobooks saved in the user's library.

Args:
    limit: Max audiobooks to return per page (1-50, default 20)
    offset: Number of audiobooks to skip for pagination (default 0)

Returns:
    SavedAudiobooks with 'items' and pagination info
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds useful pagination behavior (limit range 1-50, default 20; offset default 0) and hints at the return shape, but says nothing about how many saved audiobooks typically exist, ordering, 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.

Conciseness4/5

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

A single purpose sentence followed by a compact Args/Returns block; nothing is padded. The Returns section is slightly redundant given an output schema exists, but the structure is front-loaded and scannable.

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 two-parameter read-only list endpoint with annotations covering safety and an output schema covering returns, the definition supplies everything needed to call it correctly. The only gap is guidance on selecting this versus check_saved_audiobooks or get_saved_tracks-style siblings.

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 0%, so the description carries the burden and does it well: it documents both parameters with their valid range and defaults that the bare schema omits. It could go further by stating whether offset-based paging is stable, but the essentials are present.

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 verb and resource ('Get the audiobooks saved in the user's library'), which clearly distinguishes it from write-side siblings like save_audiobooks or remove_saved_audiobooks. It does not explicitly name the nearest alternative (check_saved_audiobooks), so it stops short of full 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 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 or when-not-to-use guidance; the agent must infer from the name that this lists saved audiobooks rather than checking save status. No mention of prerequisites such as requiring an authenticated user, which matters for a 'user's library' endpoint.

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

get_saved_episodesGet Saved EpisodesA
Read-onlyIdempotent

Get the podcast episodes saved in the user's library.

Args:
    limit: Max episodes to return per page (1-50, default 20)
    offset: Number of episodes to skip for pagination (default 0)

Returns:
    EpisodeList with 'items' (episodes with show and added_at) and pagination info
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered; the description adds genuinely new behavior: page size bounded to 1-50 with a default of 20, offset-based skipping, and the shape of what comes back (items with show and added_at plus pagination info). It does not disclose whether results are ordered by added_at or what happens when offset exceeds library size.

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 one-line purpose, then compact Args/Returns blocks where every line adds information. The docstring formatting is slightly heavy for a two-parameter tool, and the Returns section partially duplicates the existing output 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 simple read-only paged list tool with only two optional params, the description covers purpose, parameter bounds, and return shape. The returns sentence is redundant given the output schema exists, and ordering guarantees are unstated, 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.

Parameters4/5

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

Schema description coverage is 0% — the schema lists only types and defaults with no titles or bounds — so the description carries the full burden and does so: it gives the valid range (1-50) that is absent from the schema, restates the default 20, and explains offset as a skip count for pagination. The only gap is that the two params are not tied to a recommended paging pattern.

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 ('Get') and a precise resource ('podcast episodes saved in the user's library'), which separates it from get_saved_shows and get_show_episodes. It stops short of naming those siblings or explaining how this differs from check_saved_episodes, so it is clear but not maximally 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 phrase 'saved in the user's library' implies the retrieval use case versus listing episodes of a given show, and the pagination args imply paging through large libraries. There is no explicit when-to-use/when-not guidance, no mention of check_saved_episodes or get_show_episodes as alternatives, and no note on typical page-size strategy.

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

get_saved_showsGet Saved ShowsA
Read-onlyIdempotent

Get the podcast shows saved in the user's library.

Args:
    limit: Max shows to return per page (1-50, default 20)
    offset: Number of shows to skip for pagination (default 0)

Returns:
    SavedShows with 'items' (shows with added_at) and pagination info
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds that each item carries an 'added_at' field and that results are paginated, but it does not mention auth requirements, ordering guarantees, or what an empty library returns; the Returns block also overlaps with the existing output 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?

The docstring-style layout front-loads the one-sentence purpose and then groups args and returns, which is easy to scan. The Returns section is partly redundant with the output schema, but no sentence is genuinely wasteful.

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-optional-parameter read tool with full annotation coverage and an output schema, the definition covers purpose, parameter ranges and pagination shape. The only real omission is routing guidance among the many sibling read/check tools.

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 0%, so the description must carry the load, and it does: it supplies the 1-50 valid range for limit and the defaults for both limit (20) and offset (0), none of which appear in the schema. It could still clarify offset semantics relative to ordering, but the critical constraints are present.

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 uses a specific verb and resource ('Get the podcast shows saved in the user's library'), which cleanly separates this tool from siblings such as get_saved_tracks, get_saved_albums and get_saved_audiobooks. It does not explicitly name the near-neighbours check_saved_shows or get_show_episodes, so the differentiation is implicit 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 Guidelines3/5

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

Reading 'saved' shows implies the retrieval use case, and the pagination args hint at paging through a library. However, nothing tells the agent when to prefer this over check_saved_shows (existence check) or get_show_episodes (episode listing), and there are no stated preconditions such as required auth scopes.

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

get_saved_tracksGet Liked SongsA
Read-onlyIdempotent

Get user's saved/liked tracks (Liked Songs library).

Args:
    limit: Max tracks to return per page (1-50, default 20)
    offset: Number of tracks to skip for pagination (default 0)

Returns:
    SavedTracks with 'items' (tracks with added_at timestamp) and pagination info
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description still adds genuinely new behavioral facts: the per-page ceiling of 1-50 (absent from the schema, which has no min/max), the default page size, the offset-based pagination model, and the fact that each returned track carries an added_at timestamp.

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?

Purpose is front-loaded in one line, then Args and Returns in a compact docstring layout with no filler. Every line carries information an agent can act on.

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 two-parameter paginated read with an output schema, this covers params, page bounds, and return shape adequately, and annotations cover safety. Minor gaps: it does not state that "user" means the authenticated user (auth requirement) or whether an empty library returns an empty items array.

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 0%, so the description must carry the load, and it does: both parameters get meaning (max per page, tracks to skip) plus the undocumented 1-50 range and both defaults. It stops short of explaining what happens when offset exceeds the library size or how to detect the last page.

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 ("Get user's saved/liked tracks") and pins the scope with "(Liked Songs library)", which separates it in spirit from get_tracks and get_playlist_tracks. It never names a sibling explicitly, so the differentiation is implied by the scope phrase rather than spelled out.

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 "Liked Songs library" framing implies when this is the right tool, but there is no explicit when-to-use, when-not-to-use, or pointer to alternatives such as get_tracks, check_saved_tracks, or save_tracks/remove_saved_tracks among the 44 siblings. Usage is inferable but not guided.

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

get_show_episodesGet Show EpisodesA
Read-onlyIdempotent

Get a podcast show's episodes, with the user's resume point for each.

Args:
    show_id: Show ID, URI or open.spotify.com URL
    limit: Max episodes to return per page (1-50, default 20)
    offset: Number of episodes to skip for pagination (default 0)

Returns:
    EpisodeList with 'items' and pagination info
NameRequiredDescriptionDefault
limitNo
offsetNo
show_idYes

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds real value beyond them by noting that each episode carries the user's resume point and that results are paginated, but it says nothing about rate limits, auth scope, or behavior for an unknown/invalid show id.

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 purpose is front-loaded in one sentence, followed by a clean Args/Returns breakdown with no filler. The Returns line is somewhat redundant given a real output schema exists, but overall it is tight and scannable.

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 three-parameter read tool with an output schema and full annotation coverage, the definition supplies enough to call it correctly: id format, pagination range, and the notable resume-point payload. Minor gaps remain around invalid-id behavior and any market/locale constraints.

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 0% schema description coverage the schema gives only bare names and defaults, so the description must compensate — and it largely does, stating show_id accepts an ID, URI or open.spotify.com URL and bounding limit to 1-50. Offset is explained as a page skip, which is adequate but minimal.

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 first sentence names a specific verb and resource ("Get a podcast show's episodes") and adds a distinguishing detail: the user's resume point is included per episode. It separates itself from get_saved_episodes and get_saved_shows by scoping to a single show, though it never names those siblings 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?

Usage is only implied — an agent can infer this tool is for browsing episodes of one known show, but the description never states when to prefer it over get_saved_episodes or get_saved_shows, nor does it mention prerequisites such as needing a valid show id from a show search/list.

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

get_top_itemsTop Artists and TracksA
Read-onlyIdempotent

Get the user's top artists or tracks over a time range.

This remains useful when recommendations or related artists are unavailable
to the app. Spotify's policy also restricts analysis and AI ingestion.

Args:
    item_type: 'tracks' or 'artists' (default 'tracks')
    time_range: 'short_term' (~4 weeks), 'medium_term' (~6 months) or 'long_term'
    limit: Max items to return (1-50, default 20)

Returns:
    TopItems with either 'tracks' or 'artists' populated
NameRequiredDescriptionDefault
limitNo
item_typeNotracks
time_rangeNomedium_term

Output Schema

NameRequiredDescription
tracksNo
artistsNo
time_rangeYes

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is covered. The description adds a real behavioral fact — that Spotify policy restricts analysis/AI ingestion of this data — plus the return shape, but says nothing about auth scope or rate limits for an open-world call.

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

Conciseness3/5

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

The Args/Returns structure is easy to scan, but the second sentence about recommendation availability and Spotify policy is tangential framing that does not help an agent call the tool, and 'Returns' restates what the output schema already declares.

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-optional-parameter read tool with no required args and an output schema, the definition covers operation, parameter values and defaults adequately. It falls short only on invoking-context details such as scopes or what happens with empty history.

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 0%, so the description carries the burden and largely does: it enumerates item_type values, spells out limit as 1-50 with default 20, and decodes time_range into approximate durations (~4 weeks, ~6 months), which the schema's bare strings do not. It omits the schema's own default for time_range (medium_term) and gives no format guidance beyond the labels.

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 first sentence gives a specific verb and resource ('Get the user's top artists or tracks') plus a scope qualifier (time range), which separates it from list-type siblings like get_followed_artists or get_saved_tracks. The remaining sentences do not name any sibling, so the differentiation is implicit 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 Guidelines3/5

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

Usage is only implied: the note that it 'remains useful when recommendations or related artists are unavailable' hints at a fallback scenario but never tells the agent when to pick this over get_followed_artists, get_artist, or get_tracks. There are no exclusions or prerequisites.

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

get_tracksGet TracksA
Read-onlyIdempotent

Get detailed information about one or more Spotify tracks.

Args:
    track_ids: Single track ID or list of track IDs (up to 50)

Returns:
    TrackList with 'tracks' containing track metadata including release_date.
    For single ID, returns {'tracks': [track]}.

Note: Batch lookup is much more efficient where it is available - 50 tracks
in 1 API call instead of 50. Spotify withholds the batch endpoint from some
apps, in which case this transparently falls back to one request per track,
so the result is the same either way.
NameRequiredDescriptionDefault
track_idsYes

Output Schema

NameRequiredDescription
tracksYes

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/openWorld, but the description adds meaningful behavior beyond them: the tool prefers a batch endpoint and transparently degrades to one request per track when Spotify withholds it, so output is identical either way. That cost/latency disclosure is exactly the kind of context annotations cannot convey.

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

Conciseness3/5

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

Front-loaded with the purpose, which is good, but the note is redundant — '50 tracks in 1 API call instead of 50' restates itself, and the fallback paragraph could be one clause shorter. The Args/Returns pseudo-docstring formatting repeats structure the schema and output schema already encode.

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 lookup with an output schema present, the description covers input shape, return shape, and the hidden batching behavior. The main remaining gap is ID format and behavior on invalid/unknown IDs, which an agent would otherwise discover only by error.

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 0%, so the description carries the burden and does: it documents that track_ids accepts a single string or a list, and caps the list at 50. That is the key semantic an agent needs to avoid an API error, though ID format (URI vs bare ID) is left unspecified.

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+resource: 'Get detailed information about one or more Spotify tracks', making the batch/single duality explicit. It is clearly a metadata lookup by ID, distinct from search_music or get_saved_tracks, but it never names a sibling or states why you'd pick this over get_playlist_tracks/get_album.

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?

Implied usage is 'you already have track IDs and want metadata', and the batch-efficiency note is a genuine usage tip. However, it gives no explicit when-to-use vs alternatives (e.g. search_music when you don't have IDs) and no failure/error guidance for invalid IDs.

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

list_devicesAvailable DevicesA
Read-onlyIdempotent

List the user's available Spotify devices.

Returns:
    DeviceList; use transfer_playback with a device id to make one active
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
devicesYes

TDQS

A4.3/5.0
Behavior3/5

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

Annotations already establish readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is clear. The description adds that the result is a DeviceList and that devices are the user's available ones, which reinforces the open-world nature, but it does not add substantial new behavioral detail beyond what annotations and the output schema already 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?

The description is two short sentences with no filler. The core action and resource appear first, followed by a useful return-type note and a direct pointer to the dependent sibling 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?

For a zero-parameter read-only listing tool with annotations covering safety and an output schema present, the description covers the essential purpose and the main downstream action. No critical information 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?

The input schema has zero parameters)Skip everything; description cannot add parameter meaning. With no params, the baseline is 4, and the description appropriately avoids fabricating param 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?

The description uses a specific verb and resource: 'List the user's available Spotify devices.' It clearly differentiates this from the sibling transfer_playback by noting the returned device id can be passed to that tool to make the device active. An agent can immediately understand what this tool does and how it relates to nearby 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 a clear practical usage context: call this to see available devices, then use transfer_playback with a returned device id to activate one. It does not explicitly state exclusions or alternatives, but for a simple zero-parameter read tool, the sequential guidance is sufficient.

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

list_playlistsList My PlaylistsA
Read-onlyIdempotent

Get current user's playlists with pagination support.

Args:
    limit: Max playlists to return per page (1-50, default 20)
    offset: Number of playlists to skip for pagination (default 0)

Returns:
    PlaylistList with 'items' (list of playlists) and pagination info ('total', 'limit', 'offset')

Note: For users with many playlists, use offset to paginate through results.
Example: offset=0 gets playlists 1-20, offset=20 gets playlists 21-40, etc.
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare read-only, idempotent, and open-world behavior. The description adds pagination semantics, default and maximum page size, and return structure. It does not mention auth requirements or filtering, but with annotations the disclosure is solid.

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, then uses Args/Returns/Note/Example structure clearly. The pagination example is somewhat verbose and the Returns section duplicates the output schema, but overall it is well organized.

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 two-parameter read-only list tool with an output schema and annotations, the description covers what is needed: defaults, limits, pagination behavior, and response shape. Nothing critical about invoking it correctly is missing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must carry parameter meaning. It documents limit as 1-50 with default 20, offset with default 0, and provides a pagination example that is absent from 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 'Get current user's playlists' with pagination support, a clear verb and resource. It distinguishes naturally from get_playlist by listing rather than fetching one, but does not name the sibling 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?

Explains how to paginate when a user has many playlists, which is useful usage context. However, it gives no explicit guidance on when to choose this over get_playlist or get_playlist_tracks, and no exclusions.

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

remove_saved_albumsRemove Saved AlbumsB
DestructiveIdempotent

Remove albums from the user's library.

Args:
    album_ids: Album IDs or URIs (up to 20)
NameRequiredDescriptionDefault
album_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, and openWorldHint=true, so the safety profile is largely covered. The description adds one useful operational detail — the batch limit of 20 — but does not say whether removals are reversible or what happens when an ID is not currently saved.

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 front-loaded and precise, with the batch limit placed right next to the parameter. The literal "Args:" wrapper is docstring boilerplate rather than prose, but it costs little space.

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?

An output schema exists, so return values need not be explained, and the batch semantics are covered. However, for a destructive library mutation the description omits authorization scope and partial-failure behavior (e.g., invalid or unsaved IDs), 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.

Parameters4/5

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

Schema description coverage is 0% and the schema only types the field as an array of strings, so the description carries real weight by clarifying that entries may be album IDs or URIs and that at most 20 may be supplied. That is meaningful semantics the schema alone does not convey.

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 ("Remove albums from the user's library"), which cleanly separates it from save_albums and check_saved_albums. It does not explicitly name the sibling alternatives, but the action and target are unambiguous.

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 or when-not-to-use guidance, and no mention of prerequisites such as the user authorization scope required to modify a library. An agent must infer usage purely from the tool name and the phrase "from the user's library".

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

remove_saved_audiobooksRemove Saved AudiobooksB
DestructiveIdempotent

Remove audiobooks from the user's library.

Args:
    audiobook_ids: Audiobook IDs or URIs (up to 50)
NameRequiredDescriptionDefault
audiobook_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.3/5.0
Behavior3/5

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

The annotations already declare destructiveHint=true, idempotentHint=true, readOnlyHint=false, and openWorldHint=true, so the safety profile is covered. The description adds one genuinely new behavioral fact: a batch cap of 50 IDs per call. It does not disclose what happens when an ID is invalid or not saved (silent skip vs. error), nor the auth scope required for a destructive library mutation.

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 sentence of purpose followed by a single Args block with no filler; the destructive nature of the operation and the batch limit are both surfaced up front. The docstring-style Args heading is slightly redundant with the schema but costs almost nothing.

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 single-parameter tool with an output schema, the description covers what is removed and the batch limit, so the minimum is met. It omits partial-failure semantics and irreversibility, which matter for a destructiveHint mutation, leaving real gaps for an agent deciding how to call it safely.

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 0%, so the description must carry the parameter meaning, and it does: it tells the agent the array accepts either bare audiobook IDs or URIs and is capped at 50 entries. That is meaningfully more than the schema, which only says 'array of strings.' It lacks format specifics or examples, which keeps it below a 5.

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: 'Remove audiobooks from the user's library.' An agent can immediately distinguish this from save_audiobooks, get_saved_audiobooks, and check_saved_audiobooks. It stops short of explicitly differentiating itself from the parallel remove_saved_albums / remove_saved_shows / remove_saved_tracks siblings, though the resource name does that implicitly.

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, no mention of alternatives such as save_audiobooks or check_saved_audiobooks, and no statement of prerequisites (e.g. the item must currently be saved). Usage is only implied by the tool name and the phrase 'from the user's library.'

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

remove_saved_episodesRemove Saved EpisodesB
DestructiveIdempotent

Remove podcast episodes from the user's library.

Args:
    episode_ids: Episode IDs or URIs (up to 50)
NameRequiredDescriptionDefault
episode_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true, so the safety profile is covered. The description adds a genuinely useful constraint, the 50-item cap, but says nothing about what happens with invalid or already-unsaved episode IDs, whether removal is reversible, or any rate limiting.

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 purpose statement is a single front-loaded sentence with no filler. The docstring-style 'Args:' block is slightly vestigial since it restates the parameter name, but the content it adds is substantive.

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?

An output schema exists, so return values need not be explained. However, for a destructive library mutation, the definition omits guidance on partial failures, behavior with IDs not currently saved, and required authorization, leaving meaningful 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 description coverage is 0% and the schema only names the field 'Episode Ids'. The description compensates well by specifying that values may be episode IDs or URIs and that at most 50 may be passed, which the schema alone does not convey.

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: 'Remove podcast episodes from the user's library.' This clearly distinguishes it from save_episodes and get_saved_episodes, though it never names those siblings explicitly. An agent can identify the operation without ambiguity.

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 mention of prerequisites (e.g. user authorization/scopes required to modify a library), and no routing to alternatives such as check_saved_episodes to verify presence first. Usage is only implied by the purpose sentence.

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

remove_saved_showsRemove Saved ShowsB
DestructiveIdempotent

Remove podcast shows from the user's library.

Args:
    show_ids: Show IDs or URIs (up to 50)
NameRequiredDescriptionDefault
show_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=true, readOnlyHint=false and openWorldHint=true, so the safety profile is covered. The description adds the batch ceiling of 50 items, which is useful operational context, but says nothing about permanence, behavior on IDs that were never saved, or partial-failure handling.

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 blocks with the purpose front-loaded ahead of the argument note; nothing is padded. The 'Args:' block is slightly redundant with the schema but earns its place by adding format and limit detail.

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 low-complexity single-parameter mutation; the description covers purpose and the one argument's format and cap, annotations cover destructiveness and idempotency, and an output schema exists so return values need not be explained. Only error/partial-success semantics are left unspecified.

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 0%, so the description must carry the parameter burden, and it does: it specifies that show_ids accepts either raw IDs or Spotify URIs and caps the batch at 50. The only gap is that array element format and error behavior on invalid IDs are not stated.

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 ("Remove podcast shows") and scopes it to "the user's library", which distinguishes it from remove_saved_albums, remove_saved_episodes and remove_tracks_from_playlist. It does not name the counterpart save_shows or get_saved_shows, 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 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 or when-not-to-use guidance, no mention of the counterpart tools (save_shows, get_saved_shows, check_saved_shows), and no stated prerequisites such as required scopes. Usage is only inferable from the verb in the name.

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

remove_saved_tracksUnlike TracksA
DestructiveIdempotent

Remove tracks from the user's saved (liked) tracks.

Args:
    track_ids: Track IDs or URIs (up to 50)
NameRequiredDescriptionDefault
track_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A4/5.0
Behavior3/5

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

The annotations already carry the key behavioral signals: destructiveHint=true, readOnlyHint=false, and idempotentHint=true. The description adds only a capacity constraint ('up to 50') and otherwise relies on the operation name and annotations. It does not contradict the annotations, but it does not deepen behavioral understanding much 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 extremely compact: one purpose sentence plus a one-line Args entry. Every word adds value, and the most important scoping information ('saved (liked) tracks') is front-loaded. No filler or repetition of schema details.

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 one-parameter, output-schema-bearing tool with annotations covering destructive and idempotent behavior, the description is nearly complete. It covers the target resource and the important parameter limit. A small gap is the absence of any guidance distinguishing this from playlist-removal operations, but that is not critical to calling 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 description coverage is 0%, so the description carries the burden for explaining track_ids. It adds meaningful semantics: values can be Track IDs or URIs, and at most 50 are accepted. This is useful, though it stops short of giving exact URI formats or examples, so it is not a perfect compensation.

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 ('Remove') and a precise resource ('the user's saved (liked) tracks'), which clearly distinguishes this tool from siblings like remove_tracks_from_playlist. The title 'Unlike Tracks' reinforces the intent. An agent can immediately tell 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 operation itself implies when to use it: whenever tracks need to be removed from the saved/liked library. However, it does not explicitly contrast it with alternatives such as remove_tracks_from_playlist or note when not to use it. Usage guidance is present by implication, not by explicit direction.

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

remove_tracks_from_playlistRemove Tracks from PlaylistB
Destructive

Remove tracks or podcast episodes from a playlist.

Args:
    playlist_id: Playlist ID
    track_uris: Track or episode URIs/URLs to remove. Bare IDs are tracks.
NameRequiredDescriptionDefault
track_urisYes
playlist_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare this as a destructive, non-idempotent, open-world mutation, so the safety profile is carried. The description adds a useful behavioral note that bare IDs are interpreted as tracks, but says nothing about required scopes/auth, whether removing a non-existent track errors or silently succeeds, or how positions shift after removal.

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-line purpose statement followed by two tight argument notes; nothing is padded or redundant. The Args block format is conventional and scannable.

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?

An output schema exists, so return values need not be explained, and annotations cover the mutation risk. However, for a destructive playlist mutation with 0% schema coverage, missing scope/permission and edge-case behavior leaves the agent with real gaps before calling it.

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

Parameters2/5

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

Schema description coverage is 0%, so the description carries the full burden and only partly meets it. It labels playlist_id and describes track_uris as accepting track/episode URIs or URLs plus bare IDs, but gives no URI format example, no guidance on array size limits, and no note about duplicate handling.

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 ('Remove') and resource ('tracks or podcast episodes from a playlist'), which clearly separates it from remove_saved_tracks and remove_saved_episodes. It stops short of naming those siblings explicitly, but the 'from a playlist' scoping makes the target 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 by the resource scope — you use it to edit playlist membership, not the user's saved library — but there is no explicit when-to-use or when-not-to-use guidance, and no mention of reorder_playlist as the alternative for rearranging rather than deleting entries.

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

reorder_playlistReorder PlaylistA
Destructive

Move a contiguous block of tracks to a new position within a playlist.

Args:
    playlist_id: Playlist ID
    range_start: Zero-based position of the first track to move
    insert_before: Zero-based position to insert the moved block before.
        Pass the playlist's total track count to move the block to the end.
    range_length: Number of consecutive tracks to move (default 1)
    snapshot_id: Optional playlist snapshot ID to guard against concurrent edits

Returns:
    ActionResult with the new snapshot_id

Note: Positions are zero-based. Example: move the first 3 tracks to just
before position 10 with range_start=0, range_length=3, insert_before=10.
NameRequiredDescriptionDefault
playlist_idYes
range_startYes
snapshot_idNo
range_lengthNo
insert_beforeYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already indicate mutation and destructiveness; the description adds meaningful behavior details: tracks are moved as a contiguous block, positions are zero-based, range_length defaults to 1, and snapshot_id is an optional concurrency guard. It accurately represents a mutating operation without contradicting the destructiveHint.

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 well-structured with a one-sentence summary, compact Args list, Returns note, and illustrative example. Every sentence adds necessary information and there is no filler or repetition of the input schema.

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 five-parameter mutating tool, the description fully explains parameters, return value, positional conventions, and an edge case. The output schema covers return details, and annotations cover safety characteristics, so nothing essential is missing for correct invocation.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden, and it succeeds. Every parameter is explained in Args, including required positional semantics, the insert_before end-of-playlist trick, the default for range_length, and the purpose of snapshot_id.

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: 'Move a contiguous block of tracks to a new position within a playlist.' This goes beyond the title by defining the exact behavior and scope, and it is clearly distinct from sibling operations like adding or removing tracks.

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 operational context, including how to move a block to the end by passing the playlist's total track count, and how snapshot_id guards against concurrent edits. It does not explicitly compare against add/remove alternatives, but the 'within a playlist' framing and contiguous-block requirement make the appropriate use case clear.

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

save_albumsSave AlbumsB
Idempotent

Save albums to the user's library.

Args:
    album_ids: Album IDs or URIs (up to 20)
NameRequiredDescriptionDefault
album_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds one genuinely useful behavioral limit ('up to 20'), but is silent on duplicate handling beyond what the idempotency hint implies, on required auth scope, and on failure behavior for invalid IDs.

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 purpose sentence is front-loaded and the constraint follows immediately; nothing is padded. The 'Args:' docstring artifact is slightly mechanical but does not waste the reader's attention.

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?

An output schema exists, so return-value explanation is not needed, and the batch-size limit is a helpful addition. For a user-library mutation among many near-identical siblings, however, the definition lacks guidance on prerequisite checks, scopes, and error conditions, leaving meaningful 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 0%, so the description carries the full burden — and it does add real meaning beyond the bare array type: accepted values may be either IDs or URIs, and at most 20 may be supplied. It still omits the error/truncation behavior when more than 20 are passed, keeping it below a 5.

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 ('Save albums to the user's library'), which is unambiguous on its own. It does not, however, distinguish itself from the closely related siblings get_saved_albums, remove_saved_albums, and check_saved_albums, so the agent must infer the boundary from names alone.

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 is given: nothing says whether to call check_saved_albums first, how this differs from remove_saved_albums, or what scope/auth the operation requires. Usage is only implied by the verb 'save'.

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

save_audiobooksSave AudiobooksB
Idempotent

Save audiobooks to the user's library.

Args:
    audiobook_ids: Audiobook IDs or URIs (up to 50)
NameRequiredDescriptionDefault
audiobook_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety and repeat-call profile is covered structurally. The description adds one genuinely useful behavioral constraint, the 50-item cap, which lets an agent batch without exceeding limits. Beyond that it says nothing about what happens to already-saved items or how invalid IDs are reported.

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-sentence purpose followed by a focused Args block; no filler and the key information is front-loaded. The header/Args formatting is slightly verbose for a single parameter but every line 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?

The tool is simple (one required parameter) and an output schema exists, so return values need not be explained. However, for a library-mutating tool with no guidance on idempotent behavior on already-saved entries or failure modes for bad IDs, the description leaves gaps an agent would want filled.

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 0% and the schema only declares an untyped-looking array of strings, so the description must carry the load. It does so meaningfully by stating the parameter accepts either IDs or URIs and is bounded at 50 entries — two facts absent from the schema. It still omits URI formatting details, but the value added is real.

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?

"Save audiobooks to the user's library" states a specific verb (save) and resource (audiobooks) plus the destination (user's library), which cleanly distinguishes it from get_saved_audiobooks, check_saved_audiobooks and remove_saved_audiobooks. It stops short of explicitly naming those siblings, so the differentiation is inferred from the verb rather than spelled out.

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 mention of prerequisites, and no reference to the obvious alternatives (check_saved_audiobooks to test whether an audiobook is already saved, remove_saved_audiobooks to undo). An agent must infer the routing from the tool name alone.

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

save_episodesSave EpisodesA
Idempotent

Save podcast episodes to the user's library.

Args:
    episode_ids: Episode IDs or URIs (up to 50)
NameRequiredDescriptionDefault
episode_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds genuine behavioral context with the 50-episode cap, but says nothing about the authentication requirement for a user library or what happens to duplicates despite the idempotent hint.

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 sentence is front-loaded and wastes nothing. The 'Args:' block partially restates the schema, but it is short and its content (URIs, 50 limit) is not redundant.

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 not be explained, and annotations cover safety and idempotency for this single-parameter mutation. The description supplies the two missing essentials — the value formats and the batch limit — making it sufficient to call the tool 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 0% (the single parameter is just an untyped array of strings), so the description carries the burden. It does add real meaning: accepted values include URIs as well as plain IDs, and there is a hard limit of 50 — information not present 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?

The description states a specific verb and resource: saving podcast episodes to the user's library. It distinguishes itself implicitly from siblings like remove_saved_episodes and get_saved_episodes via the verb, though it never names an alternative 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?

There is no guidance on when to use this versus check_saved_episodes or get_saved_episodes, and no note about whether calling it on already-saved episodes is safe. The agent must infer usage entirely from the name.

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

save_showsSave ShowsB
Idempotent

Save (follow) podcast shows to the user's library.

Args:
    show_ids: Show IDs or URIs (up to 50)
NameRequiredDescriptionDefault
show_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety and repeat-safety profile is covered. The description adds the 50-item cap and the fact that IDs or URIs are accepted, but says nothing about what happens with already-saved shows, invalid IDs, or permission requirements. Useful but thin given annotations do most of the work.

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-line purpose statement up front, then a single Args entry — nothing superfluous. The Google-style Args block is a slightly formal wrapper for one parameter but does not waste tokens.

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?

An output schema exists, so return values need no explanation, and annotations cover safety and idempotency for a single-parameter mutation. What's missing is any routing guidance against the large family of adjacent save/follow/check tools, which matters given 45 siblings.

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 0% — the schema only says 'array of strings' with no per-parameter description — so the description carries the burden and does compensate by specifying accepted formats (IDs or URIs) and a hard limit of 50. It stops short of example values or error behavior for malformed identifiers.

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 — 'Save (follow) podcast shows to the user's library' — and the parenthetical disambiguates 'save' as following. The resource noun ('shows') distinguishes it from the many sibling save/remove tools (save_albums, save_episodes, save_audiobooks), though it does not explicitly name any of them.

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 versus alternatives such as save_episodes, follow_playlist, or check_saved_shows, nor any note on preconditions (e.g., valid IDs, auth scope). The only contextual hint is the implicit library-writing nature of the verb.

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

save_tracksLike TracksA
Idempotent

Save (like) tracks to the user's library.

Args:
    track_ids: Track IDs or URIs (up to 50)
NameRequiredDescriptionDefault
track_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A4/5.0
Behavior3/5

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

The description adds a limit of 50 track_ids, which is beyond the annotations. It restates the write nature, which is already conveyed by readOnlyHint=false, and the idempotent nature is covered by idempotentHint=true. No additional behavioral traits such as side effects or error conditions are disclosed, so the description adds only marginal value 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?

The description is brief and front-loaded, stating the action first and then documenting the parameter in a clear Args block. Every sentence adds value, and there is no extraneous 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?

The tool is simple with one parameter, an output schema, and annotations covering the safety profile. The description supplies the necessary parameter semantics and limit, so an agent can invoke it correctly. It does not cover all possible context (e.g., auth scopes), but this is acceptable given the low complexity and existing structured data.

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 schema description coverage at 0%, the description compensates by explaining that track_ids accepts Track IDs or URIs and caps at 50. This provides meaning beyond the raw array-of-strings schema, though it could elaborate on ID vs URI formats.

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 identifies the action 'Save (like)' and the target 'tracks to the user's library', distinguishing it from siblings like add_tracks_to_playlist (which adds to a playlist) and remove_saved_tracks (which removes from the 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 implies usage when the user wants to persist tracks in their library, but it does not provide explicit when-to-use guidance or mention alternatives such as check_saved_tracks or add_tracks_to_playlist. This leaves the agent to infer the correct context from the action name and sibling names.

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

search_musicSearch SpotifyA
Read-onlyIdempotent

Search Spotify for tracks, albums, artists, or playlists.

Args:
    query: Search query
    qtype: Type ('track', 'album', 'artist', 'playlist')
    limit: Max results per page (1-50, default 10). Spotify caps search at 10
        per page for restricted apps and rejects anything larger; a larger
        limit is retried at the cap rather than failing. Check the returned
        `limit` for what was actually served, and use `offset` to go deeper.
    offset: Number of results to skip for pagination (default 0)
    year: Filter by year (e.g., '2024')
    year_range: Filter by year range (e.g., '2020-2024')
    genre: Filter by genre (e.g., 'electronic', 'hip-hop')
    artist: Filter by artist name
    album: Filter by album name

Returns:
    SearchResults with 'items' (list of tracks) and pagination info ('total', 'limit', 'offset')

Note: Filters use Spotify's search syntax. For large result sets, use offset to paginate.
Example: query='love', year='2024', genre='pop' searches for 'love year:2024 genre:pop'
NameRequiredDescriptionDefault
yearNo
albumNo
genreNo
limitNo
qtypeNotrack
queryYes
artistNo
offsetNo
year_rangeNo

Output Schema

NameRequiredDescription
nextNo
itemsYes
limitYes
totalYes
offsetYes
previousNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, openWorld), but the description adds genuinely non-obvious behavior: Spotify caps at 10 per page for restricted apps, a larger limit is retried at the cap rather than failing, and the caller should read the returned `limit` to see what was actually served. The only blemish is 'items (list of tracks)', which is misleading when qtype is album, artist, or playlist.

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 Args/Returns/Note structure is clean, front-loaded with the one-line purpose, and the pagination caveat sits in the limit entry where the agent will read it. It runs slightly long, and the closing Note largely restates the example that precedes it, but no section 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?

For a nine-parameter search tool with a declared output schema, this is complete: filters, pagination, caps, retry behavior, return shape, and a worked example are all present. An agent has everything needed to construct a correct call and to iterate across pages without further guessing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden and does so: it documents all nine parameters, gives the string format for year and year_range ('2024', '2020-2024'), supplies genre examples, states the limit range and default, and explains offset's pagination role. The composed example ('love year:2024 genre:pop') clarifies how the filter params are actually translated into Spotify syntax.

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?

'Search Spotify for tracks, albums, artists, or playlists' gives a specific verb (search) plus the resource classes covered, and the qtype list makes the scope concrete. It doesn't explicitly differentiate from ID-based siblings like get_artist or get_tracks, so an agent must infer that this is the discovery path versus the direct-lookup path.

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 tells you how to page through large result sets ('use offset to go deeper') and how to combine filters, which is real usage guidance. However, it never states when to choose search_music over get_tracks, get_artist, get_album, or get_playlist, nor does it name any alternative — the when-not-to-use case is entirely left to inference.

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

transfer_playbackSwitch DeviceA
Idempotent

Move playback to a different device (see list_devices).

Args:
    device_id: Target device ID
    play: Start playing after the transfer (default True)
NameRequiredDescriptionDefault
playNo
device_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already capture the mutation and idempotency profile (readOnlyHint=false, idempotentHint=true), so the description's additional context is moderate. It usefully discloses that playback can start after transfer via the play argument, but it does not mention preconditions such as the target device needing to be active or what happens on failure.

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 impressively compact, with the core action and prerequisite in one sentence and a minimal args list. Every line earns its place; there is no filler or repetition of schema details.

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 tool with an output schema and annotations, the description covers the essential invocation context: what the tool does, how to find valid targets, and the one optional behavioral flag. It could mention device activity requirements or error cases, but the guidance to use list_devices mitigates that 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 description coverage is 0%, so the description must compensate. It does by explaining device_id as the target device and play as 'Start playing after the transfer' with its default. This goes beyond the bare schema titles and gives the agent operational meaning for both arguments.

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 action ('Move playback') on a specific resource ('a different device'), which is unambiguous. It also points to list_devices, distinguishing it from playback-control siblings like control_playback. The vague title 'Switch Device' is clarified by the description.

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 communicates the purpose and directs the agent to list_devices for finding target devices)Skip to content. It does not explicitly contrast with alternatives like control_playback or add_to_queue, but the context is clear enough for selecting this tool over unrelated siblings.

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

unfollow_artistsUnfollow ArtistsA
DestructiveIdempotent

Unfollow artists. Requires user-follow-modify; reauthorize if it is missing.

Args:
    artist_ids: Artist IDs or URIs (up to 50)
NameRequiredDescriptionDefault
artist_idsYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true, so the safety profile is covered. The description adds genuinely new context beyond them by stating the required scope and the reauthorization path, which annotations never express. It still omits what is actually destroyed/lost, whether unfollowing is recoverable by re-following, and how partial failures among the 50 IDs are handled.

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 lines, front-loaded with the action and immediately followed by the blocking prerequisite. The docstring-style 'Args:' block is slightly awkward formatting but earns its space given the zero schema coverage.

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 the annotations already declare destructiveness and idempotency. With the scope requirement and the batch/format limits supplied, an agent has everything needed to invoke this 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 description coverage is 0%, so the description must carry the parameter burden, and it does: it specifies accepted formats ('Artist IDs or URIs') and a hard batch limit (up to 50), neither of which appears in the schema. That is meaningful compensating detail, though it does not say what happens for invalid or unknown IDs.

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 ('Unfollow artists'), which unambiguously identifies the operation and is easily distinguished from the inverse sibling follow_artists. It does not explicitly name the alternative, but the name and verb leave little 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 context is limited to a prerequisite: it names the required OAuth scope (user-follow-modify) and tells the agent to reauthorize if it is missing, which is actionable. However, there is no guidance on when to prefer this over check_following_artists or follow_artists, no exclusion cases, and no note on behavior when an artist is not currently followed.

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

unfollow_playlistUnfollow PlaylistA
DestructiveIdempotent

Unfollow a playlist, removing it from the user's library.

For playlists the user owns this is how Spotify deletes them — there is no
separate delete endpoint.

Args:
    playlist_id: Playlist ID or URI
NameRequiredDescriptionDefault
playlist_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, so the bar is lower; the description adds genuine value by specifying what gets destroyed: for an owned playlist, the playlist itself is permanently deleted. This non-obvious consequence goes beyond the generic destructive flag and matches the annotations with no contradiction.

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 plus a one-line args note, with the core action and effect front-loaded before the deletion nuance. Every sentence earns its place: the first states what it does, the second captures the critical gotcha, and the args line documents the only input. 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 tool with one required parameter, a full annotation profile (destructive, idempotent), and an output schema present, the description covers the only non-obvious trap an agent would face: owned playlists are deleted via unfollow. 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.

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate — and it does by documenting 'playlist_id: Playlist ID or URI.' The schema only says 'string' with title 'Playlist Id,' so the added 'or URI' format guidance is real semantic value beyond the structured data. For a single-parameter tool this is sufficient, though no provenance guidance for obtaining the ID is given.

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 pairing — 'Unfollow a playlist, removing it from the user's library' — and adds the key distinction that for owned playlists this is how Spotify deletes them. This clearly differentiates it from track-level siblings like remove_tracks_from_playlist or remove_saved_tracks, so an agent won't confuse removing content from a playlist with removing the playlist 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?

The statement 'For playlists the user owns this is how Spotify deletes them — there is no separate delete endpoint' is an explicit usage rule that tells an agent to reach for this tool even when the user's intent is deletion. It provides clear context but stops short of naming sibling alternatives or giving 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.

update_playlist_detailsEdit Playlist DetailsC
DestructiveIdempotent

Modify playlist details.

Args:
    playlist_id: Playlist ID
    name: New playlist name (optional)
    description: New playlist description (optional)
    public: Whether playlist should be public (optional)
NameRequiredDescriptionDefault
nameNo
publicNo
descriptionNo
playlist_idYes

Output Schema

NameRequiredDescription
statusYes
messageYes
snapshot_idNo

TDQS

C2.6/5.0
Behavior2/5

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

Annotations already indicate a mutation (readOnlyHint=false), idempotence, and destructiveness. The description adds no behavioral context beyond 'Modify' – it does not explain that existing values will be overwritten, what happens if parameters are null, or any side effects like visibility changes. It neither contradicts the annotations nor supplements them meaningfully.

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

Conciseness3/5

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

The description is brief and front-loaded with a clear summary, which is good. However, the Args list largely duplicates the input schema, so the added structural value is low. It is appropriately sized but not as economical as it could be if it replaced repetition with substantive guidance.

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 destructiveHint=true, the lack of detail about null semantics, overwrite behavior, and side effects leaves the definition incomplete. An agent could incorrectly assume that passing null clears a field or that all optional fields require explicit values. The output schema exists, so return-value documentation is not needed, but operational context is missing.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate. It rephrases schema titles ('New playlist name', 'Whether playlist should be public') but adds almost no new meaning. It fails to explain the critical null-default semantics: whether null means 'leave unchanged' or 'clear the field'. This ambiguity is central to 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?

The description states a concrete verb and resource: 'Modify playlist details.' It clearly distinguishes this from sibling tools that handle track management (add/remove/reorder) or retrieval, though it doesn't explicitly name a sibling. It is not a tautology and leaves little ambiguity about the 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?

No guidance is given about when to use this tool versus alternatives like create_playlist, reorder_playlist, or unfollow_playlist. The description simply states the action without explaining prerequisites, exclusions, or contexts where another tool would be more appropriate.

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. 34 tool updatesv0.8.1
    • Addedcheck_saved_audiobooks
    • Addedcheck_saved_episodes
    • Addedcheck_saved_shows
    • Changedcontrol_playback4 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
      • addedOutput schema / properties / currently_playing_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Currently Playing Type"
        +}
    • Changedcreate_playlist3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Addedfollow_artists
    • Addedfollow_playlist
    • Changedget_album4 fields changed
      • addedOutput schema / $defs / Album / properties / added_at
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Added At"
        +}
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Changedget_artist3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Addedget_followed_artists
    • Changedget_playback_state4 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
      • addedOutput schema / properties / currently_playing_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Currently Playing Type"
        +}
    • Changedget_playlist3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Changedget_playlist_tracks3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Changedget_queue3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Changedget_recently_played3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Addedget_saved_albums
    • Addedget_saved_audiobooks
    • Addedget_saved_episodes
    • Addedget_saved_shows
    • Changedget_saved_tracks3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Addedget_show_episodes
    • Changedget_top_items3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Changedget_tracks3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Changedlist_playlists3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Addedremove_saved_albums
    • Addedremove_saved_audiobooks
    • Addedremove_saved_episodes
    • Addedremove_saved_shows
    • Addedsave_albums
    • Addedsave_audiobooks
    • Addedsave_episodes
    • Addedsave_shows
    • Changedsearch_music3 fields changed
      • addedOutput schema / $defs / Track / properties / show
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show"
        +}
      • addedOutput schema / $defs / Track / properties / show_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Show Id"
        +}
      • addedOutput schema / $defs / Track / properties / type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Type"
        +}
    • Addedunfollow_artists
  2. 1 tool updatev0.7.0
    • Changedcreate_playlist1 field changed
      • changedInput schema / properties / public / default
        Previous value: -trueNew value: +false
  3. 34 tool updatesv0.6.1
    • Addedcheck_following_artists
    • Addedcheck_saved_albums
    • Addedcheck_saved_tracks
    • Addedcontrol_playback
    • Changedcreate_playlist6 fields changed
      • addedOutput schema / $defs / Track / properties / id / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedOutput schema / $defs / Track / properties / id / default
        Added value: +null
      • removedOutput schema / $defs / Track / properties / id / type
        Removed value: -"string"
      • addedOutput schema / $defs / Track / properties / is_local
        Added value: +{
        +  "default": false,
        +  "title": "Is Local",
        +  "type": "boolean"
        +}
      • addedOutput schema / $defs / Track / properties / played_at
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Played At"
        +}
      • changedOutput schema / $defs / Track / required
        Previous value: -[
        -  "name",
        -  "id",
        -  "artist"
        -]New value: +[
        +  "name",
        +  "artist"
        +]
    • Addedget_album
    • Removedget_album_info
    • Addedget_artist
    • Removedget_artist_info
    • Addedget_me
    • Addedget_playback_state
    • Addedget_playlist
    • Removedget_playlist_info
    • Changedget_playlist_tracks6 fields changed
      • addedOutput schema / $defs / Track / properties / id / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedOutput schema / $defs / Track / properties / id / default
        Added value: +null
      • removedOutput schema / $defs / Track / properties / id / type
        Removed value: -"string"
      • addedOutput schema / $defs / Track / properties / is_local
        Added value: +{
        +  "default": false,
        +  "title": "Is Local",
        +  "type": "boolean"
        +}
      • addedOutput schema / $defs / Track / properties / played_at
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Played At"
        +}
      • changedOutput schema / $defs / Track / required
        Previous value: -[
        -  "name",
        -  "id",
        -  "artist"
        -]New value: +[
        +  "name",
        +  "artist"
        +]
    • Changedget_queue6 fields changed
      • addedOutput schema / $defs / Track / properties / id / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedOutput schema / $defs / Track / properties / id / default
        Added value: +null
      • removedOutput schema / $defs / Track / properties / id / type
        Removed value: -"string"
      • addedOutput schema / $defs / Track / properties / is_local
        Added value: +{
        +  "default": false,
        +  "title": "Is Local",
        +  "type": "boolean"
        +}
      • addedOutput schema / $defs / Track / properties / played_at
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Played At"
        +}
      • changedOutput schema / $defs / Track / required
        Previous value: -[
        -  "name",
        -  "id",
        -  "artist"
        -]New value: +[
        +  "name",
        +  "artist"
        +]
    • Addedget_recently_played
    • Changedget_saved_tracks6 fields changed
      • addedOutput schema / $defs / Track / properties / id / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedOutput schema / $defs / Track / properties / id / default
        Added value: +null
      • removedOutput schema / $defs / Track / properties / id / type
        Removed value: -"string"
      • addedOutput schema / $defs / Track / properties / is_local
        Added value: +{
        +  "default": false,
        +  "title": "Is Local",
        +  "type": "boolean"
        +}
      • addedOutput schema / $defs / Track / properties / played_at
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Played At"
        +}
      • changedOutput schema / $defs / Track / required
        Previous value: -[
        -  "name",
        -  "id",
        -  "artist"
        -]New value: +[
        +  "name",
        +  "artist"
        +]
    • Addedget_top_items
    • Removedget_track_info
    • Addedget_tracks
    • Removedget_user_playlists
    • Addedlist_devices
    • Addedlist_playlists
    • Removedmodify_playlist_details
    • Removedplayback_control
    • Addedremove_saved_tracks
    • Addedreorder_playlist
    • Removedreorder_playlist_tracks
    • Addedsave_tracks
    • Addedsearch_music
    • Removedsearch_tracks
    • Addedtransfer_playback
    • Addedunfollow_playlist
    • Addedupdate_playlist_details
  4. 18 tool updatesv0.3.1
    • Changedadd_to_queue5 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / description
        Added value: +"Result of a state-changing operation."
      • addedOutput schema / properties
        Added value: +{
        +  "message": {
        +    "title": "Message",
        +    "type": "string"
        +  },
        +  "snapshot_id": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Snapshot Id"
        +  },
        +  "status": {
        +    "title": "Status",
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "message"
        +]
      • changedOutput schema / title
        Previous value: -"add_to_queueDictOutput"New value: +"ActionResult"
    • Changedadd_tracks_to_playlist5 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / description
        Added value: +"Result of a state-changing operation."
      • addedOutput schema / properties
        Added value: +{
        +  "message": {
        +    "title": "Message",
        +    "type": "string"
        +  },
        +  "snapshot_id": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Snapshot Id"
        +  },
        +  "status": {
        +    "title": "Status",
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "message"
        +]
      • changedOutput schema / title
        Previous value: -"add_tracks_to_playlistDictOutput"New value: +"ActionResult"
    • Changedcreate_playlist5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"A Spotify playlist."
      • addedOutput schema / properties
        Added value: +{
        +  "description": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Description"
        +  },
        +  "id": {
        +    "title": "Id",
        +    "type": "string"
        +  },
        +  "name": {
        +    "title": "Name",
        +    "type": "string"
        +  },
        +  "owner": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Owner"
        +  },
        +  "public": {
        +    "anyOf": [
        +      {
        +        "type": "boolean"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Public"
        +  },
        +  "total_tracks": {
        +    "anyOf": [
        +      {
        +        "type": "integer"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Total Tracks"
        +  },
        +  "tracks": {
        +    "anyOf": [
        +      {
        +        "items": {
        +          "$ref": "#/$defs/Track"
        +        },
        +        "type": "array"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Tracks"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "name",
        +  "id"
        +]
      • changedOutput schema / title
        Previous value: -"create_playlistDictOutput"New value: +"Playlist"
    • Changedget_album_info5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Album": {
        +    "description": "A Spotify album.",
        +    "properties": {
        +      "album_type": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Type"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "genres": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Genres"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "label": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Label"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      },
        +      "release_date_precision": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date Precision"
        +      },
        +      "total_tracks": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Total Tracks"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Album",
        +    "type": "object"
        +  },
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"An album with its tracks."
      • addedOutput schema / properties
        Added value: +{
        +  "album": {
        +    "$ref": "#/$defs/Album"
        +  },
        +  "tracks": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Tracks",
        +    "type": "array"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "album",
        +  "tracks"
        +]
      • changedOutput schema / title
        Previous value: -"get_album_infoDictOutput"New value: +"AlbumInfo"
    • Changedget_artist_info5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Artist": {
        +    "description": "A Spotify artist.",
        +    "properties": {
        +      "followers": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Followers"
        +      },
        +      "genres": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Genres"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id"
        +    ],
        +    "title": "Artist",
        +    "type": "object"
        +  },
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"An artist with their top tracks."
      • addedOutput schema / properties
        Added value: +{
        +  "artist": {
        +    "$ref": "#/$defs/Artist"
        +  },
        +  "top_tracks": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Top Tracks",
        +    "type": "array"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "artist",
        +  "top_tracks"
        +]
      • changedOutput schema / title
        Previous value: -"get_artist_infoDictOutput"New value: +"ArtistInfo"
    • Removedget_audio_features
    • Changedget_playlist_info5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"A Spotify playlist."
      • addedOutput schema / properties
        Added value: +{
        +  "description": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Description"
        +  },
        +  "id": {
        +    "title": "Id",
        +    "type": "string"
        +  },
        +  "name": {
        +    "title": "Name",
        +    "type": "string"
        +  },
        +  "owner": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Owner"
        +  },
        +  "public": {
        +    "anyOf": [
        +      {
        +        "type": "boolean"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Public"
        +  },
        +  "total_tracks": {
        +    "anyOf": [
        +      {
        +        "type": "integer"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Total Tracks"
        +  },
        +  "tracks": {
        +    "anyOf": [
        +      {
        +        "items": {
        +          "$ref": "#/$defs/Track"
        +        },
        +        "type": "array"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Tracks"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "name",
        +  "id"
        +]
      • changedOutput schema / title
        Previous value: -"get_playlist_infoDictOutput"New value: +"Playlist"
    • Changedget_playlist_tracks5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"Paginated tracks from a single playlist."
      • addedOutput schema / properties
        Added value: +{
        +  "items": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Items",
        +    "type": "array"
        +  },
        +  "limit": {
        +    "anyOf": [
        +      {
        +        "type": "integer"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Limit"
        +  },
        +  "offset": {
        +    "title": "Offset",
        +    "type": "integer"
        +  },
        +  "returned": {
        +    "title": "Returned",
        +    "type": "integer"
        +  },
        +  "total": {
        +    "title": "Total",
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "items",
        +  "total",
        +  "offset",
        +  "returned"
        +]
      • changedOutput schema / title
        Previous value: -"get_playlist_tracksDictOutput"New value: +"PlaylistTracks"
    • Changedget_queue5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"Currently playing track plus the upcoming queue."
      • addedOutput schema / properties
        Added value: +{
        +  "currently_playing": {
        +    "anyOf": [
        +      {
        +        "$ref": "#/$defs/Track"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null
        +  },
        +  "queue": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Queue",
        +    "type": "array"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "queue"
        +]
      • changedOutput schema / title
        Previous value: -"get_queueDictOutput"New value: +"QueueState"
    • Removedget_recommendations
    • Changedget_saved_tracks5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"Paginated saved/liked tracks."
      • addedOutput schema / properties
        Added value: +{
        +  "items": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Items",
        +    "type": "array"
        +  },
        +  "limit": {
        +    "title": "Limit",
        +    "type": "integer"
        +  },
        +  "next": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Next"
        +  },
        +  "offset": {
        +    "title": "Offset",
        +    "type": "integer"
        +  },
        +  "previous": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Previous"
        +  },
        +  "total": {
        +    "title": "Total",
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "items",
        +  "total",
        +  "limit",
        +  "offset"
        +]
      • changedOutput schema / title
        Previous value: -"get_saved_tracksDictOutput"New value: +"SavedTracks"
    • Changedget_track_info5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"A list of tracks."
      • addedOutput schema / properties
        Added value: +{
        +  "tracks": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Tracks",
        +    "type": "array"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "tracks"
        +]
      • changedOutput schema / title
        Previous value: -"get_track_infoDictOutput"New value: +"TrackList"
    • Changedget_user_playlists5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Playlist": {
        +    "description": "A Spotify playlist.",
        +    "properties": {
        +      "description": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Description"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "owner": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Owner"
        +      },
        +      "public": {
        +        "anyOf": [
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Public"
        +      },
        +      "total_tracks": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Total Tracks"
        +      },
        +      "tracks": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "$ref": "#/$defs/Track"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Tracks"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id"
        +    ],
        +    "title": "Playlist",
        +    "type": "object"
        +  },
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"Paginated list of playlists."
      • addedOutput schema / properties
        Added value: +{
        +  "items": {
        +    "items": {
        +      "$ref": "#/$defs/Playlist"
        +    },
        +    "title": "Items",
        +    "type": "array"
        +  },
        +  "limit": {
        +    "title": "Limit",
        +    "type": "integer"
        +  },
        +  "next": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Next"
        +  },
        +  "offset": {
        +    "title": "Offset",
        +    "type": "integer"
        +  },
        +  "previous": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Previous"
        +  },
        +  "total": {
        +    "title": "Total",
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "items",
        +  "total",
        +  "limit",
        +  "offset"
        +]
      • changedOutput schema / title
        Previous value: -"get_user_playlistsDictOutput"New value: +"PlaylistList"
    • Changedmodify_playlist_details5 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / description
        Added value: +"Result of a state-changing operation."
      • addedOutput schema / properties
        Added value: +{
        +  "message": {
        +    "title": "Message",
        +    "type": "string"
        +  },
        +  "snapshot_id": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Snapshot Id"
        +  },
        +  "status": {
        +    "title": "Status",
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "message"
        +]
      • changedOutput schema / title
        Previous value: -"modify_playlist_detailsDictOutput"New value: +"ActionResult"
    • Changedplayback_control1 field changed
      • addedOutput schema / $defs / Track / properties / added_at
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Added At"
        +}
    • Changedremove_tracks_from_playlist5 fields changed
      • removedOutput schema / additionalProperties
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / description
        Added value: +"Result of a state-changing operation."
      • addedOutput schema / properties
        Added value: +{
        +  "message": {
        +    "title": "Message",
        +    "type": "string"
        +  },
        +  "snapshot_id": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Snapshot Id"
        +  },
        +  "status": {
        +    "title": "Status",
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "status",
        +  "message"
        +]
      • changedOutput schema / title
        Previous value: -"remove_tracks_from_playlistDictOutput"New value: +"ActionResult"
    • Addedreorder_playlist_tracks
    • Changedsearch_tracks5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "Track": {
        +    "description": "A Spotify track with metadata.",
        +    "properties": {
        +      "added_at": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Added At"
        +      },
        +      "album": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album"
        +      },
        +      "album_id": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Album Id"
        +      },
        +      "artist": {
        +        "title": "Artist",
        +        "type": "string"
        +      },
        +      "artists": {
        +        "anyOf": [
        +          {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Artists"
        +      },
        +      "duration_ms": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Duration Ms"
        +      },
        +      "external_urls": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "type": "string"
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "External Urls"
        +      },
        +      "id": {
        +        "title": "Id",
        +        "type": "string"
        +      },
        +      "name": {
        +        "title": "Name",
        +        "type": "string"
        +      },
        +      "popularity": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Popularity"
        +      },
        +      "release_date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "title": "Release Date"
        +      }
        +    },
        +    "required": [
        +      "name",
        +      "id",
        +      "artist"
        +    ],
        +    "title": "Track",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / description
        Added value: +"Paginated search results."
      • addedOutput schema / properties
        Added value: +{
        +  "items": {
        +    "items": {
        +      "$ref": "#/$defs/Track"
        +    },
        +    "title": "Items",
        +    "type": "array"
        +  },
        +  "limit": {
        +    "title": "Limit",
        +    "type": "integer"
        +  },
        +  "next": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Next"
        +  },
        +  "offset": {
        +    "title": "Offset",
        +    "type": "integer"
        +  },
        +  "previous": {
        +    "anyOf": [
        +      {
        +        "type": "string"
        +      },
        +      {
        +        "type": "null"
        +      }
        +    ],
        +    "default": null,
        +    "title": "Previous"
        +  },
        +  "total": {
        +    "title": "Total",
        +    "type": "integer"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "items",
        +  "total",
        +  "limit",
        +  "offset"
        +]
      • changedOutput schema / title
        Previous value: -"search_tracksDictOutput"New value: +"SearchResults"
  5. 19 tool updatesv1.0.0
    • Addedadd_to_queue
    • Changedadd_tracks_to_playlist4 fields changed
      • addedOutput schema / additionalProperties
        Added value: +{
        +  "type": "string"
        +}
      • removedOutput schema / properties
        Removed value: -{
        -  "result": {
        -    "additionalProperties": {
        -      "type": "string"
        -    },
        -    "title": "Result",
        -    "type": "object"
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "result"
        -]
      • changedOutput schema / title
        Previous value: -"add_tracks_to_playlistOutput"New value: +"add_tracks_to_playlistDictOutput"
    • Changedcreate_playlist5 fields changed
      • removedOutput schema / $defs
        Removed value: -{
        -  "Track": {
        -    "description": "A Spotify track with metadata.",
        -    "properties": {
        -      "album": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Album"
        -      },
        -      "artist": {
        -        "title": "Artist",
        -        "type": "string"
        -      },
        -      "artists": {
        -        "anyOf": [
        -          {
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Artists"
        -      },
        -      "duration_ms": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Duration Ms"
        -      },
        -      "external_urls": {
        -        "anyOf": [
        -          {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "External Urls"
        -      },
        -      "id": {
        -        "title": "Id",
        -        "type": "string"
        -      },
        -      "name": {
        -        "title": "Name",
        -        "type": "string"
        -      },
        -      "popularity": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Popularity"
        -      }
        -    },
        -    "required": [
        -      "name",
        -      "id",
        -      "artist"
        -    ],
        -    "title": "Track",
        -    "type": "object"
        -  }
        -}
      • removedOutput schema / description
        Removed value: -"A Spotify playlist."
      • removedOutput schema / properties
        Removed value: -{
        -  "description": {
        -    "anyOf": [
        -      {
        -        "type": "string"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "default": null,
        -    "title": "Description"
        -  },
        -  "id": {
        -    "title": "Id",
        -    "type": "string"
        -  },
        -  "name": {
        -    "title": "Name",
        -    "type": "string"
        -  },
        -  "owner": {
        -    "anyOf": [
        -      {
        -        "type": "string"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "default": null,
        -    "title": "Owner"
        -  },
        -  "public": {
        -    "anyOf": [
        -      {
        -        "type": "boolean"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "default": null,
        -    "title": "Public"
        -  },
        -  "total_tracks": {
        -    "anyOf": [
        -      {
        -        "type": "integer"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "default": null,
        -    "title": "Total Tracks"
        -  },
        -  "tracks": {
        -    "anyOf": [
        -      {
        -        "items": {
        -          "$ref": "#/$defs/Track"
        -        },
        -        "type": "array"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "default": null,
        -    "title": "Tracks"
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "name",
        -  "id"
        -]
      • changedOutput schema / title
        Previous value: -"Playlist"New value: +"create_playlistDictOutput"
    • Addedget_album_info
    • Addedget_artist_info
    • Addedget_audio_features
    • Removedget_item_info
    • Addedget_playlist_info
    • Addedget_playlist_tracks
    • Addedget_queue
    • Addedget_recommendations
    • Addedget_saved_tracks
    • Addedget_track_info
    • Changedget_user_playlists5 fields changed
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "title": "Offset",
        +  "type": "integer"
        +}
      • removedOutput schema / $defs
        Removed value: -{
        -  "Playlist": {
        -    "description": "A Spotify playlist.",
        -    "properties": {
        -      "description": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Description"
        -      },
        -      "id": {
        -        "title": "Id",
        -        "type": "string"
        -      },
        -      "name": {
        -        "title": "Name",
        -        "type": "string"
        -      },
        -      "owner": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Owner"
        -      },
        -      "public": {
        -        "anyOf": [
        -          {
        -            "type": "boolean"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Public"
        -      },
        -      "total_tracks": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Total Tracks"
        -      },
        -      "tracks": {
        -        "anyOf": [
        -          {
        -            "items": {
        -              "$ref": "#/$defs/Track"
        -            },
        -            "type": "array"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Tracks"
        -      }
        -    },
        -    "required": [
        -      "name",
        -      "id"
        -    ],
        -    "title": "Playlist",
        -    "type": "object"
        -  },
        -  "Track": {
        -    "description": "A Spotify track with metadata.",
        -    "properties": {
        -      "album": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Album"
        -      },
        -      "artist": {
        -        "title": "Artist",
        -        "type": "string"
        -      },
        -      "artists": {
        -        "anyOf": [
        -          {
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Artists"
        -      },
        -      "duration_ms": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Duration Ms"
        -      },
        -      "external_urls": {
        -        "anyOf": [
        -          {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "External Urls"
        -      },
        -      "id": {
        -        "title": "Id",
        -        "type": "string"
        -      },
        -      "name": {
        -        "title": "Name",
        -        "type": "string"
        -      },
        -      "popularity": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Popularity"
        -      }
        -    },
        -    "required": [
        -      "name",
        -      "id",
        -      "artist"
        -    ],
        -    "title": "Track",
        -    "type": "object"
        -  }
        -}
      • removedOutput schema / properties
        Removed value: -{
        -  "result": {
        -    "items": {
        -      "$ref": "#/$defs/Playlist"
        -    },
        -    "title": "Result",
        -    "type": "array"
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "result"
        -]
      • changedOutput schema / title
        Previous value: -"get_user_playlistsOutput"New value: +"get_user_playlistsDictOutput"
    • Removedmanage_queue
    • Changedmodify_playlist_details4 fields changed
      • addedOutput schema / additionalProperties
        Added value: +{
        +  "type": "string"
        +}
      • removedOutput schema / properties
        Removed value: -{
        -  "result": {
        -    "additionalProperties": {
        -      "type": "string"
        -    },
        -    "title": "Result",
        -    "type": "object"
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "result"
        -]
      • changedOutput schema / title
        Previous value: -"modify_playlist_detailsOutput"New value: +"modify_playlist_detailsDictOutput"
    • Changedplayback_control2 fields changed
      • addedOutput schema / $defs / Track / properties / album_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Album Id"
        +}
      • addedOutput schema / $defs / Track / properties / release_date
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Release Date"
        +}
    • Changedremove_tracks_from_playlist4 fields changed
      • addedOutput schema / additionalProperties
        Added value: +{
        +  "type": "string"
        +}
      • removedOutput schema / properties
        Removed value: -{
        -  "result": {
        -    "additionalProperties": {
        -      "type": "string"
        -    },
        -    "title": "Result",
        -    "type": "object"
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "result"
        -]
      • changedOutput schema / title
        Previous value: -"remove_tracks_from_playlistOutput"New value: +"remove_tracks_from_playlistDictOutput"
    • Changedsearch_tracks10 fields changed
      • addedInput schema / properties / album
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Album"
        +}
      • addedInput schema / properties / artist
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Artist"
        +}
      • addedInput schema / properties / genre
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Genre"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "title": "Offset",
        +  "type": "integer"
        +}
      • addedInput schema / properties / year
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Year"
        +}
      • addedInput schema / properties / year_range
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Year Range"
        +}
      • removedOutput schema / $defs
        Removed value: -{
        -  "Track": {
        -    "description": "A Spotify track with metadata.",
        -    "properties": {
        -      "album": {
        -        "anyOf": [
        -          {
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Album"
        -      },
        -      "artist": {
        -        "title": "Artist",
        -        "type": "string"
        -      },
        -      "artists": {
        -        "anyOf": [
        -          {
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Artists"
        -      },
        -      "duration_ms": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Duration Ms"
        -      },
        -      "external_urls": {
        -        "anyOf": [
        -          {
        -            "additionalProperties": {
        -              "type": "string"
        -            },
        -            "type": "object"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "External Urls"
        -      },
        -      "id": {
        -        "title": "Id",
        -        "type": "string"
        -      },
        -      "name": {
        -        "title": "Name",
        -        "type": "string"
        -      },
        -      "popularity": {
        -        "anyOf": [
        -          {
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "default": null,
        -        "title": "Popularity"
        -      }
        -    },
        -    "required": [
        -      "name",
        -      "id",
        -      "artist"
        -    ],
        -    "title": "Track",
        -    "type": "object"
        -  }
        -}
      • removedOutput schema / properties
        Removed value: -{
        -  "result": {
        -    "items": {
        -      "$ref": "#/$defs/Track"
        -    },
        -    "title": "Result",
        -    "type": "array"
        -  }
        -}
      • removedOutput schema / required
        Removed value: -[
        -  "result"
        -]
      • changedOutput schema / title
        Previous value: -"search_tracksOutput"New value: +"search_tracksDictOutput"
  6. 9 tool updates
    • First observedadd_tracks_to_playlist
    • First observedcreate_playlist
    • First observedget_item_info
    • First observedget_user_playlists
    • First observedmanage_queue
    • First observedmodify_playlist_details
    • First observedplayback_control
    • First observedremove_tracks_from_playlist
    • First observedsearch_tracks

TDQS

B3.4/5.0

Scored across 48 tools

Disambiguation4/5

Most tools target a clear resource+action pair (save_tracks vs check_saved_tracks vs get_saved_tracks, follow_artists vs check_following_artists), and descriptions explicitly cross-reference each other. The main soft spots are control_playback being a multi-action mega-tool that partly overlaps transfer_playback and add_to_queue, and the large family of save/remove/check/get library tools for six resource types that a hurried agent could mix up.

Naming Consistency4/5

Nearly everything follows a verb_noun pattern (get_tracks, save_albums, remove_saved_shows, list_playlists, check_saved_episodes), with predictable get_/save_/remove_/check_ prefixes per resource. Minor deviations like get_me and control_playback (verb-only, multiplexed) are the only breaks in the pattern.

Tool Count2/5

48 tools is heavy for a single MCP surface; the library-management matrix (get/save/remove/check for tracks, albums, shows, episodes, audiobooks, artists, playlists) alone accounts for ~20 tools. It mirrors the Spotify API faithfully, but many of these will rarely be selected and inflate the decision space for an agent.

Completeness4/5

Coverage is broad: playback control, queue, playlists with reorder, library CRUD across all media types, podcasts, audiobooks, and personalization. Gaps are mostly read-side detail endpoints — no get_show, get_episode, or get_audiobook metadata tools, and playlist deletion is only reachable via unfollow_playlist — but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers