scrobble-gateway
Integrates with Last.fm by syncing a user's complete listening history via the Last.fm API (user.getRecentTracks) into a local SQLite master database, with hourly incremental updates. Enables querying recent plays, top tracks/artists in arbitrary date ranges, period comparisons, artist listening depth, session extraction, and changes in listening preferences over time.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@scrobble-gatewayWhat were my top artists in September 2025?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
scrobble-gateway
自分のLast.fmの聴取履歴を一か所に集めて扱う、自宅サーバー上のサービスである。 全履歴をSQLiteに保存し、毎時Last.fmと同期したうえで、MCPサーバーとしてChatGPTやClaudeから読めるようにしている。
Last.fm API ──▶ scrobble-gateway ──▶ MCP(claude.ai / ChatGPT / 自分)
(マスター DB) ──▶ health-ojimpo(日次の再生件数)
──▶ Cosense 同期(予定)なぜ作ったか
2021年から、SpotifyとApple Musicで再生した曲をLast.fmにscrobbleしてきた。2026年10月時点で9.5万件ある。 この履歴を、AIと話しながら掘り返したかった。「9月は何をよく聴いていたか」「去年の今ごろと比べて何が増えたか」「このアーティストに最初にハマったのはいつか」といった問いである。 毎朝の音楽レコメンドもAIに作らせていて、その材料としても長期・期間別の嗜好が要る。
履歴そのものは、自作の健康ダッシュボードhealth-ojimpoがすでに毎時取り込んでいた。 当初はhealth-ojimpoのDBをMCPから読む案を考えたが、採らなかった。 health-ojimpoは各サービスのAPIを叩く側として作ってきた。ここで他から叩かれる側にすると、役割が崩れる。 Last.fmのAPIキーと完全な履歴を持つ場所を1つに絞り、health-ojimpoもMCPもその利用者にする。そのために作ったのがこのリポジトリである。
Related MCP server: lastfm-mcp
設計の考え方
Last.fmのデータの窓口はここだけにする。 APIキーもマスターDBも、ここに1つずつ置く。移行が済めば、health-ojimpoが持つのは日次の再生時間のような派生値だけになり、完全な履歴を重複して抱えることはない
MCPは自前のDBを読む。 その場でLast.fm APIを叩かないので、任意の期間で集計でき、応答も速い(9月1か月分のランキングで0.1秒未満)。Last.fm側の障害やレート制限にも左右されない
正本はLast.fm。 初回はhealth-ojimpoのDBをコピーせず、Last.fmから全件を取り直した(9.5万件で約7分)。コピーすると、取り込み側に溜まった表記揺れまで引き継いでしまう
ゼロから書かない。 既存のLast.fm MCPを6つ比べ、構成がいちばん近いsptmru/lastfm-mcpを土台にした(比較の経緯はDEVLOG.md)。コピーではなく履歴ごとmergeしてあるので、上流の修正はそのまま取り込める。そのため、こちらの変更は上流のコードと衝突しにくいよう小さく保っている
上流から変えたこと
土台のsptmru/lastfm-mcpはよくできているが、自分の9.5万件を載せて運用してみると、足りないところがあった。
変更 | 理由 |
差分同期で直近72時間を取り直す | Spotify経由のscrobbleは、Last.fmに遅れて、順不同で届く。「最新のscrobbleの時刻より後」だけを取ると、あとから届いた古い時刻の再生を永久に取りこぼす |
起動時と毎時の自動同期 | 上流はツールかCLIから手動で同期する作りなので、放っておくと索引が古くなる |
名寄せ表にMBIDのインデックスを張る | 上流はMusicBrainz IDの列にインデックスが無く、9.5万件の初回名寄せに25分以上かかる計算になっていた。その間はサーバー全体が止まる。インデックスを張れば22秒で済む |
SpotifyのLikeをLast.fmのLoveに同期する(直近に再生した曲だけ) | 上流にも同期はあるが、5,000曲を超えるLikeライブラリ全体を一度に突き合わせる方式である。こちらは毎時、直近72時間に再生した曲のうちLike済みのものにだけLoveを付ける。書き込みが必ず自分の再生に結びつくので、覚えのない書き込みが大量に起きることはない。同期は一方向で、Likeを外してもLoveは外さない。書くのは確実に一致した曲だけである |
任意期間のツール | 上流の期間別トップと期間比較は、Last.fmの固定期間(7日・1か月・12か月など)しか受け付けない。これでは「9月と8月」「今年と去年」に答えられない |
OAuth 2.1 | 上流には認証が無い。外に公開するなら必須である |
外部サービスとの連携
Last.fm
読み取りに使うAPIはuser.getRecentTracksだけで、APIキーさえあればユーザー認証なしで読める。
書き込みはLike同期のtrack.loveだけである。こちらはShared secretで署名し、一度だけブラウザで承認して得たセッションキーを使う。
実際に動かして分かったLast.fmの癖が2つある。どちらも、これからLast.fmの履歴を扱う人の役に立つと思う。
scrobbleは後から届く。 health-ojimpoの取り込みを「前回の最新時刻より後」だけを取る差分取得にしたところ、2週間で12件の取りこぼしが出た。抜けた曲はすべてSpotifyで再生したもので、届くのが遅れたうえに、時刻の順番も前後していた。差分取得の起点は少し遡らせておく必要がある
全ページを順に取ると、ページの境目で同じブロックが2回返ってくることがある。 そのぶん一覧の総数もふくらむ。主キーで重複を弾けばDBは正しくなるが、件数の検証にページ総数は使えない。
from/toで期間を区切った件数を使う
MCP(claude.ai / ChatGPT)
MCPはStreamable HTTPで話す。ツールは上流の約30個に任意期間の2個を足した、32個である。 直近の再生、期間別ランキング、期間比較、アーティストの聴き込み度、セッションの切り出し、時期ごとの嗜好の変化点などを扱える。一覧と使い方は上流の READMEにある。
認証はOAuth 2.1にした。ChatGPTのコネクタはOAuthしか受け付けず、claude.aiのカスタムコネクタは固定のBearerトークンを送れない。両方から使うなら、OAuthしか選択肢がない。
認可サーバーは、別に作ったCosense用MCP(cosense-mcp)のものを1人用に絞って移植した。動的クライアント登録、PKCE、resourceによる宛先の検証、issパラメータの完全一致など、ChatGPTとclaude.aiの両方で通すために踏んだ罠への対処も、そのまま持ってきている。
利用者の認証はパスフレーズ1つで行う。
MCP SDKはv2系を使っている。ただ、v2にはトークンを検証する部品しか無く、トークンを発行する認可サーバーの部品が無い。そこだけSDK v1のmcpAuthRouterを使っている。
Cloudflare Tunnel
自宅サーバー(arigato-nas)の4104番をCloudflare Tunnelで公開している。ポートは開けていない。
health-ojimpo
健康ダッシュボードがLast.fmから使っていたのは日ごとの再生件数だけで、件数×3.5分をその日の音楽再生時間とみなしている。
そこで、Dockerネットワークの中だけに開いた内部REST(GET /daily-plays)で、日次の件数だけを渡すようにした。health-ojimpoはもうLast.fm APIを叩かず、完全な履歴も持たない。
このポートは外に公開していないので、Cloudflare Tunnelを通らず、OAuthも要らない。
切り替えは2026年10月5日に行った。backendの差し替え1回で旧来の取り込みの停止と新しい取り込みの開始が同時に起きるようにしておき、二重取り込みの期間を作らなかった。 切り替え前に1,933日分の日次件数を突き合わせ、違いが出るのは旧データに表記揺れの重複があった4日だけだと確かめてから反映した。
動かし方
Node.js 22.5以上(node:sqliteを使うため)か、Dockerが必要である。
cp .env.example .env
# LASTFM_API_KEY と LASTFM_USERNAME を書く
# 外に公開するなら MCP_PUBLIC_URL と MCP_OAUTH_PASSPHRASE も書く
docker compose up -d --build
curl -s http://127.0.0.1:4104/healthz起動すると全履歴の取得が自動で始まり、終わったあとは毎時の差分同期に切り替わる。進み具合は/healthzで確認できる。
主な設定は次のとおり。全項目は.env.exampleにある。
変数 | 既定 | 意味 |
|
| 差分同期で遡る時間。 |
|
| 起動時と毎時の自動同期 |
| なし | 両方そろうとOAuthが有効になる。片方だけでは起動しない |
|
| 認証なしでHTTPを開くことを明示的に許可する。指定しなければ、認証なしでは起動しない |
| なし | 受け付けるHostヘッダ。公開ホスト名を足し忘れると403になる |
テストはnpm test、型チェックはnpm run typecheckで実行できる。
これから
旧資産の片付け。 health-ojimpoに残してある旧来の取り込みコードとscrobbleのテーブルは、ロールバック期間が終わったら消す
日本語表記と英語表記の名寄せ。 いまは「エイプリルブルー」と「AprilBlue」、「宇多田ヒカル」と「Hikaru Utada」が別のアーティストとして数えられている。MusicBrainz IDの付いていない曲が多いためである
毎朝のレコメンドへの組み込み。 期間別の嗜好の統計をCosenseへ機械的に書き出し、AIが毎朝読む嗜好プロファイルの材料にする
上流への還元。 後着分の取りこぼしとインデックスの修正は、上流でもそのまま効く
ライセンスとクレジット
MITライセンス。土台はsptmru/lastfm-mcp(MIT)で、その著作権表示はLICENSEにそのまま残したうえで、こちらの変更分の表示を足してある。 開発の経緯と判断の記録はDEVLOG.mdに、作業上の手引きはCLAUDE.mdにまとめてある。 コードの大半はClaude Codeと一緒に書いた。
This server cannot be deployed
Maintenance
Related MCP Connectors
The media memory layer for AI agents and their humans. Your AI client gets 29 tools to search your collection, add items, update ratings, preview music, and find patterns across everything you've read, watched, and listened to.
Multi-tenant hosted MCP server for Oura Ring — 21 read-only tools, OAuth per user.
Query your Twitch streams, events, supporters, raids & rankings from an AI assistant via OAuth.
Carbon Voice MCP serves as a bridge that connects AI assistants like ChatGPT, Claude, and Cursor to a user's Carbon Voice account, turning voice messages and conversations into a private, on-demand knowledge base. It provides 28 specialized tools for comprehensive voice messaging management, including creating and sending messages, accessing conversation history with instant transcription, running AI actions (summarization, TLDR generation, meeting notes), and managing workspace collaboration through folders, contacts, and team communications.
Related MCP Servers
- AlicenseAqualityDmaintenanceConnects AI assistants to a self-hosted Your Spotify instance and Spotify's Web API for deep listening analytics and playback control. It enables users to query unlimited listening history, generate custom Wrapped summaries, and manage playlists through natural language.18Apache 2.0
- AlicenseNot gradedqualityAmaintenanceA Model Context Protocol (MCP) server for Last.fm. Gives AI assistants access to your listening history, music discovery, and detailed track/artist/album information.23 npm49MIT
- AlicenseNot gradedqualityBmaintenanceProvides Last.fm listening analytics and recommendations by combining Last.fm and MusicBrainz metadata, maintaining a local listening index, and recording explicit preferences. Enables queries for listening summaries, taste profiles, artist context, and evidence-backed recommendations via MCP tools.23 npmMIT
- AlicenseAqualityBmaintenanceLets AI assistants answer questions about your Spotify listening history, including taste evolution, top artists, recently played, and playlist analysis.881 npmMIT