Skip to main content
Glama
yuhuacheng

TIDAL MCP: My Custom Picks

recommend_tracks

Get personalized music recommendations from TIDAL based on specific tracks or your favorite songs, with options to filter by mood, genre, or release date.

Instructions

Recommends music tracks based on specified track IDs or can use the user's TIDAL favorites if no IDs are provided.

USE THIS TOOL WHENEVER A USER ASKS FOR:
- Music recommendations
- Track suggestions
- Music similar to their TIDAL favorites or specific tracks
- "What should I listen to?"
- Any request to recommend songs/tracks/music based on their TIDAL history or specific tracks

This function gets recommendations based on provided track IDs or retrieves the user's 
favorite tracks as seeds if no IDs are specified.

When processing the results of this tool:
1. Analyze the seed tracks to understand the music taste or direction
2. Review the recommended tracks from TIDAL
3. IMPORTANT: Do NOT include any tracks from the seed tracks in your recommendations
4. Ensure there are NO DUPLICATES in your recommended tracks list
5. Select and rank the most appropriate tracks based on the seed tracks and filter criteria
6. Group recommendations by similar styles, artists, or moods with descriptive headings
7. For each recommended track, provide:
   - The track name, artist, album
   - Always include the track's URL to make it easy for users to listen to the track
   - A brief explanation of why this track might appeal to the user based on the seed tracks
   - If applicable, how this track matches their specific filter criteria       
