MCPcopy
hub / github.com/sjdonado/idonthavespotify

github.com/sjdonado/idonthavespotify @1.8.3 sqlite

repository ↗ · DeepWiki ↗ · release 1.8.3 ↗
232 symbols 593 edges 69 files 10 documented · 4%
README

IDHS (I Don't Have Spotify)

Copy a link from your favorite streaming service, paste it into the search bar, and voilà! Links to the track on all other supported platforms are displayed. If the original source is Spotify you'll even get a quick audio preview to ensure it's the right track.

Note: Playlists are out of scope. Only individual tracks, albums, artists, and podcasts are supported.

Supported Streaming Services

Adapters represent the streaming services supported by the Web App and the Raycast Extension. Each adapter allows the app to convert links from one platform to others. The table below shows which features are available for each one:

Adapter Inverted Search Official API Verified Links
Spotify Yes No Yes
Tidal Yes Yes Yes
YouTube Music Yes No Yes
Apple Music Yes No Yes
Deezer Yes Yes Yes
SoundCloud Yes No Yes
Qobuz Yes No Yes
Bandcamp Yes No Yes
Pandora Yes No Yes

Architecture overview: Parsers and Adapters

IDHS extracts metadata from the provided link and uses that information to create a new query for public search engines or official APIs, such as Apple Music, YouTube, and SoundCloud. It selects the result that seems most relevant, but it cannot guarantee that the returned link is the exact track you want or even a song at all. Suggestions for improving the query-building workflow are welcome, with the main constraint being to keep requests fast and excluding brute-force retries to avoid rate limits.

Parsers (src/parsers)

Identify the incoming link's platform and extract normalized metadata (title, description, type, image, and optional audio) as well as a consistent search query. For example, a Spotify link is parsed to gather Open Graph metadata and produce a query string that represents the track/album/artist/show/episode. This query is later used to search other platforms.

Adapters (src/adapters)

Turn that normalized query into outbound links for each destination platform (Spotify, YouTube Music, Apple Music, Deezer, SoundCloud, Tidal). Each adapter is responsible for: - Performing a platform-specific search (API or HTML-based) using the normalized query - Returning a result with type, url, and flags like isVerified and notAvailable - Preferring "verified" links when the platform provides a reliable match signal

This separation keeps the system modular: parsers focus on understanding the source, while adapters focus on finding the best possible destination links.

Web App

image

Extensions

Raycast

Source code: https://github.com/raycast/extensions/tree/main/extensions/idonthavespotify

Local Setup

The list of environment variables is available in .env.test. To complete the values for the following variables: - TIDAL_CLIENT_ID and TIDAL_CLIENT_SECRET, refer to TIDAL Developer Portal. - YOUTUBE_API_KEY, refer to Google Developers Console.

Note: Spotify search uses an anonymous access token extracted from the Spotify web player (open.spotify.com) via a TOTP-based authentication flow. This is necessary because as of March 2026, Spotify restricted their Web API to require a Premium account for Development Mode and limited the available endpoints. Since this project doesn't have a premium account, we use the same internal GraphQL API that the Spotify web player itself uses. The token is auto-refreshed (~1 hour expiry) and requires no developer account.

Ensure that the values are correctly added to your .env file to configure the API keys properly.

  • To get the app up:
bun install
bun dev
  • To run with url-shortener:

Set this ENV file URL_SHORTENER_API_KEY, with the value used in docker-compose.yml

docker compose up -d
bun install
bun dev

More info

Contributions are more than welcome, just open a PR and I'll review it promptly.

Icon Generated by https://deepai.org/machine-learning-model/text2img

Extension points exported contracts — how you extend this code

BuildOptions (Interface)
(no doc)
build.config.ts
ServiceGuardConfig (Interface)
(no doc)
src/utils/service-guard.ts
YoutubeDataResponse (Interface)
(no doc)
src/parsers/youtube.ts
TidalAuthResponse (Interface)
(no doc)
src/adapters/tidal.ts
RateLimitErrorProps (Interface)
(no doc)
src/views/components/rate-limit-error.tsx
CacheEntry (Interface)
(no doc)
src/services/cache.ts
RateLimitConfig (Interface)
(no doc)
src/config/rate-limit.ts
MockEntry (Interface)
(no doc)
tests/utils/http-mock.ts

Core symbols most depended-on inside this repo

onGet
called by 61
tests/utils/http-mock.ts
cleanSearchQuery
called by 39
src/utils/query.ts
metaTagContent
called by 27
src/utils/scraper.ts
set
called by 26
src/services/cache.ts
get
called by 18
src/utils/http-client.ts
cacheSearchResultLink
called by 17
src/services/cache.ts
getCheerioDoc
called by 15
src/utils/scraper.ts
onPost
called by 14
tests/utils/http-mock.ts

Shape

Function 123
Method 43
Interface 34
Class 20
Enum 12

Languages

TypeScript100%

Modules by API surface

src/services/cache.ts26 symbols
src/utils/rate-limit-middleware.ts18 symbols
src/adapters/spotify.ts14 symbols
src/utils/http-client.ts13 symbols
tests/utils/shared.ts10 symbols
tests/utils/http-mock.ts10 symbols
src/utils/service-guard.ts10 symbols
src/views/controllers/search_card_controller.js9 symbols
src/parsers/qobuz.ts7 symbols
build.config.ts7 symbols
src/adapters/bandcamp.ts6 symbols
src/parsers/youtube.ts5 symbols

Dependencies from manifests, versioned

@eslint/js9.39.2 · 1×
@hotwired/stimulus3.2.2 · 1×
@tailwindcss/cli4.1.18 · 1×
@types/bun1.3.6 · 1×
@types/howler2.2.12 · 1×
@types/string-similarity4.0.2 · 1×
@typescript-eslint/eslint-plugin8.38.0 · 1×
@typescript-eslint/parser8.38.0 · 1×
@umami/node0.4.0 · 1×
cheerio1.1.2 · 1×
domhandler5.0.3 · 1×
eslint9.39.2 · 1×

For agents

$ claude mcp add idonthavespotify \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact