Sign inSign up

lenfenn/songfinder-mcp

By lenfenn

Updated about 1 month ago

MCP server for music recognition: identify any song, then get its BPM, key and Camelot code.

Image
0

355

lenfenn/songfinder-mcp repository overview

Song Finder — audio in, identified track out

Song Finder MCP Server

Identify any song, then get its BPM, musical key and harmonically compatible tracks — from inside Claude, Cursor, or any MCP client.

npm downloads MCP Docker License Node TypeScript API key Website

English · 简体中文 · 日本語 · 한국어 · Español · Deutsch · Français


An MCP server for music recognition and audio analysis, backed by Song Finder — a free online song finder that identifies music from a file, a microphone recording, or a link.

Ask your assistant "what song is playing in this YouTube video?" and it answers. Then ask "what's the BPM and key?" and "find me something that mixes into it" — and it chains straight through.


What it does

ToolWhat you get
identify_songSong title, artist, album, label, release date and Spotify / Apple Music links — from a URL or a local audio file
search_tracksCatalogue lookup by title/artist, returning ISRC codes
get_track_analysisTempo (BPM), musical key, Camelot code, harmonically compatible keys, energy, danceability, valence, acousticness, loudness
find_similar_tracksSimilar tracks — optionally restricted to harmonically compatible keys for DJ sets

identify_song accepts links from YouTube, TikTok, Instagram, SoundCloud, Bilibili and X, plus any direct audio or video URL. Local files can be mp3, m4a, wav, flac, ogg, opus, aac or webm.

No API key. No account. No rate card.


Install

Claude Code
claude mcp add songfinder -- npx -y songfinder-mcp
Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "songfinder": {
      "command": "npx",
      "args": ["-y", "songfinder-mcp"]
    }
  }
}
Cursor / Windsurf / Cline / Zed

Same shape — command: npx, args: ["-y", "songfinder-mcp"].

Requires Node.js 20 or newer.

Docker

No Node.js on the host, and the server runs sandboxed — worth having, since an MCP server otherwise executes with whatever your agent can reach.

{
  "mcpServers": {
    "songfinder": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "lenfenn/songfinder-mcp"]
    }
  }
}

Also on GitHub Container Registry as ghcr.io/songfinder-dev/songfinder-mcp — same image, same digests.

-i is not optional: the server speaks JSON-RPC over stdin and stdout, with no port and no HTTP.

To identify local files, mount the directory holding them. Inside a container, file_path refers to the container's filesystem, so a host path the container cannot see comes back as "no readable file":

{
  "command": "docker",
  "args": ["run", "-i", "--rm", "-v", "/Users/you/Music:/audio:ro", "ghcr.io/songfinder-dev/songfinder-mcp"]
}

Then ask for /audio/track.mp3 rather than the host path. :ro keeps it read-only — the server only ever reads.

Images are built for amd64 and arm64 natively, so Apple Silicon runs without emulation.


Example session

You: What song is playing in this video? (pastes a YouTube link)

Assistant (calls identify_song) Blinding Lights Match confidence: 100% · ISRC: USUG11904206

You: Is it fast? What key?

Assistant (calls get_track_analysis) Blinding Lights — The Weeknd · Album: After Hours · Released: 2020 Tempo: 171 BPM · Key: C#/Db Major (Camelot 3B, Open Key 8d) Mixes with: 3A, 2B, 4B Energy 73% · Danceability 51% · Valence 33% · Loudness −6.0 dB

You: Give me three tracks that mix into it.

Assistant (calls find_similar_tracks with harmonic: true)

(Those analysis figures are the real output, not a mock-up.)


Why the Camelot code matters

Two tracks in adjacent Camelot positions share enough harmonic content to be layered without clashing. 3B mixes cleanly into 3A, 2B and 4B — which is exactly what find_similar_tracks filters on when you pass harmonic: true.

The analysis also cross-checks tempo against a second provider. When the two disagree by more than ~3 BPM, the output says so — that gap almost always means one source read the track at half- or double-time, which matters enormously if you are beatmatching.


Notes on behaviour

Recognition costs real quota, so the endpoint rate-limits per IP. If you fire several identify_song calls back to back you will see a "rate limited" message; wait a few seconds.

Not everything is identifiable. Live versions, unreleased edits, heavily-processed remixes and instrumental beds frequently have no catalogue entry. When a clip lands on an intro or a silent gap, pass start_seconds to sample further in.

The credited artist is whichever catalogue entry matched. Widely re-uploaded tracks often match a white-label or re-upload record rather than the original release, so a famous song can come back credited to a label nobody has heard of. The title is still correct — search_tracks on that title surfaces the original, and the tool output says as much when it happens.

Local files are uploaded to songfinder.dev for identification and are not retained. Keep excerpts under 10MB — a 10–20 second clip is plenty and identifies faster than a full track.

Acoustic coverage is uneven. Long-tail and regional releases often have a tempo but no genre, or no analysis at all. Missing fields are omitted rather than reported as null.


Configuration

VariableDefaultPurpose
SONGFINDER_API_URLhttps://songfinder.devPoint at a different deployment

Development

pnpm install
pnpm build
node test/smoke.mjs      # real JSON-RPC handshake against the live API
pnpm inspect             # MCP Inspector

The smoke test is deliberately unmocked. The failure worth catching — a renamed field or a tightened origin check upstream — is invisible to a mocked test and is the one that actually happens.


License

MIT

Tag summary

Content type

Image

Digest

sha256:e1d67b414

Size

57.7 MB

Last updated

about 1 month ago

docker pull lenfenn/songfinder-mcp