Skip to main content
Glama
SoundCloud MCP Server

SoundCloud MCP Server

by jamiew

SoundCloud MCP Server

Search SoundCloud, discover music, manage playlists, and use your library from MCP clients like Claude Code and ChatGPT.

Here's an example:

https://github.com/user-attachments/assets/89625322-d329-46ef-9987-e25396b68c23

This integration is unofficial and not affiliated with SoundCloud.

It runs locally over stdio, or on Cloudflare Workers over Streamable HTTP so you can use it from your phone.

You have to deploy the worker yourself. We don't run a shared instance at this time.

Local setup

Requires Node 22.18+ or 24.11+ LTS and pnpm. See package.json for exact versions.

  1. Create an app at https://soundcloud.com/you/apps. Save its client ID and secret. Register http://localhost:8888/callback as the redirect URI, or set a matching custom URI below.

  2. Install and configure:

    pnpm install
    cp .env.example .env

    Fill in the app credentials in .env.

  3. Build and run:

    pnpm build
    pnpm start

For personal data and writes, run pnpm run auth. It opens a browser and saves rotating tokens to ~/.soundcloud-mcp/tokens.json with mode 600. Use pnpm run auth --no-browser to print the login URL. You can also use the connect_soundcloud and auth_status tools. Public search uses cached client-credentials tokens without user login. To sign out, run pnpm run auth --sign-out or call sign_out. Both revoke the app's access at SoundCloud and delete the token file.

Claude Code

The repo's .mcp.json registers this server as soundcloud-local. Run pnpm build, fill in .env at the repo root, then start claude in the repo and approve the project server when prompted. Its paths use ${CLAUDE_PROJECT_DIR:-.}, which falls back to . because Claude Code runs the server from the project root, so no absolute paths are needed. Login tokens still live in ~/.soundcloud-mcp/tokens.json.

Claude Desktop

Open Settings > Developer > Edit Config and add:

{
  "mcpServers": {
    "soundcloud": {
      "command": "node",
      "args": ["/absolute/path/to/soundcloud-mcp/build/index.js"],
      "env": {
        "SOUNDCLOUD_CLIENT_ID": "your-client-id",
        "SOUNDCLOUD_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Fully quit and reopen Claude Desktop. Other stdio clients use the same command and environment variables. Build before connecting; clients run JavaScript, not TypeScript. Paths must be absolute: clients do not expand ~ or shell variables. If a GUI client cannot find Node, use its absolute path from which node.

The config file is at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Local environment

pnpm start and pnpm run auth load .env through Node. Direct node build/index.js calls need environment variables supplied by the client.

Variable

Purpose

SOUNDCLOUD_CLIENT_ID

Required app client ID

SOUNDCLOUD_CLIENT_SECRET

Required app secret

SOUNDCLOUD_REDIRECT_URI

Defaults to http://localhost:8888/callback; must match the app

SOUNDCLOUD_TOKEN_FILE

Defaults to ~/.soundcloud-mcp/tokens.json

MCP_DEBUG

Set true for verbose stderr logging

Related MCP server: Spotify MCP Server

Worker setup

  1. Run pnpm install. Set your worker name in wrangler.jsonc.

  2. Create a KV namespace:

    pnpm exec wrangler kv namespace create soundcloud-mcp-OAUTH_KV

    Put the returned ID in wrangler.jsonc under the OAUTH_KV binding. Keep the migrations block; on existing deployments it removes the old SoundCloudMCP Durable Object.

  3. Set each secret with pnpm exec wrangler secret put <NAME>:

    • SOUNDCLOUD_CLIENT_ID

    • SOUNDCLOUD_CLIENT_SECRET

    • COOKIE_ENCRYPTION_KEY: generate with openssl rand -hex 32

    • ALLOWED_USERS: comma-separated profile URL slugs (the name in soundcloud.com/name) or numeric user IDs. Display names do not match.

    • ENABLE_WRITE_TOOLS: set to true to offer the Social and Playlists tools. Unset, the worker only reads.

  4. Register https://<your-worker>.workers.dev/callback on your SoundCloud app. It must match exactly.

  5. Run pnpm worker:deploy, then connect your MCP client to https://<your-worker>.workers.dev/mcp and complete browser OAuth.

For local development, copy .dev.vars.example to .dev.vars, fill it in, and run pnpm worker:dev at http://localhost:8789. Register its /callback URL when testing local OAuth.

CI deploys pushes to main when the repository variable DEPLOY_ENABLED is true and secret CLOUDFLARE_API_TOKEN is set. If the repository variable ENABLE_WRITE_TOOLS is set, CI copies it into the worker secret of the same name before deploying. Forks must also set their account ID in .github/workflows/ci.yml. Reconnect clients after deploying new tools; clients cache the tool list.

Set ALLOWED_USERS unless you intend to offer public access. Empty or unset allows any SoundCloud account to use your API quota. Access is checked at the OAuth callback and tool registration, and the worker deletes stored tokens for accounts removed from the list. Public hosting also needs a review of SoundCloud's terms and shared rate limits; see #1. SoundCloud's terms restrict acting on users' behalf, so write tools stay off unless you set ENABLE_WRITE_TOOLS.

The worker serves an install page at /, a privacy page at /privacy, an icon at /icon.svg, and OAuth at /authorize, /callback, /token, and /register. It stores each user's SoundCloud tokens, encrypted, in KV until they call sign_out or 30 days pass. Update src/worker/privacy.ts if you change what the worker stores.

Tools

Both servers share these tools. Only the local server has connect_soundcloud and auth_status. On the hosted server, sign_out revokes the app's access at SoundCloud and deletes your stored tokens for every connected client.

Group

Tools

Auth

connect_soundcloud, auth_status (local only), sign_out

Search

resolve_url, search_tracks, search_playlists, search_users

Discovery

get_track, get_user, get_user_tracks, get_user_playlists, get_user_likes, get_user_reposts, get_user_web_profiles, get_related_tracks, get_related_artists

Audience

get_track_likers, get_track_reposters, get_playlist_reposters, get_user_followers, get_user_followings

Playback and browsing

get_playlist, get_playlist_tracks, get_station, get_stream_url, get_comments, next_page

Library (login)

get_profile, get_my_likes, get_my_reposts, get_my_playlists, get_my_tracks, get_my_followings, get_my_followers, is_following, get_feed, get_recently_played

Social (login)

like_track, unlike_track, like_playlist, unlike_playlist, repost_track, unrepost_track, repost_playlist, unrepost_playlist, follow_user, unfollow_user, add_comment

Playlists (login)

create_playlist, update_playlist, add_tracks_to_playlist, remove_track_from_playlist, delete_playlist

  • IDs accept numbers or URNs such as soundcloud:tracks:123; prefer URNs.

  • get_user_tracks and get_my_tracks accept sort="asc" or sort="desc".

  • The likes and reposts list tools accept kind="tracks" (default) or kind="playlists". The likes tools also accept kind="stations". get_feed accepts kind="all" to include playlist activity.

  • get_station takes a station URN from a track's or user's station_urn. like_playlist and unlike_playlist also accept station URNs.

  • Pass next_href to next_page for cursor pagination. Use SoundCloud API URLs only; authenticated requests include your token.

  • Playlist track changes replace the full tracklist. Adding or removing a track fails when SoundCloud hides some of the playlist's tracks, since the rewrite would delete them. Comments have no delete tool or public API endpoint; treat them as permanent.

  • Stream URLs expire, and blocked tracks have no stream. Full tracks stream over HLS; the only MP3 is a short preview.

  • Results list each track, user and playlist compactly: ids and URNs, title or name, uploader, duration, links, counts, access and dates. Playlists in a list show track_count without their tracks; read one with get_playlist for its tracklist. Permalinks drop utm_* tracking parameters. Pass verbose: true to get every field SoundCloud sends, such as descriptions. Resources return full objects.

Tools provide behavior annotations, structured results, and resource links. Resources include soundcloud://me/{profile,playlists,likes} and templates for soundcloud://{tracks,users,playlists}/{id}.

Development

Shared API and MCP code lives in src/{client,tools,types,server,icon}.ts. src/index.ts and src/stdio/ handle local auth and transport; src/worker.ts and src/worker/ handle Workers OAuth and HTTP.

  • pnpm check: lint, Markdown lint, both typechecks, and tests. Tests run on Node, plus a few in workerd against the bundled Worker.

  • pnpm verify: build and check the live stdio server, including read tools, resources, and a temporary playlist create/like/read/delete cycle. Requires login and writes to the connected account.

  • pnpm exec wrangler deploy --dry-run: bundle the worker without deploying. No test verifies a deployment.

See CLAUDE.md for safety and verification rules and GitHub issues for open work. Use the soundcloud-api-sync skill before adding endpoints or checking upstream changes. It records the synced-through date; issue #2 holds the coverage gaps. The standalone audit is:

node .claude/skills/soundcloud-api-sync/audit.mjs --since 2026-10-28

The official spec is authoritative. Track release notes and spec edits.

Contributors

Available Tools

53 tools
add_commentAdd commentA

Post a comment with an optional timestamp. Comments must be enabled; the API has no undo.

Inputs: body (required), trackId (required), verbose, timestamp.

add_tracks_to_playlistAdd tracks to playlistC

Append tracks to an existing playlist.

Inputs: trackIds (required), playlistId (required), verbose.

auth_statusAuth statusA
Read-only

Check whether a SoundCloud user is logged in.

Inputs: no named parameters.

connect_soundcloudConnect SoundCloudA

Log in through your browser and save the token for future sessions.

Inputs: no named parameters.

create_playlistCreate playlistA

Create a playlist with optional tracks. Private by default.

Inputs: title (required), sharing, verbose, trackIds, +1 more.

delete_playlistDelete playlistB
DestructiveIdempotent

Delete a playlist permanently.

Inputs: playlistId (required).

follow_userFollow userC
Idempotent

Follow a user.

Inputs: userId (required).

get_commentsGet track commentsB
Read-only

Get comments on a track, with their timestamps into the audio.

Inputs: trackId (required), limit, verbose. Returns: next_href, collection

get_feedGet my feedA
Read-only

List recent activity from people the connected user follows: tracks by default, or all for playlists too.

Inputs: kind, limit, verbose. Returns: next_href, collection

get_my_followersGet my followersB
Read-only

List the users who follow the connected user.

Inputs: limit, verbose. Returns: next_href, collection

get_my_followingsGet who I followC
Read-only

List the users the connected user follows.

Inputs: limit, verbose. Returns: next_href, collection

get_my_likesGet my likesB
Read-only

List tracks, playlists, or stations the connected user has liked.

Inputs: kind, limit, verbose. Returns: next_href, collection

get_my_playlistsGet my playlistsB
Read-only

List the connected user's playlists.

Inputs: limit, verbose. Returns: next_href, collection

get_my_repostsGet my repostsB
Read-only

List tracks or playlists the connected user has reposted.

Inputs: kind, limit, verbose. Returns: next_href, collection

get_my_tracksGet my uploadsB
Read-only

List the connected user's uploads. Sort: asc for oldest first, desc for newest.

Inputs: sort, limit, verbose. Returns: next_href, collection

get_playlistGet playlistC
Read-only

Get a playlist's details and its tracks.

Inputs: playlistId (required), verbose.

get_playlist_repostersGet playlist repostersC
Read-only

List the users who reposted a playlist.

Inputs: playlistId (required), limit, verbose. Returns: next_href, collection

get_playlist_tracksGet playlist tracksC
Read-only

List a page of playlist tracks.

Inputs: playlistId (required), limit, verbose. Returns: next_href, collection

get_profileGet my profileB
Read-only

Get the connected user's SoundCloud profile.

Inputs: verbose.

get_recently_playedGet recently playedB
Read-only

Tracks the connected user played recently, most recent first.

Inputs: limit, verbose. Returns: next_href, collection

get_stationGet stationA
Read-only

Get a station (system playlist) and its tracks. Tracks and users carry a station_urn; get_my_likes with kind=stations lists liked ones.

Inputs: stationUrn (required), verbose.

get_stream_urlGet stream URLA
Read-only

Get temporary audio URLs: HLS for full tracks, MP3 for previews. Blocked tracks have no stream.

Inputs: trackId (required).

get_trackGet trackC
Read-only

Get details for one track.

Inputs: trackId (required), verbose.

get_track_likersGet track likersB
Read-only

List the users who liked a track.

Inputs: trackId (required), limit, verbose. Returns: next_href, collection

get_track_repostersGet track repostersC
Read-only

List the users who reposted a track.

Inputs: trackId (required), limit, verbose. Returns: next_href, collection

get_userGet userC
Read-only

Get a user's public profile.

Inputs: userId (required), verbose.

get_user_followersGet an artist's followersC
Read-only

List the users who follow a user.

Inputs: userId (required), limit, verbose. Returns: next_href, collection

get_user_followingsGet who an artist followsC
Read-only

List the users a user follows.

Inputs: userId (required), limit, verbose. Returns: next_href, collection

get_user_likesGet an artist's likesC
Read-only

List tracks, playlists, or stations a user has liked.

Inputs: userId (required), kind, limit, verbose. Returns: next_href, collection

get_user_playlistsGet an artist's playlistsC
Read-only

List the playlists a user has published.

Inputs: userId (required), limit, verbose. Returns: next_href, collection

get_user_repostsGet an artist's repostsC
Read-only

List tracks or playlists a user has reposted.

Inputs: userId (required), kind, limit, verbose. Returns: next_href, collection

get_user_tracksGet an artist's tracksA
Read-only

List a user's uploads. Find ids with search_users. Sort: asc for oldest first, desc for newest.

Inputs: userId (required), sort, limit, verbose. Returns: next_href, collection

get_user_web_profilesGet an artist's linksB
Read-only

List the external links on a user's profile, such as a website or socials.

Inputs: userId (required), limit. Returns: items

is_followingCheck if I follow a userA
Read-only

Check whether the connected user follows a user. Unknown users count as not followed.

Inputs: userId (required). Returns: following

like_playlistLike playlistC
Idempotent

Like a playlist or a station.

Inputs: playlistId (required).

like_trackLike trackD
Idempotent

Like a track.

Inputs: trackId (required).

next_pageNext pageA
Read-only

Fetch next_href with a GET to the SoundCloud API (https://developers.soundcloud.com/docs/api/guide).

Inputs: nextHref (required), verbose.

remove_track_from_playlistRemove track from playlistC
DestructiveIdempotent

Remove one track from a playlist.

Inputs: trackId (required), playlistId (required), verbose.

repost_playlistRepost playlistB
Idempotent

Repost a playlist to the user's followers.

Inputs: playlistId (required).

repost_trackRepost trackC
Idempotent

Repost a track to the user's followers.

Inputs: trackId (required).

resolve_urlResolve a SoundCloud URLA
Read-only

Resolve a soundcloud.com or on.soundcloud.com link to a track, user, playlist, or station. Use for pasted SoundCloud links; pass station URNs to get_station.

Inputs: url (required), verbose.

search_playlistsSearch playlistsC
Read-only

Search SoundCloud playlists by keyword.

Inputs: query (required), limit, verbose. Returns: next_href, collection

search_tracksSearch tracksB
Read-only

Search SoundCloud tracks by keyword, with optional genre/tag/BPM filters.

Inputs: query (required), tags, bpmTo, limit, +6 more. Returns: next_href, collection

search_usersSearch usersC
Read-only

Search SoundCloud users/artists by keyword.

Inputs: query (required), limit, verbose. Returns: next_href, collection

sign_outSign outA
DestructiveIdempotent

Revoke this app's SoundCloud access and delete the stored token. Public search still works afterward.

Inputs: no named parameters.

unfollow_userUnfollow userC
Idempotent

Unfollow a user.

Inputs: userId (required).

unlike_playlistUnlike playlistC
Idempotent

Remove a like from a playlist or a station.

Inputs: playlistId (required).

unlike_trackUnlike trackC
Idempotent

Remove a like from a track.

Inputs: trackId (required).

unrepost_playlistRemove playlist repostC
Idempotent

Remove a repost of a playlist.

Inputs: playlistId (required).

unrepost_trackRemove repostC
Idempotent

Remove a repost of a track.

Inputs: trackId (required).

update_playlistUpdate playlistA
DestructiveIdempotent

Edit a playlist's title, description, or sharing. trackIds replaces and orders the entire tracklist.

Inputs: playlistId (required), title, sharing, verbose, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.9/5.0

    Scored across 53 tools

    Disambiguation4/5

    Tools are largely separable by a clear resource+actor pattern (get_my_likes vs get_user_likes, get_track_likers vs get_track_reposters), and descriptions add helpful boundaries. A few overlaps remain fuzzy, notably get_playlist (returns tracks) vs get_playlist_tracks, and the generic next_page which could apply to any listing tool.

    Naming Consistency4/5

    The dominant convention is consistent snake_case verb_noun (search_tracks, like_playlist, get_user_followers), applied across virtually all tools. Minor deviations (is_following, auth_status, resolve_url, next_page) are readable predicates but break the strict verb_noun pattern.

    Tool Count2/5

    53 tools is well above a comfortable surface for a single agent to select from reliably. Much of the bloat comes from parallel families (my_* mirroring user_*, separate like/unlike/repost/unrepost pairs for tracks and playlists) that could be collapsed with parameters.

    Completeness4/5

    Coverage is broad: search, detail fetches, likes/reposts/follows, playlist create/update/delete, comments, stations, streaming URLs, and auth lifecycle are all present. Gaps are minor: no comment editing or deletion, and no track upload/delete (largely an API limitation).

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      An MCP server that enables AI assistants to search, analyze, and retrieve information about audio samples from Freesound.org through their API.
      8
      2
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      MCP server for the Spotify Web API — gives Claude and other AI assistants tools to search music, control playback, manage playlists, library, and podcasts.
      47
      5
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An unofficial MCP server that provides access to Spotify's Web API through the Model Context Protocol, enabling AI assistants to search music, manage playlists, and control playback.
      29 npm
      9
      ISC