Skip to main content
Glama

FreqBlog Music Metadata

Get Recommendations

get_recommendations
Read-only

Recommended tracks for one or more seed tracks — the drop-in for Spotify's removed GET /v1/recommendations. Blends up to 5 catalog seed tracks into a single point in audio-feature space and returns the nearest catalogue tracks, RE-RANKED by genre affinity (so a feature-close cross-genre track doesn't outrank same-genre picks).

Returns `seeds` (each {id, found}), `count`, and `tracks` (each {track, score,
genre_relation}; each track carries its `genre`). `genre_relation` is "same", "compatible"
(different but mixable family), "cross" (unrelated), or "unknown" (either side has no mapped
genre), measured against the PRIMARY seed — the first of your seed_tracks we could actually
use, so reordering seed_tracks changes it and a skipped seed never becomes the reference.
With a SINGLE seed the field is the ranking's own verdict, so it explains the order (same as
suggest_next_track). With SEVERAL seeds the ranking considers ALL of them while the label stays
relative to your primary seed, so a "cross" label on a multi-seed call does NOT mean the track
was pushed down — it may share a family with another of your seeds. `score` is the raw
audio-feature cosine similarity in [0,1]; genre affinity influences the ORDER, not the score,
so the list is NOT strictly score-descending.
Use cross_genre=strict to return same-genre-family tracks ONLY (off-genre dropped
server-side), or allow to disable the genre ranking. seed_tracks are catalog itunes_track_ids
from search_catalog or the itunes_track_id field of a get_audio_features result.

NO id? Pass `track` (+ optional `artist`) instead and we resolve the name to the best catalog
match and seed on it — the resolved track is echoed back as `seed_query`; seed_tracks wins if
both are given.

TUNING: `min`/`max` are HARD filters and `target` is a preference (nearer ranks higher,
nothing removed), over acousticness, danceability, duration_ms, energy,
loudness, tempo and valence. NOTE: `popularity` (2026-08-27), `liveness`, `speechiness`
(2026-09-26) and `instrumentalness` (2026-09-27) are RETIRED as tunables and return a 400 —
popularity recorded how a track entered our catalogue, not audience size; the other three
are returned as null for catalogue tracks. Values are FreqBlog's own (not Spotify's):
energy and valence (models of how energetic / positive the preview sounds) on our own scales, danceability/acousticness on AcousticBrainz's scale —
derive thresholds from our values rather than reusing Spotify-tuned ones. e.g. min={"tempo": 100},
max={"tempo": 130}, target={"energy": 0.8} for energetic 100-130 BPM tracks. When you tune,
the response adds a `filters` block saying what applied, how many tracks each bound removed
(`dropped_by`) and whether the bounds ran out of catalogue before `limit` (`limit_reached`)
— if the list comes back short, read that BEFORE assuming the catalogue is thin.
Costs 2 quota units.

Input Schema

NameRequiredDescriptionDefault
maxNoHARD upper bounds, e.g. {'tempo': 130}. Same attributes as `min`. Combine the two for a range.
minNoHARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, loudness, tempo, valence.
limitNoNumber of recommendations to return (default 20).
trackNoSeed by track NAME instead of an id — resolved to the best catalog match (echoed back as seed_query). Pair with artist to disambiguate. Ignored when seed_tracks is given.
artistNoArtist name narrowing the track seed (case-insensitive).
targetNoPREFERRED values, e.g. {'energy': 0.8}. Tracks nearer the value rank higher; unlike min/max nothing is removed. Same attributes as `min`.
cross_genreNoGenre handling (mirrors suggest_next_track): 'auto' (default) re-ranks by genre affinity so a feature-close cross-genre track can't outrank same-genre picks; 'strict' = same genre-family only (off-genre dropped server-side); 'allow' = genre-blind (pure audio-feature cosine).auto
seed_tracksNo1-5 catalog itunes_track_ids to base recommendations on, e.g. ['apple_ad1829eeccb70f9a'] (blended into a feature-space centroid). Omit and use track(+artist) to seed by name instead.
exclude_seed_artistsNoDrop tracks by any of the seed artists (default false).

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / min / description
      Previous value: -"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, loudness, tempo, valence."New value: +"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, loudness, tempo, valence."
  2. Changed1 schema field changed
    • changedInput schema / properties / min / description
      Previous value: -"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, loudness, speechiness, tempo, valence."New value: +"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, loudness, tempo, valence."
  3. Changed1 schema field changed
    • changedInput schema / properties / min / description
      Previous value: -"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, liveness, loudness, speechiness, tempo, valence."New value: +"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, loudness, speechiness, tempo, valence."
  4. Changed1 schema field changed
    • changedInput schema / properties / min / description
      Previous value: -"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, liveness, loudness, popularity, speechiness, tempo, valence."New value: +"HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, liveness, loudness, speechiness, tempo, valence."
  5. Changed3 schema fields changed
    • addedInput schema / properties / max
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": {
      +        "type": "number"
      +      },
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "HARD upper bounds, e.g. {'tempo': 130}. Same attributes as `min`. Combine the two for a range.",
      +  "title": "Max"
      +}
    • addedInput schema / properties / min
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": {
      +        "type": "number"
      +      },
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "HARD lower bounds, e.g. {'tempo': 100, 'energy': 0.5}. Tracks below the bound — and tracks we hold no analysed value for — are dropped. Attributes: acousticness, danceability, duration_ms, energy, instrumentalness, liveness, loudness, popularity, speechiness, tempo, valence.",
      +  "title": "Min"
      +}
    • addedInput schema / properties / target
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": {
      +        "type": "number"
      +      },
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "PREFERRED values, e.g. {'energy': 0.8}. Tracks nearer the value rank higher; unlike min/max nothing is removed. Same attributes as `min`.",
      +  "title": "Target"
      +}
  6. Changed10 schema fields changed
    • addedInput schema / properties / artist
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 200,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Artist name narrowing the track seed (case-insensitive).",
      +  "title": "Artist"
      +}
    • addedInput schema / properties / seed_tracks / anyOf
      Added value: +[
      +  {
      +    "items": {
      +      "type": "string"
      +    },
      +    "maxItems": 5,
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / properties / seed_tracks / default
      Added value: +null
    • changedInput schema / properties / seed_tracks / description
      Previous value: -"1-5 catalog itunes_track_ids to base recommendations on, e.g. ['apple_ad1829eeccb70f9a'] (blended into a feature-space centroid)."New value: +"1-5 catalog itunes_track_ids to base recommendations on, e.g. ['apple_ad1829eeccb70f9a'] (blended into a feature-space centroid). Omit and use track(+artist) to seed by name instead."
    • removedInput schema / properties / seed_tracks / items
      Removed value: -{
      -  "type": "string"
      -}
    • removedInput schema / properties / seed_tracks / maxItems
      Removed value: -5
    • removedInput schema / properties / seed_tracks / minItems
      Removed value: -1
    • removedInput schema / properties / seed_tracks / type
      Removed value: -"array"
    • addedInput schema / properties / track
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 200,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Seed by track NAME instead of an id — resolved to the best catalog match (echoed back as seed_query). Pair with artist to disambiguate. Ignored when seed_tracks is given.",
      +  "title": "Track"
      +}
    • removedInput schema / required
      Removed value: -[
      -  "seed_tracks"
      -]
  7. Changed1 schema field changed
    • addedInput schema / properties / cross_genre
      Added value: +{
      +  "default": "auto",
      +  "description": "Genre handling (mirrors suggest_next_track): 'auto' (default) re-ranks by genre affinity so a feature-close cross-genre track can't outrank same-genre picks; 'strict' = same genre-family only (off-genre dropped server-side); 'allow' = genre-blind (pure audio-feature cosine).",
      +  "title": "Cross Genre",
      +  "type": "string"
      +}
  8. Added

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only declare readOnlyHint and openWorldHint; the description adds materially more: quota cost (2 units), server-side dropping in strict mode, the fact that ordering is not score-descending, 400 outcomes for retired tunables, value-scale provenance (own scales vs AcousticBrainz vs Spotify-tuned), and the filters/dropped_by/limit_reached diagnostic block. That is far beyond what annotations convey and directly shapes how an agent interprets a short list.

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

Conciseness4/5

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

Front-loaded and organized under implicit headings (seeding, return shape, TUNING), with no filler sentences. It is long, and the multi-seed genre_relation paragraph is dense enough to slow reading, though the ambiguity it resolves (a 'cross' label not implying demotion on multi-seed calls) is genuinely non-obvious. Slightly overlength for its purpose, but nearly every sentence earns its place.

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?

For a 9-parameter tool with zero required params, an output schema, and a non-obvious ranking algorithm, this covers what an agent needs: seeding fallbacks, genre-mode behavior, filter semantics, cost, error cases, and how to read the response when results are short. Nothing material is left to inference.

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?

Schema coverage is 100%, but the description still adds meaning the schema cannot: min/max are HARD filters that also drop unanalysed tracks while target is a non-removing preference, the retired attributes and why (popularity measured catalogue entry, others null for catalogue tracks), and the instruction to derive thresholds from FreqBlog's scales rather than Spotify's, with a concrete min/max/target example.

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?

Opens with a specific verb+resource and scope ('Recommended tracks for one or more seed tracks'), then immediately positions itself against the removed Spotify endpoint and against siblings like suggest_next_track and search_catalog, which are named as the source of seed ids. An agent can distinguish this from build_setlist, suggest_next_track or find_tracks_by_bpm without opening any schema.

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?

Explicitly states the two seeding routes (seed_tracks ids vs track(+artist) name resolution), the precedence rule when both are given, the three cross_genre modes with when to pick each, and where the ids come from (search_catalog, get_audio_features). It also names the exclusion condition (retired tunables -> 400) and the sibling whose genre semantics it mirrors (suggest_next_track).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources