Skip to main content
Glama
jamiew

Spotify MCP Server

get_audio_features

Retrieve audio analysis data for Spotify tracks including tempo, key, energy, danceability, and other musical characteristics. Analyze up to 100 tracks in a single API call to understand their sonic properties.

Instructions

Get audio features for one or more tracks (tempo, key, energy, danceability, etc).

Args:
    track_ids: Single track ID or list of track IDs (up to 100)

Returns:
    Dict with 'features' list containing audio features for each track.
    Features include: tempo, key, mode, time_signature, danceability, energy,
    valence, loudness, speechiness, acousticness, instrumentalness, liveness.

Note: Batch lookup is efficient - 100 tracks = 1 API call.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
track_idsYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The handler function for the 'get_audio_features' tool. Registered via @mcp.tool() decorator. Normalizes input track IDs, calls Spotify API's audio_features endpoint, parses results using AudioFeatures Pydantic model, and returns structured features data.
    @mcp.tool()
    @log_tool_execution
    def get_audio_features(track_ids: str | list[str]) -> dict[str, Any]:
        """Get audio features for one or more tracks (tempo, key, energy, danceability, etc).
    
        Args:
            track_ids: Single track ID or list of track IDs (up to 100)
    
        Returns:
            Dict with 'features' list containing audio features for each track.
            Features include: tempo, key, mode, time_signature, danceability, energy,
            valence, loudness, speechiness, acousticness, instrumentalness, liveness.
    
        Note: Batch lookup is efficient - 100 tracks = 1 API call.
        """
        try:
            # Normalize to list
            ids = [track_ids] if isinstance(track_ids, str) else track_ids
    
            if len(ids) > 100:
                raise ValueError("Maximum 100 track IDs per request (Spotify API limit)")
    
            logger.info(f"🎼 Getting audio features for {len(ids)} track(s)")
            result = spotify_client.audio_features(ids)
    
            features_list = []
            for features in result:
                if features:
                    audio = AudioFeatures(
                        id=features["id"],
                        tempo=features.get("tempo"),
                        key=features.get("key"),
                        mode=features.get("mode"),
                        time_signature=features.get("time_signature"),
                        danceability=features.get("danceability"),
                        energy=features.get("energy"),
                        valence=features.get("valence"),
                        loudness=features.get("loudness"),
                        speechiness=features.get("speechiness"),
                        acousticness=features.get("acousticness"),
                        instrumentalness=features.get("instrumentalness"),
                        liveness=features.get("liveness"),
                    )
                    features_list.append(audio.model_dump())
    
            return {"features": features_list}
        except SpotifyException as e:
            raise convert_spotify_error(e) from e
  • Pydantic BaseModel defining the schema for audio features data returned by the tool. Used to structure and validate the output from Spotify's audio_features API.
    class AudioFeatures(BaseModel):
        """Audio features for a track."""
    
        id: str
        tempo: float | None = None
        key: int | None = None
        mode: int | None = None
        time_signature: int | None = None
        danceability: float | None = None
        energy: float | None = None
        valence: float | None = None
        loudness: float | None = None
        speechiness: float | None = None
        acousticness: float | None = None
        instrumentalness: float | None = None
        liveness: float | None = None
  • The @mcp.tool() decorator registers the get_audio_features function as an MCP tool, using the function name as the tool name.
    @mcp.tool()
Behavior4/5

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

With no annotations provided, the description carries full burden and does well: it discloses the batch capability (up to 100 tracks) and efficiency note (100 tracks = 1 API call), which are valuable behavioral traits beyond basic functionality. It doesn't cover error handling or rate limits, but gives practical performance context.

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, followed by structured sections (Args, Returns, Note) that efficiently organize information without waste. Every sentence adds value, such as the efficiency note.

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

Completeness5/5

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

Given 1 parameter with no schema descriptions, an output schema exists, and no annotations, the description is complete: it explains the parameter semantics, lists return features, and adds behavioral context (batch efficiency). The output schema handles return structure, so no need to detail format.

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

Parameters5/5

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

The schema has 0% description coverage, so the description must compensate fully. It adds crucial semantics: track_ids can be a single ID or list, with a limit of up to 100 IDs, and explains this enables batch lookup. This goes well beyond the bare schema definition.

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 audio features') and resource ('for one or more tracks'), with explicit examples of the features returned (tempo, key, energy, etc.). It distinguishes from siblings like get_track_info (which likely provides metadata, not audio analysis) by focusing on acoustic characteristics.

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

Usage Guidelines4/5

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

The description provides clear context for when to use this tool (to retrieve audio features like tempo, danceability) and implies batch efficiency. However, it does not explicitly state when not to use it or name specific alternatives among siblings (e.g., get_track_info for non-audio data).

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

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