Set up the spotatui MCP server

August 8, 2026 · View on GitHub

Give this to your AI agent. Copy the line below into Claude Code, Codex, Gemini CLI, Cursor, or any agent that can read files and run commands:

Read docs/mcp-setup.md in the spotatui repo (or
https://raw.githubusercontent.com/LargeModGames/spotatui/main/docs/mcp-setup.md)
and set up the spotatui MCP server for me, following it exactly.

Everything the agent needs is in this file. It is written as instructions for the agent, so it is fine to hand over verbatim.


What this sets up

spotatui exposes your music player and listening history as MCP tools, so an AI agent can act as your DJ: read what you have been listening to, search the catalogue, and queue tracks. No API key is required — the agent you already have installed and authenticated does the thinking.

Your agent ──stdio(MCP)──> `spotatui mcp` ──loopback TCP──> running spotatui

Instructions for the agent

Follow these steps in order. After each step, run the verification command and do not continue until it passes.

Step 0 — Read this before running anything

Never run spotatui mcp to test the setup. That command is the server: it reads JSON-RPC from stdin and blocks until the stream closes, so it will appear to hang and you will learn nothing from it.

Use spotatui mcp status instead. It is safe, returns immediately, and exits non-zero when the setup is not ready:

spotatui mcp status          # human-readable report
spotatui mcp status --json   # same thing, machine-readable

Run it now to see the starting state. Two outcomes are both normal before setup, and they mean different things:

  • it fails at control-file — the binary is right, the socket is not on yet. Go to Step 2.
  • it fails with unrecognized subcommand 'mcp' — this build does not have the feature at all. Go to Step 1.

Step 1 — Confirm the binary has the feature compiled in

spotatui mcp status
  • If the first line reads ok binary spotatui <version> with the mcp-server feature, continue to Step 2.

  • If the command fails with something like unrecognized subcommand 'mcp', this build does not include the feature. Install one that does:

    cargo install --locked spotatui --features mcp-server
    # or, from a checkout:
    cargo install --locked --path . --features mcp-server
    

    The feature is not in default, so a plain cargo build omits it. Do not assume any particular binary has it — the spotatui mcp status check above is the way to tell.

Step 2 — Turn on the control socket

The socket is opt-in. Edit spotatui's config.yml and set, under the behavior: key:

behavior:
  mcp_enabled: true

Create the behavior: section if the file does not have one. Do not remove or reorder anything else in the file.

Which config.yml. spotatui resolves its config directory as $XDG_CONFIG_HOME/spotatui when XDG_CONFIG_HOME is set to an absolute path, and ~/.config/spotatui otherwise — so do not assume the second one. spotatui mcp status prints the resolved directory; use the path it reports. On Windows the fallback is %USERPROFILE%\.config\spotatui.

Step 3 — Restart spotatui

The socket is opened at startup, so a running instance will not pick this up.

Ask the user to quit spotatui and start it again. Do not try to start spotatui yourself — it is a full-screen terminal application and needs a real terminal; launching it from a tool call will either fail or hang.

When it starts, spotatui briefly shows MCP server listening on 127.0.0.1:<port>.

Step 4 — Verify the connection

spotatui mcp status

All three checks must read ok, and the exit code must be 0:

ok   binary         spotatui 0.40.3 with the mcp-server feature
ok   control-file   found (port 43219, pid 12345) at /home/you/.config/spotatui/mcp.json
ok   connection     handshake accepted; server speaks protocol 2026-07-28

The control-file line reports the path spotatui actually resolved, which is where its config.yml lives too.

If connection fails but control-file passed, the control file is stale from a previous run — have the user restart spotatui again.

Step 5 — Register the server with your client

Plugin-capable clients can replace this step. The repo ships an agent plugin (agent-plugin/) that registers this server and adds a DJ skill in one install: in Claude Code, /plugin marketplace add LargeModGames/spotatui then /plugin install spotatui@spotatui; clients that read the Agent Plugins format load the same directory. See agent-plugin/README.md. Steps 1-4 above are still required either way — the plugin registers the server, it cannot build the binary, set mcp_enabled, or start spotatui.

If you installed the plugin, skip the rest of this step and go to Step 6. Running a registration command as well would register the server twice, and its tools would appear under both names.

Otherwise, use whichever line matches the client you are running in:

# Claude Code
claude mcp add spotatui -- spotatui mcp

# Codex  (usage is `codex mcp add <NAME> -- <COMMAND>...`)
codex mcp add spotatui -- spotatui mcp

For any other client, add a stdio server with command spotatui and args ["mcp"]. As raw JSON (Claude Desktop, Cursor, Windsurf, Zed and others use this shape):

{
  "mcpServers": {
    "spotatui": {
      "command": "spotatui",
      "args": ["mcp"]
    }
  }
}

TOML, for ~/.codex/config.toml:

[mcp_servers.spotatui]
command = "spotatui"
args = ["mcp"]

If spotatui is not on PATH for the client's environment, use the absolute path: command -v spotatui on Linux and macOS, Get-Command spotatui in PowerShell.

Step 6 — Confirm the tools are visible

Reload or restart your client so it picks up the new server, then list your tools. You should see eight, all prefixed with the server name (mcp__spotatui__… in Claude Code, or mcp__plugin_spotatui_spotatui__… if you installed the plugin — a plugin's tools carry its name too):

ToolWhat it does
get_listening_historyAggregate taste summary: top artists, tracks, albums, recent plays
get_now_playingCurrent track, play state, queue depth
get_queueUpcoming tracks
search_tracksFind tracks and their URIs, each marked owned or new
queue_tracksAdd tracks by URI, or by title + artist; exclude_owned skips ones they already have
play_nowStart a track immediately
skip_trackSkip to the next track
set_dj_vibeRecord a standing direction for the built-in auto-queue DJ (does not start it)

Then confirm it end-to-end by calling get_now_playing. A successful call proves the whole chain. Report the result to the user and stop — setup is done.


Troubleshooting

SymptomCause and fix
unrecognized subcommand 'mcp'Binary built without the feature — Step 1.
spotatui mcp status fails at control-filemcp_enabled is not set, or spotatui has not been restarted since it was — Steps 2 and 3.
Fails at connection, control-file passedStale control file from a killed process. Restart spotatui.
spotatui mcp seems to hangWorking as intended: that command is the server. Use spotatui mcp status.
Client shows the server as failedThe client spawns spotatui mcp, which needs spotatui on its PATH. Re-register with the absolute path from command -v spotatui.
Tools appear but every call returns "spotatui is not available"The relay started but no player is running. Start spotatui.
A tool returns "spotatui has no Spotify session"The catalogue tools need Spotify. Log in from the spotatui UI.
Tracks are "not found" when queueing by nameExpected for a track that is not in the catalogue. queue_tracks reports which ones it dropped — read the result and pick alternatives.
The first search_tracks says the playlist index is still buildingExpected once per spotatui run. owned reflects Liked Songs only for that one search; the crawl runs in the background so every search after it is complete. Search again if it matters.
exclude_owned returns "could not read your playlists"The playlist crawl failed, so the filter could not run and nothing was queued rather than being queued unfiltered. Retry, or call again without exclude_owned.

To undo everything: remove the server from your client (claude mcp remove spotatui), set mcp_enabled: false, and restart spotatui.


Notes for the agent, once it is working

  • Call get_listening_history first when choosing music. It returns aggregate names only — no identifiers, no timestamps.
  • queue_tracks can partially fail. It reports which tracks it could not find. Read the result rather than assuming everything was queued.
  • Prefer queue_tracks over play_now unless the user asked to hear something immediately; play_now interrupts what is playing.
  • search_tracks tells you what they already have. Every result is marked [owned] or [new]owned meaning it is in their Liked Songs or in a playlist they own or collaborate on. When they asked for something new, pick the ones marked new. When they asked for a specific track, queue it whether they own it or not; that is what they asked for.
  • queue_tracks takes exclude_owned: true if you would rather have the guarantee than do the filtering yourself. It skips anything they already have and reports what it skipped, and it substitutes nothing — so you may get back fewer tracks than you asked for. Leave it off (the default) when the user named specific tracks.
  • set_dj_vibe does not start anything. It records a standing direction for the optional in-TUI auto-queue DJ, which may be switched off or not built into this binary at all. The result tells you which; when nothing will act on it, the vibe is still stored and comes back from get_listening_history, so honour it yourself when you queue. There is no tool to turn continuous auto-queue on — that is the user's key in the TUI. To keep music flowing, poll get_now_playing for queue_depth and top up with queue_tracks.
  • Every change you make raises a visible status message in the user's TUI, so they can see what you did.

What the user should know

  • The socket listens on loopback only and requires a token from mcp.json in the same config directory (mode 0600, in a 0700 directory). A local process that can read that file can control your player and read your listening history — the same trust level as the existing Spotify token cache.
  • Data sent to your agent's model provider: whatever the agent chooses to send. get_listening_history returns track, artist, and album names only.
  • Turning it off is one line: mcp_enabled: false, then restart.

See also docs/ai-dj.md for the DJ that runs inside spotatui without an agent, and docs/configuration.md for every config key.