Skip to main content
Glama
peterish8

TuneTidy

by peterish8

TuneTidy

Hosted ChatGPT ↔ Spotify control — a small Connect website + MCP server so ChatGPT can act on your Spotify account.

Spotify stays the music app. TuneTidy is the middle layer: link once, then control playlists, playback (including exact-cue seek), and optional offline ZIP export from chat.

Not a Spotify clone. Not a self-host Docker product for end users. You (operator) deploy once; everyone else just Connects.


What it does

For

Experience

End user

Open Connect → Link Spotify → add MCP URL in ChatGPT → chat

Operator

Deploy to Render (or similar), set env secrets once

ChatGPT

Calls 17 MCP tools; Spotify tokens never leave the server

Capabilities (Milestone A)

  • Connect site — Spotify OAuth (Authorization Code), encrypted token storage

  • Playlist control — list, create, add/remove tracks, update details

  • Playback — play / pause / seek / now-playing; exact-cue (beat-drop seek with confirmation)

  • Offline export — Spotify metadata → match on JioSaavn/Gaana APIs → ZIP download
    (not Spotify stream ripping)

  • Safety — write tools need confirmationToken + idempotencyKey; AES-256-GCM for tokens


Related MCP server: spotify-mcp-server

Architecture

Browser  ──►  apps/web   (Next.js Connect + OAuth)
ChatGPT  ──►  apps/mcp   (Fastify JSON-RPC MCP @ POST /mcp)
                 │
                 ▼
           packages/core  (use cases)
                 │
     ┌───────────┼───────────┐
     ▼           ▼           ▼
 packages/   packages/   packages/
  spotify       db        saavn
     │           │           │
 Spotify API  Postgres   Saavn/Gaana APIs

Path

Role

apps/web

Connect UX, Spotify OAuth routes, health

apps/mcp

Remote MCP: tools/list, tools/call, export downloads

apps/worker

Job worker skeleton (exports currently run in MCP process)

packages/spotify

Only place that calls Spotify HTTP

packages/auth

Token crypto, JWT verify, dev bypass

packages/db

Drizzle schema, migrations, repositories

packages/core

Playback cues, offline export pipeline

packages/saavn

Search/match for offline export

packages/mcp-contracts

Shared Zod tool schemas

docs/

Architecture, MCP catalog, deploy, security

.planning/

Roadmap / GSD state (optional for operators)


MCP tools (17)

Endpoint: POST /mcp (JSON-RPC). Also: GET /mcp, GET /tools.

Group

Tools

Read

account_get_status, playlists_list, library_get_summary, playback_get_state, playback_resolve_cue

Write

playlist_create, playlist_add_tracks, playlist_remove_tracks, playlist_update_details, playback_play, playback_pause, playback_seek, playback_play_exact_cue

Offline

offline_export_preview, offline_export_start, offline_export_status, offline_export_get_result

Full contracts: docs/MCP_TOOL_CATALOG.md.


Quick start (local)

Requirements: Node ≥ 22, pnpm 9, Postgres (Docker optional).

# 1. Install
pnpm install

# 2. Env
cp .env.example .env
# Generate encryption key:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
# Set TOKEN_ENCRYPTION_KEY_CURRENT and DATABASE_URL

# 3. Database
docker compose up -d          # optional local Postgres
pnpm db:migrate
# pnpm db:seed               # optional

# 4. Run
pnpm dev:web                  # http://127.0.0.1:3000
pnpm dev:mcp                  # http://127.0.0.1:3100

Minimum env for local Connect + MCP

Variable

Notes

DATABASE_URL

Postgres connection string

TOKEN_ENCRYPTION_KEY_CURRENT

32-byte key, base64

SPOTIFY_CLIENT_ID / SECRET

Spotify Developer Dashboard

SPOTIFY_REDIRECT_URI

e.g. http://127.0.0.1:3000/api/spotify/callback

ALLOW_DEV_AUTH_BYPASS

true for local MCP without Auth0

DEV_USER_ID

Stable user id when bypass is on

APP_BASE_URL / MCP_BASE_URL

Defaults in .env.example

Auth0 vars are required for production-style login; dev bypass skips MCP Bearer checks.

See .env.example for the full list (Saavn URLs, cover storage, classifier stubs, etc.).

Smoke MCP (dev bypass)

curl -s -X POST http://127.0.0.1:3100/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Don’t use paid Render Postgres. Use Convex free for encrypted Spotify tokens:

  1. npx convex dev / npx convex deploy (see docs/CONVEX_FREE_MULTIUSER.md)

  2. Render 2 free Web Services: tunetidy-web + tunetidy-mcp (no Postgres service)

  3. Env: STORAGE_BACKEND=convex, CONVEX_URL, CONVEX_SERVER_KEY, encryption key, Spotify app

  4. Users open Connect → Link Spotify once → ChatGPT uses MCP

Mode

Docs

Convex multi-user (free)

docs/CONVEX_FREE_MULTIUSER.md

MCP-only single user (no DB)

docs/SINGLE_USER_FREE_DEPLOY.md

Local Postgres

docs/DEPLOYMENT.md


Scripts

Command

Purpose

pnpm dev / dev:web / dev:mcp

Local apps

pnpm db:migrate / db:seed

Schema + seed

pnpm typecheck

TypeScript across packages

pnpm test

Unit tests (Vitest)

pnpm test:contract

Spotify client contracts

pnpm build

Production builds

pnpm verify

lint + typecheck + tests + build


Security & compliance

  • Spotify refresh/access tokens are encrypted at rest; tools never return them.

  • Destructive writes are confirmation + idempotency gated.

  • Offline export uses third-party catalog APIs (Saavn-compatible / Gaana). Not official Spotify Offline. Operators are responsible for ToS/legal fit in their region.

  • Never commit .env — only .env.example.

More: docs/SECURITY.md.


Docs

Doc

Content

docs/MCP_TOOL_CATALOG.md

All tools + curl examples

docs/ARCHITECTURE.md

Package boundaries

docs/FEATURES_EXACT_CUE_PLAYBACK.md

Beat-drop / exact seek

docs/FEATURES_OFFLINE_EXPORT.md

JioSaavn match → ZIP

docs/DEPLOYMENT.md

Local + credential setup

docs/CODE_AUDIT_REPORT.md

Build completeness audit

docs/CONNECT_LOCAL_TEST.md

Connect smoke checklist

Planning source (optional): .planning/, archive PRDs under all_raw_infos/.


Status

Area

State

Connect + Spotify OAuth

✅ Implemented

MCP tools (17)

✅ Implemented

Exact-cue playback

✅ Implemented

Offline export (preview → ZIP)

✅ Implemented

Automated tests / typecheck

✅ Passing in CI path

Production Render + live ChatGPT smoke

⬜ Operator (you)

Full library organizer (rules, heavy sync UI)

⬜ Backlog


License

Private / unlicensed unless you add a license file. Spotify, JioSaavn, Gaana, Auth0, and ChatGPT are trademarks of their respective owners; this project is an independent companion stack.

Related MCP Connectors

Related MCP Servers