Skip to main content
Glama
rcnsh

music-warehouse-mcp

by rcnsh

An MCP server that lets an AI agent (Claude Code, Claude Desktop, Cursor and others) query the Spotify listening history stored by a music-warehouse Worker. The agent answers from your own data, years of it, not Spotify's last 50 plays. It runs locally over stdio and only reads.

NOTE

This needs your own music-warehouse deployment. If you don't have one yet, start with the warehouse'squick start.

What it does

Ask things like:

  • "What was I into in spring 2022?"

  • "When did I first play Shelter?"

  • "How has my listening changed since I moved?"

and the agent picks the right tools: fifteen of them, all read-only, covering search, plays, top artists and songs over any range, per-artist and per-song history, precomputed stats, Wrapped-style summaries, upcoming concerts, and what's playing now.

Responses are trimmed for an agent: no image URLs or Spotify API links, play times shown in the local zone, Spotify objects cut to name, artists, album and id.

Related MCP server: SpotifyScraper MCP Server

How it works

flowchart LR
  A[AI agent] <-->|stdio| M[music-warehouse-mcp]
  M -->|"GET /api/* (read token)"| W[music-warehouse Worker]

Every tool calls the Worker's /api/* routes with a read-only token. The Worker does the storage and aggregation; this server only shapes the answers.

Why stdio, not a remote server

Running locally keeps the token on your machine and needs no change to the Worker beyond the read routes. The trade-off is that claude.ai on the web and mobile can't use it: their custom connectors need a remote server with OAuth.

Requirements

  • A deployed music-warehouse Worker at a version that has /api/search and /api/top-tracks (October 2026 or later), and /api/concerts for upcoming_concerts. To sign in with Spotify instead of copying a token, it also needs Spotify sign-in.

  • Node.js 20 or later.

It isn't published to npm; install it from source as below.

Quick start

git clone https://github.com/rcnsh/music-warehouse-mcp && cd music-warehouse-mcp
npm install
npm run login -- --url https://music-warehouse.<you>.workers.dev
claude mcp add --scope user music-warehouse \
  -e MUSIC_WAREHOUSE_URL=https://music-warehouse.<you>.workers.dev \
  -- node "$PWD/dist/index.js"

Then /mcp in Claude Code shows it connected. Each step is explained below.

Setup

1. Build

git clone https://github.com/rcnsh/music-warehouse-mcp && cd music-warehouse-mcp
npm install          # also builds dist/

2. Get a read token

Sign in with Spotify (easiest). Use the Spotify account that owns the warehouse:

npm run login -- --url https://music-warehouse.<you>.workers.dev

It opens your browser (and prints the URL in case it doesn't), and once you approve, saves a read token for that warehouse to ~/.config/music-warehouse-mcp/tokens.json ($XDG_CONFIG_HOME if set), readable only by you. The token is listed on the warehouse as MCP (<hostname>) (see the warehouse's device tokens); pass --name to choose another. It expires after 90 days: the tools then say so, and you run the same command again. The server reads the file on every call, so a new sign-in needs no restart.

--url defaults to MUSIC_WAREHOUSE_URL. If you install the clone globally (npm install -g .), the same command is music-warehouse-mcp login --url ….

Or store a token yourself. On macOS, put the Worker's READ_TOKEN in the Keychain, under the service music-warehouse-mcp and your Worker's host as the account. security prompts for it, so it never lands in your shell history:

security add-generic-password -s music-warehouse-mcp -a music-warehouse.<you>.workers.dev -w

Elsewhere, set MUSIC_WAREHOUSE_TOKEN in the MCP client's config instead (see Configuration). Either one wins over a signed-in token.

IMPORTANT

Use a read token, neverADMIN_TOKEN: nothing here needs more.

3. Add it to your client

For every project:

claude mcp add --scope user music-warehouse \
  -e MUSIC_WAREHOUSE_URL=https://music-warehouse.<you>.workers.dev \
  -- node "$PWD/dist/index.js"

