mcp server
sonora-mcp
Security-first Spotify MCP server (stdio): OAuth PKCE without client secret, least-privilege scopes, tokens kept outside the repo.
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- Node.js 20 or newer
{
"mcpServers": {
"sonora-mcp": {
"command": "npx",
"args": [
"-y",
"sonora-mcp"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 29, 2026Sonora MCP
A small, security-first Model Context Protocol server for Spotify. Ask your AI assistant what is playing, search the catalogue and (optionally) play or pause music.
Español: README.es.md
- OAuth Authorization Code + PKCE, no Client Secret. Nothing sensitive to leak from the repo or your MCP config.
- Least privilege. Default
read-onlymode requests two read scopes. Write tools are not registered at all unless you opt intoplaybackmode. - Tokens stay on your machine, outside any repo:
~/.config/sonora-mcp/(dir0700, file0600, atomic writes, automatic refresh). - No telemetry. The only hosts contacted are
accounts.spotify.comandapi.spotify.com. - Built for Spotify's 2026 API: search
limit≤ 10, Development Mode aware error messages. - TypeScript (strict, ESM), official
@modelcontextprotocol/sdk, stdio transport, zod-validated inputs, mocked-HTTP test suite.
Status
Sprint 1 is implemented (see Roadmap). Not yet published to npm: install from source.
Tools
| Tool | Mode | Description |
|---|---|---|
search | all | Search tracks, albums, artists, playlists (types array, limit 1–10, offset paging) |
now_playing | all | Current track/episode, progress and device |
play | playback | Start/resume playback, optionally a Spotify URI and device |
pause | playback | Pause playback |
Modes and scopes
| Mode (default first) | Scopes requested | Tools |
|---|---|---|
read-only | user-read-playback-state, user-read-currently-playing | search, now_playing |
playback | the two above + user-modify-playback-state | + play, pause |
Choose with SONORA_MODE or --mode (applies to both login and serve). If you log in as read-only and
later start the server as playback, tools return a clear message asking you to run
sonora-mcp login --mode playback.
Requirements
- Node.js ≥ 24
- A Spotify account. Spotify's Development Mode (Feb 2026 rules) requires the app owner to have Premium, allows up to 5 authorised users and a single Client ID per developer. Playback control also needs Premium.
Install (from source)
git clone https://github.com/encodi/sonora-mcp.git
cd sonora-mcp
npm ci
npm run build
Configure Spotify (step by step)
-
Open the Spotify Developer Dashboard and log in.
-
Create app.
- App name / App description: anything (e.g. "Sonora MCP", "Personal MCP server").
- Redirect URIs: add exactly
http://127.0.0.1:8888/callbackand click Add. Use the IP literal127.0.0.1, notlocalhost— Spotify only allows HTTP for loopback IPs. To use another port, setSPOTIFY_REDIRECT_PORTand registerhttp://127.0.0.1:<port>/callback. - Which API/SDKs are you planning to use? → Web API.
- Accept the terms and Save.
-
Open the app → Settings and copy the Client ID. You do not need (and must not use) the Client Secret.
-
In Settings → User management, make sure your own Spotify account (name + email) is listed (Development Mode only works for allow-listed users).
-
Export the Client ID in the shell where you will log in:
export SPOTIFY_CLIENT_ID=<your client id>
Log in
# read-only (default)
node dist/index.js login
# or, to enable play/pause
node dist/index.js login --mode playback
The command prints an authorization URL (and tries to open your browser; add --no-open to skip that).
Approve the request in Spotify; the browser is redirected to http://127.0.0.1:8888/callback, the server
validates state, exchanges the code with the PKCE verifier and stores the tokens in
$XDG_CONFIG_HOME/sonora-mcp/tokens.json (or ~/.config/sonora-mcp/tokens.json).
Other commands:
node dist/index.js status # who/what is stored (never prints tokens)
node dist/index.js logout # deletes the token file
node dist/index.js --help
Use with an MCP client
Claude Desktop, Cursor, and any stdio MCP client (use absolute paths):
{
"mcpServers": {
"sonora": {
"command": "node",
"args": ["/absolute/path/to/sonora-mcp/dist/index.js"],
"env": {
"SPOTIFY_CLIENT_ID": "<your client id>",
"SONORA_MODE": "read-only"
}
}
}
}
The Client ID is not a secret, but keep it in your local client config, not in a repository.
Configuration reference
| Variable | Default | Description |
|---|---|---|
SPOTIFY_CLIENT_ID | – (required) | Client ID of your Spotify app |
SPOTIFY_REDIRECT_PORT | 8888 | Loopback callback port (register the matching redirect URI) |
SONORA_MODE | read-only | read-only or playback |
SONORA_LOG_LEVEL | info | error, warn, info, debug (logs go to stderr, redacted) |
XDG_CONFIG_HOME | ~/.config | Base directory for sonora-mcp/tokens.json |
Security
See SECURITY.md for the policy and private reporting. In short: PKCE (S256) without a secret,
constant-time state check, loopback-only one-shot callback server, tokens 0600 in a 0700 directory outside
the repo, redacted logs, minimal scopes, write tools opt-in, no telemetry, no hosts besides Spotify's.
Development
npm ci
npm run format:check && npm run lint && npm run typecheck && npm test && npm run build
Contributing: CONTRIBUTING.md · Process: docs/WORKFLOW.md · Board: docs/BOARD.md.
Roadmap
Tracked in milestones and issues.
- Sprint 1 – Fundamentos: skeleton, CI, PKCE login/logout, token storage, HTTP client,
search,now_playing,play/pause, modes. ✅ - Sprint 2 – Biblioteca y playlists: playlists and their items, saved tracks, library save/remove, create playlists (new opt-in modes/scopes).
- Sprint 3 – Cola, dispositivos y robustez: queue, devices/transfer, skip/seek/volume/shuffle/repeat, rate-limit backoff, error catalogue.
- v0.1.0: npm publishing with provenance, changelog, client setup guides, security review.
License
MIT © 2026 Enrique Coronado. Not affiliated with Spotify AB. "Spotify" is a trademark of Spotify AB.