Skip to main content
Glama
Dthen

listenbrainz-mcp

by Dthen

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
pingA

Health check. Returns {"ok": true}.

get_listensA

Fetch a user's listens, or their currently-playing track.

Endpoints: GET /1/user/{user_name}/listens GET /1/user/{user_name}/playing-now (when playing_now=True)

Args: user_name — ListenBrainz username; count — 1..1000 (default 25); min_ts/max_ts — unix timestamps (mutually exclusive); playing_now — return the currently-playing track instead of listen history. When playing_now=True, count/min_ts/max_ts are ignored entirely.

get_listen_summaryA

Total listen count and connected services for a user, merged.

Endpoints: GET /1/user/{user_name}/listen-count GET /1/user/{user_name}/services

Args: user_name — ListenBrainz username whose total listen count and connected services are fetched.

Both responses' payloads are merged into a single payload object. If either call returns an error envelope, it is returned as-is (fail fast — errors are never merged with success payloads).

submit_listenA

Submit listens to ListenBrainz (single, playing_now, or import), or delete the user's currently-playing track.

Endpoints: POST /1/submit-listens POST /1/playing-now/delete

Args: listen_type — one of "single", "playing_now", "import"; listens — list of listen dicts, each with listened_at (unix ts, not for playing_now) and track_metadata {track_name, artist_name, ...}; return_msid — ask the server to return generated MSIDs. Import mode allows at most 1000 listens per request. clear_playing_now — instead of submitting, POST to /1/playing-now/delete; takes precedence over listen_type/listens, which are ignored entirely when it is True.

manage_listenA

Delete a listen, or read/set the user's latest-import timestamp.

Endpoints: POST /1/delete-listen (action="delete_listen") GET /1/latest-import (action="get_latest_import") POST /1/latest-import (action="set_latest_import")

Args: action — "delete_listen" (needs listened_at + track_metadata), "get_latest_import" (needs user_name), or "set_latest_import" (needs user_name + timestamp). listened_at and timestamp are unix seconds. All are auth-required upstream. For get_latest_import, upstream's literal null error/status fields are stripped, so the envelope never contains a misleading "error": null.

search_usersA

Search ListenBrainz users by name.

Endpoints: GET /1/search/users

Args: search_term — text to search for; page_size — results per page, clamped to at most 100 (default 25). NOTE the wire call goes to /1/search/users/ WITH a trailing slash — required live (2026-08-22 probe; slashless spelling 308s into an error envelope), mirroring the metadata lookup precedent.

get_similar_usersA

Find a user's similar users, or how similar two users are.

Endpoints: GET /1/user/{user_name}/similar-users GET /1/user/{user_name}/similar-to/{other_user_name}

Args: user_name — ListenBrainz username; other_user_name — when given, compare user_name against this second user instead of listing user_name's similar users.

get_user_statsA

Fetch a user's top entities (artists, releases, etc.).

Endpoints: GET /1/stats/user/{user_name}/artists GET /1/stats/user/{user_name}/releases GET /1/stats/user/{user_name}/release-groups GET /1/stats/user/{user_name}/recordings

Args: user_name — ListenBrainz username; entity — one of "artists", "releases", "release-groups", "recordings"; range — one of this_week/this_month/this_year/week/month/quarter/year/half_yearly/ all_time (default all_time); count — 1..1000 (default 25); offset — non-negative (default 0).

get_activity_statsA

Fetch a user's listening activity, maps, and activity summaries.

Endpoints: GET /1/stats/user/{user_name}/listening-activity GET /1/stats/user/{user_name}/daily-activity GET /1/stats/user/{user_name}/artist-map GET /1/stats/user/{user_name}/year-in-music GET /1/stats/user/{user_name}/year-in-music/{year} GET /1/stats/user/{user_name}/year-in-music/legacy/{year} GET /1/stats/user/{user_name}/artist-activity GET /1/stats/user/{user_name}/era-activity GET /1/stats/user/{user_name}/genre-activity GET /1/stats/user/{user_name}/artist-evolution-activity

