A Spotify MCP (Model Context Protocol) server with dual-mode support (CLI and MCP protocol) for controlling Spotify playback, managing playlists, and searching music
The server defines 12 tools with explicit schemas and descriptions visible in server.py. However, critical gaps reduce the overall score: (1) Most tool descriptions are under 50 characters and lack context about when to use them, state-modification intent, or prerequisites. (2) Several parameter descriptions are generic or missing ('artist' in play_song says 'optional' but not format/length constraints; 'limit' in search_songs lacks bounds). (3) No output schemas are documented, the source shows only input schemas. (4) Error handling is not visible in the provided code, no recovery guidance, error classification, or actionable error messages. (5) Parameters like 'search_type' lack enums despite accepting a constrained set of values ('track', 'artist', 'album', 'playlist'). (6) No evidence of idempotent operation patterns or dry-run support for destructive operations (pause, skip, delete). The tool definitions exist and are structurally sound, but they lack the depth and specificity required for production-grade LLM agent use. Average baseline for community tools scoring ~50 - 55; this server is at the low end due to sparse descriptions and missing output documentation.
Output schemas not documented for any tool. LLMs cannot plan downstream calls or extract chaining data (e.g., playlist_id after create_playlist). This breaks tool composition.
'search_type' parameter in search_songs lacks enum constraint. Description mentions 'track, artist, album, playlist' but JSON schema does not enforce these values. LLMs will hallucinate invalid types.
'limit' parameter in search_songs has no min/max bounds. Unbounded numbers invite LLMs to pass absurd values (e.g., limit=999999) causing API timeouts or excessive token usage.
Document output schema for every tool. Use the pattern: 'Returns: {field_name: type, ...}' in the description or add a separate outputSchema field to the Tool object. For create_playlist, explicitly state: 'Returns: {playlist_id: string, playlist_name: string, public: boolean}'.
Expand tool descriptions to 50 - 200 characters. Template: '[Action]. Use this to [context/when]. Returns [key data]. [Error recovery hint if applicable].' Example: 'Pause the current playback. Call this when the user wants to pause music. Returns the updated playback state. If no active device, suggest list_devices() first.'
Add enum constraint to search_type parameter in search_songs: {"type": "string", "enum": ["track", "artist", "album", "playlist"], "description": "Type of search: track, artist, album, or playlist."}
Add min/max bounds to limit parameter in search_songs: {"type": "integer", "minimum": 1, "maximum": 50, "description": "Number of results to return (1 - 50; default 20)."} and update description to reflect the default.
For optional parameters (artist), expand descriptions: 'Artist name (optional; improves search accuracy. If omitted, search by song_title only).'
Implement pagination for get_user_playlists and search_songs. Add offset/limit or cursor parameters and return a total_count field. Example: 'get_user_playlists(offset=0, limit=20) returns {playlists: [...], total_count: 42, next_offset: 20}'.
Add error handling and recovery guidance. In the code, wrap Spotify API calls in try/catch and return structured errors: {"error": "<error_type>", "message": "<user-friendly message>", "recovery": "<suggested next tool or action>"}. Example: 'No active device. Try calling authenticate_spotify first, or use a Spotify app on a device.'
Spec posture evidence
Inferred effective spec: <=2025-11-25.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
Score history
Overall score trend
First recorded score · v2 rubric
57/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-23
D
57
<=2025-11-25
v2
previous_trackwriteauthsource verified65/100
Go back to the previous track
resume_playbackwriteauthsource verified68/100
Resume paused playback
search_songsread onlyauthsource verified63/100
Search for songs, artists, albums, or playlists
set_volumewriteauthsource verified70/100
Set playback volume (0-100)
skip_trackwriteauthsource verified65/100
Skip to the next track
Most tool descriptions are under 50 characters and lack actionable context. They state WHAT (e.g., 'Pause current playback') but not WHEN to use it, state-modification intent, or error recovery. Baseline is 194 chars; these average ~35 chars.
Optional parameters ('artist' in play_song, 'artist' in add_to_playlist) lack format constraints. Description says 'optional' but not what happens if omitted, expected format, or length limits.
No pagination support documented for list/discovery tools (get_user_playlists, search_songs). No mention of limits, offsets, or cursors. Large result sets will exhaust context window.
Destructive operations (pause_playback, skip_track, add_to_playlist) lack confirmation/dry-run patterns. No evidence of idempotent retry support or user confirmation before executing irreversible actions.
No error handling or recovery guidance visible in tool definitions. Source code shows setup but no try/catch blocks with actionable error messages. Errors like 'No active device' or 'Playlist not found' lack guidance on next steps.
For destructive operations (skip_track, pause_playback), add a confirm parameter or document that these are NOT idempotent if called multiple times in rapid succession. Provide guidance on safe retry patterns.
Enforce parameter validation at the tool entry point. For set_volume, validate 0 ≤ volume_percent ≤ 100 and return actionable errors if bounds violated: 'Invalid volume: 150. Must be 0 - 100.'
Add a 'requires_active_playback' note to tools like pause_playback, skip_track, and resume_playback. Description template: 'Pauses the current playback. Requires an active playback session (if none exists, returns an error with guidance to call authenticate_spotify and start playback first).'
Consider adding a 'get_available_devices' or 'list_devices' discovery tool to help agents troubleshoot 'no active device' errors when calling playback control tools.
Document which tools are read-only vs. write/destructive. Add a note to tool descriptions or use tool annotations (if supported) to flag write operations: 'This tool modifies playback state.'