8. Format your response as a nicely presented list of recommendations with helpful context (remember to include the track's URL!)
9. Begin with a brief introduction explaining your selection strategy
10. Lastly, unless specified otherwise, you should recommend MINIMUM 20 tracks (or more if possible) to give the user a good variety to choose from.

[IMPORTANT NOTE] If you're not familiar with any artists or tracks mentioned, you should use internet search capabilities if available to provide more accurate information.

Args:
    track_ids: Optional list of TIDAL track IDs to use as seeds for recommendations.
              If not provided, will use the user's favorite tracks.
    filter_criteria: Specific preferences for filtering recommendations (e.g., "relaxing music," 
                     "recent releases," "upbeat," "jazz influences")
    limit_per_track: Maximum number of recommendations to get per track (NOTE: default: 20, unless specified otherwise, we'd like to keep the default large enough to have enough candidates to work with)
    limit_from_favorite: Maximum number of favorite tracks to use as seeds (NOTE: default: 20, unless specified otherwise, we'd like to keep the default large enough to have enough candidates to work with)
    
Returns:
    A dictionary containing both the seed tracks and recommended tracks

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
track_idsNo
filter_criteriaNo
limit_per_trackNo
limit_from_favoriteNo

Implementation Reference

  • The primary handler function for the 'recommend_tracks' MCP tool. Decorated with @mcp.tool() for automatic registration and schema inference from type hints. Implements the full logic: authentication check, seed track retrieval (from provided IDs or user favorites), recommendation fetching via internal helper, and structured response.
    @mcp.tool()
    def recommend_tracks(track_ids: Optional[List[str]] = None, filter_criteria: Optional[str] = None, limit_per_track: int = 20, limit_from_favorite: int = 20) -> dict:
        """
        Recommends music tracks based on specified track IDs or can use the user's TIDAL favorites if no IDs are provided.
        
        USE THIS TOOL WHENEVER A USER ASKS FOR:
        - Music recommendations
        - Track suggestions
        - Music similar to their TIDAL favorites or specific tracks
        - "What should I listen to?"
        - Any request to recommend songs/tracks/music based on their TIDAL history or specific tracks
        
        This function gets recommendations based on provided track IDs or retrieves the user's 
        favorite tracks as seeds if no IDs are specified.
        
        When processing the results of this tool:
        1. Analyze the seed tracks to understand the music taste or direction
        2. Review the recommended tracks from TIDAL
        3. IMPORTANT: Do NOT include any tracks from the seed tracks in your recommendations
        4. Ensure there are NO DUPLICATES in your recommended tracks list
        5. Select and rank the most appropriate tracks based on the seed tracks and filter criteria
        6. Group recommendations by similar styles, artists, or moods with descriptive headings
        7. For each recommended track, provide:
           - The track name, artist, album
           - Always include the track's URL to make it easy for users to listen to the track
           - A brief explanation of why this track might appeal to the user based on the seed tracks
           - If applicable, how this track matches their specific filter criteria       
        8. Format your response as a nicely presented list of recommendations with helpful context (remember to include the track's URL!)
        9. Begin with a brief introduction explaining your selection strategy
        10. Lastly, unless specified otherwise, you should recommend MINIMUM 20 tracks (or more if possible) to give the user a good variety to choose from.
        
        [IMPORTANT NOTE] If you're not familiar with any artists or tracks mentioned, you should use internet search capabilities if available to provide more accurate information.
        
        Args:
            track_ids: Optional list of TIDAL track IDs to use as seeds for recommendations.
                      If not provided, will use the user's favorite tracks.
            filter_criteria: Specific preferences for filtering recommendations (e.g., "relaxing music," 
                             "recent releases," "upbeat," "jazz influences")
            limit_per_track: Maximum number of recommendations to get per track (NOTE: default: 20, unless specified otherwise, we'd like to keep the default large enough to have enough candidates to work with)
            limit_from_favorite: Maximum number of favorite tracks to use as seeds (NOTE: default: 20, unless specified otherwise, we'd like to keep the default large enough to have enough candidates to work with)
            
        Returns:
            A dictionary containing both the seed tracks and recommended tracks
        """
        # 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 recommend music. Please use the tidal_login() function."
            }
        
        # Initialize variables to store our seed tracks and their info
        seed_track_ids = []
        seed_tracks_info = []
        
        # If track_ids are provided, use them directly
        if track_ids and isinstance(track_ids, list) and len(track_ids) > 0:
            seed_track_ids = track_ids
            # Note: We don't have detailed info about these tracks, just IDs
            # This is fine as the recommendation API only needs IDs
        else:
            # If no track_ids provided, get the user's favorite tracks
            tracks_response = get_favorite_tracks(limit=limit_from_favorite)
            
            # Check if we successfully retrieved tracks
            if "status" in tracks_response and tracks_response["status"] == "error":
                return {
                    "status": "error",
                    "message": f"Unable to get favorite tracks for recommendations: {tracks_response['message']}"
                }
            
            # Extract the track data
            favorite_tracks = tracks_response.get("tracks", [])
            
            if not favorite_tracks:
                return {
                    "status": "error",
                    "message": "I couldn't find any favorite tracks in your TIDAL account to use as seeds for recommendations."
                }
            
            # Use these as our seed tracks
            seed_track_ids = [track["id"] for track in favorite_tracks]
            seed_tracks_info = favorite_tracks
        
        # Get recommendations based on the seed tracks
        recommendations_response = _get_tidal_recommendations(
            track_ids=seed_track_ids,
            limit_per_track=limit_per_track,
            filter_criteria=filter_criteria
        )
        
        # Check if we successfully retrieved recommendations
        if "status" in recommendations_response and recommendations_response["status"] == "error":
            return {
                "status": "error",
                "message": f"Unable to get recommendations: {recommendations_response['message']}"
            }
        
        # Get the recommendations
        recommendations = recommendations_response.get("recommendations", [])
        
        if not recommendations:
            return {
                "status": "error",
                "message": "I couldn't find any recommendations based on the provided tracks. Please try again with different tracks or adjust your filtering criteria."
            }
        
        # Return the structured data to process
        return {
            "status": "success",
            "seed_tracks": seed_tracks_info,  # This might be empty if direct track_ids were provided
            "seed_track_ids": seed_track_ids,
            "recommendations": recommendations,
            "filter_criteria": filter_criteria,
            "seed_count": len(seed_track_ids),
        }
  • Internal helper function called by recommend_tracks to fetch batch recommendations from the Tidal Flask backend API. Handles validation, HTTP request, error handling, and optional filtering.
    def _get_tidal_recommendations(track_ids: list = None, limit_per_track: int = 20, filter_criteria: str = None) -> dict:
        """
        [INTERNAL USE] Gets raw recommendation data from TIDAL API.
        This is a lower-level function primarily used by higher-level recommendation functions.
        For end-user recommendations, use recommend_tracks instead.
        
        Args:
            track_ids: List of TIDAL track IDs to use as seeds for recommendations.
            limit_per_track: Maximum number of recommendations to get per track (default: 20)
            filter_criteria: Optional string describing criteria to filter recommendations
                             (e.g., "relaxing", "new releases", "upbeat")
        
        Returns:
            A dictionary containing recommended tracks based on seed tracks and filtering criteria.
        """
        try:        
            # Validate track_ids
            if not track_ids or not isinstance(track_ids, list) or len(track_ids) == 0:
                return {
                    "status": "error",
                    "message": "No track IDs provided for recommendations."
                }
                    
            # Call the batch recommendations endpoint
            payload = {
                "track_ids": track_ids,
                "limit_per_track": limit_per_track,
                "remove_duplicates": True
            }
            
            response = requests.post(f"{FLASK_APP_URL}/api/recommendations/batch", json=payload)
            
            if response.status_code != 200:
                error_data = response.json()
                return {
                    "status": "error",
                    "message": f"Failed to get recommendations: {error_data.get('error', 'Unknown error')}"
                }
            
            recommendations = response.json().get("recommendations", [])
            
            # If filter criteria is provided, include it in the response for LLM processing
            result = {
                "recommendations": recommendations,
                "total_count": len(recommendations)
            }
            
            if filter_criteria:
                result["filter_criteria"] = filter_criteria
                
            return result
            
        except Exception as e:
            return {
                "status": "error",
                "message": f"Failed to get recommendations: {str(e)}"
            }
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 effectively describes the tool's behavior: it can use either provided track IDs or the user's TIDAL favorites as seeds, returns both seed and recommended tracks, and includes important processing instructions (e.g., not including seed tracks in recommendations, avoiding duplicates). However, it doesn't mention rate limits, authentication needs, or error conditions.

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 and usage guidelines, but it becomes overly verbose with 10 detailed processing instructions for the agent. While some instructions are helpful, others (like formatting requirements and internet search suggestions) exceed what's typically needed in a tool description and could be streamlined.

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 the complexity of a recommendation tool with 4 parameters, no annotations, and no output schema, the description does a good job of explaining the tool's behavior, parameters, and expected usage. It covers the main aspects well, though it could benefit from more detail about the return structure (beyond 'a dictionary containing both the seed tracks and recommended tracks') and any limitations or error cases.

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 in the schema. It provides clear explanations for all four parameters: 'track_ids' (optional seeds), 'filter_criteria' (specific preferences), 'limit_per_track' (recommendations per track), and 'limit_from_favorite' (favorite tracks to use as seeds). The description adds meaningful context beyond the bare parameter names in the schema.

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: 'Recommends music tracks based on specified track IDs or can use the user's TIDAL favorites if no IDs are provided.' This specifies the verb ('recommends'), resource ('music tracks'), and distinguishes it from sibling tools like 'get_favorite_tracks' or 'create_tidal_playlist' which have different functions.

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 guidance on when to use this tool with a bulleted list of user request scenarios (e.g., 'Music recommendations', 'Track suggestions', 'What should I listen to?'). It also distinguishes usage from alternatives by specifying this is for recommendations based on track IDs or favorites, unlike sibling tools that manage playlists or retrieve favorites directly.

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