Skip to main content
Glama

SpotifyPlaylist

Create, manage, and modify Spotify playlists by adding or removing tracks, updating details, and viewing playlist contents.

Instructions

Manage Spotify playlists. - get: Get a list of user's playlists. - get_tracks: Get tracks in a specific playlist. - add_tracks: Add tracks to a specific playlist. - remove_tracks: Remove tracks from a specific playlist. - change_details: Change details of a specific playlist. - create: Create a new playlist.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform: 'get', 'get_tracks', 'add_tracks', 'remove_tracks', 'change_details', 'create'.
playlist_idNoID of the playlist to manage.
track_idsNoList of track IDs to add/remove.
nameNoName for the playlist (required for create and change_details).
descriptionNoDescription for the playlist.
publicNoWhether the playlist should be public (for create action).

Implementation Reference

  • Handler logic for executing the SpotifyPlaylist tool. Dispatches based on 'action' parameter to various playlist operations by calling corresponding methods on spotify_client.
    case "Playlist": logger.info(f"Playlist operation with arguments: {arguments}") action = arguments.get("action") match action: case "get": logger.info(f"Getting current user's playlists with arguments: {arguments}") playlists = spotify_client.get_current_user_playlists() return [types.TextContent( type="text", text=json.dumps(playlists, indent=2) )] case "get_tracks": logger.info(f"Getting tracks in playlist with arguments: {arguments}") if not arguments.get("playlist_id"): logger.error("playlist_id is required for get_tracks action.") return [types.TextContent( type="text", text="playlist_id is required for get_tracks action." )] tracks = spotify_client.get_playlist_tracks(arguments.get("playlist_id")) return [types.TextContent( type="text", text=json.dumps(tracks, indent=2) )] case "add_tracks": logger.info(f"Adding tracks to playlist with arguments: {arguments}") track_ids = arguments.get("track_ids") if isinstance(track_ids, str): try: track_ids = json.loads(track_ids) # Convert JSON string to Python list except json.JSONDecodeError: logger.error("track_ids must be a list or a valid JSON array.") return [types.TextContent( type="text", text="Error: track_ids must be a list or a valid JSON array." )] spotify_client.add_tracks_to_playlist( playlist_id=arguments.get("playlist_id"), track_ids=track_ids ) return [types.TextContent( type="text", text="Tracks added to playlist." )] case "remove_tracks": logger.info(f"Removing tracks from playlist with arguments: {arguments}") track_ids = arguments.get("track_ids") if isinstance(track_ids, str): try: track_ids = json.loads(track_ids) # Convert JSON string to Python list except json.JSONDecodeError: logger.error("track_ids must be a list or a valid JSON array.") return [types.TextContent( type="text", text="Error: track_ids must be a list or a valid JSON array." )] spotify_client.remove_tracks_from_playlist( playlist_id=arguments.get("playlist_id"), track_ids=track_ids ) return [types.TextContent( type="text", text="Tracks removed from playlist." )] case "change_details": logger.info(f"Changing playlist details with arguments: {arguments}") if not arguments.get("playlist_id"): logger.error("playlist_id is required for change_details action.") return [types.TextContent( type="text", text="playlist_id is required for change_details action." )] if not arguments.get("name") and not arguments.get("description"): logger.error("At least one of name, description or public is required.") return [types.TextContent( type="text", text="At least one of name, description, public, or collaborative is required." )] spotify_client.change_playlist_details( playlist_id=arguments.get("playlist_id"), name=arguments.get("name"), description=arguments.get("description") ) return [types.TextContent( type="text", text="Playlist details changed." )] case "create": logger.info(f"Creating playlist with arguments: {arguments}") if not arguments.get("name"): logger.error("name is required for create action.") return [types.TextContent( type="text", text="name is required for create action." )] playlist = spotify_client.create_playlist( name=arguments.get("name"), description=arguments.get("description"), public=arguments.get("public", True) ) return [types.TextContent( type="text", text=json.dumps(playlist, indent=2) )] case _: return [types.TextContent( type="text", text=f"Unknown playlist action: {action}." "Supported actions are: get, get_tracks, add_tracks, remove_tracks, change_details, create." )] case _:
  • Pydantic model defining the input schema for the SpotifyPlaylist tool, used to generate the tool schema.
    class Playlist(ToolModel): """Manage Spotify playlists. - get: Get a list of user's playlists. - get_tracks: Get tracks in a specific playlist. - add_tracks: Add tracks to a specific playlist. - remove_tracks: Remove tracks from a specific playlist. - change_details: Change details of a specific playlist. - create: Create a new playlist. """ action: str = Field( description="Action to perform: 'get', 'get_tracks', 'add_tracks', 'remove_tracks', 'change_details', 'create'.") playlist_id: Optional[str] = Field(default=None, description="ID of the playlist to manage.") track_ids: Optional[List[str]] = Field(default=None, description="List of track IDs to add/remove.") name: Optional[str] = Field(default=None, description="Name for the playlist (required for create and change_details).") description: Optional[str] = Field(default=None, description="Description for the playlist.") public: Optional[bool] = Field(default=True, description="Whether the playlist should be public (for create action).")
  • Registers the SpotifyPlaylist tool (as Playlist.as_tool()) in the list of available tools returned to MCP clients.
    @server.list_tools() async def handle_list_tools() -> list[types.Tool]: """List available tools.""" logger.info("Listing available tools") # await server.request_context.session.send_notification("are you recieving this notification?") tools = [ Playback.as_tool(), Search.as_tool(), Queue.as_tool(), GetInfo.as_tool(), Playlist.as_tool(), ] logger.info(f"Available tools: {[tool.name for tool in tools]}") return tools
  • Helper method to retrieve the current user's playlists, called by 'get' action.
    def get_current_user_playlists(self, limit=50) -> List[Dict]: """ Get current user's playlists. - limit: Max number of playlists to return. """ playlists = self.sp.current_user_playlists() if not playlists: raise ValueError("No playlists found.") return [utils.parse_playlist(playlist, self.username) for playlist in playlists['items']]
  • Helper method to create a new playlist, called by 'create' action in the handler.
    def create_playlist(self, name: str, description: Optional[str] = None, public: bool = True): """ Create a new playlist. - name: Name for the playlist. - description: Description for the playlist. - public: Whether the playlist should be public. """ if not name: raise ValueError("Playlist name is required.") try: user = self.sp.current_user() user_id = user['id'] playlist = self.sp.user_playlist_create( user=user_id, name=name, public=public, description=description ) self.logger.info(f"Created playlist: {name} (ID: {playlist['id']})") return utils.parse_playlist(playlist, self.username, detailed=True) except Exception as e: self.logger.error(f"Error creating playlist: {str(e)}") raise

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/varunneal/spotify-mcp'

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