encore
Provides personalized music search and recommendation tools powered by Last.fm listening data, including plays, tags, and friend relationships, exposed as agent-callable MCP tools for artist discovery and recommendation.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
encore
Personalized music search and recommendation, measured. Seven recommenders and a learning-to-rank search stack, run on real Last.fm listening data. The evaluation is leak-free and reports confidence intervals and significance tests. The winning stack is served over HTTP and as MCP tools that an LLM agent can call.
Headline results
Question | Answer (held-out test data, 3 random splits) |
Does personalizing search help? | NDCG@10 0.524 vs 0.376 for the same LambdaMART ranker without personal features: +40.7% [95% CI +38.0%, +43.4%], p < 1e-260, 5,493 queries |
vs. a typical "lexical + popularity" search baseline? | +110% NDCG@10 (0.524 vs 0.248) |
Where does it help most? | Broad queries such as "rock" or "electronic": 0.211 vs 0.039 NDCG@10 (5.4×) |
Best recommender? | LightGCN with the friend graph, NDCG@10 0.279 ± 0.005. EASE reaches 98% of that and trains about 100× faster (0.6 s vs 63 s) |
Do friends help? | In recommendation, slightly: +1.7% [+0.4%, +3.1%], p = 0.03. In search, no: −0.1%, p = 0.94 |
Is it fast enough to serve? | Full search stack (retrieve 200 → 12 features → LambdaMART): p50 0.79 ms, p99 1.44 ms per query on a laptop CPU |

Related MCP server: mcp-spotify
What's here
flowchart LR
D[Last.fm HetRec 2011<br/>plays · tags · friends] --> S[per-user 70/10/20 split<br/>×3 seeds]
S --> R[7 recommenders<br/>MostPop · ItemKNN · EASE · iALS<br/>BPR-MF · LightGCN · LightGCN+Social]
S --> T[tag index + BM25<br/>held-out tag events removed]
R -->|train-only CF scores| F[12 ranking features]
T --> F
F --> L[LambdaMART<br/>LightGBM lambdarank]
L --> E[Engine]
E --> A[FastAPI]
E --> M[MCP server<br/>5 agent tools]
R & L --> V[metrics · bootstrap CIs<br/>paired Wilcoxon · slices · SHAP]src/encore/models.py: seven recommenders behind onefit/scoreinterface, written from the papers in NumPy and PyTorch. Covers neighbourhood, closed-form linear, confidence-weighted MF, pairwise MF, and graph convolution with an optional social graph.src/encore/search.py: discovery search. Word-level BM25 retrieval over artist tag documents, 12 features (query match, popularity, three CF scores, user taste vs. artist tags, user interest in the query, friends' listening), and LambdaMART re-ranking.src/encore/metrics.py: NDCG / Recall / MRR, coverage, popularity bias, bootstrap CIs, and paired significance tests.src/encore/engine.py,api.py,mcp_server.py: the benchmarked model served as is. Every search result can be explained with per-feature TreeSHAP contributions.tests/: 20 offline tests on a synthetic catalog, including the leakage guards. CI also smoke-runs both benchmarks on the real dataset.docs/METHODOLOGY.mdanddocs/REFERENCES.md: the task definitions, leakage controls, credits, and limitations, written out in full.
Results
All numbers are produced by the scripts and stored in results/. The
full tables, including every paired test and the chosen hyperparameters, are in
results/RESULTS.md.
1. Personalized discovery search
A listener types a genre or mood and wants artists new to them. Queries are top tags of each user's held-out artists. Every ranker sees the same BM25 top-200 candidates, which contain 81% of the relevant artists.
Ranker | Personal signal | NDCG@10 (mean ± std, 3 splits) | Recall@10 | MRR@10 |
BM25 | — | 0.138 ± 0.003 | 0.264 | 0.103 |
BM25 + popularity (tuned) | — | 0.248 ± 0.002 | 0.399 | 0.214 |
CF only (EASE score) | ✓ | 0.296 ± 0.004 | 0.463 | 0.272 |
BM25 + popularity + EASE (tuned linear blend) | ✓ | 0.352 ± 0.003 | 0.519 | 0.327 |
LambdaMART, non-personalized features only | — | 0.376 ± 0.006 | 0.550 | 0.340 |
LambdaMART, no CF features | ✓ | 0.486 ± 0.004 | 0.651 | 0.459 |
LambdaMART, no social features | ✓ | 0.523 ± 0.007 | 0.678 | 0.502 |
LambdaMART, all features | ✓ | 0.524 ± 0.007 | 0.680 | 0.502 |
Comparing full LambdaMART with non-personalized LambdaMART separates the value of personalization from the value of switching to a learned ranker. Both use the same model class and training data; only the personal features differ.
Personalization matters most where the query alone says least. For broad tags shared by more than 123 artists, non-personalized ranking is close to guessing (NDCG@10 0.04–0.09) and the personal ranker reaches 0.21. The SHAP breakdown shows the same picture. After the query-tag match, the ranker relies on ItemKNN similarity to the user's history, on how well the user's taste matches the artist's tags, and on iALS. The friend-graph features carry almost no weight, and dropping them changes nothing measurable.
The same query from two listeners, served by the trained model (Engine.search):
| Top 5 |
Anonymous (popularity-aware fallback) | Isis · Mogwai · 65daysofstatic · God Is an Astronaut · Interpol |
User 2 (Depeche Mode, Daft Punk, Goldfrapp, Gorillaz…) | Sigur Rós · M83 · Broken Social Scene · The American Dollar · The Notwist |
The personalized list moves toward the electronic and dream-pop side of post-rock, which fits that listener's history.
2. Recommendation

Model | NDCG@10 | Recall@20 | Coverage@10 | Fit time |
LightGCN + friend graph | 0.279 ± 0.005 | 0.358 | 0.50 | 63 s |
LightGCN | 0.276 ± 0.003 | 0.351 | 0.37 | 51 s |
EASE | 0.273 ± 0.001 | 0.347 | 0.29 | 0.6 s |
iALS | 0.265 ± 0.004 | 0.346 | 0.33 | 2.7 s |
ItemKNN | 0.264 ± 0.001 | 0.336 | 0.43 | 0.1 s |
BPR-MF | 0.224 ± 0.006 | 0.296 | 0.46 | 1.7 s |
MostPop | 0.093 ± 0.003 | 0.123 | 0.01 | — |
The ranking is a cost/quality decision, not only a leaderboard. LightGCN+Social wins on accuracy and covers 50% of the catalog in top-10 lists, against 29% for EASE. EASE gets 98% of the accuracy in under a second with no tuning beyond one regularizer. That is why the served search stack uses EASE as one of its CF features, alongside iALS and ItemKNN.
What's established vs. what's new here
Every model, metric and protocol in this repo comes from published work, credited in
docs/REFERENCES.md. No new algorithm is claimed. What this repo
adds is a set of controlled measurements on one public dataset:
New measurements. We did not find these reported elsewhere for HetRec Last.fm.
The size of the personalization effect, isolated from the ranker. On identical candidates, with the same learner and training queries, adding personal features lifts discovery-search NDCG@10 by +40.7%. The gain over the classic BM25 + popularity baseline is +110%, or 0.276 NDCG. The controlled comparison splits that gain: about half (0.148) comes from the personal features, and the rest from learning to rank at all.
Collaborative filtering still adds value inside search once taste profiles are present. Removing the three CF features (keeping tag-based taste) costs 7.3% (p ≈ 1e-42). Tag-based user profiles alone, the classic folksonomy approach, leave measurable accuracy on the table.
The friend graph helps recommendation slightly but adds nothing to search. +1.7% for LightGCN with vs. without friend edges (p = 0.03 on split 0; positive on all three splits, but close to zero on one). Exactly 0 in search (−0.1%, p = 0.94) once CF features are present. In this data, friends' signal appears to be already captured by co-listening.
Results that confirm prior findings (credited, not claimed as discoveries):
Personalization pays off most on broad queries (5.4× on broad tags vs. 1.7× on narrow ones). This matches Teevan, Dumais & Liebling (SIGIR 2008): personalization helps most where intent varies across users.
A well-tuned linear model (EASE) gets within 2% of the best graph neural model at about 1% of the training cost. This matches Ferrari Dacrema et al. (RecSys 2019) and Steck (2019).
How the evaluation avoids fooling itself
Artist tag profiles drop every tag event on a held-out (user, artist) pair, so a user's own tags cannot leak into queries or features.
All search features come from models fit on the training split only.
Artists the user already plays are never candidates, so a model cannot win by re-surfacing them.
Hyperparameter grids, linear-blend weights, LambdaMART early stopping and neural early stopping all use validation data. Test is scored once per split.
Results are reported over three random splits, with 95% bootstrap CIs and paired Wilcoxon tests for every claim above.
Limitations are spelled out in docs/METHODOLOGY.md.
The main ones: the dataset is small (1.8K users, 2.8K artists), queries are tags rather than
logged search strings, and nothing here was tested online.
Reproduce
git clone https://github.com/Brennan-Richards/encore && cd encore
python -m venv .venv && source .venv/bin/activate
make install # pip install -e ".[serve,dev]"
make test # 20 offline tests, ~5 s
make all # download (2.5 MB, SHA-256 pinned) → recsys (~17 min) → search (~4 min) → reportOn an Apple M3 laptop CPU, the full recommendation benchmark (tuning plus three splits)
takes about 17 minutes and the search benchmark about 4. make smoke runs both with tiny
grids in about a minute.
Serve it
make serve # http://localhost:8000/docs
curl "localhost:8000/search?q=post-rock&user_id=2&k=5"
curl "localhost:8000/explain?q=post-rock&user_id=2&artist=Sigur%20R%C3%B3s"To give Claude (or any MCP client) the tools search_music, recommend_artists,
similar_artists, user_profile and explain_ranking:
{
"mcpServers": {
"encore": { "command": "/path/to/encore/.venv/bin/python", "args": ["-m", "encore.mcp_server"] }
}
}The served engine is the split-0 model exactly as benchmarked. User profiles therefore show only training-split artists. Anonymous queries use the tuned BM25 + popularity ranker, because the personal ranker was never trained on users without history.
Next steps
Natural-language queries: an LLM rewrites "something moody for a rainy drive" into catalog tags, evaluated with an LLM-as-judge against held-out listening.
Two-tower candidate generation with approximate nearest-neighbour search in place of BM25-only retrieval, and recall@K measured at each stage.
Navigational queries (artist names) and a re-finding setting, to complement discovery.
A larger, timestamped dataset (e.g. LFM-1b-style session logs) for a temporal split.
Credits
Data: Last.fm. The HetRec 2011 Last.fm-2k release was built by Ignacio Fernández-Tobías, Iván Cantador and Alejandro Bellogín (UAM) and is distributed by GroupLens for non-commercial use. It is cited as Cantador, Brusilovsky & Kuflik, HetRec 2011, RecSys 2011. The data is downloaded at run time and not redistributed here.
Methods: every model, metric and protocol is cited, with the file that implements it, in
docs/REFERENCES.md.Development: built with Claude Code as an AI pair-programmer. Commits carry a
Co-Authored-Bytrailer.
License
MIT for the code. The dataset keeps its original terms.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Music industry tools for AI agents: artist research, catalogs, release plans and content.
Autonomous music production for AI agents with MIDI generation, QC and provenance.
AI music and podcast platform for autonomous agents. SoundCloud for AI bots.
Cloud or self-hosted knowledge for AI agents: hybrid search, reranking, GraphRAG, scoped MCP tools.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables interaction with Spotify through LLMs using OAuth2 authentication. Supports music search, playback control, playlist management, and device management through natural language commands.142MIT
- AlicenseAqualityCmaintenanceMCP server for Spotify that enables playlist building and music discovery through 19 tools, allowing LLM agents to search tracks/artists/albums, manage playlists, control playback, and access personal listening data.201MIT
- FlicenseNot gradedqualityCmaintenanceProvides four MCP tools for neural retrieval: personalized user recommendations, item-to-item similarity, cold-start text search, and explainable recommendation scores, enabling LLM agents to query a trained two-tower recommender over Amazon Reviews data.1-
- AlicenseAqualityBmaintenanceEnables natural-language inquiries about personal listening history and playlist creation with enforced hard constraints and automated repair.4MIT