Skip to main content
Glama
thelma-tertrais

music-mcp-agent

README.md
# Music AI Agent — MCP Server - specialized in classical music recognition

A Python MCP server exposing music analysis tools: catalog search, track
metadata, local tempo/key/energy detection, recommendations, and optional
song recognition.

## Why it's built this way

Spotify locked down its `audio-features`, `audio-analysis`, `recommendations`,
and `related-artists` endpoints for all new apps in November 2024, and hasn't
reopened them. So:

- **Search + track metadata** → still Spotify (works great).
- **Tempo / key / energy** → computed locally with `librosa` on an actual
  audio file, instead of asking Spotify for numbers it no longer gives out.
- **Recommendations** → Last.fm's `track.getSimilar`, which is still free
  and public.
- **"What song is this?"** → a separate problem (audio fingerprinting), done
  via AudD's API — optional, only needed if you want that specific feature.

## Setup

```bash
cd music-mcp-agent
python -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
```

Fill in `.env`:
- `SPOTIFY_CLIENT_ID` / `SPOTIFY_CLIENT_SECRET` — required for search & metadata.
  Create an app at https://developer.spotify.com/dashboard (takes ~2 minutes,
  no approval wait — client-credentials apps don't need extended access).
- `LASTFM_API_KEY` — required for `get_similar_tracks`. Free, instant:
  https://www.last.fm/api/account/create
- `AUDD_API_KEY` — optional, only for `identify_song`. Free tier at https://audd.io/

## Run it

```bash
python server.py
```

## Connect it to Claude Desktop

Add to your Claude Desktop config (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "music-agent": {
      "command": "/absolute/path/to/venv/bin/python",
      "args": ["/absolute/path/to/music-mcp-agent/server.py"]
    }
  }
}
```

Restart Claude Desktop. The tools will show up under the 🔌 icon.

## Tools

| Tool | Input | What it does |
|---|---|---|
| `search_music` | `query`, `limit` | Search Spotify catalog |
| `get_track_info` | `track_id` | Full metadata for a track |
| `analyze_audio_file` | `file_path` (local) | Tempo, key, energy — no API |
| `get_similar_tracks` | `artist`, `track`, `limit` | Recommendations via Last.fm |
| `identify_song` | `file_path` (local clip) | Fingerprint recognition via AudD |
| `resolve_classical_work` | `query` (raw title/artist string) | Extracts composer, work, performers via MusicBrainz |
| `find_live_performances` | `query` (work/composer/orchestra), `city` | Upcoming concerts via Songkick |

### Classical music: why two extra steps

Spotify and Last.fm treat a classical recording as one flat string —
`"Symphony No. 5 in C Minor, Op. 67: I. Allegro con brio"` — with composer,
work, and performing orchestra mashed together inconsistently. Neither is a
good source for "what's this piece" or "who's performing it live," so:

1. `resolve_classical_work` uses **MusicBrainz** (free, no key needed beyond
   a descriptive User-Agent) to split that string into composer + canonical
   work title.
2. `find_live_performances` takes that composer/work/orchestra and searches
   **Songkick's** events database for upcoming concerts, optionally filtered
   by city.

Typical flow: `search_music` → `resolve_classical_work` on the result →
`find_live_performances` with the resolved composer or orchestra name.

**Songkick access isn't instant** — you have to apply at
https://www.songkick.com/developer and approval is manual (can take a
couple of weeks), so plan for that lead time before you rely on
`find_live_performances`.

**Note on Bachtrack**: it's the most classical-specific concert listings
site, but it has no public developer API — only a searchable website — so
it isn't wired in here.

## Next steps to extend this

- Add caching (the Spotify token, repeated searches, MusicBrainz lookups)
  with something like `diskcache` — MusicBrainz in particular rate-limits
  to ~1 request/second per the terms of their free API.
- Add a `create_playlist` tool if you get user-auth (Authorization Code flow)
  working instead of client-credentials — needed for anything that writes to
  a user's account.
- Swap `analyze_audio_file` to batch-process a folder for a full library scan.
- If AudD's free tier is too limited, ACRCloud is the other common choice for
  fingerprinting, similar integration shape.
- Once Songkick access comes through, consider adding a `subscribe_orchestra`
  tool that periodically checks an orchestra's calendar and only surfaces new
  additions — more useful than re-querying the full calendar each time.


Structure: 
music-mcp-agent/
├── config.py              # loads all env vars, once
├── server.py              # MCP registration only
├── clients/
│   ├── __init__.py        # marks clients/ as a Python package
│   ├── spotify.py         # search + track info
│   ├── audio_analysis.py  # local librosa tempo/key/energy
│   ├── lastfm.py          # similar tracks
│   ├── audd.py            # song recognition
│   ├── musicbrainz.py     # classical work resolution
│   └── songkick.py        # live performances
├── requirements.txt
├── .env.example
└── README.md