A catalogue for a physical vinyl and CD collection. It exists to answer four questions that a music player cannot:
- What do I own? Every pressing, with catalogue numbers, labels, composers, and BPM.
- What is it worth? Grade-aware valuations tracked over time, not a single guess.
- What do I tell the insurer? A dated schedule of every item, its condition, what it cost, and what it is worth today.
- How does my collection compare? Discogs community have/want counts turn into a scarcity signal per release.
A Release is an edition that exists in the world — a specific pressing with a catalogue number, a label, and a tracklist, shared by everyone who owns one. A Copy is the object on your shelf: it has a condition, a purchase price, a storage location, and photographs of its actual scuffs.
Everything follows from that split:
| Attached to a Release | Attached to a Copy |
|---|---|
| Artists, composers, publisher | Media and sleeve grade |
| Tracklist, durations, BPM, ISRC | Purchase price, date, seller |
| Cover art | Condition photographs |
| Discogs / MusicBrainz IDs | Valuations and insurance value |
| Community have/want counts | Ripped audio |
Valuation never attaches to a Release, because a VG copy and an NM copy of the same pressing are not worth the same money. Ripped audio belongs to a Copy because you ripped that disc, and a needledrop is itself evidence of condition.
| Provider | What it is good for |
|---|---|
| Discogs | Pressings, catalogue numbers, labels, marketplace prices, scarcity |
| MusicBrainz | Works, composers, conductors, stable MBIDs |
| Local files | Rips that no database knows about; real sample rates; measured BPM |
All three implement the same MetadataProvider protocol and return plain
dataclasses, so a provider can never half-write to the database.
Files live on disk; the database stores relative paths and SHA-256 hashes. The whole library can be moved without touching a single row.
$MRC3000_MEDIA_ROOT/
art/ cover scans, label shots, condition photographs
audio/ one directory per album
Neither the library nor the database is committed — the database holds purchase prices and storage locations, which is exactly the information a burglar would like to have.
uv sync # add --extra audio for BPM and key detection
export DISCOGS_TOKEN=... # https://www.discogs.com/settings/developers
uv run mrc3000 inituv run mrc3000 serve # web UI on http://127.0.0.1:8321Server-rendered FastAPI + Jinja, no JSON API and no build step — this is a single-user app browsing a local database, so a second language and an API contract would be cost without benefit.
| Page | What it does |
|---|---|
/ |
The shelf: cover grid, sortable by value, artist, title, year, or recency |
/search |
Look up a pressing on Discogs, MusicBrainz, or your own files |
/add |
Confirm the pressing, then describe your copy: grades, price, location |
/release/{id} |
Tracklist with BPM, scarcity, and every copy you own with its valuation history |
/insurance |
The schedule an insurer asks for, plus CSV download |
It binds to loopback by default. The database holds purchase prices and storage locations, which is not something to put on a shared network.
uv run mrc3000 search "Kind of Blue" # look up a pressing on Discogs
uv run mrc3000 search 5099706334323 # or by barcode
uv run mrc3000 list # the collection, most valuable first
uv run mrc3000 grade 12 --media VG+ --sleeve NM
uv run mrc3000 insure --csv schedule.csv # the document for the insurer
uv run mrc3000 analyse rip.flac # BPM and key from the audio itself
uv run mrc3000 scan # what is in the local library| Variable | Default | Purpose |
|---|---|---|
MRC3000_HOME |
platform data dir | Database location |
MRC3000_MEDIA_ROOT |
$MRC3000_HOME/library |
Art and audio |
MRC3000_DATABASE_URL |
SQLite in MRC3000_HOME |
Any SQLAlchemy URL |
MRC3000_CURRENCY |
GBP |
Reporting currency |
DISCOGS_TOKEN |
— | Required for Discogs lookup and pricing |
DISCOGS_USERNAME |
— | Required to sync your Discogs collection |
Goldmine grades throughout — M, NM, VG+, VG, G+, G, F, P — because
that is what Discogs prices against and what insurers recognise. Grade is
ordered, so Grade.NM > Grade.VG works.
Usable. The domain model, providers, reporting, web UI, and the add/valuation
write path are in place. Not yet built: add/revalue as CLI commands (both
exist in the web UI only), Discogs collection sync, condition-photo upload,
Alembic migrations, and BPM write-back from analyse into the database.
Discogs allows 60 requests/minute authenticated; MusicBrainz allows one per second and requires a descriptive user agent. Bulk operations must be paced — this is the main constraint on any full-collection refresh.
MIT.