commendation
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| RECOM_GRAPH | No | Set 0 to disable the music graph and use native signals only. | 1 |
| RECOM_DB_PATH | No | Mood index, labels, history, feedback. Scoped per backend - Spotify uses store-spotify.db. | ~/.recom/store.db |
| RECOM_PROVIDER | No | Which backend provider to use. Defaults to youtube; set to spotify to use the Spotify backend. | youtube |
| RECOM_CACHE_TTL | No | How long a cached set stays usable (seconds). Set to 0 to disable caching. | 21600 |
| RECOM_CACHE_PATH | No | Where the cached library exclusion set lives. | ~/.recom/library_cache.json |
| RECOM_JUDGE_BATCH | No | Songs per labelling request. | 12 |
| RECOM_JUDGE_MODEL | No | Model for lyric-based labelling. | claude-opus-5 |
| RECOM_JUDGE_EFFORT | No | Effort level for that labelling. | low |
| RECOM_SEED_WORKERS | No | How many seeds are gathered concurrently. | 6 |
| RECOM_GRAPH_DB_PATH | No | The music-graph cache. Shared by every backend. | ~/.recom/graph.db |
| RECOM_SPOTIFY_MCP_ARGS | No | Path to spotify-mcp's server.py. Required for the Spotify backend. | |
| RECOM_YTMUSIC_MCP_ARGS | No | Path to ytmusic-mcp's server.py. Required for the YouTube Music backend. | |
| RECOM_SPOTIFY_MCP_COMMAND | No | Path to the Python interpreter for the spotify-mcp server. Required for the Spotify backend. | |
| RECOM_YTMUSIC_MCP_COMMAND | No | Path to the Python interpreter for the ytmusic-mcp server. Required for the YouTube Music backend. | |
| RECOM_SPOTIFY_CAPABILITIES | No | Comma-separated radio,related,artist to re-enable Spotify's native signals if your app has Extended Quota Mode. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| recommend_from_songA | Recommend new songs similar to a seed song. Seed the search either with a known Combines YouTube Music's radio, its separate "related" signal, and the seed artist's own catalog plus related artists' catalogs, then ranks by how many independent signals agreed on each candidate. Never returns the seed song itself, and never returns a song already in Liked Music or in ANY of the user's playlists. By default candidates can come from OTHER artists too (radio/related
signals surface stylistically similar tracks, not just the seed artist's
own catalog) -- pass
When a language filter leaves too few results -- seeding from a Punjabi song and asking for English usually does -- the surviving songs are used as fresh seeds to reach more of that language in the same neighbourhood, since filtering alone can only return what happened to be in the seed's own pool. Set expand_across_language=False to skip that and get the short list.
Returns {"songs": [...], "notes": [...], "filters": {...}} -- notes carry anything the user should hear about, such as results dropped for having no language label. The library exclusion set is cached for speed; newly liked songs are always honoured, but call refresh_library() after adding songs to a playlist by other means. |
| recommend_from_playlistA | Recommend new songs based on an entire playlist. Randomly samples up to seed_sample_size tracks from the playlist as seeds (the whole playlist if it's smaller), runs the same multi-signal candidate generation as recommend_from_song for each, and pools/ranks the results. Never returns a song already in Liked Music, already in the source playlist, or already in ANY other of the user's playlists. The library exclusion set is cached for speed; newly liked songs are always honoured, but call refresh_library() after adding songs to a playlist by other means. |
| songs_by_artistA | Return actual songs by a specific artist -- a direct catalog pull, not a similarity recommendation like recommend_from_song/recommend_from_playlist. Resolves This is a hard requirement, not best-effort -- if fewer than Remix/feature variants of the same underlying song (e.g. a track and its
"(feat. ...)" credit under a different videoId) count once, not once
per variant -- see The library exclusion set is cached for speed; newly liked songs are always honoured, but call refresh_library() after adding songs to a playlist by other means. |
| refresh_libraryA | Rebuild the cached library exclusion set from scratch, right now. Every recommendation tool excludes songs already in Liked Music or any of your playlists. That set is expensive to build (~20s), so it's cached and reused. Liking a song is picked up immediately regardless, but adding a song to some other playlist is only seen once the cache is rebuilt. Call this after adding songs to a playlist by other means (e.g. a playlist-management tool) if you want the next recommendation to account for them without waiting out the cache TTL. |
| recommend_for_moodA | Recommend new songs that match how the listener actually feels right now. Unlike recommend_from_song, the mood decides where candidates come from: seeds are drawn from the listener's OWN library nearest the target mood, then expanded through radio/related/artist signals and songs from YouTube's mood playlists. Results are still guaranteed absent from their library. Describing the mood -- in priority order:
If they also point at a specific playlist ("look at this playlist and recommend me songs for how I feel"), use recommend_from_playlist_for_mood instead -- it seeds from that playlist's own fitting tracks rather than from the whole library. This is READ-ONLY. If they asked for a PLAYLIST rather than a list, this tool is step one of three: get the songs here, create the playlist from the returned videoIds with a playlist-management tool, then call refresh_library() so those tracks are excluded from later recommendations. The result carries |
| recommend_from_playlist_for_moodA | Recommend new songs from ONE playlist, shaped by how the listener feels. For "I feel like this -- look at this playlist and find me songs". Use this over recommend_from_playlist whenever a mood is part of the ask, and over recommend_for_mood whenever a specific playlist is. Unlike recommend_from_playlist, which samples a few tracks at random and ignores mood entirely: EVERY track in the playlist is read and scored for mood fit, and only genuine matches -- tracks whose own mood resolves and actually fits the target -- are used as seeds. An off-mood playlist therefore yields few seeds or none, which is reported rather than papered over by seeding from tracks that don't fit. Seeding costs ~4 API calls per seed, so the best-fitting seeds are capped
(default 20, override with Mood arguments behave exactly as in recommend_for_mood ( This is READ-ONLY -- it never creates a playlist or adds anything anywhere. To turn the result into a real playlist, pass the returned videoIds to a playlist-management tool, then call refresh_library() so the new tracks are excluded from later recommendations. |
| read_my_moodA | Infer the listener's current mood from recent listening, with evidence. Returns the inferred Lead with the evidence, not the verdict. "You've had these three on loop since yesterday -- want something that sits there with you, or something that lifts?" is the point of this tool; asserting "you are sad" is not. Mood inference is often wrong, so offer it as a read the user can correct. |
| explain_recommendationA | Explain why a song was recommended, in mood terms. Reports the song's mood vector, which layer produced it (Claude reading the lyrics, YouTube mood-playlist membership, or the artist's own average), the named moods it sits closest to, and the mood it was last served against. |
| record_feedbackB | Record what the listener thought of a recommendation.
|
| index_statusA | Report how much of the mood index exists, so gaps are visible not silent. Covers the mood-playlist crawl, how much of the listener's library carries a mood label and from which layer, and whether Claude-based labelling is configured. Low coverage means recommendations are ranking mostly on signal agreement rather than on mood -- worth saying out loud. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 10 tools
Tool names and descriptions clearly delineate purposes: recommend_from_song seeds by a song, recommend_from_playlist seeds by playlist, recommend_for_mood uses mood, recommend_from_playlist_for_mood combines both. songs_by_artist and explain_recommendation are distinct. Minor potential confusion between recommend_from_playlist_for_mood and recommend_for_mood, but descriptions explicitly guide selection.
All tool names follow a consistent verb_noun pattern (recommend_from_song, read_my_mood, record_feedback, etc.) with snake_case throughout, no deviations.
10 tools provide a well-scoped set covering recommendation generation, library management, feedback, mood reading, explanation, and status—each earns its place without excess.
Comprehensive lifecycle coverage: multiple recommendation entry points (by song, playlist, mood, playlist+mood), library refresh, mood inference, feedback recording, explanation, and index status. No obvious gaps for a music recommendation system.