Releases: rianvdm/lastfm-mcp
Release list
lastfm-mcp v2.5.0 — Latest MCP protocol support
The server now speaks the current MCP revision (2026-07-28, the stateless one) natively, while older clients keep working through the SDK's compatibility lane. Tool responses also got smarter about what to call next, and two long-standing crash bugs in the public catalog tools are gone.
Breaking changes
- The
Mcp-Session-Idheader is no longer read or echoed, since the 2026-07-28 spec removed protocol sessions. If you connected through the manual/loginflow, pass?session_id=on the/mcpURL, which was always the documented way. Nothing changes for OAuth clients such as Claude.ai, Claude Code, or Claude Desktop.
What's new
- MCP 2026-07-28 support:
server/discover, the_metarequest envelope, and theMCP-Protocol-Version,Mcp-Method, andMcp-Nameheaders. Clients on the 2024 and 2025 revisions still connect withinitializeand get the same tools. - Every tool response ends with a "Next steps" block listing the most likely follow-up calls with their exact arguments. Where the response has a clear top item (your top artist this month, the most recent week in a chart list), the first suggestion is filled in with it. The server also ships instructions naming the recommended tool path per entity, so a model lands on the right verb without reading all 21 descriptions.
- Numeric parameters (
limit,page,from,to) accept strings, because some clients send numbers that way. The same bounds still apply. - Resource templates advertise a description and MIME type.
/mcpis rate limited per IP at 60 requests a minute to protect the shared Last.fm API budget. That is well above what any interactive client does.
Fixes
get_album_info,get_track_info, andget_artist_infono longer throw for an album, track, or artist with exactly one tag, one track, or one similar artist, or with none at all. Last.fm sends those as a bare object or leaves the key out; the tools handle all three shapes now. This was producing a few dozen errors a week in production.- A failed Last.fm fetch raised a second, unhandled rejection alongside the error the caller already received.
- The discovery card and
server_inforeported protocol2024-11-05. Both now report2026-07-28.
Under the hood
@modelcontextprotocol/server2.0 and@modelcontextprotocol/client2.0 replace the v1 SDK, with Cloudflare Agents SDK 0.21 (createMcpHandlerfromagents/mcp/server) and@cloudflare/workers-oauth-provider0.10.npm auditon production dependencies reports zero vulnerabilities, down from 14.- All tool, prompt, and resource registrations use the
register*APIs withz.object()schemas. - Two OAuth workarounds for Claude.ai's RFC 8707
resourceparameter are gone; the provider handles it correctly now. - Test stack is vitest 4,
@cloudflare/vitest-pool-workers0.22, and Node 22. CI runs the suite again (174 tests) after a long stretch with that step disabled. New tests drive a real SDK client through the Worker on both protocol lanes and snapshot the advertised catalogue. - Dead code removed: the session-logging utilities, leftover type files, and an unused OAuth registration wrapper.
lastfm-mcp v2.4.0 — Top tracks and 8K fewer lines
The big shifts in this release: three new tools, a glassmorphism-redesigned landing page, timezone-aware day boundaries on get_recent_tracks, and a 8,300-line cull of the original session-based worker now that the OAuth path has been the only one in production for a while.
What's new
- Three new tools.
get_top_tracksfills the obvious symmetry gap with the existingget_top_artistsandget_top_albums.get_artist_top_tracksandget_artist_top_albumssurface an artist's globally most-played catalog — useful for "what's the canonical record by X" questions. - Date-aware
get_recent_tracks. Newdateparam accepts aYYYY-MM-DDcalendar date plus atimezone(IANA name, e.g.America/New_York) and the server computes the correct UTC day boundaries. Way better than jugglingfrom/toUnix timestamps for "what did I listen to yesterday" queries. The response also echoes the queried range back so an LLM can self-verify it asked the right question. - Redesigned landing page at lastfm-mcp.com — glassmorphism, animated waves, glow effects.
Fixes
get_album_infono longer renders[object Object]when Last.fm returns the album artist as an object instead of a string. Latent bug, fixed via aformatArtisthelper that handles both shapes.
Under the hood
- Deleted the legacy worker. Removed
src/index.tsplus the homemade JSON-RPC dispatch layer insrc/protocol/and the SSE transport insrc/transport/. The OAuth worker (src/index-oauth.ts) has been the only production deployment for months; the legacy[env.legacy]block inwrangler.tomlwas never deployed to Cloudflare. Net diff: −8,293 lines, 0 added. Test suite went from 376 tests / 5 failing → 167 tests / 0 failing. - Dropped dead deps:
crypto-js,@types/crypto-js,oauth-1.0a— zero imports. - Removed dead throttle.
LastfmClient.throttleRequestwas per-request (clients are instantiated per-request in the OAuth worker), so it never observed a previous request — it did nothing while implying rate-limit safety. Existing 429-aware retry handles rate limits correctly. - Dynamic tool catalog. The
lastfm_auth_statustool list lives in one place now (src/mcp/tools/catalog.ts) instead of being hardcoded in three.
v2.3.1 — Timezone-aware date formatting
What's new
Track play times in get_recent_tracks now display in the correct timezone instead of silently using UTC. Previously, a track played at 11pm Pacific would show as the next day — causing Claude to say "yesterday" when it was today, or confuse morning/evening.
Changes
- Added optional
timezoneparameter toget_recent_tracks(IANA format, e.g."America/New_York"). Defaults to UTC. - All date formatting now uses an explicit UTC timestamp (
Mar 17, 2026, 2:04 AM UTC) instead of the runtime-local format (3/17/2026), making dates unambiguous regardless of where the server runs. - Invalid timezone strings fall back to UTC with a visible warning.
- Shared
formatTimestamputility eliminates duplicated date logic across the codebase.
v2.3.0 - Automatic OAuth Browser Flow
What's New
This release fixes the authentication experience for all MCP clients. Previously, connecting any client (Claude Code, Claude Desktop, opencode) to the server required manually copying and pasting a login URL. Now the browser opens automatically and the entire auth flow is hands-free.
OAuth Browser Flow Fix
- Automatic browser open on first connection — Unauthenticated
POST /mcprequests now return401 + WWW-Authenticate: Bearer resource_metadata=...per the MCP OAuth 2.1 spec. Conforming clients (Claude Code, Claude Desktop, opencode) detect this response and open the browser to Last.fm automatically — no copy-paste URL required - Preserved manual login path — Clients that previously authenticated via
/logincontinue to work without re-authenticating. The server checks for an existing session viaMcp-Session-Idheader + KV lookup before falling through to the OAuth provider - Legacy
session_idparam path unchanged — Direct session-based connections (e.g.?session_id=...) are unaffected
Security Fix (from v2.2.0 hotfix)
- JWT timing side-channel — Replaced string comparison of JWT signatures with
crypto.subtle.timingSafeEqual()to prevent timing-based token forgery attacks - SSE global mutable state — Eliminated a shared mutable
Mapacross requests in the SSE transport layer that could leak session data between concurrent users
Test Infrastructure
- CJS
ajvcompatibility — The Cloudflare Workers test pool (@cloudflare/vitest-pool-workers) couldn't load the nested CommonJSajvmodule from@modelcontextprotocol/sdk. Fixed by aliasingajvandajv-formatsto minimal ESM stubs invitest.config.mts, restoring full test suite execution - New OAuth test suite — 34 tests across 3 files covering: unauthenticated 401 behavior, OAuth metadata endpoints,
Mcp-Session-Idheader routing, and a full 7-step OAuth round-trip (client registration → PKCE authorize → Last.fm callback → token exchange → authenticated MCP call)
Full Changelog
v2.2.0 - Security Hardening & MCP Server Review
What's New
This release addresses all P0 (critical) and P1 (important) findings from a comprehensive security and best-practices review of the MCP server against Cloudflare's MCP server building guidelines.
Security Improvements
- CSRF protection on login flow —
/loginnow sets a_csrf_tokensecure cookie that is validated on/callback, preventing cross-site request forgery attacks on the OAuth flow - Content Security Policy headers — The auth success page is now served with
Content-Security-Policy,X-Frame-Options: DENY, andX-Content-Type-Options: nosniffheaders. Username and session data are sanitized before rendering - Typed OAuth resource param fix — Replaced unsafe
(oauthReqInfo as any).resource = undefinedwith properly typed assertion to prevent audience mismatch when Claude.ai sends the full MCP endpoint URL
Reliability Improvements
- Error handling on all MCP tools — All 17 tool callbacks (6 public + 11 authenticated) are now wrapped in try/catch with user-friendly error messages via a
toolError()helper, preventing unhandled exceptions from crashing tool calls - Session lookup bug fix —
handleUnauthenticatedMcpnow checks KV for existing sessions viaMcp-Session-Idheader instead of generating a new UUID on every request. This fixes the issue where login worked but subsequent MCP tool calls couldn't find the session - Context-aware success page — Auth success page now shows "close this window" for users arriving from an MCP client session, and config instructions for manual
/loginvisitors
Code Quality
- Tool code deduplication — Eliminated ~500 lines of duplicated tool registration code between OAuth and non-OAuth paths. Single
registerAuthenticatedToolswith pluggableAuthMessageConfig, whereregisterAuthenticatedToolsWithOAuthis a 3-line wrapper - Deduplicated routes — Removed 5 duplicate route handlers from
oauth-handler.tsthat were already handled inindex-oauth.ts - OAuth server factory — Replaced per-request
McpServercreation in OAuth handler with sharedcreateMcpServer()factory - ABOUTME comments — All 29 source files now have standardized
// ABOUTME:header comments - Dynamic base URLs — Replaced hardcoded URLs with
new URL(request.url).originderivation - Bundle size reduced — From 2824 KiB to 2726 KiB (-98 KiB) by removing duplicate client imports
New Files
src/utils/security.ts— CSRF token generation/validation, CSP header builder, HTML sanitizationsrc/mcp/tools/error-handler.ts— ReusabletoolError()helper for MCP tool error responsesdocs/MCP-SERVER-REVIEW.md— Full assessment document with all findingsdocs/TODO.md— P2 cleanup items for future work
Full Changelog
v2.1.1
What's New
Unauthenticated MCP Access
MCP clients that don't support OAuth 2.1 (like Antigravity, Windsurf) can now connect and use public tools without authentication.
- Public tools work immediately - track info, artist info, album info, similar artists/tracks
- Authenticated tools prompt for login - when you try to access personal data, you'll get a helpful message with login instructions
- Session ID support - the server generates and returns an
Mcp-Session-Idheader for session continuity
Redesigned Setup Documentation
The marketing page setup section has been completely redesigned:
- Vertical list layout instead of cramped grid
- Complete JSON configs for each client (not just snippets)
- Added setup instructions for:
- Claude.ai / Claude Desktop
- Windsurf / Antigravity
- Claude Code
- OpenCode
- Cursor
- Continue.dev / Zed / Other MCP Clients
Other Changes
- Standardized test file naming (
*.test.ts) - Fixed
auth_status→lastfm_auth_statustypo in README - Added implementation plan documentation
Full Changelog
- Allow unauthenticated MCP initialization for non-OAuth clients
- Redesign setup section with complete client configurations
- Add OpenCode setup with correct config format
v2.1.0 - Marketing Page Redesign
What's New
- Dark theme with Last.fm red (#d51007) accents
- Updated setup instructions for Claude.ai, Windsurf, and other MCP clients
- Sample queries section in 2×2 grid layout
- Copy buttons on code blocks
- Red headphone SVG favicon
- Cleaner, more minimal design
v2.0.0 - OAuth 2.0 Support for All Clients
Major release with full OAuth 2.0 support for Claude.ai, Claude Desktop, Claude Code, and Windsurf.
What's New
OAuth 2.0 Authentication
- Full OAuth 2.0 support now works with all major MCP clients
- No more manual session URL workarounds needed
- Seamless browser-based authentication flow
- Persistent sessions across conversations
Bug Fixes
- Fixed OAuth token audience mismatch with Claude.ai
- Clear resource parameter in authorize handler to prevent audience being set
- Strip resource parameter from token requests
- Updated oauth-protected-resource to return base URL without path
Documentation
- Simplified README with unified setup instructions
- Custom domain: https://lastfm-mcp.com
Breaking Changes
- Old OAuth grants have been invalidated (users need to re-authenticate once)
Last.fm MCP Server v1.0.0 - Official Launch
Hey y'all, happy to call this the first stable release of the Last.fm MCP Server! This production-ready server bridges AI assistants with Last.fm's comprehensive music database.
🌟 What's Included
🎧 Personal Music Data
- Recent listening history with pagination
- Top artists, albums, and loved tracks
- Comprehensive listening statistics
- Personalized music recommendations
🕰️ Temporal Queries ⭐ New Feature
- Ask "When did I start listening to Led Zeppelin?"
- Explore "What was I obsessed with in summer 2023?"
- Access your complete Last.fm listening history by time period
- Weekly artist and track charts from any date range
🎵 Public Music Information
- Detailed track, artist, and album information
- Music discovery with similar artists and tracks
- Rich metadata and music recommendations
🔐 Secure & Reliable
- Last.fm Web Authentication with 7-day sessions
- Smart caching system optimized for different data types
- Rate limiting and retry logic built-in
- Global edge deployment on Cloudflare Workers
🚀 Getting Started
Add to your Claude Desktop config:
{
"mcpServers": {
"lastfm": {
"command": "npx",
"args": ["mcp-remote", "https://lastfm-mcp-prod.rian-db8.workers.dev/sse"]
}
}
}
Then ask Claude questions like:
- "What are my recent tracks?"
- "When did I start listening to [artist]?"
- "What was I listening to in [time period]?"
- "Find artists similar to my favorites"
🎯 Perfect For
- Music enthusiasts who want AI-powered music insights
- Developers building music-related AI applications
- Data analysts exploring personal listening patterns
- Anyone curious about their musical journey over time
📚 Full Documentation
See the README.md for complete setup instructions, API documentation, and examples.