Spotify MCP Server
Search Spotify, control playback, and manage playlists, Liked Songs, and follows through an MCP client.
Search & browse: Search tracks, albums, artists, and playlists with filters and pagination; fetch track, artist, and album details (including top tracks and album track lists for single items).
Playback control: Read the current playback state, play/pause/skip/seek/change volume/shuffle/repeat, list and transfer devices, and view or add to the queue.
Playlists & library: List, create, update, add/remove/reorder tracks in playlists, unfollow/delete playlists; read Liked Songs, like/unlike tracks, and check saved tracks, saved albums, and followed artists.
User insights: Get your Spotify profile, top artists/tracks over time ranges, and recently played tracks.
Provides control over Spotify playback (start, pause, skip), enables searching for tracks/albums/artists/playlists, retrieves detailed information about music content, and manages the Spotify queue.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Spotify MCP Serverplay my Discover Weekly playlist"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.

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.
Create an app in the Spotify developer dashboard.
Register
http://127.0.0.1:8888as its redirect URI, exactly as written.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 syncIn 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. 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
28 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 |
| Read your profile |
| Search tracks, albums, artists, or playlists with filters and pagination |
| Read up to 50 tracks; individual reads when batching is unavailable |
| Read up to 50 artists; top tracks for a single artist |
| Read up to 20 albums; track list for a single album |
| Read current track, device, progress, shuffle, and repeat |
| Play, pause, skip, seek, volume, shuffle, and repeat |
| List Spotify Connect devices |
| Move playback to another device |
| Read now playing and upcoming tracks |
| Queue a track |
| List your playlists with pagination |
| Read playlist metadata without tracks |
| Read playlist tracks with pagination |
| Create a private playlist; set |
| Change name, description, or visibility |
| Add up to 100 tracks |
| Remove tracks with confirmation where supported |
| Move a block of tracks |
| Unfollow a playlist, including your own |
| Read Liked Songs with pagination |
| Like tracks |
| Unlike tracks |
| Check up to 50 tracks against Liked Songs |
| Check up to 20 saved albums |
| Check up to 50 followed artists |
| Read top artists or tracks over a time range |
| 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.
Track saves/removals and track/artist membership checks accept 50 items, sent upstream in batches of 40. Album 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 setis_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_EXCEEDEDand ordinary rate limits withRetry-Afterwhen 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
28 toolsadd_to_queueAdd to QueueA
Add a track to the playback queue.
Args:
track_id: Track ID, spotify:track: URI or open.spotify.com URL
Returns:
Status and message
| Name | Required | Description | Default |
|---|---|---|---|
| track_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutating, non-idempotent operation. The description adds that it targets the playback queue and returns a status/message, but it does not disclose likely failure conditions (e.g., no active device) or the effect of repeated calls. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded, with a clear action statement followed by compact Args and Returns sections. Every line adds useful information and there is no redundant prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with an output schema, the description covers accepted input formats and summarizes the return value well. It could mention edge cases like requiring an active playback device, but the core invocation information is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only a raw string property with zero description coverage chosen. The description explicitly defines the accepted formats: track ID, spotify:track URI, or open.spotify.com URL, which is essential and fully compensates for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Add') and a specific resource ('the playback queue'), clearly distinguishing it from playlist-focused siblings like add_tracks_to_playlist. There is no ambiguity about what the tool operates on.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool over alternatives, no exclusions, and no prerequisites such as requiring an active playback device or authentication context. It only restates the action itself, leaving selection entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_tracks_to_playlistAdd Tracks to PlaylistC
Add tracks to a playlist.
Args:
playlist_id: Playlist ID
track_uris: List of track URIs (up to 100)
| Name | Required | Description | Default |
|---|---|---|---|
| track_uris | Yes | ||
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is not read-only and not destructive. The description adds minimal behavioral context beyond 'add'; it does not specify whether tracks are appended, duplicates handled, or errors reported. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very short and front-loaded with a clear purpose. However, it is somewhat under-specified for a two-parameter tool, and the Args section is minimal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema and annotations, the description still lacks important contextual information such as error handling, authentication requirements, and differentiation from sibling tools. It is adequate for basic invocation but incomplete for robust usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning beyond the schema by stating 'playlist_id: Playlist ID' and 'track_uris: List of track URIs (up to 100)'. This compensates for the 0% schema description coverage, clarifying the URI limit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Add tracks to a playlist,' which is a specific verb and resource. It distinguishes the tool from siblings like 'remove_tracks_from_playlist' and 'reorder_playlist_tracks', though it could be more explicit about the operation's scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives like 'modify_playlist_details' or 'reorder_playlist_tracks'. No context on prerequisites or restrictions is provided.
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 ArtistsARead-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
| Name | Required | Description | Default |
|---|---|---|---|
| artist_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| checked | Yes | |
| results | Yes |
TDQS
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.
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.
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.
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.
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.
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 AlbumsARead-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
| Name | Required | Description | Default |
|---|---|---|---|
| album_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| checked | Yes | |
| results | Yes |
TDQS
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.
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.
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.
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.
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.
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_tracksCheck Liked SongsARead-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
| Name | Required | Description | Default |
|---|---|---|---|
| track_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| checked | Yes | |
| results | Yes |
TDQS
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.
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.
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.
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.
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.
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 to play (action='play'; ignored when context_uri is set)
context_uri: Album/playlist/artist 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.
| Name | Required | Description | Default |
|---|---|---|---|
| state | No | ||
| action | Yes | ||
| device_id | No | ||
| track_ids | No | ||
| context_uri | No | ||
| position_ms | No | ||
| volume_percent | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| track | No | |
| device | No | |
| repeat | No | |
| volume | No | |
| shuffle | No | |
| is_playing | Yes | |
| progress_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Given annotations already mark it as a mutating, non-idempotent operation, the description goes further by disclosing that confirmation is best effort with at most five post-action reads, that stale state may be returned, and that verification does not cover every requested transition. This goes well beyond the annotation's bare flags and compensates for the open world nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a one-line summary, prerequisites, a labeled Args block, Returns note, and a caveats paragraph. It is longer than minimal, but the length is justified by the number of parameter dependencies and behavioral caveats; there is no redundant prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a seven-parameter tool with zero schema descriptions, the description covers prerequisites, parameter semantics, and best-effort return behavior. It does not enumerate error conditions or invalid-action handling, but the output schema covers return types, so the description is complete enough for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so this description carries the full burden of explaining parameters. It defines each argument: action values, track_ids vs context_uri precedence, position_ms and volume_percent requirements, state options, and device_id default. This is exactly the level of semantic detail the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Control Spotify playback' and enumerates the exact actions (play, pause, seek, volume, shuffle, repeat), making the function's job unmistakable. It does not name sibling tools explicitly, but the action list clearly differentiates it from readers like get_playback_state and transfer_playback.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by requiring a Premium subscription and an active device, and by tying specific parameters to specific actions. It does not explicitly compare this tool with siblings like get_playback_state or transfer_playback, nor state when not to use it. So usage guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_playlistCreate PlaylistA
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
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| public | No | ||
| description | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| owner | No | |
| public | No | |
| tracks | No | |
| description | No | |
| total_tracks | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false (a write operation) and destructiveHint=false. The description adds minimal behavioral context by noting it returns the created Playlist, but it does not disclose side effects (e.g., playlist appears in user's library) or any permission requirements. The bar is lower due to annotations, but the description adds only a thin layer of value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a tight docstring with Args and Returns sections, no filler. Every sentence earns its place, and the essential information (name, description, public, return) is front-loaded. Highly efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the output schema, and annotations, the description covers the essentials. It could mention authentication or that the playlist is created for the authenticated user, but this is minor. The description is adequate for an agent to call it correctly without further context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (no descriptions in the schema), so the description compensates by explaining each parameter: name, description, and public, including defaults. This adds meaning beyond the schema's type and default fields. It lacks constraints like length limits, but the core semantics are covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (Create) and resource (Spotify playlist), clearly distinguishing it from sibling tools like get_playlist or update_playlist_details. No ambiguity about what the tool accomplishes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. While it is the only creation tool among siblings, it does not mention prerequisites (e.g., authentication), nor does it clarify that it should not be used for updating or retrieving playlists. Implied by context but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_albumGet AlbumARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| album_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| albums | Yes | |
| tracks | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description adds valuable behavioral context: the exact batch limit of 20, the request order preservation in the response, and the conditional inclusion of tracks only for single-album requests. This goes beyond the annotations to explain how the tool behaves in edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a one-sentence purpose, then a clear Args section, then Returns. Every sentence adds value—no filler. The batching cap and response behavior are front-loaded, and the format is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the simple schema (one parameter), the tool has nuanced behavior around batching and response shape. The description covers both the parameter format and the return semantics (order preservation, conditional tracks). With an output schema present, the description does not need to repeat everything, but it explains the key non-obvious aspects completely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero description coverage, but the description fully compensates: it explains that album_ids can be a single ID/URI or a list up to 20, and even clarifies Spotify's cap. This is essential information an agent needs to invoke the tool correctly, and it is not available from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get details for one or more Spotify albums, batched into a single request', identifying the specific verb, resource, and batching behavior. It distinguishes itself from sibling tools like get_tracks and get_artist by focusing on albums and noting the batch cap difference (20 for albums vs 50 for tracks/artists), making it unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage context by explaining batching and the batch cap, and clarifies that tracks are only returned for single-album requests. However, it does not explicitly say when not to use this tool or point to alternatives (e.g., 'for track details use get_tracks'). The batching context is clear but the exclusions are absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_artistGet ArtistARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| artist_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| artists | Yes | |
| top_tracks | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the readOnly/idempotent/openWorld annotations by disclosing concrete behavior: results preserve request order, top_tracks is populated only for single-artist requests, and withheld endpoints yield an empty list instead of an error. This is exactly the kind of edge-case behavior an agent needs to interpret responses correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured, with Args and Returns sections that each add necessary detail. There is no filler or repetition; every sentence contributes a distinct fact about invocation or response behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only tool with an output schema and safety annotations, the description covers invocation, batching, ordering, and edge-case return behavior. Nothing an agent needs to call it correctly or interpret its result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only the property name and type, but the description fully explains the parameter's meaning: an artist ID/URI, a list of up to 50, and the request-count implication. With one parameter and 0% schema coverage, the description carries the entire semantic burden and succeeds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Get details') and a specific resource ('Spotify artists'), and clarifies that the call supports batching one or more up to 50 artists. This distinguishes it from sibling tools like get_tracks, get_album, or get_playlist without requiring schema inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context: it can accept a single ID/URI or a list, with an explicit batching note that a list costs one Spotify request rather than one per artist. It doesn't name alternatives or list exclusions, but the resource scope is clear enough that an agent can decide when to call this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_meSpotify ProfileARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| No | ||
| country | No | |
| product | No | |
| followers | No | |
| display_name | No |
TDQS
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.
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.
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.
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.
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.
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 PlayingARead-onlyIdempotent
Get the current playback state: track, device, progress, shuffle and repeat.
Returns:
PlaybackState (is_playing is False when nothing is playing)
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| track | No | |
| device | No | |
| repeat | No | |
| volume | No | |
| shuffle | No | |
| is_playing | Yes | |
| progress_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, and open-world behavior. The description adds useful behavioral detail not in annotations: it returns a PlaybackState and explicitly notes that is_playing is False when nothing is playing, which clarifies an edge case.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose and followed by a useful return-value note. Every sentence earns its place with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters, rich annotations, and an output schema, this description is complete for correct invocation by an agent. It states what the tool returns and even covers the nothing-playing case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description correctly lists the returned fields instead of inventing parameter semantics, and no parameter documentation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Describes the action and resource clearly: 'Get the current playback state' followed by concrete fields (track, device, progress, shuffle, repeat). This makes the purpose unambiguous, though it doesn't explicitly contrast with sibling tools such as control_playback.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for reading current playback information, and the read-only annotations reinforce that. However, it offers no explicit guidance on when to prefer this tool over alternatives like get_queue, list_devices, or control_playback.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_playlistGet PlaylistARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| owner | No | |
| public | No | |
| tracks | No | |
| description | No | |
| total_tracks | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safe read-only nature is covered. The description adds an important behavioral boundary by stating that the result is playlist metadata only and excludes tracks. This is useful context beyond the annotations, though it does not detail error behavior 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is clearly structured with Args, Returns, and a Note, making it easy to scan. However, it is redundant: the Returns line already says 'no tracks - use get_playlist_tracks for tracks', and the Note repeats the same instruction. A more concise version would remove this duplication.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple single-parameter read-only tool, the description covers the core information: what it does, its argument, its return scope, and the correct sibling for tracks. The main gap is the lack of playlist_id format guidance, but the output schema and annotations carry much of the burden. Overall, an agent can use this tool correctly with minimal inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 only says 'playlist_id: Spotify playlist ID', which adds little beyond the schema property name 'Playlist Id'. It does not explain the expected format, how to extract the ID from a playlist URL, or provide any example, leaving a meaningful gap for a required parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get basic information about a Spotify playlist' and immediately distinguishes itself from the sibling get_playlist_tracks by explicitly saying 'no tracks'. This makes the tool's scope obvious and prevents confusion with track-related playlist tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to use get_playlist_tracks for tracks and notes that it supports full pagination. This gives a clear when-to-use alternative for the main ambiguity, though it does not mention when to use list_playlists or other playlist-related siblings. Overall, the guidance is strong for the most likely confusion.
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 TracksARead-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)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes | |
| limit | No | |
| total | Yes | |
| offset | Yes | |
| returned | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint, so the safety profile is established. The description adds non-obvious behavioral details beyond those annotations: the 10,000-item safety cap, pagination skip semantics, and the caution warning for limit=None on large playlists. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded, followed by compact Args and Returns sections and a practical Note. The pagination examples are genuinely useful but somewhat repetitive (three near-identical illustrations); all content earns its place though a leaner version could drop one example.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, all three parameters, the return shape, pagination patterns, and a safety caveat. An output schema exists, so return values are doubly documented. For a read-only, paginated list tool this is essentially complete; only auth and rate-limit notes are absent, and those are not critical for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full weight for parameter meaning. It explains limit's None semantics with the 10,000 safety ceiling, offset's skip behavior and default of 0, and playlist_id's role as the target resource — exactly the non-obvious semantics an agent needs that the bare schema types cannot convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Get tracks from a playlist with full pagination support') that clearly identifies the operation. The resource is unambiguous and implicitly distinct from siblings like get_playlist (playlist metadata) and get_tracks (tracks by ID), though it doesn't name them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides concrete pagination usage patterns (limit=100/offset=0 for the first page, offset=100 for the next, limit=None for all tracks) and warns when caution is needed on very large playlists. It doesn't state exclusions or when to prefer a sibling tool, but the guidance is clear enough for correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_queueGet QueueARead-onlyIdempotent
Get the current playback queue. Returns: Currently playing track and queue of upcoming tracks
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| queue | Yes | |
| currently_playing | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, covering safety and side effects. The description adds the key behavioral detail that the result includes the currently playing track and upcoming tracks, which is useful beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely compact, front-loaded with the primary action, and includes a concise return summary. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read-only queue retrieval tool with an output schema, the description is fully adequate. It states the action and the return content, and the annotations cover the operational safety profile.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema coverage is effectively complete, so there is no parameter documentation burden for the description to carry. The baseline of 4 applies because no parameters exist to explain.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 current playback queue' and explicitly states what will be returned. It is clearly distinguishable from sibling tools like get_playback_state or add_to_queue.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes clear that this tool is for retrieving the current queue, which is appropriate context for when to use it. It does not explicitly name alternatives or exclusion cases, but with zero parameters and a focused resource, the intended usage is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recently_playedRecently PlayedARead-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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering the safety profile. The description adds useful behavior: it states the ordering (most recent first) and the presence of a 'played_at' timestamp in the return, which are not implied by annotations. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with the core purpose front-loaded in the first sentence. The Args and Returns sections are clearly structured, though there is minor redundancy (e.g., repeating 'limit' meaning). Overall, it is efficient and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one parameter and an output schema, the description covers everything needed: purpose, ordering, parameter constraints, and return format. No critical information is missing, and the annotations provide the safety context. It is complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must fully document the parameter. It explains 'limit' with a max range (1-50) and a default (20), which exceeds the schema's default. This is complete and precise, giving the agent all necessary semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and the resource 'recently played tracks' with ordering 'most recent first'. This is specific and distinguishes it from sibling tools like get_top_items or get_playback_state by resource, though it does not explicitly name alternatives. It is clear enough for an agent to select correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is used when recently played tracks are needed, but provides no explicit guidance on when to use it versus siblings like get_playback_state or get_queue. There are no exclusion criteria or alternative references, so the usage context is only implied.
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 SongsARead-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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | |
| items | Yes | |
| limit | Yes | |
| total | Yes | |
| offset | Yes | |
| previous | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint. The description adds useful behavioral detail not in the annotations, such as pagination behavior, the limit range, and that items include an added_at timestamp. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured: a one-sentence purpose followed by Args and Returns blocks. Every line conveys distinct information, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple paginated read operation with two optional parameters, the description covers purpose, parameter meaning, and return shape. Safety is already covered by annotations. It does not explicitly discuss authentication or alternative tools, but those are not critical gaps for this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has no parameter descriptions (0% coverage), so the description must compensate. It fully does: limit is explained as 'Max tracks to return per page (1-50, default 20)' and offset as 'Number of tracks to skip for pagination (default 0)'—adding range, defaults, and semantics beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Get user's saved/liked tracks (Liked Songs library)', naming a specific verb and resource. This clearly distinguishes it from sibling mutation tools like save_tracks and remove_saved_tracks, and from other retrieval tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description identifies the exact use case—fetching the user's Liked Songs library—so an agent can infer when to call it. It does not explicitly name alternative tools or exclusions, but the resource label is unambiguous and the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_top_itemsTop Artists and TracksARead-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
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| item_type | No | tracks | |
| time_range | No | medium_term |
Output Schema
| Name | Required | Description |
|---|---|---|
| tracks | No | |
| artists | No | |
| time_range | Yes |
TDQS
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 behavioral context: Spotify policy restricts analysis/AI ingestion-cultural, and the returned object populates only the selected item_type. This is meaningful beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured with a clear one-sentence purpose, brief contextual note, and list of parameter semantics. Every line earns its place and there is no redundant repetition of schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema and annotations covering read-only/idempotent behavior, the description is complete: it covers purpose, parameters, defaults, and return shape. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by documenting all three parameters: item_type options and default, time_range options with approximate durations, and limit range with default. This is exactly the semantic information an agent needs to call the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: get the user's top artists or tracks over a time range. This clearly identifies the resource and qualifiers, and is distinct from sibling tools like get_tracks or get_recently_played.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when the tool is useful, specifically when recommendations or related artists are unavailable jews. It does not explicitly name alternative tools or give when-not-to-use exclusions, but the use case is clearly conveyed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tracksGet TracksARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| track_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| tracks | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint, openWorldHint), the description discloses a meaningful behavioral trait: batch lookup may be withheld by Spotify and the tool transparently falls back to one request per track while guaranteeing the same result. This is exactly the kind of non-obvious behavior that saves an agent from assuming API limitations. It also clarifies the return shape for single vs. multiple IDs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded summary followed by Args, Returns, and Note sections. Each section adds necessary context. The note is slightly verbose ('50 tracks in 1 API call instead of 50' could be clearer), but every sentence earns its place and no extraneous content is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not enumerate every return field; it still highlights release_date and the single-ID return shape. Annotations cover safety (readOnly) and idempotency, while the description covers the parameter limit and fallback behavior. Nothing essential for invoking this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only the type (string or array of strings) with zero description coverage. The description compensates fully by stating that track_ids accepts a single ID or list, the 50-track cap, and the batch/fallback behavior tied to that parameter. An agent gets all the semantic information needed to construct a valid call.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb and resource: 'Get detailed information about one or more Spotify tracks.' This clearly distinguishes it from sibling tools like get_artist, get_album, or get_saved_tracks, which target different resources. The scope is unambiguous and immediately actionable for an agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool (when you have track IDs and need their metadata), and the note about batch efficiency adds a relevant usage consideration ('50 tracks in 1 API call'). However, it does not explicitly state alternatives or when not to use this tool compared to siblings like get_saved_tracks or search_music. The guidance is present but implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_devicesAvailable DevicesARead-onlyIdempotent
List the user's available Spotify devices.
Returns:
DeviceList; use transfer_playback with a device id to make one active
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| devices | Yes |
TDQS
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.
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.
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.
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.
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.
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 PlaylistsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | |
| items | Yes | |
| limit | Yes | |
| total | Yes | |
| offset | Yes | |
| previous | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering the safety profile. The description adds value by explaining pagination behavior (limit/offset), the return shape (PlaylistList with items and pagination info), and a concrete example. This goes beyond the annotations and clarifies expected behavior 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with labeled Args, Returns, and Note sections. It starts with the purpose, provides essential details, and includes a helpful example without any fluff. Every sentence contributes to understanding or usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool, the description is complete. It covers both parameters, explains pagination, and references the output schema. Annotations handle safety and side-effect disclosures. No critical information an agent needs to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description is the sole source of parameter meaning. It fully compensates by explaining limit (1-50, default 20) and offset (default 0) with clear semantics and an example. This adds significant meaning beyond the bare schema types and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get current user's playlists with pagination support.' This clearly distinguishes it from siblings like get_playlist (singular, specific playlist) and create_playlist, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context that this tool lists the current user's playlists, and the pagination note explains how to handle large result sets. However, it does not explicitly mention when to use this tool versus alternatives like get_playlist for a single playlist or search_music for non-owned playlists. Usage guidance is implied but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_saved_tracksUnlike TracksADestructiveIdempotent
Remove tracks from the user's saved (liked) tracks.
Args:
track_ids: Track IDs or URIs (up to 50)
| Name | Required | Description | Default |
|---|---|---|---|
| track_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
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.
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.
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.
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.
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.
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 PlaylistBDestructive
Remove tracks from a playlist.
Args:
playlist_id: Playlist ID
track_uris: List of track URIs to remove
| Name | Required | Description | Default |
|---|---|---|---|
| track_uris | Yes | ||
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description merely restates what the tool does, adding no behavioral details beyond the annotations (destructiveHint=true, readOnlyHint=false). It does not disclose whether removal is reversible, whether it requires ownership, or what happens to the playlist order. The annotations already convey destructive nature, so the description adds minimal value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short but includes unnecessary 'Args:' format that repeats the function name. It is not front-loaded with the most critical information (e.g., that this is destructive). Could be more concise by removing the docstring boilerplate and focusing on usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema (not shown), the description omits side effects (e.g., permanent removal, impact on playlist length), authentication needs, or rate limits. For a destructive action with two required parameters, the description should provide more context to avoid misuse.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description provides basic meanings for both parameters ('Playlist ID' and 'List of track URIs to remove'), which the schema lacks entirely (0% coverage). However, no format, constraints, or examples are given. For a simple two-parameter tool, this is minimally adequate but not helpful for complex usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Remove tracks') and the resource ('a playlist'), using a specific verb and noun. This distinguishes it from sibling tools such as 'add_tracks_to_playlist' or 'reorder_playlist_tracks'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives, such as 'modify_playlist_details' or 'reorder_playlist_tracks'. There are no preconditions, caveats, or context about authorization, making it hard for an AI agent to decide when to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reorder_playlistReorder PlaylistADestructive
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.
| Name | Required | Description | Default |
|---|---|---|---|
| playlist_id | Yes | ||
| range_start | Yes | ||
| snapshot_id | No | ||
| range_length | No | ||
| insert_before | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
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.
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.
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.
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.
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.
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_tracksLike TracksAIdempotent
Save (like) tracks to the user's library.
Args:
track_ids: Track IDs or URIs (up to 50)
| Name | Required | Description | Default |
|---|---|---|---|
| track_ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
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.
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.
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.
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.
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.
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 SpotifyARead-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'
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | ||
| album | No | ||
| genre | No | ||
| limit | No | ||
| qtype | No | track | |
| query | Yes | ||
| artist | No | ||
| offset | No | ||
| year_range | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | |
| items | Yes | |
| limit | Yes | |
| total | Yes | |
| offset | Yes | |
| previous | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/openWorld annotations, the description discloses a non-obvious behavior: Spotify caps search at 10 per page for restricted apps and retries larger limits at the cap rather than failing. It also tells the agent to check the returned limit and use offset for deeper pagination, which is valuable behavioral guidance.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured into Args, Returns, Note, and Example, making it scannable and front-loaded. It is longer than a one-liner, but the extra length is justified by the nine parameters and the pagination quirk; no filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with an output schema and rich annotations, the description covers all the operational essentials: query types, all filters, limit/offset behavior, the API cap, the returned fields, and a concrete example. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully compensate, and it does. Every parameter is documented with a concise semantic explanation, limit includes its range and default plus the retry behavior, qtype lists the accepted values, and the example shows how filters combine into Spotify's search syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action ('Search Spotify') and explicitly enumerates the resource types: tracks, albums, artists, or playlists. It is immediately distinguishable from sibling get_* tools, none of which perform free-text search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: searching by query and optionally filtering by year, genre, artist, etc. It does not explicitly name alternatives like get_tracks for when an ID is already known, but the search-focused framing and the sibling tool names make the appropriate usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
transfer_playbackSwitch DeviceAIdempotent
Move playback to a different device (see list_devices).
Args:
device_id: Target device ID
play: Start playing after the transfer (default True)
| Name | Required | Description | Default |
|---|---|---|---|
| play | No | ||
| device_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
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.
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.
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.
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.
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.
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_playlistUnfollow PlaylistADestructiveIdempotent
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
| Name | Required | Description | Default |
|---|---|---|---|
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
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.
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.
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.
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.
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.
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 DetailsCDestructiveIdempotent
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)
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| public | No | ||
| description | No | ||
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | Yes | |
| message | Yes | |
| snapshot_id | No |
TDQS
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.
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.
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.
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.
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.
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 tool update
v0.7.0- Changed
create_playlist1 field changed- changed
Input schema / properties / public / defaultPrevious value: -trueNew value: +false
34 tool updates
v0.6.1- Added
check_following_artists - Added
check_saved_albums - Added
check_saved_tracks - Added
control_playback - Changed
create_playlist6 fields changed- added
Output schema / $defs / Track / properties / id / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / $defs / Track / properties / id / defaultAdded value: +null - removed
Output schema / $defs / Track / properties / id / typeRemoved value: -"string" - added
Output schema / $defs / Track / properties / is_localAdded value: +{ + "default": false, + "title": "Is Local", + "type": "boolean" +} - added
Output schema / $defs / Track / properties / played_atAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Played At" +} - changed
Output schema / $defs / Track / requiredPrevious value: -[ - "name", - "id", - "artist" -]New value: +[ + "name", + "artist" +]
- Added
get_album - Removed
get_album_info - Added
get_artist - Removed
get_artist_info - Added
get_me - Added
get_playback_state - Added
get_playlist - Removed
get_playlist_info - Changed
get_playlist_tracks6 fields changed- added
Output schema / $defs / Track / properties / id / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / $defs / Track / properties / id / defaultAdded value: +null - removed
Output schema / $defs / Track / properties / id / typeRemoved value: -"string" - added
Output schema / $defs / Track / properties / is_localAdded value: +{ + "default": false, + "title": "Is Local", + "type": "boolean" +} - added
Output schema / $defs / Track / properties / played_atAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Played At" +} - changed
Output schema / $defs / Track / requiredPrevious value: -[ - "name", - "id", - "artist" -]New value: +[ + "name", + "artist" +]
- Changed
get_queue6 fields changed- added
Output schema / $defs / Track / properties / id / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / $defs / Track / properties / id / defaultAdded value: +null - removed
Output schema / $defs / Track / properties / id / typeRemoved value: -"string" - added
Output schema / $defs / Track / properties / is_localAdded value: +{ + "default": false, + "title": "Is Local", + "type": "boolean" +} - added
Output schema / $defs / Track / properties / played_atAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Played At" +} - changed
Output schema / $defs / Track / requiredPrevious value: -[ - "name", - "id", - "artist" -]New value: +[ + "name", + "artist" +]
- Added
get_recently_played - Changed
get_saved_tracks6 fields changed- added
Output schema / $defs / Track / properties / id / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - added
Output schema / $defs / Track / properties / id / defaultAdded value: +null - removed
Output schema / $defs / Track / properties / id / typeRemoved value: -"string" - added
Output schema / $defs / Track / properties / is_localAdded value: +{ + "default": false, + "title": "Is Local", + "type": "boolean" +} - added
Output schema / $defs / Track / properties / played_atAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Played At" +} - changed
Output schema / $defs / Track / requiredPrevious value: -[ - "name", - "id", - "artist" -]New value: +[ + "name", + "artist" +]
- Added
get_top_items - Removed
get_track_info - Added
get_tracks - Removed
get_user_playlists - Added
list_devices - Added
list_playlists - Removed
modify_playlist_details - Removed
playback_control - Added
remove_saved_tracks - Added
reorder_playlist - Removed
reorder_playlist_tracks - Added
save_tracks - Added
search_music - Removed
search_tracks - Added
transfer_playback - Added
unfollow_playlist - Added
update_playlist_details
18 tool updates
v0.3.1- Changed
add_to_queue5 fields changed- removed
Output schema / additionalPropertiesRemoved value: -{ - "type": "string" -} - added
Output schema / descriptionAdded value: +"Result of a state-changing operation." - added
Output schema / propertiesAdded value: +{ + "message": { + "title": "Message", + "type": "string" + }, + "snapshot_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Snapshot Id" + }, + "status": { + "title": "Status", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "message" +] - changed
Output schema / titlePrevious value: -"add_to_queueDictOutput"New value: +"ActionResult"
- Changed
add_tracks_to_playlist5 fields changed- removed
Output schema / additionalPropertiesRemoved value: -{ - "type": "string" -} - added
Output schema / descriptionAdded value: +"Result of a state-changing operation." - added
Output schema / propertiesAdded value: +{ + "message": { + "title": "Message", + "type": "string" + }, + "snapshot_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Snapshot Id" + }, + "status": { + "title": "Status", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "message" +] - changed
Output schema / titlePrevious value: -"add_tracks_to_playlistDictOutput"New value: +"ActionResult"
- Changed
create_playlist5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"A Spotify playlist." - added
Output schema / propertiesAdded 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" + } +} - added
Output schema / requiredAdded value: +[ + "name", + "id" +] - changed
Output schema / titlePrevious value: -"create_playlistDictOutput"New value: +"Playlist"
- Changed
get_album_info5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"An album with its tracks." - added
Output schema / propertiesAdded value: +{ + "album": { + "$ref": "#/$defs/Album" + }, + "tracks": { + "items": { + "$ref": "#/$defs/Track" + }, + "title": "Tracks", + "type": "array" + } +} - added
Output schema / requiredAdded value: +[ + "album", + "tracks" +] - changed
Output schema / titlePrevious value: -"get_album_infoDictOutput"New value: +"AlbumInfo"
- Changed
get_artist_info5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"An artist with their top tracks." - added
Output schema / propertiesAdded value: +{ + "artist": { + "$ref": "#/$defs/Artist" + }, + "top_tracks": { + "items": { + "$ref": "#/$defs/Track" + }, + "title": "Top Tracks", + "type": "array" + } +} - added
Output schema / requiredAdded value: +[ + "artist", + "top_tracks" +] - changed
Output schema / titlePrevious value: -"get_artist_infoDictOutput"New value: +"ArtistInfo"
- Removed
get_audio_features - Changed
get_playlist_info5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"A Spotify playlist." - added
Output schema / propertiesAdded 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" + } +} - added
Output schema / requiredAdded value: +[ + "name", + "id" +] - changed
Output schema / titlePrevious value: -"get_playlist_infoDictOutput"New value: +"Playlist"
- Changed
get_playlist_tracks5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"Paginated tracks from a single playlist." - added
Output schema / propertiesAdded 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" + } +} - added
Output schema / requiredAdded value: +[ + "items", + "total", + "offset", + "returned" +] - changed
Output schema / titlePrevious value: -"get_playlist_tracksDictOutput"New value: +"PlaylistTracks"
- Changed
get_queue5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"Currently playing track plus the upcoming queue." - added
Output schema / propertiesAdded value: +{ + "currently_playing": { + "anyOf": [ + { + "$ref": "#/$defs/Track" + }, + { + "type": "null" + } + ], + "default": null + }, + "queue": { + "items": { + "$ref": "#/$defs/Track" + }, + "title": "Queue", + "type": "array" + } +} - added
Output schema / requiredAdded value: +[ + "queue" +] - changed
Output schema / titlePrevious value: -"get_queueDictOutput"New value: +"QueueState"
- Removed
get_recommendations - Changed
get_saved_tracks5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"Paginated saved/liked tracks." - added
Output schema / propertiesAdded 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" + } +} - added
Output schema / requiredAdded value: +[ + "items", + "total", + "limit", + "offset" +] - changed
Output schema / titlePrevious value: -"get_saved_tracksDictOutput"New value: +"SavedTracks"
- Changed
get_track_info5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"A list of tracks." - added
Output schema / propertiesAdded value: +{ + "tracks": { + "items": { + "$ref": "#/$defs/Track" + }, + "title": "Tracks", + "type": "array" + } +} - added
Output schema / requiredAdded value: +[ + "tracks" +] - changed
Output schema / titlePrevious value: -"get_track_infoDictOutput"New value: +"TrackList"
- Changed
get_user_playlists5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"Paginated list of playlists." - added
Output schema / propertiesAdded 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" + } +} - added
Output schema / requiredAdded value: +[ + "items", + "total", + "limit", + "offset" +] - changed
Output schema / titlePrevious value: -"get_user_playlistsDictOutput"New value: +"PlaylistList"
- Changed
modify_playlist_details5 fields changed- removed
Output schema / additionalPropertiesRemoved value: -{ - "type": "string" -} - added
Output schema / descriptionAdded value: +"Result of a state-changing operation." - added
Output schema / propertiesAdded value: +{ + "message": { + "title": "Message", + "type": "string" + }, + "snapshot_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Snapshot Id" + }, + "status": { + "title": "Status", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "message" +] - changed
Output schema / titlePrevious value: -"modify_playlist_detailsDictOutput"New value: +"ActionResult"
- Changed
playback_control1 field changed- added
Output schema / $defs / Track / properties / added_atAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Added At" +}
- Changed
remove_tracks_from_playlist5 fields changed- removed
Output schema / additionalPropertiesRemoved value: -{ - "type": "string" -} - added
Output schema / descriptionAdded value: +"Result of a state-changing operation." - added
Output schema / propertiesAdded value: +{ + "message": { + "title": "Message", + "type": "string" + }, + "snapshot_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Snapshot Id" + }, + "status": { + "title": "Status", + "type": "string" + } +} - added
Output schema / requiredAdded value: +[ + "status", + "message" +] - changed
Output schema / titlePrevious value: -"remove_tracks_from_playlistDictOutput"New value: +"ActionResult"
- Added
reorder_playlist_tracks - Changed
search_tracks5 fields changed- added
Output schema / $defsAdded 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" + } +} - added
Output schema / descriptionAdded value: +"Paginated search results." - added
Output schema / propertiesAdded 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" + } +} - added
Output schema / requiredAdded value: +[ + "items", + "total", + "limit", + "offset" +] - changed
Output schema / titlePrevious value: -"search_tracksDictOutput"New value: +"SearchResults"
19 tool updates
v1.0.0- Added
add_to_queue - Changed
add_tracks_to_playlist4 fields changed- added
Output schema / additionalPropertiesAdded value: +{ + "type": "string" +} - removed
Output schema / propertiesRemoved value: -{ - "result": { - "additionalProperties": { - "type": "string" - }, - "title": "Result", - "type": "object" - } -} - removed
Output schema / requiredRemoved value: -[ - "result" -] - changed
Output schema / titlePrevious value: -"add_tracks_to_playlistOutput"New value: +"add_tracks_to_playlistDictOutput"
- Changed
create_playlist5 fields changed- removed
Output schema / $defsRemoved 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" - } -} - removed
Output schema / descriptionRemoved value: -"A Spotify playlist." - removed
Output schema / propertiesRemoved 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" - } -} - removed
Output schema / requiredRemoved value: -[ - "name", - "id" -] - changed
Output schema / titlePrevious value: -"Playlist"New value: +"create_playlistDictOutput"
- Added
get_album_info - Added
get_artist_info - Added
get_audio_features - Removed
get_item_info - Added
get_playlist_info - Added
get_playlist_tracks - Added
get_queue - Added
get_recommendations - Added
get_saved_tracks - Added
get_track_info - Changed
get_user_playlists5 fields changed- added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "title": "Offset", + "type": "integer" +} - removed
Output schema / $defsRemoved 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" - } -} - removed
Output schema / propertiesRemoved value: -{ - "result": { - "items": { - "$ref": "#/$defs/Playlist" - }, - "title": "Result", - "type": "array" - } -} - removed
Output schema / requiredRemoved value: -[ - "result" -] - changed
Output schema / titlePrevious value: -"get_user_playlistsOutput"New value: +"get_user_playlistsDictOutput"
- Removed
manage_queue - Changed
modify_playlist_details4 fields changed- added
Output schema / additionalPropertiesAdded value: +{ + "type": "string" +} - removed
Output schema / propertiesRemoved value: -{ - "result": { - "additionalProperties": { - "type": "string" - }, - "title": "Result", - "type": "object" - } -} - removed
Output schema / requiredRemoved value: -[ - "result" -] - changed
Output schema / titlePrevious value: -"modify_playlist_detailsOutput"New value: +"modify_playlist_detailsDictOutput"
- Changed
playback_control2 fields changed- added
Output schema / $defs / Track / properties / album_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Album Id" +} - added
Output schema / $defs / Track / properties / release_dateAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Release Date" +}
- Changed
remove_tracks_from_playlist4 fields changed- added
Output schema / additionalPropertiesAdded value: +{ + "type": "string" +} - removed
Output schema / propertiesRemoved value: -{ - "result": { - "additionalProperties": { - "type": "string" - }, - "title": "Result", - "type": "object" - } -} - removed
Output schema / requiredRemoved value: -[ - "result" -] - changed
Output schema / titlePrevious value: -"remove_tracks_from_playlistOutput"New value: +"remove_tracks_from_playlistDictOutput"
- Changed
search_tracks10 fields changed- added
Input schema / properties / albumAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Album" +} - added
Input schema / properties / artistAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Artist" +} - added
Input schema / properties / genreAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Genre" +} - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "title": "Offset", + "type": "integer" +} - added
Input schema / properties / yearAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Year" +} - added
Input schema / properties / year_rangeAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Year Range" +} - removed
Output schema / $defsRemoved 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" - } -} - removed
Output schema / propertiesRemoved value: -{ - "result": { - "items": { - "$ref": "#/$defs/Track" - }, - "title": "Result", - "type": "array" - } -} - removed
Output schema / requiredRemoved value: -[ - "result" -] - changed
Output schema / titlePrevious value: -"search_tracksOutput"New value: +"search_tracksDictOutput"
9 tool updates
- First observed
add_tracks_to_playlist - First observed
create_playlist - First observed
get_item_info - First observed
get_user_playlists - First observed
manage_queue - First observed
modify_playlist_details - First observed
playback_control - First observed
remove_tracks_from_playlist - First observed
search_tracks
TDQS
Scored across 28 tools
Most tools have clearly distinct purposes, and the descriptions carefully separate near-neighbors like get_saved_tracks vs check_saved_tracks. A few pairs (get_tracks/get_saved_tracks, unfollow_playlist/remove_tracks_from_playlist) are close enough in name to require reading descriptions carefully.
Tool names generally follow a clear verb_noun pattern, and sets like check_saved_* and remove_*_from_playlist are internally consistent. There is some inconsistency between get_ and list_ for collections (get_saved_tracks vs list_playlists vs list_devices), but it does not seriously impede readability.
28 tools is on the heavy side for a single MCP server, and the agent must juggle a large surface. Each tool does earn its place, but the count exceeds the range where the tool set feels tightly scoped.
The set covers playlists, saved tracks, search, and playback well, but album and artist library handling is one-sided: check_saved_albums and check_following_artists have no corresponding save/remove album or follow/unfollow artist tools. There is also no way to list saved albums, leaving obvious lifecycle gaps that will cause agent failures for those workflows.
Maintenance
Related MCP Connectors
- platform7nOAuthtech.p7n
Connect Claude to your Platform7n workspaces — chat, links, and tasks. One-click OAuth.
Connect Claude to Fathom meeting recordings, transcripts, and summaries
Generate AI music via the Lacuna Music API from MCP clients like Claude Desktop & Code.
One workspace of tools for Claude and ChatGPT: connect 600+ apps, generate media, build tools.
Related MCP Servers
- FlicenseAqualityDmaintenanceConnects Claude with Spotify, enabling playback control, search functionality, and queue management through Spotify's API.4-
- FlicenseNot gradedqualityDmaintenanceConnects Claude with Spotify to control playback, search music, get track information, and manage the queue through conversation.1-
- FlicenseAqualityDmaintenanceConnects Claude with Spotify, allowing users to control playback, search for music, get track/artist information, and manage the queue via the Spotify API.51-
- FlicenseNot gradedqualityDmaintenanceEnables Claude to control Spotify features including playback control, playlist management, search, and accessing user's listening history and preferences through the Spotify API.1-