Spotify MCP Server
This server lets Claude control and explore a Spotify account via MCP: playback, search, playlists, library management, and user stats.
Control playback: play, pause, skip, seek, volume, shuffle, repeat, transfer between devices, and view/add to queue
Search Spotify: tracks, albums, artists, playlists with filters and pagination
Manage playlists: create, edit details, fetch tracks, add/remove/reorder up to 100 tracks in bulk, unfollow/delete playlists
Manage library: get liked songs, like/unlike tracks, check saved tracks/albums, check followed artists
Get user data: profile, top artists/tracks, recently played, current playback state, available devices
Fetch rich metadata: details for tracks, artists, albums, and playlists, including album/artist top 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 server
mcp-name: io.github.jamiew/spotify-mcp
MCP server connecting Claude with Spotify. This fork of varunneal/spotify-mcp adds smart-batching tools and advanced playlist features that optimize API usage.
This server runs locally over stdio. Want a hosted MCP instead? The sister project spotify-mcp-cloudflare deploys to Cloudflare Workers in a few minutes, with OAuth in the browser and no local install for anyone connecting.
Features
Core Functionality
Playback Control: Start, pause, skip tracks, manage queue
Search & Discovery: Find tracks, albums, artists, playlists with pagination
Real-time State: Live user profile and playback status
Resources: Read user, playback, track, playlist, artist, and album state by URI
Modern MCP Protocol
Server instructions: whole-surface guidance ships once per session instead of per tool
Structured output: every tool returns a typed schema, not a bare dict
Tool annotations & icons: read-only/destructive hints, titles, and a Spotify glyph
Progress notifications: live updates while paginating large playlists
Elicitation: destructive playlist removals ask for confirmation on clients that support it
Enhanced Playlist Tools (New in this fork)
Smart Batch Operations: Add/remove up to 100 tracks in single API calls
Large Playlist Support: Efficiently handle playlists with 1000+ tracks using pagination
Advanced Playlist Management: Create, modify details, reorder tracks, bulk track operations
API-Optimized Workflows: Intelligent batching reduces API calls by 60-80%
Tools
Tool | Does |
| The signed-in user's profile |
| Search tracks, albums, artists or playlists, with filters and regime-aware page limits |
| Details for up to 50 tracks in one request; individual reads when batching is unavailable |
| Details for up to 50 artists in one request; top tracks when you ask for a single artist |
| Details for up to 20 albums in one request; the track list when you ask for a single album |
| What's playing now: track, device, progress, shuffle, repeat |
| Play, pause, next, previous, seek, volume, shuffle, repeat; best-effort state confirmation |
| Available Spotify Connect devices |
| Move playback to another device |
| Now playing plus the upcoming queue |
| Queue a track |
| The user's playlists, paginated |
| Playlist metadata without its tracks; track count when available |
| Playlist tracks, paginated to any size |
| Create a playlist |
| Rename a playlist or change its description/visibility |
| Add up to 100 tracks in one call |
| Remove tracks (confirms first where the client supports it) |
| Move a block of tracks to a new position |
| Unfollow a playlist — how Spotify deletes your own |
| Liked Songs, paginated |
| Like tracks |
| Unlike tracks |
| Which of up to 50 tracks are already liked, without paging the library |
| Which of up to 20 albums are already saved |
| Which of up to 50 artists the user follows |
| Top artists or tracks over a time range |
| Recently played tracks with timestamps |
tests/test_tool_metadata.py fails if this table drifts from the code, or if a tool ships
without a title, icon and behaviour annotations.
Restricted apps cap search pages at 10 results. Advance with the returned offset + limit,
not the requested page size. Individual track fallbacks can require up to 50 Spotify requests.
Playlist limit/offset count positions, so a page includes any unresolved rows at those
positions. Local files and unresolved rows come back with id: null, local files also set
is_local, and they keep their position so reorder_playlist indices stay correct.
Related MCP server: Spotify MCP Server
Installation
Requires a Spotify Premium account and uv >= 0.54.
1. Get Spotify API keys
Create an app at developer.spotify.com/dashboard.
Add redirect URI
http://127.0.0.1:8888— it must match exactly what you set below.Copy the Client ID and Client Secret.
2. Add the server to your MCP client
Every client runs the same command — uvx spotify-mcp-jamiew — with your three Spotify env vars. No clone, no local path.
Standard config (works in most clients):
{
"mcpServers": {
"spotify": {
"command": "uvx",
"args": ["spotify-mcp-jamiew"],
"env": {
"SPOTIFY_CLIENT_ID": "your_client_id",
"SPOTIFY_CLIENT_SECRET": "your_client_secret",
"SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888"
}
}
}
}claude mcp add spotify \
-e SPOTIFY_CLIENT_ID=your_client_id \
-e SPOTIFY_CLIENT_SECRET=your_client_secret \
-e SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888 \
-- uvx spotify-mcp-jamiewAdd -s user to install it globally across all projects. Verify with claude mcp list.
Add the standard config above to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows), then fully restart Claude Desktop.
codex mcp add spotify \
--env SPOTIFY_CLIENT_ID=your_client_id \
--env SPOTIFY_CLIENT_SECRET=your_client_secret \
--env SPOTIFY_REDIRECT_URI=http://127.0.0.1:8888 \
-- uvx spotify-mcp-jamiewOr add to ~/.codex/config.toml:
[mcp_servers.spotify]
command = "uvx"
args = ["spotify-mcp-jamiew"]
[mcp_servers.spotify.env]
SPOTIFY_CLIENT_ID = "your_client_id"
SPOTIFY_CLIENT_SECRET = "your_client_secret"
SPOTIFY_REDIRECT_URI = "http://127.0.0.1:8888"Add to ~/.hermes/config.yaml, then run /reload-mcp (or restart Hermes):
mcp_servers:
spotify:
command: uvx
args: [spotify-mcp-jamiew]
env:
SPOTIFY_CLIENT_ID: your_client_id
SPOTIFY_CLIENT_SECRET: your_client_secret
SPOTIFY_REDIRECT_URI: http://127.0.0.1:8888Add the standard config above to ~/.openclaw/openclaw.json (under mcpServers), then openclaw gateway restart.
Most MCP clients read a JSON file with an mcpServers block — drop the standard config above into it.
Using something else? Paste this to your agent:
Install the spotify-mcp MCP server from https://github.com/jamiew/spotify-mcp — it's on PyPI as
spotify-mcp-jamiew, run it withuvx spotify-mcp-jamiew, and set env varsSPOTIFY_CLIENT_ID,SPOTIFY_CLIENT_SECRET, andSPOTIFY_REDIRECT_URI=http://127.0.0.1:8888.
git clone https://github.com/jamiew/spotify-mcp.git
cd spotify-mcp
uv syncThen point your client at the checkout:
{
"mcpServers": {
"spotify": {
"command": "uv",
"args": ["--directory", "/path/to/spotify-mcp", "run", "spotify-mcp"],
"env": {
"SPOTIFY_CLIENT_ID": "your_client_id",
"SPOTIFY_CLIENT_SECRET": "your_client_secret",
"SPOTIFY_REDIRECT_URI": "http://127.0.0.1:8888"
}
}
}
}To run the latest unpublished commit without cloning: uvx --from git+https://github.com/jamiew/spotify-mcp.git spotify-mcp.
On first use the server opens a browser for Spotify OAuth; the token is cached locally for later runs.
Usage Examples
"Create a chill study playlist with 20 tracks" → Search + playlist creation + bulk track addition
"Show me the first 50 tracks from my 'Liked Songs'" → Pagination for large playlists
"Find similar artists to Radiohead and add their top tracks to my queue" → Search + artist info + queue management
Development
Built with the FastMCP framework — focused single-purpose tools spanning playback, search, queue, and playlist management, with type-safe APIs and comprehensive test coverage.
Debug with MCP Inspector:
npx @modelcontextprotocol/inspector uv --directory /path/to/spotify_mcp run spotify-mcpContributors
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 which artists the user follows. One request for up to 50.
Artists are followed rather than saved, so this reads follows, not the
saved-albums library.
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 readOnly, openWorld, and idempotent hints. The description adds beyond them: it clarifies the follow-state source, batching limit of 50, and the return mapping from artist id to boolean. No contradiction 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?
Four compact sentences plus Args/Returns block with no filler. The core purpose is front-loaded, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 rich annotations and an output schema, the description fully covers input semantics, batch limit, and conceptual distinction. Nothing essential 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 coverage is 0%, so the description must compensate, and it does: artist_ids accepts Artist IDs or URIs up to 50 and the result maps each Spotify artist id to true if followed. It could add exact URI format, but this is adequate.
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 and resource: 'Check which artists the user follows.' It immediately distinguishes follows from saved albums, so it is clearly differentiated from check_saved_albums and other sibling 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?
Provides clear context by explaining that artists are followed rather than saved, so the tool reads follows, not the saved-albums library. It does not name a sibling explicitly, but the exclusion is explicit enough for an agent to route correctly.
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.
One request for up to 20 albums — Spotify's cap for albums is lower than the
50 it allows for tracks.
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 this as read-only, idempotent, and open-world. The description adds valuable behavior beyond that: the per-request album cap (20, contrasted with Spotify's 50 for tracks) and the response behavior that maps each album ID to true if saved. This is useful context without contradicting 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-organized: purpose first, then the batch limitation, then Args and Returns. Every sentence earns its place and there is no redundant or promotional language.
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, read-only tool with an output schema and supportive annotations, the description covers the key facts an agent needs: what the tool does, accepted argument format, the request cap, and the shape of the result. Minor omissions like explicit behavior for false membership or invalid IDs are acceptable given the output schema exists.
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 only declares an array of strings with no per-parameter documentation, so the description carries the burden. It compensates well by specifying that album_ids accepts 'Album IDs or URIs' and that the maximum is 20 items. It could be even stronger with an example or explicit note about mixing IDs and URIs, but it is sufficiently informative.
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 and resource: 'Check which albums are already saved to the library.' This clearly identifies the tool as a membership-checking operation for albums, which is enough to distinguish it from nearby siblings like check_saved_tracks or get_saved_tracks, though it does not explicitly name them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a practical constraint ('One request for up to 20 albums') but does not explain when an agent should choose this tool over alternatives such as check_saved_tracks or save_tracks. There is no explicit when-to-use or when-not-to-use guidance, only an implied use case from the first sentence.
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.
One request for up to 50 tracks. Use this before save_tracks to skip what is
already there, rather than reading get_saved_tracks page by page.
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 safety profile is covered. The description adds the key behavioral constraint: one request handles up to 50 tracks, and the return maps each track id to a boolean. This is useful context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the purpose is in the first sentence, usage guidance follows, and the Args/Returns section is minimal and scannable. Every sentence earns its place.
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 read-only tool with an output schema, the description covers the essential behavior, usage context, and return shape. It could mention error cases or exact URI formats, but nothing critical is missing 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 coverage is 0%, so the description must compensate. It explains track_ids accepts Track IDs or URIs and caps at 50, which adds meaning beyond the raw array-of-strings schema. It doesn't detail URI formats, but the core semantics are clear.
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 which tracks are already liked, with a specific verb and resource. It distinguishes itself from get_saved_tracks by noting it avoids paging the whole library, and from save_tracks by being the pre-check step.
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 says to use this before save_tracks to skip already-liked tracks, and contrasts it with reading get_saved_tracks page by page. This gives clear when-to-use guidance and names alternatives.
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: True)
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 already flag readOnlyHint=false, so the agent knows this is a mutating operation. The description adds that the function returns the created Playlist, which is a useful behavioral detail beyond the annotations. However, it does not disclose side effects, authentication requirements, or rate limits, so it only marginally surpasses what annotations already provide.
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 concise: a one-sentence purpose, a bullet-like list of args, and a return line. The main purpose is front-loaded, and every sentence earns its place without redundancy or filler. This is exemplary structure.
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 create operation with an output schema, the description covers the essential purpose and parameters. It lacks notes on authentication prerequisites or edge cases, but given the output schema and the straightforward nature of the action, the agent has enough to call it correctly. The absence of explicit usage exclusions is a minor 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?
With schema description coverage at 0%, the description effectively compensates by explaining each parameter: name is 'Playlist name', description is 'Playlist description (default: empty)', and public is 'Whether playlist is public (default: True)'. This adds semantic meaning that the schema's bare type/default fields lack, giving agents the intent behind each argument.
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 'Create a new Spotify playlist,' which is a specific verb and resource. The title and name align perfectly, and the intended action is distinct from siblings like update_playlist_details or add_tracks_to_playlist. No ambiguity remains about 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 description does not explicitly state when to use this tool versus alternatives. The name and purpose imply that it is for creating new playlists, but there is no guidance such as 'use this instead of update_playlist_details for existing playlists.' Thus, usage context is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
With /recommendations, audio-features and related-artists withdrawn from
third-party apps, this is the measured foundation for taste profiling and
building suggestions.
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 detail beyond annotations: the valid time-range meanings, limit bounds, and that the return object will populate only one of 'tracks' or 'artists' based on item_type.
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 front-loaded with the core action and uses a compact Args/Returns structure. The context paragraph about withdrawn endpoints adds strategic value for selecting the tool, though it is not strictly required for invoking it. Overall, each section earns its place without padding.
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?
All three parameters are documented, the return shape is named, and annotations plus an output schema cover the remaining operational details. Minor gaps remain, such as not spelling out the time_range default in the description, but the schema fills that in. The tool can be called correctly from the description 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?
Schema description coverage is 0%, so the description fully carries the parameter documentation. It explains every parameter in plain language: item_type values with default, time_range definitions with approximate durations, and limit range (1-50) with default. This goes well 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 states a specific verb and resource: 'Get the user's top artists or tracks over a time range.' It also clarifies the core toggle between item types. It does not explicitly differentiate itself from siblings such as get_recently_played or get_me, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when this tool matters: with recommendations, audio-features, and related-artists withdrawn, this is 'the measured foundation for taste profiling and building suggestions.' It does not list exclusions or alternative sibling tools, but the intended use case is clear.
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.
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
Each tool targets a distinct resource and action. Playback control vs transfer, queue vs playlist adds, and check functions for different entity types are all clearly separated by name and description.
All 28 tools follow a consistent snake_case verb_noun pattern (get_, list_, add_, remove_, control_, transfer_, search_, create_, update_, reorder_, save_, check_, unfollow_). No mixing of styles or ambiguous verbs.
28 tools is above the typical 3-15 range but justified by the breadth of the Spotify API. Each tool covers a distinct capability and none appear redundant, so the count is reasonable for a full-featured integration.
Playlist management and playback control are well covered, but there are notable gaps: no save/remove album, no follow/unfollow artists, and no list for followed artists or saved albums beyond check functions. This limits some library management 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-