MusicSeed — Dependency & Workflow Architecture
Web, CLI, REST API, and MCP · September 2026 · SQLite only No Docker No ML runtime REST API Next.js web
This document explains every dependency MusicSeed relies on today — Python packages, data stores, network services — and how data flows through the four main workflows (import, enrich, sonic import, recommend) and the user surfaces (CLI, MCP agent tools, and the Next.js web UI via the REST API). It exists to track how small the install surface has become, so publishing MusicSeed as open source means a new user needs as little as possible.
socket only;
servers on other subnets are found through the optional plex.tv/api/resources
account lookup (httpx, needs a Plex token). uv is development-only tooling — the
end-user install is plain python3 -m venv + pip. That's the whole
thing — no database server, no containers, no native ML libraries.
1. The big picture
Python packages (core)
7
sqlalchemy, pyyaml, httpx, numpy, pydantic, rich, paramiko — all pure-Python or widely pre-built wheels.
Python packages (surfaces)
2 + 3 + 2 + Node
cli: typer, rich · api: fastapi, uvicorn, python-multipart · mcp: mcp, anyio · web: next, react, react-dom (Node). Web talks to api over HTTP; api, cli, and mcp depend on core via editable paths.
Extra database processes
0
No database server or container runtime. The product runs a local API/UI server; MCP can run as a subprocess or HTTP server.
2. Dependency ledger (before → after)
Python packages
| Package | Role | Status |
|---|---|---|
| sqlalchemy | ORM over the SQLite state file | kept core |
| httpx | HTTP to Plex API + ListenBrainz/Spotify | kept core |
| numpy | Sonic vector math (matmul, cosine) over the local vector store | kept core |
| pydantic | Config + service result models | kept core |
| pyyaml | config.yaml loading | kept core |
| rich | Progress rendering inside import/enrich pipelines | kept core |
| paramiko | Verified SSH execution and streaming of consistent SQLite backups | kept core |
| typer | CLI framework | kept cli |
| fastapi | REST API request handling | kept api |
| uvicorn | ASGI server for the API | kept api |
| python-multipart | HTML form parsing (setup wizard, credential forms) | kept api |
| next / react / react-dom | Next.js + React client-rendered web UI (Node) | kept web |
| mcp | MCP server framework for the agent surface | kept mcp |
| anyio | Worker-thread offload for synchronous core service calls | kept mcp |
| jinja2 | Server-rendered templates | removed · React rewrite |
| htmx (vendored file) | Fragment updates without a JS build step | removed · React rewrite |
| essentia-tensorflow | Self-generated audio embeddings (MusiCNN) | removed · Phase 1 |
| psycopg[binary] | PostgreSQL driver | removed · Phase 3 |
| pgvector | Vector column type + cosine-distance query | removed · Phase 2 |
Infrastructure & system requirements
| Component | Former role | Status |
|---|---|---|
| PostgreSQL 16 server | MusicSeed state database | removed · Phase 3 |
| Docker / docker-compose | Ran the Postgres container | removed · Phase 3 |
| pg_trgm extension | Trigram indexes (never queried) | removed · Phase 3 |
| TensorFlow runtime | Pulled in by essentia; amd64-only | removed · Phase 1 |
| Audio-file access | Reading music files to embed them | removed · Phase 1 |
| Stored embeddings | Vector(200) column, zero-padded from 50 | removed · Phase 2 |
What remains external (and can't be removed)
| Dependency | Why it exists | Access |
|---|---|---|
| Plex metadata DB | Source of truth for artists/albums/tracks/tags/play history | read-only, stdlib sqlite3 |
| Plex blobs DB | Plex's own 50-dim sonic analysis vectors | read-only, import time (copied into musicseed.db) |
| Plex HTTP API | Creating/populating playlists; triggering sonic analysis | optional, token-gated |
| ListenBrainz | Popularity enrichment via recording MBIDs | optional, rate-limited |
| Spotify Web API | Fallback popularity/metadata when MBIDs are missing | optional, credentialed |
track_vectors table (import-plex-sonic /
POST /sonic/import), then rebuilds the in-memory L2-normalized matrix
(sonic.py → SonicVectors) from that local store when a recommendation runs. The
blobs database is read only at import time, so there is no vector index, no ANN index, and no
embedding pipeline to maintain.
3. Workflows
3.1 Import — Plex metadata → musicseed.db
musicseed-cli import — one-way copy of artists, albums, tracks, genres, moods, styles, play history. The Plex file is never written to.3.2 Enrich — popularity signals (async, resumable)
musicseed-cli enrich --source listenbrainz|spotify — attempted tracks are flagged so interrupted runs resume. This is the only workflow that spends third-party API calls, which is why old Postgres data was migrated rather than re-fetched.3.3 Sonic import — copy vectors into musicseed.db, read local store at query time
track_vectors table at import time, then cached in raw/normalized matrices. Recommendations score every eligible track using local vector lookups. Cache memory scales with vector count; query latency is measured, not assumed instantaneous. See docs/resolvers/retrieval-decision.md for benchmarks and limits. No ANN index or pgvector column is needed.3.4 Recommend — six signals, explainable
musicseed-cli recommend previews; playlist / populate confirm and apply the exact approved IDs over Plex HTTP, without recomputing. Full retrieval hydrates only seeds and selected tracks. sonic-refresh is a separate, explicitly confirmed remote-analysis mutation.4. What a brand-new user needs (open-source readiness)
Prerequisites
· Python 3.12+, SQLite 3, Node.js/npm (install only)
· Plex Media Server with a music library, sonically analyzed
· Optional: Spotify API credentials (fallback enrichment only)
Install (from a git clone)
./scripts/install.sh
musicseed then open http://127.0.0.1:8789
The first-run wizard discovers Plex, initializes the database, and walks through import/enrichment. Node is not needed after install.
Still on the road to pip install musicseed
| Gap | Notes |
|---|---|
| PyPI packaging | core, api, cli, and mcp are separate Python distributions; the Next.js UI is built with npm. Source installs join Python packages through editable paths. |
| Plex DB discovery | Server discovery is solved (GDM/SSDP; plex.tv/api/resources for other subnets). On-disk db_path probes macOS and Linux candidates; Windows is untested. |
| Sonic analysis coverage | Recommendation quality depends on Plex having analyzed the library; sonic-probe reports coverage, sonic-refresh triggers the Butler task. |
5. Verify the current state
# From the repository root, after syncing each app environment:
uv run --project core ruff check core/src
uv run --project api pytest api/tests -q
uv run --project cli pytest cli/tests -q
uv run --project mcp pytest mcp/tests -q
python3 -m compileall -q core/src/musicseed api/src/musicseed_api cli/src/musicseed_cli mcp/src/musicseed_mcp
.venv-docs/bin/mkdocs build --strict
# Read-only checks against a configured local library:
uv run --project cli musicseed-cli status
uv run --project cli musicseed-cli recommend --seed-id 123 --limit 20 --explain