Files
mcp-spotify/docs/superpowers/plans/2026-05-25-bpm-enrichment.md
2026-05-25 21:34:23 +02:00

5.9 KiB

BPM Enrichment Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add a bpm field (tempo from Spotify audio-features) to every track object returned by the MCP server.

Architecture: A private _enrich_with_bpm(sp, tracks) helper in spotify_client.py batch-fetches audio features for a list of parsed track dicts (100 IDs per API call) and adds a bpm field in place. Each of the three track-returning functions stores the track id during parsing, then calls this helper before returning.

Tech Stack: Python 3.11+, spotipy (sp.audio_features()), no new dependencies.


Task 1: Add _enrich_with_bpm helper

Files:

  • Modify: spotify_client.py — add helper after _format_duration

  • Step 1: Add the helper function

In spotify_client.py, insert the following function immediately after _format_duration (around line 58):

def _enrich_with_bpm(sp: spotipy.Spotify, tracks: list[dict]) -> None:
    ids = [t["id"] for t in tracks]
    for i in range(0, len(ids), 100):
        chunk_ids = ids[i : i + 100]
        features = sp.audio_features(chunk_ids)
        for track, feat in zip(tracks[i : i + 100], features):
            track["bpm"] = round(feat["tempo"], 1) if feat else None
  • Step 2: Verify syntax
cd /Users/kriss/Dev/scm/scm.vilanet.fr/kriss/mcp-spotify
.venv/bin/python -c "import spotify_client; print('OK')"

Expected: OK


Task 2: Add id field and BPM enrichment to get_playlist_tracks

Files:

  • Modify: spotify_client.py:get_playlist_tracks

  • Step 1: Add "id" to the track dict and call the helper

In get_playlist_tracks, add "id": track["id"], to the results.append({...}) block (alongside "uri"), and add _enrich_with_bpm(sp, results) just before the return statement:

            results.append({
                "name": track["name"],
                "artists": [a["name"] for a in track["artists"]],
                "album": track["album"]["name"],
                "duration_ms": track["duration_ms"],
                "duration": _format_duration(track["duration_ms"]),
                "popularity": track.get("popularity"),
                "id": track["id"],
                "uri": track["uri"],
                "added_at": item["added_at"],
            })
        page += 1
        response = sp.next(response) if response["next"] else None
    _enrich_with_bpm(sp, results)
    _dbg(f"get_playlist_tracks returning {len(results)} tracks")
    return results
  • Step 2: Smoke test
SPOTIPY_CLIENT_ID=d66baed203d1461a860acbc5db27e3f5 \
SPOTIPY_CLIENT_SECRET=6d9ccf95957749ffac433919b585f4ff \
SPOTIPY_REDIRECT_URI=http://127.0.0.1:8888/callback \
.venv/bin/python -c "
import spotify_client, json
tracks = spotify_client.get_playlist_tracks('7LhqpCM88rPqDqxTLadLmf')
for t in tracks[:3]:
    print(t['name'], '|', t.get('bpm'), 'bpm')
" 2>/dev/null

Expected: 3 lines like oh baby | 128.0 bpm


Task 3: Add id field and BPM enrichment to list_saved_tracks

Files:

  • Modify: spotify_client.py:list_saved_tracks

  • Step 1: Add "id" to the track dict and call the helper

In list_saved_tracks, add "id": track["id"], to the results.append({...}) block, and add _enrich_with_bpm(sp, results) just before the return statement:

            results.append({
                "name": track["name"],
                "artists": [a["name"] for a in track["artists"]],
                "album": track["album"]["name"],
                "duration_ms": track["duration_ms"],
                "duration": _format_duration(track["duration_ms"]),
                "popularity": track["popularity"],
                "id": track["id"],
                "uri": track["uri"],
                "added_at": item["added_at"],
            })
    _enrich_with_bpm(sp, results)
    return results
  • Step 2: Smoke test
SPOTIPY_CLIENT_ID=d66baed203d1461a860acbc5db27e3f5 \
SPOTIPY_CLIENT_SECRET=6d9ccf95957749ffac433919b585f4ff \
SPOTIPY_REDIRECT_URI=http://127.0.0.1:8888/callback \
.venv/bin/python -c "
import spotify_client
tracks = spotify_client.list_saved_tracks(limit=3)
for t in tracks:
    print(t['name'], '|', t.get('bpm'), 'bpm')
" 2>/dev/null

Expected: 3 lines with bpm values.


Task 4: Add id field and BPM enrichment to search_tracks

Files:

  • Modify: spotify_client.py:search_tracks

  • Step 1: Add "id" to the track dict and call the helper

In search_tracks, add "id": track["id"], to the results.append({...}) block, and add _enrich_with_bpm(sp, results) just before the return statement:

    for track in response["tracks"]["items"]:
        results.append({
            "name": track["name"],
            "artists": [a["name"] for a in track["artists"]],
            "album": track["album"]["name"],
            "duration_ms": track["duration_ms"],
            "duration": _format_duration(track["duration_ms"]),
            "popularity": track["popularity"],
            "id": track["id"],
            "uri": track["uri"],
        })
    _enrich_with_bpm(sp, results)
    return results
  • Step 2: Smoke test
SPOTIPY_CLIENT_ID=d66baed203d1461a860acbc5db27e3f5 \
SPOTIPY_CLIENT_SECRET=6d9ccf95957749ffac433919b585f4ff \
SPOTIPY_REDIRECT_URI=http://127.0.0.1:8888/callback \
.venv/bin/python -c "
import spotify_client
tracks = spotify_client.search_tracks('LCD Soundsystem', limit=3)
for t in tracks:
    print(t['name'], '|', t.get('bpm'), 'bpm')
" 2>/dev/null

Expected: 3 lines with bpm values.


Task 5: Commit

  • Commit all changes
git add spotify_client.py
git commit -m "feat: add bpm field to all track-returning tools via audio-features endpoint"