Skip to main content
Glama
boristopalov

Spotify MCP Server

by boristopalov

SpotifyPlayback

Control Spotify playback: get current track info, start or resume music, pause playback, or skip tracks using the Spotify MCP Server.

Instructions

Manages the current playback with the following actions: - get: Get information about user's current track. - start: Starts of resumes playback. - pause: Pauses current playback. - skip: Skips current track.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform: 'get', 'start', 'pause' or 'skip'.
track_idNoSpecifies track to play for 'start' action. If omitted, resumes current playback.
num_skipsNoNumber of tracks to skip for `skip` action.

Implementation Reference

  • Handler logic for the 'SpotifyPlayback' tool inside handle_call_tool(), dispatching actions to Spotify API client methods: get_current_track(), start_playback(), pause_playback(), skip_track().
    case "Playback":
        action = arguments.get("action")
        match action:
            case "get":
                logger.info("Attempting to get current track")
                curr_track = spotify_client.get_current_track()
                if curr_track:
                    logger.info(f"Current track retrieved: {curr_track.get('name', 'Unknown')}")
                    return [types.TextContent(
                        type="text",
                        text=json.dumps(curr_track, indent=2)
                    )]
                logger.info("No track currently playing")
                return [types.TextContent(
                    type="text",
                    text="No track playing."
                )]
            case "start":
                logger.info(f"Starting playback with arguments: {arguments}")
                spotify_client.start_playback(track_id=arguments.get("track_id"))
                logger.info("Playback started successfully")
                return [types.TextContent(
                    type="text",
                    text="Playback starting with no errors."
                )]
            case "pause":
                logger.info("Attempting to pause playback")
                spotify_client.pause_playback()
                logger.info("Playback paused successfully")
                return [types.TextContent(
                    type="text",
                    text="Playback paused successfully."
                )]
            case "skip":
                num_skips = int(arguments.get("num_skips", 1))
                logger.info(f"Skipping {num_skips} tracks.")
                spotify_client.skip_track(n=num_skips)
                return [types.TextContent(
                    type="text",
                    text="Skipped to next track."
                )]
  • Pydantic model defining the input schema for SpotifyPlayback tool, used to generate the tool schema via model_json_schema().
    class Playback(ToolModel):
        """Manages the current playback with the following actions:
        - get: Get information about user's current track.
        - start: Starts of resumes playback.
        - pause: Pauses current playback.
        - skip: Skips current track.
        """
        action: str = Field(description="Action to perform: 'get', 'start', 'pause' or 'skip'.")
        track_id: Optional[str] = Field(default=None, description="Specifies track to play for 'start' action. If omitted, resumes current playback.")
        num_skips: Optional[int] = Field(default=1, description="Number of tracks to skip for `skip` action.")
  • Registers the SpotifyPlayback tool (as 'SpotifyPlayback') by including Playback.as_tool() in the list returned by list_tools().
    @server.list_tools()
    async def handle_list_tools() -> list[types.Tool]:
        """List available tools."""
        logger.info("Listing available tools")
        tools = [
            Playback.as_tool(),
            Search.as_tool(),
            Queue.as_tool(),
            GetInfo.as_tool(),
        ]
        logger.info(f"Available tools: {[tool.name for tool in tools]}")
        return tools
  • Core helper method get_current_track() in SpotifyClient, called by 'get' action.
    def get_current_track(self) -> Optional[Dict]:
        """Get information about the currently playing track"""
        try:
            # current_playback vs current_user_playing_track?
            current = self.sp.current_user_playing_track()
            if not current:
                self.logger.info("No playback session found")
                return None
            if current.get('currently_playing_type') != 'track':
                self.logger.info("Current playback is not a track")
                return None
    
            track_info = utils.parse_track(current['item'])
            if 'is_playing' in current:
                track_info['is_playing'] = current['is_playing']
    
            self.logger.info(
                f"Current track: {track_info.get('name', 'Unknown')} by {track_info.get('artist', 'Unknown')}")
            return track_info
        except Exception as e:
            self.logger.error("Error getting current track info", exc_info=True)
            raise
  • Core helper method start_playback() in SpotifyClient, called by 'start' action to start/resume playback with optional track_id. Includes validation decorator. (excerpt omitted for length)
    def start_playback(self, track_id=None, device=None):
        """
        Starts track playback. If track_id is omitted, resumes current playback.
        - track_id: ID of track to play, or None.
        """
        try:
            if not track_id:
                if self.is_track_playing():
                    self.logger.info("No track_id provided and playback already active.")
                    return
                if not self.get_current_track():
                    raise ValueError("No track_id provided and no current playback to resume.")
    
            uris = [f'spotify:track:{track_id}'] if track_id else None
            device_id = device.get('id') if device else None
    
            result = self.sp.start_playback(uris=uris, device_id=device_id)
            self.logger.info(f"Playback started successfully{' for track_id: ' + track_id if track_id else ''}")
            return result
        except Exception as e:
            self.logger.error(f"Error starting playback: {str(e)}", exc_info=True)
            raise

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/boristopalov/spotify-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server