cd /news/artificial-intelligence/harmonic-mixing-over-mcp-the-dj-set-… Β· home β€Ί topics β€Ί artificial-intelligence β€Ί article
[ARTICLE Β· art-58895] src=dev.to β†— pub= topic=artificial-intelligence verified=true sentiment=↑ positive

Harmonic mixing over MCP: the DJ set-builder Spotify never shipped

FreqBlog rebuilt Spotify's deprecated Audio Features, Recommendations, and Related Artists endpoints and added a DJ set-builder with harmonic mixing over MCP. The API exposes pairwise transition scoring, next-track ranking, and full setlist ordering around the Camelot wheel, accessible via REST or MCP for LLMs and agents.

read5 min views1 publishedJul 14, 2026

When Spotify deprecated Audio Features, Recommendations, and Related Artists for new apps in November 2024, a wave of "drop-in replacement" APIs appeared. Most stop at parity: you send a track, you get BPM, key and energy back. Useful β€” but that's the same lookup Spotify already gave you.

FreqBlog went a layer further. It rebuilt the dead endpoints, then shipped the thing Spotify never had: a set-builder. Pairwise transition scoring, next-track ranking, and full setlist ordering around the Camelot wheel. And the whole surface is exposed over an MCP server, so an LLM or agent can plan a DJ set by calling tools directly β€” no glue code between the model and the music theory.

This is for people building music or AI tooling. I'll show the harmonic-mixing model concretely, then call it two ways: plain REST and MCP.

Before the interesting part, the boring-but-necessary drop-ins:

GET /recommendations

(and the MCP tool get_recommendations

) β€” the replacement for the removed /v1/recommendations

, re-ranked by genre affinity so a feature-close cross-genre track can't outrank same-genre picks.GET /related-artists

β€” replaces the killed related-artists endpoint.GET /v1/audio-features/{id}

returns a bare Spotify AudioFeaturesObject

; GET /v1/audio-features?ids=

returns the {"audio_features":[...]}

array envelope. Both mirror Spotify's own shapes, so porting existing code is a small diff.The native lookup is flatter and richer. GET /lookup

resolves a track by name, ISRC, MusicBrainz ID or Spotify ID and returns one flat object β€” over 40 fields, no nesting:

curl -s "https://api.freqblog.com/lookup?track=Strobe&artist=deadmau5&wait=10" \
  -H "X-Api-Key: $FREQBLOG_KEY"
// shape (values illustrative) β€” every feature is top-level, no "audio_features" wrapper
{
  "track_name": "Strobe",
  "artist_name": "deadmau5",
  "bpm": 128.0,
  "key": "B",
  "camelot": "1A",
  "mode": "minor",
  "energy": 0.61,
  "danceability": 0.72,
  "valence": 0.35,
  "genre": "progressive house"
}

Two things worth knowing: bpm

and key

are always present and non-null, and ?wait=10

opts into a bounded synchronous mode β€” up to 25 seconds β€” that returns the analysed track inline as a 200

instead of the default 202 + Retry-After

when a track isn't cached yet.

Every musical key maps to a clock position on the Camelot wheel: a number 1

–12

plus a letter (A

= minor, B

= major). Two tracks mix without a key clash when they sit next to each other on the wheel: the same key, the relative major/minor (same number, flipped letter), or the adjacent +1

/-1

neighbours. Jump +7

and you get the classic energy-boost mix.

find_compatible_keys

is pure theory β€” no catalog hit, zero quota:

// find_compatible_keys(camelot="8A", extended=true)
{
  "camelot": "8A",
  "compatible": [
    { "camelot": "8A", "relation": "same" },
    { "camelot": "8B", "relation": "relative" },      // minor <-> major
    { "camelot": "7A", "relation": "adjacent_down" }, // -1
    { "camelot": "9A", "relation": "adjacent_up" },   // +1
    { "camelot": "3A", "relation": "energy_boost" },  // +7  (extended=true)
    { "camelot": "1A", "relation": "energy_drop" }    // -7  (extended=true)
  ]
}

Knowing which keys could mix is table stakes. score_transition

rates how well one real track mixes into another, 0

–100

, blending Camelot key compatibility, octave-aware BPM proximity (half/double-time counts as a match), and energy smoothness β€” and it hands back a human reason:

// score_transition(from_track_id="apple_ad1829eeccb70f9a",
//                  to_track_id="apple_7c1120fbe0")  β€” costs 1 quota
{
  "score": 91,
  "components": { "harmonic": 95, "tempo": 92, "energy": 86 },
  "reason": "8A->9A +1 adjacent, 126->128 BPM (+2.0), energy +0.04"
}

There's no raw key/BPM endpoint anywhere that gives you that β€” the pairwise judgement is the product.

suggest_next_track

takes the track that's playing and returns the top-N catalog tracks to play next, each with the same score, components and reason (e.g. "11B->11B same key, 118->117 BPM (-0.29), energy +0.12"

). It's genre-aware by default, so an off-genre track that only coincidentally shares your key/BPM sinks to the bottom.

build_setlist

orders an entire crate (2–100 tracks) into a beat-matched set that follows an energy arc

β€” peak_time

, warmup

, cooldown

, or flat

β€” keeping every consecutive transition harmonically and tempo-smooth. It returns an overall flow_score

, the tracks in play order, and the per-step transitions.

Here's where it stops being an API and starts being a capability you hand to a model. Point any MCP client at:

https://mcp.freqblog.com/mcp

That exposes twelve tools β€” search_catalog

, get_audio_features

, get_audio_features_batch

, find_tracks_by_bpm

, find_tracks_by_key

, find_compatible_keys

, get_recommendations

, get_related_artists

, score_transition

, suggest_next_track

, build_setlist

, tag_track

. The agent orchestrates them itself. A single prompt like "build me a 90-minute peak-time set from these ten tracks" becomes:

search_catalog

on each fuzzy name β†’ concrete itunes_track_id

sbuild_setlist(track_ids=[...], arc="peak_time")

β†’ ordered set + flow_score

itunes_track_id

s to GET /export/rekordbox

(also traktor

, m3u

, cuesheet

, csv

) and drop the crate straight into your DJ softwareNo orchestration code on your side β€” the tool descriptions carry enough for the model to chain them. The set-builder tools cost a little more quota than a plain lookup (score_transition

1, get_recommendations

2, suggest_next_track

3, build_setlist

5), because each one is doing real combinatorial work.

Auth is an X-Api-Key

header (a ?key=

query fallback exists for browser and email links). Everything above is also available as plain REST β€” GET /transition

, GET /next-track

, POST /setlist

, GET /similar?track_id=...

β€” if you'd rather not run an MCP client. It's on RapidAPI too. Pricing starts at Β£0.17/1k, and the free tier is 1,000 requests/month, which is plenty to prototype a set planner.

itunes_track_id

s, so a track has to resolve first (search_catalog

/ /lookup

). Coverage is deep but not universal β€” niche or regional catalogs have holes./analyze

and /identify

β€” not the audio itself.Grab a free key and the OpenAPI docs at ** api.freqblog.com/docs**, or read more about the API on

── more in #artificial-intelligence 4 stories Β· sorted by recency
── more on @freqblog 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/harmonic-mixing-over…] indexed:0 read:5min 2026-07-14 Β· β€”