Skip to main content
Glama
keenanbb

TIDAL MCP Server

by keenanbb

get_artist_top_tracks

Retrieve an artist's most popular tracks from TIDAL by providing the artist ID and optional limit.

Instructions

Get an artist's most popular tracks.

Args: artist_id: ID of the artist limit: Maximum tracks to return (default: 10, max: 50)

Returns: List of the artist's top tracks

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
artist_idYes
limitNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
countYesNumber of tracks returned
queryNoSearch query used (for search results)
statusYesOperation status (success/error)
tracksYesList of track objects

Implementation Reference

  • The core handler function for the 'get_artist_top_tracks' tool. Decorated with @mcp.tool() for registration in FastMCP. Fetches artist details, retrieves top tracks via TidalAPI's artist.get_top_tracks(), maps to Track models, and returns a TrackList response. Includes authentication check and error handling.
    @mcp.tool()
    async def get_artist_top_tracks(artist_id: str, limit: int = 10) -> TrackList:
        """
        Get an artist's most popular tracks.
    
        Args:
            artist_id: ID of the artist
            limit: Maximum tracks to return (default: 10, max: 50)
    
        Returns:
            List of the artist's top tracks
        """
        if not await ensure_authenticated():
            raise ToolError("Not authenticated. Please run the 'login' tool first.")
    
        try:
            limit = min(max(1, limit), 50)
    
            artist = await anyio.to_thread.run_sync(session.artist, artist_id)
            if not artist:
                raise ToolError(f"Artist with ID '{artist_id}' not found")
    
            top_tracks = await anyio.to_thread.run_sync(
                lambda: artist.get_top_tracks(limit=limit)
            )
    
            tracks = []
            for track in top_tracks:
                tracks.append(
                    Track(
                        id=str(track.id),
                        title=track.name,
                        artist=track.artist.name if track.artist else artist.name,
                        album=track.album.name if track.album else "Unknown Album",
                        duration_seconds=track.duration,
                        url=f"https://tidal.com/browse/track/{track.id}",
                    )
                )
    
            return TrackList(
                status="success",
                count=len(tracks),
                tracks=tracks,
            )
        except ToolError:
            raise
        except Exception as e:
            raise ToolError(f"Failed to get artist top tracks: {str(e)}")
  • Pydantic model defining the output schema for get_artist_top_tracks and other track list responses. Used as return type annotation in the handler.
    class TrackList(BaseModel):
        """List of tracks with metadata."""
    
        status: str = Field(description="Operation status (success/error)")
        query: Optional[str] = Field(None, description="Search query used (for search results)")
        count: int = Field(description="Number of tracks returned")
        tracks: List[Track] = Field(description="List of track objects")
  • Pydantic model for individual Track objects used in TrackList responses by get_artist_top_tracks.
    class Track(BaseModel):
        """Structured representation of a TIDAL track."""
    
        id: str = Field(description="Unique TIDAL track ID")
        title: str = Field(description="Track title")
        artist: str = Field(description="Primary artist name")
        album: str = Field(description="Album name")
        duration_seconds: int = Field(description="Track duration in seconds")
        url: str = Field(description="TIDAL web URL for the track")
  • Tool description listed in SERVER_INSTRUCTIONS markdown, which is passed to FastMCP constructor to inform the model of available tools.
    - get_artist_top_tracks: Get an artist's most popular tracks
Behavior2/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 mentions that it returns a list of top tracks but fails to describe key traits like whether this is a read-only operation (implied by 'Get'), potential rate limits, authentication requirements, or how popularity is determined (e.g., based on streams or charts). This leaves significant gaps for an AI agent.

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

Conciseness5/5

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

The description is front-loaded with the core purpose in the first sentence, followed by structured Args and Returns sections. Every sentence earns its place by providing essential information without redundancy, making it highly efficient and well-organized.

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

Completeness3/5

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

Given the tool's low complexity (2 parameters, no nested objects) and the presence of an output schema (which handles return values), the description is moderately complete. It covers the basic purpose and parameters but lacks behavioral context like authentication needs or error handling, which is a notable gap since no annotations are provided.

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?

The schema description coverage is 0%, so the description must compensate. It adds meaningful semantics for both parameters: artist_id is explained as 'ID of the artist', and limit includes details on default (10) and max (50) values, which are not in the schema. However, it doesn't specify the format or source of artist_id (e.g., Spotify ID), leaving some ambiguity.

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 specific action ('Get') and resource ('artist's most popular tracks'), distinguishing it from sibling tools like get_artist_albums or get_artist_radio. It precisely defines what the tool retrieves without being vague or tautological.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like get_artist_albums, get_artist_radio, or search_tracks. It lacks context about prerequisites, such as whether the artist must exist or be accessible, and offers no explicit when-not-to-use scenarios.

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

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