Run it from the clone, so $PWD is the right path. Then /mcp in Claude Code shows it connected. If you run more than one Claude Code config directory (CLAUDE_CONFIG_DIR), run the command once under each.

They take the same thing as JSON, in their MCP server config:

{
  "mcpServers": {
    "music-warehouse": {
      "command": "node",
      "args": ["/absolute/path/to/music-warehouse-mcp/dist/index.js"],
      "env": { "MUSIC_WAREHOUSE_URL": "https://music-warehouse.<you>.workers.dev" }
    }
  }
}
TIP

A GUI app may not see your shell'sPATH; if it can't start node, give its absolute path (which node).

4. Check it

MUSIC_WAREHOUSE_URL=https://music-warehouse.<you>.workers.dev npm run smoke

calls every tool once against your Worker and prints the start of each answer. Or explore interactively with npm run inspect.

Configuration

Variable

Required

Meaning

MUSIC_WAREHOUSE_URL

yes

The Worker's origin. Must be https, except on loopback (http://127.0.0.1:8787 for wrangler dev).

MUSIC_WAREHOUSE_TOKEN

no

A read token, overriding the Keychain and a signed-in token.

MUSIC_WAREHOUSE_TZ

no

IANA zone for local dates and times. Defaults to the system's.

XDG_CONFIG_HOME

no

Where login saves tokens, under music-warehouse-mcp/. Defaults to ~/.config.

The token is the first of:

  1. MUSIC_WAREHOUSE_TOKEN.

  2. The macOS Keychain entry for the Worker's host (service music-warehouse-mcp).

  3. The token npm run login saved for the Worker's origin. Tokens are saved per origin, so one is only ever sent to the warehouse that minted it.

A missing or expired token doesn't stop the server starting: each tool says how to provide one, and the next call picks it up without a restart. A rejected token (401) names the login command.

Tools

Fifteen tools, all read-only. Dates are YYYY-MM-DD local days in the configured zone.

Tool

Answers

Worker route

search

Artists and songs by name, with all-time plays. The way in to the history tools.

/api/search

get_plays

Individual plays, newest first, in a window. Pages with next_before.

/api/plays

top_artists

Plays per artist between two dates.

/api/top-artists

top_tracks

Plays per song between two dates, editions folded.

/api/top-tracks

upcoming_concerts

Ticketmaster gigs in the regions your warehouse watches, for your top artists; since for what's new.

/api/concerts

daily_play_counts

Plays per day, or summed per week or month, with a total.

/api/daily

artist_history

One artist's plays, minutes, first and last play, months, top songs.

/api/artist

track_history

The same for one song, editions folded together.

/api/track

on_this_day

Top songs on this date in each earlier year.

/api/on-this-day

get_stat

on-repeat, rhythm, top-over-time, eras or albums.

/api/stats/{name}

list_wrapped_ranges

Which ranges get_wrapped can summarise.

/api/wrapped/ranges

get_wrapped

A Wrapped-style summary of a finished range.

/api/wrapped

now_playing

What's playing right now.

/api/now-playing

recently_played_live

Spotify's last plays, including ones not stored yet.

/api/recently-played

spotify_top

Spotify's own top tracks and artists.

/api/top

NOTE

The last three are live and need the Worker's Spotify grant; the rest read stored rows and keep working when it lapses.

When a tool fails, its message says why and what to do: a rejected token names npm run login, a lapsed grant names npm run authorize in the music-warehouse repo, a stat still computing is waited out (up to 25 s) before giving up.

Development

Command

Does

npm run build

tsc → dist/

npm test

vitest: the client, formatting, sign-in, and every tool over an in-memory MCP connection

npm run typecheck

Type-checks source and tests

npm run smoke

Calls every tool once against a real Worker (needs MUSIC_WAREHOUSE_URL)

npm run inspect

Opens the MCP Inspector on dist/index.js

Tests fake fetch, so they need no Worker. The sign-in test runs the real loopback listener and plays the browser's redirect itself. npm run smoke is the end-to-end check against a real one.

Project

music-warehouse

The Worker: records your plays and serves the API

music-warehouse-gui

Native macOS app for browsing your history

