Skip to main content
Glama
yuhuacheng

TIDAL MCP: My Custom Picks

get_playlist_tracks

Retrieve all tracks from a specified TIDAL playlist to view song names, artists, albums, and durations. Provide the playlist ID to list contents.

Instructions

Retrieves all tracks from a specified TIDAL playlist.

USE THIS TOOL WHENEVER A USER ASKS FOR:
- "Show me the songs in my playlist"
- "What tracks are in my [playlist name] playlist?"
- "List the songs from my playlist"
- "Get tracks from my playlist"
- "View contents of my TIDAL playlist"
- Any request to see what songs/tracks are in a specific playlist

This function retrieves all tracks from a specific playlist in the user's TIDAL account.
The playlist_id must be provided, which can be obtained from the get_user_playlists() function.

When processing the results of this tool:
1. Present the playlist information (title, description, track count) as context
2. List the tracks in a clear, organized format with track name, artist, and album
3. Include track durations where available
4. Mention the total number of tracks in the playlist
5. If there are many tracks, focus on highlighting interesting patterns or variety

Args:
    playlist_id: The TIDAL ID of the playlist to retrieve (required)
    limit: Maximum number of tracks to retrieve (default: 100)
    
Returns:
    A dictionary containing the playlist information and all tracks in the playlist

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
playlist_idYes
limitNo

Implementation Reference

  • MCP tool handler for 'get_playlist_tracks'. Decorated with @mcp.tool() for registration. Validates input, checks authentication, and proxies HTTP request to the backend Tidal Flask API to retrieve and return playlist tracks.
    def get_playlist_tracks(playlist_id: str, limit: int = 100) -> dict:
        """
        Retrieves all tracks from a specified TIDAL playlist.
        
        USE THIS TOOL WHENEVER A USER ASKS FOR:
        - "Show me the songs in my playlist"
        - "What tracks are in my [playlist name] playlist?"
        - "List the songs from my playlist"
        - "Get tracks from my playlist"
        - "View contents of my TIDAL playlist"
        - Any request to see what songs/tracks are in a specific playlist
        
        This function retrieves all tracks from a specific playlist in the user's TIDAL account.
        The playlist_id must be provided, which can be obtained from the get_user_playlists() function.
        
        When processing the results of this tool:
        1. Present the playlist information (title, description, track count) as context
        2. List the tracks in a clear, organized format with track name, artist, and album
        3. Include track durations where available
        4. Mention the total number of tracks in the playlist
        5. If there are many tracks, focus on highlighting interesting patterns or variety
        
        Args:
            playlist_id: The TIDAL ID of the playlist to retrieve (required)
            limit: Maximum number of tracks to retrieve (default: 100)
            
        Returns:
            A dictionary containing the playlist information and all tracks in the playlist
        """
        # First, check if the user is authenticated
        auth_check = requests.get(f"{FLASK_APP_URL}/api/auth/status")
        auth_data = auth_check.json()
        
        if not auth_data.get("authenticated", False):
            return {
                "status": "error",
                "message": "You need to login to TIDAL first before I can fetch playlist tracks. Please use the tidal_login() function."
            }
        
        # Validate playlist_id
        if not playlist_id:
            return {
                "status": "error", 
                "message": "A playlist ID is required. You can get playlist IDs by using the get_user_playlists() function."
            }
        
        try:
            # Call the Flask endpoint to retrieve tracks from the playlist
            response = requests.get(
                f"{FLASK_APP_URL}/api/playlists/{playlist_id}/tracks", 
                params={"limit": limit}
            )
            
            # Check if the request was successful
            if response.status_code == 200:
                data = response.json()
                return {
                    "status": "success",                
                    "tracks": data.get("tracks", []),
                    "track_count": data.get("total_tracks", 0)
                }
            elif response.status_code == 404:
                return {
                    "status": "error",
                    "message": f"Playlist with ID {playlist_id} not found. Please check the playlist ID and try again."
                }
            elif response.status_code == 401:
                return {
                    "status": "error",
                    "message": "Not authenticated with TIDAL. Please login first using tidal_login()."
                }
            else:
                error_data = response.json()
                return {
                    "status": "error",
                    "message": f"Failed to retrieve playlist tracks: {error_data.get('error', 'Unknown error')}"
                }
        except Exception as e:
            return {
                "status": "error",
                "message": f"Failed to connect to TIDAL playlist service: {str(e)}"
            }
  • Backend Flask API endpoint that implements the actual TIDAL playlist tracks retrieval using BrowserSession.playlist().items(), formats tracks, and serves data consumed by the MCP handler.
    @app.route('/api/playlists/<playlist_id>/tracks', methods=['GET'])
    @requires_tidal_auth
    def get_playlist_tracks(playlist_id: str, session: BrowserSession):
        """
        Get tracks from a specific TIDAL playlist.
        """
        try:
            # Get limit from query parameter, default to 100 if not specified
            limit = bound_limit(request.args.get('limit', default=100, type=int))
            
            # Get the playlist object
            playlist = session.playlist(playlist_id)
            if not playlist:
                return jsonify({"error": f"Playlist with ID {playlist_id} not found"}), 404
                
            # Get tracks from the playlist with pagination if needed
            tracks = playlist.items(limit=limit)
            
            # Format track data
            track_list = [format_track_data(track) for track in tracks]
            
            return jsonify({
                "playlist_id": playlist.id,
                "tracks": track_list,
                "total_tracks": len(track_list)
            })
            
        except Exception as e:
            return jsonify({"error": f"Error fetching playlist tracks: {str(e)}"}), 500
  • Utility functions used by the playlist tracks endpoint: format_track_data standardizes track info, bound_limit sanitizes the limit parameter.
    def format_track_data(track, source_track_id=None):
        """
        Format a track object into a standardized dictionary.
        
        Args:
            track: TIDAL track object
            source_track_id: Optional ID of the track that led to this recommendation
            
        Returns:
            Dictionary with standardized track information
        """
        track_data = {
            "id": track.id,
            "title": track.name,
            "artist": track.artist.name if hasattr(track.artist, 'name') else "Unknown",
            "album": track.album.name if hasattr(track.album, 'name') else "Unknown",
            "duration": track.duration if hasattr(track, 'duration') else 0,
            "url": f"https://tidal.com/browse/track/{track.id}?u"
        }
        
        # Include source track ID if provided
        if source_track_id:
            track_data["source_track_id"] = source_track_id
            
        return track_data
    
    def bound_limit(limit: int, max_n: int = 50) -> int:
        # Ensure limit is within reasonable bounds
        if limit < 1:
            limit = 1
        elif limit > max_n:
            limit = max_n
        print(f"Limit set to {limit} (max {max_n})")    
        return limit
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly describes the read-only nature ('retrieves'), specifies the default limit parameter behavior, and provides detailed guidance on how to process and present results. However, it doesn't mention potential limitations like rate limits or authentication requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately front-loaded with the core purpose, but includes extensive processing instructions that might be better placed elsewhere. While the content is valuable, the structure could be more streamlined by separating usage guidelines from implementation details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description provides substantial context including purpose, usage guidelines, parameter semantics, and detailed processing instructions. However, it doesn't explicitly describe the return format beyond 'a dictionary containing playlist information and all tracks,' leaving some ambiguity about the exact response structure.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must compensate for the lack of parameter documentation. It provides clear semantic meaning for both parameters: playlist_id ('TIDAL ID of the playlist to retrieve') and limit ('Maximum number of tracks to retrieve'). The description also explains where to obtain playlist_id and specifies the default value for limit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with a specific verb ('retrieves') and resource ('tracks from a specified TIDAL playlist'). It distinguishes this tool from siblings like get_user_playlists (which lists playlists) and get_favorite_tracks (which retrieves favorite tracks rather than playlist tracks).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidelines with a dedicated 'USE THIS TOOL WHENEVER' section listing multiple user query patterns. It also specifies prerequisites (playlist_id must come from get_user_playlists) and distinguishes this tool from alternatives by focusing on playlist content retrieval.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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/yuhuacheng/tidal-mcp'

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