Args: user_name — ListenBrainz username; type — one of listening-activity, daily-activity, artist-map, year-in-music, year-in-music-latest, year-in-music-legacy, artist-activity, era-activity, genre-activity, artist-evolution-activity; year — required when type is year-in-music or year-in-music-legacy (not required for year-in-music-latest; ignored otherwise); range — same enum as get_user_stats (default all_time); count — 1..1000 (default 25); offset — non-negative (default 0). For listening-activity, daily-activity, artist-map, artist-activity, era-activity, genre-activity, year-in-music-latest, and artist-evolution-activity, count/offset are not sent (the API ignores them).

get_sitewide_statsA

Fetch sitewide top entities and activity.

Endpoints: GET /1/stats/sitewide/artists GET /1/stats/sitewide/releases GET /1/stats/sitewide/release-groups GET /1/stats/sitewide/recordings GET /1/stats/sitewide/listening-activity GET /1/stats/sitewide/artist-map GET /1/stats/sitewide/artist-activity GET /1/stats/sitewide/era-activity GET /1/stats/sitewide/artist-evolution-activity

Args: type — one of artists, releases, release-groups, recordings, listening-activity, artist-map, artist-activity, era-activity, artist-evolution-activity; range — same enum as get_user_stats (default all_time); count — 1..1000 (default 25); offset — non-negative (default 0). For listening-activity, artist-map, artist-activity, era-activity, and artist-evolution-activity, count/offset are not sent.

get_entity_listenersA

Fetch listeners for an artist or release-group by MBID.

Endpoints: GET /1/stats/artist/{artist_mbid}/listeners GET /1/stats/release-group/{release_group_mbid}/listeners

Args: entity — one of "artist", "release-group"; mbid — the MusicBrainz ID of the entity; range — same enum as get_user_stats (default all_time).

get_recording_metadataA

Fetch MusicBrainz metadata for one or more recordings by MBID.

Endpoints: GET /1/metadata/recording/ (single mbid) POST /1/metadata/recording/ (multiple mbids or batch=True)

Args: mbids — one or more recording MBIDs; inc — optional space-separated subset of artist tag release; batch — force the POST batch route even for a single mbid (default false). The POST body carries {"recording_mbids": [...], "inc": "..."}; the GET uses a comma-separated recording_mbids query param. On that POST body, inc must be a JSON string ("artist tag") — a JSON list is rejected by the live API. Responses are keyed by MBID.

get_entity_metadataA

Fetch MusicBrainz metadata for artists or release-groups by MBID.

Endpoints: GET /1/metadata/artist/ GET /1/metadata/release_group/

Args: entity — one of "artist", "release_group"; mbids — one or more MBIDs of that entity, at most 75 items (comma-joined on the wire; live-probed 2026-08-25 — both entity routes 502 beyond 75); inc — optional space-separated subset of artist tag release. Upstream rejects entity/inc combinations it does not support (e.g. release for artists).

lookup_metadataA

Look up a recording MSID/MBID from listen metadata names.

Endpoints: GET /1/metadata/lookup/ (single lookup by names) POST /1/metadata/lookup/ (batch of items)

Args: artist/release/track — at least one required; mapped on the wire to artist_name/release_name/recording_name. duration — track length in seconds; recording_mbid — known MBID to disambiguate. batch — list of item dicts; when given it takes PRECEDENCE over artist/release/track (which are ignored) and POSTs {"items": [...]} instead.

get_manual_mappingA

Fetch the manual MSID→MBID mapping for a recording MSID.

Endpoints: GET /1/metadata/get_manual_mapping/

Args: recording_msid — the MessyBrainz ID to look up.

submit_manual_mappingA

Submit a manual MSID→MBID mapping (auth-required upstream).

Endpoints: POST /1/metadata/submit_manual_mapping/

Args: recording_msid — the MessyBrainz ID; recording_mbid — the MusicBrainz ID it should map to. Body is sent verbatim as {"recording_msid": ..., "recording_mbid": ...}.

get_popularityA

Fetch ListenBrainz popularity: total listen + listener counts.

Endpoints: POST /1/popularity/recording (mode="batch") POST /1/popularity/artist (mode="batch") POST /1/popularity/release (mode="batch") POST /1/popularity/release-group (mode="batch") GET /1/popularity/top-recordings-for-artist/{artist_mbid} (mode="top", entity="recording") GET /1/popularity/top-release-groups-for-artist/{artist_mbid} (mode="top", entity="release-group")

Args: mode — "batch" (default) counts for explicit MBIDs; "top" for an artist's most-listened entities. batch: entity — one of "recording", "artist", "release", "release-group"; mbids — 1..1000 MBIDs POSTed as {"_mbids": [...]} (live-verified body key); the response keeps request order and returns null counts for unknown MBIDs. top: entity — "recording" or "release-group"; artist_mbid — required MBID of the artist; count — 1..1000 (default 25; integers only — non-integers get an error envelope). Top mode requires authentication upstream (401 without LISTENBRAINZ_TOKEN). Batch mode ignores artist_mbid and count.

get_recommendationsA

Fetch raw collaborative-filtering recording recommendations.

Endpoints: GET /1/cf/recommendation/user/{user_name}/recording

Args: user_name — ListenBrainz username; count — 1..1000 (default 25); offset — non-negative (default 0). Returns the RAW CF payload: recording mbids + scores only (no titles/artists) — resolve against MusicBrainz if you need names. Experimental upstream: model output quality varies.

manage_recommendation_feedbackA

Submit, delete, or read recommendation (rating) feedback.

Endpoints: POST /1/recommendation/feedback/submit (action="submit") POST /1/recommendation/feedback/delete (action="delete") GET /1/recommendation/feedback/user/{user_name} (action="get_user") GET /1/recommendation/feedback/user/{user_name}/recordings (action="get_recordings")

Args: action — one of submit, delete, get_user, get_recordings. submit: rating required — love/like/hate/dislike/ bad_recommendation; recording_mbid required. delete: recording_mbid required. get_user/get_recordings: user_name required; count — 1..1000 (default 25); offset — non-negative (default 0). get_recordings ALSO requires mbids — a non-empty list of recording MBIDs, at most 75 items (sent comma-separated as the required mbids query parameter; upstream 400s without it and dies on URL length beyond ~75). NOTE: delete/get_user/get_recordings run on the SINGULAR /recommendation/ paths shown above — the OpenAPI spec's plural /recommendations/ spellings are wrong live (404). Submit/delete require authentication upstream.

lb_radioA

Generate an LB Radio playlist or recording pool from a prompt, artist, or tag list.

Endpoints: GET /1/explore/lb-radio (mode="explore") GET /1/lb-radio/artist/{seed_artist_mbid} (mode="artist") GET /1/lb-radio/tags (mode="tags")

Args: mode — "explore" (default) generates a JSPF playlist: prompt required — upstream resolves the ENTIRE prompt as ONE MusicBrainz artist name (case-insensitive); free-text prompts fail upstream with 400 "Artist ... could not be looked up. Please use exact spelling." (live probe 2026-08-25). difficulty — easy/medium/hard (default easy; sent as the API's mode parameter). "artist" returns recordings grouped by similar artists (dict keyed by similar-artist MBID — NOT JSPF): seed_artist_mbid required; difficulty maps to the required mode param; max_similar_artists / max_recordings_per_artist (1-100, default 5/5) and the pop_begin/pop_end popularity window (percentages 0-100, begin < end, default 0-100) are ALL required upstream. "tags" returns raw recording entries [{percent, recording_mbid, source, tag_count}, ...] — NOT JSPF, and NOT a list of valid tags: tags is REQUIRED here — non-empty list of MusicBrainz tags, sent as repeated tag query params; operator — and/or (default and; sent uppercase AND/OR per spec — upstream demands it whenever the tag list is not exactly one item); pop_begin/pop_end/count (default 25) all required upstream. Responses pass through untouched. Generation routes are slow (~30s+ observed), so they run with an extended 120s client timeout instead of the 30s default.

manage_recording_feedbackA

Submit or read recording (love/hate) feedback.

Endpoints: POST /1/feedback/recording-feedback (action="submit") GET /1/feedback/user/{user_name}/get-feedback (action="get_for_user") GET /1/feedback/recording/{recording_mbid}/get-feedback-mbid (action="get_for_mbid") GET /1/feedback/recording/{recording_msid}/get-feedback (action="get_for_msid") POST /1/feedback/user/{user_name}/get-feedback-for-recordings (action="get_bulk") POST /1/feedback/import (action="import")

Args: action — one of submit, get_for_user, get_for_mbid, get_for_msid, get_bulk, import. submit: EXACTLY ONE of recording_mbid / recording_msid required plus score — 1 (love) or -1 (hate). get_for_user: user_name required; optional score filter (1/-1); count — 1..1000 (default 25); offset — non-negative (default 0). get_for_msid runs on the /recording/{msid}/ path shown above — the OpenAPI spec's /user/{recording_msid}/ spelling is wrong live (404), so do not "fix" it back. get_bulk: user_name + mbids (1..1000) via the POST variant only — the body key is recording_mbids on the wire (upstream also accepts an msids variant; inputs here are MBIDs) and the GET twin caps out around 75 recordings before URL-length middleware limits reject it (502 with no useful error), so it is deliberately not exposed. import: imports feedback FROM an external service — service ∈ lastfm, librefm and user_name = the username ON THAT SERVICE (not a ListenBrainz name); the route takes no feedback items (upstream contract feedback_api.py:302-324, live probe 2026-08-22). Submit and import require authentication upstream.

manage_pinsA

Pin, unpin, update, delete, or read pinned recordings.

Endpoints: POST /1/pin (action="pin") POST /1/pin/unpin (action="unpin") POST /1/pin/delete/{row_id} (action="delete") POST /1/pin/update/{row_id} (action="update") GET /1/{user_name}/pins (action="list") GET /1/{user_name}/pins/current (action="current") GET /1/{user_name}/pins/following (action="following") GET /1/pin/{row_id} (action="get")

Args: action — one of pin, unpin, delete, update, list, current, following, get. pin: recording_mbid required; optional blurb_content and track_metadata. unpin/delete/update/get: row_id required. update also needs blurb_content. Pins auto-expire after 7 days upstream (DAYS_UNTIL_UNPIN); unpin only DEACTIVATES the current pin while delete removes it from history entirely. NOTE: unpin runs on the /1/pin/unpin path shown above — the OpenAPI spec's POST /1/unpin spelling is wrong live (404), so do not "fix" it back. list: count — 1..1000 (default 25); offset — non-negative (default 0). All write actions require authentication upstream.

get_fresh_releasesA

Discover fresh (upcoming + recent) releases.

Endpoints: GET /1/explore/fresh-releases/ (source="explore") GET /1/user/{user_name}/fresh_releases (source="user") GET /1/explore/color/{color} (source="color")

Args: source — one of explore, user, color. explore (default): site-wide fresh releases around today or release_date (optional YYYY-MM-DD pivot); days — window size, clamped to 1..90 (default 14); sort — one of release_date, artist_credit_name, release_name; past/future — include past/future releases (booleans). user: fresh releases for a ListenBrainz username — user_name required; sort uses the same vocabulary as explore plus confidence: release_date, artist_credit_name, release_name, confidence; days/past/future as in explore. color: releases whose predominant cover-art color is close to color — REQUIRED hex only ("#rrggbb" or "rrggbb"; named colors are NOT accepted); color mode ignores days/sort/release_date/past/future. Optional filters ride along only when given; days always rides along with its clamped value.

list_playlistsA

List, recommend, or search playlists for a user.

Endpoints: GET /1/user/{playlist_user_name}/playlists (source="mine") GET /1/user/{playlist_user_name}/playlists/createdfor (source="createdfor") GET /1/user/{playlist_user_name}/playlists/collaborator (source="collaborator") GET /1/user/{playlist_user_name}/playlists/recommendations (source="recommendations") GET /1/user/{playlist_user_name}/playlists/search (source="user_search") GET /1/playlist/search (source="search")

Args: source — one of mine (default), createdfor, collaborator, recommendations, user_search, search. mine/createdfor/collaborator/ recommendations/user_search need playlist_user_name (the routes' placeholder is spelled {playlist_user_name}); search is site-wide over public playlists and ignores it. search + user_search need query — both REJECT queries shorter than 3 characters upstream, so this is enforced locally with zero calls. count/offset paginate everything except recommendations (which has no pagination parameters upstream); count — 1..1000 (default 25); offset — non-negative (default 0). mine includes private playlists when the token belongs to playlist_user_name; createdfor playlists are all public. NOTE: site-wide search (source="search") is SLOW upstream — answers in ~30s+ consistently (round-3 sweep 2026-08-25), past the 30s client default that ReadTimeouted it — so it runs with a 90s per-request timeout override (PLAYLIST_SEARCH_TIMEOUT_S).

get_playlistA

Fetch one playlist in JSPF format.

Endpoint: GET /1/playlist/{playlist_mbid}

Args: playlist_mbid required. fetch_metadata — pass false to skip looking up recording metadata upstream. limit — optional cap on the returned track array: when the playlist holds more than limit tracks, the track array is sliced to limit and a top-level "truncated": true marker (plus "truncated_to": limit) is added at the ENVELOPE's top level. The track array itself is located under whichever envelope shape upstream returns: today's live shape puts the playlist object at the TOP LEVEL of the response ("playlist"."track"; round-3 sweep 2026-08-25), while a legacy payload-wrapped shape ("payload"."playlist"."track") is also accepted defensively. Without limit NOTHING is truncated.

manage_playlistA

Create, edit, delete, copy, or transfer playlists.

Endpoints: POST /1/playlist/create (action="create") POST /1/playlist/edit/{playlist_mbid} (action="edit") POST /1/playlist/{playlist_mbid}/delete (action="delete") POST /1/playlist/{playlist_mbid}/copy (action="copy") GET /1/playlist/{playlist_mbid}/xspf (action="export_xspf"; census) POST /1/playlist/{playlist_mbid}/export/{service} (action="export"; census) GET /1/playlist/import/{service} (action="import_playlists"; census) GET /1/playlist/{service}/{external_playlist_id}/tracks (action="fetch_external_tracks"; census) POST /1/playlist/export-jspf/{service} (action="export_jspf"; census)

Args: action — one of create, edit, delete, copy, export_xspf, export, import_playlists, fetch_external_tracks, export_jspf. create: title required; optional public bool, description (sent as JSPF annotation), collaborators (list of ListenBrainz usernames). NOTE upstream reads public/collaborators from the MusicBrainz JSPF extension block and REJECTS creates lacking an explicit public flag — pass public=true/false. Only supplied fields are sent, so edit never clobbers omitted ones; edit needs playlist_mbid. delete/copy: playlist_mbid only. export_xspf: playlist_mbid; returns the XSPF XML as {"xspf": } (upstream serves text/xml, live probe 2026-08-22); optional fetch_metadata=false skips metadata lookup. export: playlist_mbid + service ∈ spotify, apple_music, soundcloud; optional is_public. import_playlists: service only — lists YOUR playlists already on that service (no id parameter exists on this route). fetch_external_tracks: service + external_playlist_id → JSPF conversion. export_jspf: service + jspf — the BARE playlist object (dict or JSON string; the server adds its own {"playlist": ...} wrapper) + optional is_public. All write actions require authentication upstream.

manage_playlist_tracksA

Add recordings to, reorder, or remove items from a playlist.

Endpoints: POST /1/playlist/{playlist_mbid}/item/add/{offset} (action="add") POST /1/playlist/{playlist_mbid}/item/move (action="move") POST /1/playlist/{playlist_mbid}/item/delete (action="delete")

Args: action — one of add, move, delete. add: playlist_mbid + recordings — bare recording MBIDs are wrapped into canonical identifier URIs (https://musicbrainz.org/recording/) and full JSPF track dicts pass through verbatim; offset (default 0, clamped non-negative) becomes the {offset} path segment; at most 100 recordings per call upstream (MAX_RECORDINGS_PER_ADD), enforced locally with zero calls. Body is JSPF {"playlist": {"track": [...]}} per server source (2026-08-22) — NOT {"recordings": [...]}. move: recording_mbid (of the track being moved), index (from), to_index, count (default 1) — all indices non-negative ints; upstream requires every one of mbid/from/to/count in the body. delete: playlist_mbid + index + count (default 1) — upstream's body needs BOTH index and count. All actions require authentication upstream.

manage_followsA

Follow, unfollow, or list a user's followers/following.

Endpoints: POST /1/user/{user_name}/follow (action="follow") POST /1/user/{user_name}/unfollow (action="unfollow") GET /1/user/{user_name}/followers (action="followers") GET /1/user/{user_name}/following (action="following")

Args: action — one of follow, unfollow, followers, following; user_name — the account being followed/unfollowed (follow/unfollow) or the account whose lists are read (followers/following). LB semantics: the Authorization token identifies the ACTING account — POST /1/user/{user_name}/follow means "{token owner} follows {user_name}" and carries no request body. followers/following take no pagination parameters upstream (full lists are returned). follow/unfollow writes require authentication upstream.

get_feedA

Read a user's timeline feed events or listen events.

Endpoints: GET /1/user/{user_name}/feed/events (mode="events") GET /1/user/{user_name}/feed/events/listens/following (mode="following") GET /1/user/{user_name}/feed/events/listens/similar (mode="similar") GET /1/user/{user_name}/feed/events/{event_id} (mode="event")

Args: mode — one of events, following, similar, event. user_name — ListenBrainz username whose feed is read (all modes; upstream also requires the token owner to match). events: full timeline events; following/similar: listen events from followed/similar users. All three accept count — 1..1000 (default 25) and unix-timestamp min_ts/max_ts (mutually exclusive here, matching the get_listens rule). event: fetch one event by its numeric id (event_id required); upstream validates the id server-side. When mode is event, count/min_ts/max_ts are ignored entirely (like playing_now in get_listens) — the census route carries no query parameters.

manage_timelineA

Create timeline events, or delete/hide/unhide/thank feed events.

Endpoints: POST /1/user/{user_name}/timeline-event/create/recording (action="create_recording") POST /1/user/{user_name}/timeline-event/create/recommend-personal (action="create_recommend_personal") POST /1/user/{user_name}/timeline-event/create/notification (action="create_notification") POST /1/user/{user_name}/timeline-event/create/review (action="create_review") POST /1/user/{user_name}/feed/events/delete (action="delete_event") POST /1/user/{user_name}/feed/events/hide (action="hide_event") POST /1/user/{user_name}/feed/events/unhide (action="unhide_event") POST /1/user/{user_name}/timeline-event/create/thanks (action="thanks")

Args: action — one of create_recording, create_recommend_personal, create_notification, create_review, delete_event, hide_event, unhide_event, thanks; user_name — timeline/feed owner (upstream requires the token owner to match for every action). create_recording: at least one of recording_mbid/recording_msid. create_recommend_personal: recording id(s) + users — non-empty list of usernames who follow you (each must already follow you upstream); optional blurb_content. create_notification: message text — upstream restricts senders to approved playlist bots. create_review: entity_name/entity_id/entity_type/text/language required, rating optional — creates the review in CritiqueBrainz (linked account required upstream). delete_event: event_type — one of recording_recommendation, notification, personal_recording_recommendation — plus event_id. hide_event/ unhide_event: event_type — hide supports recording_recommendation, personal_recording_recommendation, thanks, notification, critiquebrainz_review, recording_pin — plus event_id. thanks: original_event_type — one of recording_recommendation, personal_recording_recommendation, recording_pin — plus event_id and optional blurb_content. All actions require authentication upstream.

generate_cover_artA

Generate ListenBrainz cover art — returns an SVG string.

Endpoints: POST /1/art/grid/ (action="grid") GET /1/art/grid-stats/{user_name}/{time_range}/{dimension}/{layout}/{image_size} (action="grid-stats") GET /1/art/{custom_name}/{user_name}/{time_range}/{image_size} (action="custom") GET /1/art/year-in-music/{year}/{user_name} (action="year-in-music") POST /1/art/playlist/{playlist_mbid}/{dimension}/{layout} (action="playlist") GET /1/art/artist-grid/{artist_mbid}/{dimension}/{layout}/{image_size} (action="artist-grid")

Every success returns {"svg": "<svg ...>"} — upstream serves image/svg+xml; embed via so external cover art/fonts load. Missing YIM data → {"status": "no_data"} (204).

Args: action — one of grid, grid-stats, custom, year-in-music, playlist, artist-grid. Shared options: dimension — 1..5 (default 3); layout — non-negative design index, 0 is always a simple grid (see https://art.listenbrainz.org; unknown combos answer 400 upstream); image_size — 128..1024 pixels (default 500); time_range — one of this_week/this_month/this_year/week/month/quarter/year/half_yearly/ all_time (default all_time).

grid: composites cover art from release_mbids and/or release_group_mbids (at least one required; if BOTH are given only release_mbids are used — upstream rule). WARNING: release_group_mbids-only grids currently answer HTTP 500 upstream ("An unknown error occured.", verified live 2026-08-22) — the tool detects this exact case and returns a known-bug error advising release_mbids instead of the raw 500. Options: background — transparent, white, black or a #rrggbb code (default white); skip_missing/show_caa/caption booleans default true; cover_art_size — 250 or 500 (optional); tiles — list of comma-separated cell addresses (e.g. ["0", "1,2"]) which suppresses layout on the wire, since upstream prefers layout over tiles.

grid-stats: user top releases via user_name. custom: free-form name of a registered art type (known today: designer-top-5, designer-top-10, designer-top-10-alt, lps-on-the-floor — unknown names answer 400 upstream). year-in-music: year plus user_name; image — REQUIRED live (400 without): one of overview, stats, artists, albums, tracks, discovery-playlist, missed-playlist (default overview). playlist: body-less POST, requires authentication upstream. artist-grid: artist_mbid top release groups.

validate_tokenA

Validate the ListenBrainz auth token configured on THIS server.

Endpoint: GET /1/validate-token

Sends the server's configured LISTENBRAINZ_TOKEN to upstream and returns its verdict verbatim: {"code", "message", "valid"} plus "user_name" when valid. Useful as a health check for the server's credentials — it cannot validate any other token.

get_dump_infoA

Get information about ListenBrainz data dumps.

Endpoint: GET /1/status/get-dump-info

Args: dump_id — optional integer ID of a specific dump; omitted, information about the LATEST dump is returned. Response: {"id", "timestamp" (format YYYYMMDD-HHMMSS), "dump_type"}.

manage_settingsA

Update the authenticated user's ListenBrainz settings.

Endpoints: POST /1/settings/flair (action="flair") POST /1/settings/timezone (action="timezone") POST /1/settings/troi (action="troi") POST /1/settings/brainzplayer (action="brainzplayer")

Args: action — one of flair, timezone, troi, brainzplayer. All four routes require authentication upstream and act on the user owning the token configured on this server. Irrelevant args are ignored per action (e.g. zonename under action="flair").

flair: pass one of shake, lb-colors-sweep, light-sweep, wave, flip-horizontal, flip-vertical, flip-3d, extruded, underline, tornado, highlighter, anaglyph, sliced — or leave it unset to send null, which REMOVES the current flair. timezone: zonename required (e.g. Europe/London). troi: export_to_spotify required boolean (Troi playlist export preference). Round-3 QA (2026-08-25) found the MCP argument layer coerces some values (e.g. the string "yes") to real booleans BEFORE this server's strict-bool guard runs, so the guard effectively catches only non-coercible junk — upstream's own type-check remains the authoritative rejection layer for anything else. brainzplayer: brainzplayer_prefs object with any of youtubeEnabled/ spotifyEnabled/soundcloudEnabled/appleMusicEnabled/ funkwhaleEnabled/navidromeEnabled/brainzplayerEnabled/ internetArchiveEnabled booleans and/or dataSourcesPriority (array of strings); unknown keys are rejected.

get_service_statusA

Get freshness metrics for ListenBrainz services.

Endpoint: GET /1/status/service-status

Returns ages (in seconds) of the last data dump and stats generation runs, per-stat ages, sitewide stats age and the number of listens waiting in the incoming queue.

get_playlist_statusA

Get freshness metrics for recommendation playlists.

Endpoint: GET /1/status/playlist-status

Returns the age (in seconds) of each monitored recommendation playlist (e.g. daily-jams, weekly-jams, weekly-exploration).

get_donorsA

List MetaBrainz donors and their ListenBrainz flairs.

Endpoints: GET /1/donors/recent (mode="recent") GET /1/donors/biggest (mode="biggest") GET /1/donors/all-flairs (mode="all-flairs")

Args: mode — recent (latest donors), biggest (largest donations) or all-flairs (username → flair map for every eligible donor). count — page size for recent/biggest, clamped 1..1000 (default 25); offset — skip N entries, floored at 0 (default 0); both are ignored by all-flairs, which takes no parameters and returns an object rather than a list. all-flairs can take tens of seconds upstream; it runs with an extended 60s timeout instead of the usual 30s.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dthen/listenbrainz-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server