music-warehouse-mcp (this repo)

MCP server so AI agents can query your history

music-warehouse-spicetify

Stats inside the Spotify desktop client

music-warehouse-wrapped

Wrapped-style stories for any range, in the browser

Licence

MIT. See LICENSE.

Available Tools

14 tools
artist_historyOne artist's whole historyA
Read-onlyIdempotent

An artist's all-time plays, estimated minutes, first and last play, plays per month, and their most-played songs. Counts only plays where they are the primary artist. Give the id from search, or the name (which also catches plays from the imported export), or both.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoSpotify artist id
nameNoArtist name, matched case-insensitively

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only/idempotent semantics, and the description adds a real behavioral constraint not in the structured data: only primary-artist plays are counted, and the name path includes imported-export data. It does not discuss result size or ordering, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with what is returned before how to call it. The output enumeration is dense but every item is a distinct aggregate, so little padding; slightly long but earns its space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of describing returns and does so explicitly; with 100% schema coverage the parameters are already documented, and usage plus the primary-artist caveat close the remaining gaps. Nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: that name is case-insensitive-ish matched via the schema and, more importantly, that the name path catches imported-export plays that the id path may miss. That is genuine decision-relevant parameter context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb+resource ('An artist's all-time plays') and enumerates the returned aggregates (minutes, first/last play, plays per month, top songs), which cleanly separates it from track_history and top_artists. The scoping clause 'Counts only plays where they are the primary artist' pins down the resource boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Tells the agent how to supply the inputs (id from search, or name) and gives a decision-relevant nuance: name 'also catches plays from the imported export'. It lacks an explicit when-not/alternative-tool statement, so it stops short of 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

daily_play_countsPlays per day, week or monthA
Read-onlyIdempotent

How many plays on each local day between two dates, quiet days as 0, optionally summed into weeks (from Monday) or months. Use month or week for spans longer than a few months.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLast day, YYYY-MM-DD; default today
fromNoFirst day, YYYY-MM-DD; default 29 days ago
group_byNoDefault day

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, closed world), so the bar for extra disclosure is lower, and the description clears it: it discloses that days are "local" (timezone semantics), that empty days are returned as 0 rather than omitted, and that weeks start Monday. These are real behavioral traits not derivable from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core behavior, then the rollup option and its selection rule. No filler and no repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter read-only tool with no output schema, the description conveys the essential shape of the result (a per-day series with zeros) and the rollup behavior. It stops just short of describing response structure or format, but nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: week buckets begin Monday, day bucketing is on the local calendar day, and week/month exist specifically for long spans. Defaults and formats are already in the schema and are not restated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise aggregation: daily play counts between two dates, with silent days materialized as 0 and optional week/month rollups. That level of specificity clearly separates it from raw-play siblings (get_plays) and ranking siblings (top_tracks, top_artists), so an agent can select it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Use month or week for spans longer than a few months" is concrete, condition-based guidance on granularity choice. It does not name alternative tools or state when this tool should be avoided, so it falls short of the explicit alternatives/exclusions a 5 requires.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playsIndividual playsA
Read-onlyIdempotent

Individual stored plays, newest first, with local time, track, artists and album. Give after and before to read a window (newest first within it). If next_before is returned, pass it as before for the next, older page. For counts over a range prefer daily_play_counts or top_artists, which are far cheaper.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoOnly plays after this: YYYY-MM-DD (local midnight), an ISO datetime, or epoch-ms
limitNoDefault 50
beforeNoOnly plays before this: same forms as `after`

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and closed-world, so safety is covered. The description adds real behavioral context beyond them: newest-first ordering, local-time values, the next_before pagination contract, and a cost signal relative to aggregate siblings. It stops short of stating default page size or limits (left to schema).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with what is returned, then windowing, then pagination, then routing to cheaper alternatives. Every clause carries information; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description earns its place by describing the record contents and the next_before return value needed for paging. Combined with full schema coverage for the three parameters, an agent has everything required to call and iterate this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema by explaining the window semantics of after/before together and tying next_before to the before parameter for paging. It does not restate formats already documented in the schema, which is the right split.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Individual stored plays') plus ordering ('newest first') and returned fields (local time, track, artists, album). It also names the sibling tools that cover the cheaper aggregate case, so an agent can place it against daily_play_counts and top_artists immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-not guidance: 'For counts over a range prefer daily_play_counts or top_artists, which are far cheaper.' It also gives the windowing recipe (after/before) and the pagination recipe (pass next_before as before), leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_statPrecomputed listening statsA
Read-onlyIdempotent

All-time aggregates, refreshed every few hours. on-repeat: songs and albums played far more than usual in the last 14 days. rhythm: listening streaks and plays by hour. top-over-time: top artists and songs per quarter and per year. eras: how taste changed between the two eras the warehouse is configured with (e.g. before and after a move). albums: most-played albums, all time and per year.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond them: the data is precomputed and refreshed only every few hours (staleness) and 'eras' depends on how the warehouse is configured, which an agent cannot learn from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core statement (all-time aggregates, refresh cadence), then a tight value-by-value enumeration with no filler or repetition. Dense but every clause carries information; only minor loss for the run-on final sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must convey what comes back, and defining each stat category does that at a conceptual level. It stops short of describing response shape, grouping, or pagination, but for a read-only aggregate tool with one enum input this is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single enum parameter's five values are otherwise opaque strings, yet the description defines each one concretely (on-repeat = last-14-day over-play, rhythm = streaks/hourly, top-over-time = per quarter/year, eras = taste shift, albums = all-time/yearly). This is the parameter's documentation in all but schema form.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource ('all-time aggregates' plus five named stat categories), so an agent knows this returns precomputed listening statistics. It does not, however, explicitly distinguish itself from siblings like top_artists, top_tracks, or daily_play_counts, which overlap in subject matter, so sibling differentiation is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied rather than stated: 'refreshed every few hours' signals this is a cached/aggregate read, contrasting with live siblings like recently_played_live or now_playing, but the description never says when to prefer this over top_artists/top_tracks. No explicit exclusions or alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_wrappedWrapped-style summaryA
Read-onlyIdempotent

A Spotify-Wrapped-style summary of a finished date range: minutes, top artists, songs and albums, biggest day, streak, listening by hour and weekday, each month’s top artist and song, discoveries and a listening age. Use a range from list_wrapped_ranges; others may be refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: valid ranges are gated by list_wrapped_ranges and other ranges 'may be refused', which is a precondition an agent would otherwise learn only by failing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, purpose and payload front-loaded, with the enumeration doing real work because there is no output schema. The constraint sentence follows the payload, and nothing is repeated from the name or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description takes on the job of describing return content and does so thoroughly, and it covers the input constraint. The gap is a few details on return shape (ordering, volume of data) and exact accepted range form, which are minor for a read-only, idempotent summary tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the burden falls on the description; it partly compensates by tying 'from'/'to' to ranges produced by list_wrapped_ranges and by requiring a 'finished' range. It never states the expected format or boundary inclusivity, which the pattern alone conveys only implicitly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific, recognizable artifact (a Wrapped-style summary) over a bounded resource (a finished date range) and enumerates exactly what it returns: minutes, top artists/songs/albums, biggest day, streak, per-month leaders, discoveries, listening age. This breadth clearly separates it from narrow siblings like top_artists or top_tracks, so an agent can pick it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use a range from list_wrapped_ranges; others may be refused' gives an explicit precondition and names the sibling that supplies valid inputs, plus a soft exclusion for unlisted ranges. There is no explicit statement of when a caller should prefer top_artists/search instead for a narrower question, which keeps it short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_wrapped_rangesWrapped ranges availableA
Read-onlyIdempotent

The date ranges get_wrapped can summarise: each year with plays, and this year so far.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so the safety profile is covered. The description adds real value beyond them by disclosing the exact contents of the returned set (one entry per year with plays, plus a partial current year), which is the key behavioral fact for a zero-argument enumeration tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with zero waste that front-loads the purpose ('the date ranges get_wrapped can summarise') and then the contents. Nothing redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter, no-output-schema listing tool, the description covers what the tool does and what comes back, which is nearly everything an agent needs. It could go one step further by noting the format of the range identifiers consumed by get_wrapped, but the gap is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no parameters, so there is nothing for the description to disambiguate; baseline 4 applies. The description usefully explains what the (implicitly returned) range values represent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names the specific resource (date ranges) and explicitly ties it to the sibling get_wrapped, so an agent can distinguish it from the other list/search tools without opening any schema. The scope of what is enumerated (each year with plays, plus this year so far) is concrete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

By naming get_wrapped the description implies this is the discovery step before calling that tool, but it never states that explicitly nor gives any when-not guidance or alternatives. Usage is inferable rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

now_playingPlaying right nowA
Read-only

What Spotify is playing right now, live, or null when nothing is. Needs the warehouse's Spotify grant.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already declaring readOnlyHint=true, openWorldHint=true, and idempotentHint=false, the bar is lower, yet the description still adds value by disclosing the null return when nothing is playing and the required Spotify grant. It does not explain rate limits or response shape, but the null semantics and auth requirement are meaningful additions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences with no filler. The core behavior (live now-playing, null fallback) is front-loaded, followed by the auth prerequisite.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, no-output-schema tool, the description covers the essential facts: what it returns, the null case, and the auth grant needed. The main remaining gap is not routing the agent versus the similar recently_played_live sibling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so per the baseline this scores 4. The description correctly implies no input is needed, and there is nothing further to document.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource and state ('What Spotify is playing right now, live') and notes the null case for nothing playing. It distinguishes itself from the playback-history siblings like get_plays and recently_played_live by emphasizing the live, instantaneous snapshot, though it does not name those alternatives explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a prerequisite ('Needs the warehouse's Spotify grant') which is useful context, but offers no explicit guidance on when to choose this over the closely related recently_played_live or get_plays tools. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

on_this_dayOn this day in earlier yearsB
Read-onlyIdempotent

The most-played songs on this calendar date in each earlier year, with that day’s total plays.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoYYYY-MM-DD; default today

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent and closed-world, so the safety profile is covered. The description adds useful data semantics, per-year grouping and a per-day play total, but says nothing about how many years are returned, ordering, or output shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense sentence with zero filler, front-loading what is returned before the qualifier about totals. Nothing needs trimming or reordering.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-optional-parameter, read-only lookup with no output schema, the description covers purpose and result content adequately. It would be slightly stronger if it hinted at the response shape (e.g. one entry per year) since no output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single optional 'date' parameter is documented there with format and default, so the schema does the heavy lifting. The description adds no format or fallback detail beyond 'this calendar date'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource and scope: most-played songs on this calendar date for each earlier year, plus that day's play totals. An agent can distinguish it from track_history or daily_play_counts, though it never names those siblings explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no statement of when this beats track_history/daily_play_counts, and no exclusions. The only usable hint (date defaults to today) lives in the schema rather than the description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

recently_played_liveRecently played, live from SpotifyA
Read-only

Spotify's own last plays (at most 50), including ones the warehouse has not stored yet (it polls every 30 minutes). For anything older use get_plays. Needs the Spotify grant.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoDefault 10

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=true, openWorldHint=true), and the description adds genuinely non-obvious behavior: the warehouse polls every 30 minutes, so results can include plays not yet persisted, and the call depends on a Spotify grant. It does not mention rate limits or ordering, which keeps it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the resource and the key freshness caveat, then the alternative, then the prerequisite. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description still tells the agent what comes back (last plays, capped at 50, possibly unstored), what the freshness semantics are, and what auth is needed. Nothing essential to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already carries the default (10) and the maximum (50). The description's 'at most 50' largely restates that ceiling, so it adds little semantics beyond the structured field — baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Spotify's own last plays, at most 50') and explicitly frames the scope as the live, not-yet-warehoused view. It names sibling get_plays as the contrasting tool, so an agent can distinguish this from every other history tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (recent/live plays not yet stored) and when-not ('For anything older use get_plays'), plus the prerequisite 'Needs the Spotify grant'. Both routing and the auth condition are stated rather than inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spotify_topSpotify's top listsA
Read-only

Spotify's own top tracks and artists, live. short_term is about 4 weeks, medium_term about 6 months, long_term about a year. For exact counts over any range, use top_artists or get_stat instead. Needs the Spotify grant.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoOnly one list; default both
limitNoDefault 12
rangeNoDefault long_term

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so safety is covered. The description adds non-obvious context: 'live' implies real-time, uncached data (consistent with idempotentHint=false), and 'Needs the Spotify grant' flags an authorization prerequisite. Return format and limit behavior remain unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, each load-bearing: identity, range semantics, alternative routing, auth prerequisite. Front-loaded with the tool's identity and no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description covers identity, range meaning, routing and auth. It does not describe the response shape or pagination, but for a small three-parameter read tool with full schema coverage it is close to sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description genuinely extends the schema by defining short_term (~4 weeks), medium_term (~6 months) and long_term (~1 year) — the enum values alone convey none of that. That is real added meaning beyond the structured field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (Spotify's own top tracks and artists) with the qualifier 'live', and names sibling tools (top_artists, get_stat) as alternatives. It is mostly distinguishable, though the boundary between this and top_tracks/top_artists (whose data it returns) is left implicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'For exact counts over any range, use top_artists or get_stat instead.' It also defines the meaning of each range value, which is the key selection criterion. It stops short of saying when NOT to use it relative to top_tracks, but the guidance is concrete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

top_artistsTop artists over a date rangeA
Read-onlyIdempotent

Play counts per artist between two local dates (inclusive), most played first. Credits every artist on a track. Defaults to the last 30 days. Ranges up to 3,660 days.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLast day, YYYY-MM-DD; default today
fromNoFirst day, YYYY-MM-DD; default 29 days ago
limitNoDefault 50

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint, so the safety profile is covered. The description adds meaningful behavioral detail beyond annotations: inclusive local dates, a default 30-day window, a 3,660-day max span, and the policy of crediting every artist on a track. It stops short of describing return structure or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight, front-loaded fragments communicate purpose, ordering, counting semantics, defaults, and range limits. Every sentence earns its place with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description is expected to carry more return-value context. It conveys output ordering and a key counting rule but does not specify the returned fields (e.g., artist name, id, count) or pagination behavior. Those are minor gaps for a straightforward list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds value beyond the schema by clarifying that dates are local and inclusive, and by specifying a maximum range of 3,660 days that is not expressed in the schema. It does not add meaning for the limit parameter beyond the schema's stated default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource (play counts per artist), scope (between two local dates, inclusive), ordering (most played first), and notable counting semantics (credits every artist on a track). It clearly distinguishes the output from a simple per-track count, but does not explicitly differentiate this tool from siblings like top_tracks or artist_history.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: retrieve top artists over a date range, with defaults and a maximum span given. However, there is no explicit when-to-use guidance or comparison to alternatives such as top_tracks, artist_history, or search. It leaves the agent to infer the selection context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

top_tracksTop songs over a date rangeA
Read-onlyIdempotent

Play counts per song between two local dates (inclusive), most played first, with editions of a song (single, album, remaster) folded together. Use this for "my top songs in July" or "most played song last year". Defaults to the last 30 days. Ranges up to 3,660 days.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLast day, YYYY-MM-DD; default today
fromNoFirst day, YYYY-MM-DD; default 29 days ago
limitNoDefault 20

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the read-only/idempotent profile, and the description adds real behavioral context beyond them: editions are collapsed together, results are sorted by play count, dates are local and inclusive, and the window defaults to 30 days with a 3,660-day cap. It doesn't describe pagination or what a truncated/empty result looks like, so it's not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with what the tool returns and how it aggregates, followed by usage examples and constraints. Every sentence carries information; no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does so reasonably by naming the unit (play counts per song) and ordering. It's complete enough to call correctly, though it could say more about result shape (e.g. fields returned) given no output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds semantics the schema lacks: the dates are 'local' and 'inclusive', the default window is the last 30 days, and the maximum span is 3,660 days (the schema's limit field has no such range note). This is meaningful extra meaning on top of a fully documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('play counts per song'), the ordering ('most played first'), and the aggregation rule ('editions of a song ... folded together'). An agent can distinguish this from top_artists (artists) and track_history (per-track detail) without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete usage examples ('my top songs in July', 'most played song last year') plus the default window and max range, so the agent knows when this tool is the right fit. It never names an alternative to avoid (e.g. track_history or spotify_top), so it stops short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

track_historyOne song's whole historyA
Read-onlyIdempotent

A song's all-time plays, estimated minutes, first and last play, and plays per month, with every edition of it (single, album, remaster) folded together. Takes a track id: use search to find one by name.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesSpotify track id

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and closed-world behavior, so the safety profile is covered. The description adds genuinely useful behavioral context beyond that: it aggregates across every edition (single, album, remaster) rather than just one track release. It stops short of noting auth or pagination, hence not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loading the return contents before the id requirement. Every clause earns its place, though the parenthetical edition list is slightly dense.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the burden of explaining return values and does so thoroughly, including the edition-folding semantics. An agent has enough to call it correctly; only minor gaps (auth, whether the id must be exact) remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single parameter is fully documented as 'Spotify track id'. The description restates the type and adds the practical guidance on finding an id via search, but adds no syntax or format detail beyond the schema. Baseline 3 is appropriate for a fully-covered single param.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource and enumerates exactly what it returns (all-time plays, estimated minutes, first/last play, plays per month), plus the edition-folding behavior. It doesn't explicitly distinguish itself from the analogous sibling artist_history, but an agent reading it knows precisely what this tool produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives one routing hint ('use search to find one by name'), which covers how to obtain the required id. It does not say when to prefer this over get_plays, daily_play_counts, or artist_history, so alternative selection is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 14 tool updatesv0.1.0
    • First observedartist_history
    • First observeddaily_play_counts
    • First observedget_plays
    • First observedget_stat
    • First observedget_wrapped
    • First observedlist_wrapped_ranges
    • First observednow_playing
    • First observedon_this_day
    • First observedrecently_played_live
    • First observedsearch
    • First observedspotify_top
    • First observedtop_artists
    • First observedtop_tracks
    • First observedtrack_history

TDQS

A4/5.0

Scored across 14 tools

Disambiguation4/5

Most tools target clearly distinct query types: name search, raw plays, top lists, daily counts, entity histories, Wrapped summaries, precomputed aggregates, and live Spotify state. Some overlap remains between top_artists/top_tracks, get_stat aggregates, get_wrapped, and stored vs live recent plays, but descriptions provide explicit guidance on when to use which.

Naming Consistency4/5

All names use readable snake_case with no camelCase or chaotic variation. The set is not a strict verb_noun pattern throughout, since many tools are noun phrases like artist_history, now_playing, and spotify_top, but the convention is still predictable and consistent.

Tool Count5/5

Fourteen tools fits comfortably within the ideal 3-15 range for an analytics-style server. Each tool covers a distinct listening-history or Spotify-live query, and there is no excessive filler or fragmentation.

Completeness4/5

The surface strongly covers read-only listening analytics: search, raw plays, top artists/tracks, daily counts, artist/track histories, on-this-day, Wrapped, precomputed stats, and live Spotify tools. Minor gaps remain, such as no direct per-artist or per-track query over an arbitrary date range beyond top lists, and no metadata/import management, but core workflows are covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Connects AI assistants to a self-hosted Your Spotify instance and Spotify's Web API for deep listening analytics and playback control. It enables users to query unlimited listening history, generate custom Wrapped summaries, and manage playlists through natural language.
    18
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to securely connect to a user's personal Discogs music collection for mood-aware searching, analytics, and context-aware recommendations via Cloudflare Workers.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Lets AI assistants answer questions about your Spotify listening history, including taste evolution, top artists, recently played, and playlist analysis.
    8
    72 npm
    MIT