Skip to main content
Glama
cyanheads

musicbrainz-mcp-server

by cyanheads

Version License MCP SDK TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://musicbrainz.caseyjhand.com/mcp


Overview

Open music metadata from the live MusicBrainz Web Service v2 and the Cover Art Archive. Search by name, look up entities by MBID or by ISRC, ISWC, or barcode, page through complete linked sets, and fetch cover art. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.

Tools

Tool

Description

musicbrainz_search_entities

Lucene search over one entity type, returning ranked MBIDs with relevance scores

musicbrainz_get_artist

Artist profile: type, life span, discography, relationships, external links

musicbrainz_get_release_group

Release-group (the album across its editions): types, first-release date, editions, cover-art availability

musicbrainz_get_release

One edition: tracklist, label and catalog number, barcode, packaging

musicbrainz_get_recording

Recording (one performance): length, ISRCs, releases it appears on, performer and production credits

musicbrainz_get_work

Work (a composition): type, ISWCs, writers, and the recordings that perform it

musicbrainz_get_label

Label: type, life span, label code, external links

musicbrainz_lookup_identifier

Resolve an ISRC, ISWC, or barcode to recordings, works, or releases

musicbrainz_browse_entities

Page through every entity linked to a parent MBID

musicbrainz_get_cover_art

Cover Art Archive images for a release or release-group

Resources

Resource

Description

musicbrainz://{entity_type}/{mbid}

One entity as raw MusicBrainz JSON, with the matching get_* tool's linked data folded in

Every entity is also reachable through the get_* tools, so tool-only clients lose nothing. The resource has no list; find MBIDs with musicbrainz_search_entities.

Related MCP server: musicbrainz-mcp

Capability reference

musicbrainz_search_entities tool

  • One entityType per call (artist, release-group, release, recording, work, label) and a Lucene query with field scoping (artist:radiohead AND country:GB); limit 1–100 (default 25), offset for paging

  • Each hit carries mbid, name, and the raw 0–100 score in MusicBrainz order, plus type-specific fields such as artistCredit, isrcs, iswcs, and length. Release rows use status (Official, Bootleg, …); artist, release-group, work, and label subtypes use type. A whitespace-only query fails as blank_query


musicbrainz_get_artist tool

  • mbid, plus inc_release_groups and inc_relationships (both default true) to drop the heavier sub-resources

  • Type, gender, country, area, lifeSpan, aliases, and tags, plus releaseGroups (one page), relationships (band membership, collaborations), and externalLinks (Wikidata, Discogs, official site)


musicbrainz_get_release_group tool

  • mbid only; returns primaryType, secondaryTypes, firstReleaseDate, artistCredit with artistCreditString, tags, and one page of releases (editions)

  • coverArt (exists, count, front, back) comes from a live Cover Art Archive check; when that check fails the field is omitted with a notice, never reported as "no art"


musicbrainz_get_release tool

  • mbid only; returns media with tracks (position, title, length as m:ss, recordingId), labelInfo (label and catalogNumber), barcode, status, date, country, packaging, language/script, and releaseGroupId

  • coverArt is the availability stub from the release record; call musicbrainz_get_cover_art for image URLs


musicbrainz_get_recording tool

  • mbid, plus inc_relationships (default true) for performer, producer, and engineer credits, work links to the composition, and external links

  • Returns length, isrcs, artistCredit, firstReleaseDate, the releases it appears on, relationships, and externalLinks


musicbrainz_get_work tool

  • mbid, plus inc_relationships (default true) for writer, composer, and lyricist credits, the recordings that perform it, and external links

  • Returns type, languages, iswcs, aliases, and tags; this server keeps the first 25 recording relationships and every other relationship/link. totalCount is the exact recording-relationship count; actual omission adds truncated, shown, cap, and retrieval guidance

  • Browse recording by work to enumerate recording entities, then call musicbrainz_get_recording for their work relationship attributes and dates; browse does not reconstruct those details


musicbrainz_get_label tool

  • mbid only; returns type, country, area, lifeSpan, labelCode (the LC number without its prefix), aliases, tags, and externalLinks

  • Releases are not embedded; list them with musicbrainz_browse_entities (target_type=release, link.label)


musicbrainz_lookup_identifier tool

  • id_type isrc → recordings, iswc → works, barcode → releases; a barcode is UPC/EAN digits and returns up to 25 ranked matches, each with a score

  • result.kind (recordings | works | releases) names the arm that came back; failures are invalid_identifier or identifier_not_found


musicbrainz_browse_entities tool

  • target_type plus exactly one parent MBID in link (artist, label, release-group, release, recording, work, or area); releaseGroup/release_group alias release-group. Unknown keys and alias collisions fail by name. limit 1–100 (default 25), offset to any depth

  • Browse recording by release for recording entities in an edition; musicbrainz_get_release supplies ordered tracks, medium positions, and repeated recording occurrences. Release rows use status; subtype fields for other entities use type

  • Reports the upstream totalCount; while entities remain, truncated is set and the notice gives the next offset. A missing, extra, or malformed link fails as invalid_link, an unknown parent as entity_not_found


musicbrainz_get_cover_art tool

  • mbid and entity_type: release (default) or release-group, which resolves to a representativeRelease

  • images with front/back, types, imageUrl, and 250/500/1200px thumbnails; an entity with no art returns an empty set and hasArt: false, not an error

  • An archive 404 is checked against MusicBrainz, so an unknown MBID fails as entity_not_found; if the check itself fails, the empty set stands with a notice that existence is unconfirmed


musicbrainz://{entity_type}/{mbid} resource

  • entity_type is artist, release-group, release, recording, work, or label; returns the raw MusicBrainz record as application/json

  • Fetches the same default linked data as the matching get_* tool; failures are invalid_mbid and entity_not_found

  • Work JSON retains the first 25 recording-target relationships and all other relations/URLs, with exact count and actual truncation in recordingRelationshipSummary

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

MusicBrainz-specific:

  • Keyless client for the MusicBrainz Web Service v2 and the Cover Art Archive. Every request carries the descriptive User-Agent MusicBrainz requires, musicbrainz-mcp-server/<version> ( <contact> ), with MUSICBRAINZ_CONTACT as the contact

  • Entities are addressed by MBID (a hyphenated hexadecimal UUID, with any version/variant groups); uppercase and surrounding whitespace normalize to lowercase. Malformed/all-zero IDs fail before fetch as invalid_mbid (invalid_link for browse), while a well-shaped unknown ID remains entity_not_found

  • One process-wide limiter holds MusicBrainz calls to ~1 request/second, shared by every client of an instance, so long browse runs pace accordingly

  • Lookups fold discography, relationships, tracklists, and external links into one request; responses are cached (24 h by default), with retry and backoff on transient 5xx and HTML error pages

Agent-friendly output:

  • Artist release-groups and release-group editions embed one upstream page (25); browse enumerates the full entity set. Work recording relationships have a separate server-side cap of 25 with exact relationship counts and truthful disclosure. Artist/recording relationships and release tracklists are not subject to that slice; labels embed no releases

  • Provenance on search and browse: the effective query is echoed and the upstream total reported, so a partial window never reads as complete

  • Discriminated outputs: musicbrainz_lookup_identifier returns a kind-tagged union, so callers branch on data, not string parsing

  • Raw upstream relevance score, not a derived confidence; missing upstream fields stay absent rather than invented

Getting started

Public Hosted Instance

A public instance is available at https://musicbrainz.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

{
  "mcpServers": {
    "musicbrainz-mcp-server": {
      "type": "streamable-http",
      "url": "https://musicbrainz.caseyjhand.com/mcp"
    }
  }
}

Self-Hosted / Local

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "musicbrainz-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/musicbrainz-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "MUSICBRAINZ_CONTACT": "you@example.com"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "musicbrainz-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/musicbrainz-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "MUSICBRAINZ_CONTACT": "you@example.com"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "musicbrainz-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "-e", "MUSICBRAINZ_CONTACT=you@example.com",
        "ghcr.io/cyanheads/musicbrainz-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 MUSICBRAINZ_CONTACT=you@example.com bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.4.0 or higher (or Node.js v24+).

  • No API key or account. The server ships a default contact, but set MUSICBRAINZ_CONTACT to your own email or URL for any shared or hosted deployment.

Installation

  1. Clone the repository:

git clone https://github.com/cyanheads/musicbrainz-mcp-server.git
  1. Navigate into the directory:

cd musicbrainz-mcp-server
  1. Install dependencies:

bun install
  1. Configure environment:

cp .env.example .env
# edit .env and set MUSICBRAINZ_CONTACT (optional but recommended)

Configuration

Variable

Description

Default

MUSICBRAINZ_CONTACT

Contact (email or URL) sent in the User-Agent. Set your own on a shared or hosted instance so MusicBrainz can reach you about traffic.

repo URL

MUSICBRAINZ_BASE_URL

MusicBrainz Web Service v2 base URL; override for a private mirror or beta.

https://musicbrainz.org/ws/2

MUSICBRAINZ_RATE_LIMIT_RPS

Client-side requests-per-second ceiling (0.1–50).

1

MUSICBRAINZ_CACHE_TTL

Response cache TTL in seconds; 0 disables caching.

86400

MUSICBRAINZ_TIMEOUT_MS

Per-request HTTP timeout, in ms.

30000

MUSICBRAINZ_MAX_RETRIES

Retry attempts for transient upstream failures.

3

COVER_ART_BASE_URL

Cover Art Archive base URL.

https://coverartarchive.org

MCP_TRANSPORT_TYPE

Transport: stdio or http.

stdio

MCP_HTTP_PORT

HTTP server port.

3010

MCP_AUTH_MODE

Authentication: none, jwt, or oauth.

none

MCP_LOG_LEVEL

Log level (debug, info, warning, error, etc.).

info

OTEL_ENABLED

Enable OpenTelemetry.

false

See .env.example for the full list of optional overrides.

Running the server

Local development

  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security, packaging
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against the linter rules

Docker

docker build -t musicbrainz-mcp-server .
docker run --rm -e MUSICBRAINZ_CONTACT=you@example.com -p 3010:3010 musicbrainz-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/musicbrainz-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

Directory

Purpose

src/index.ts

createApp() entry point — registers tools and the resource, inits both services.

src/config

Server-specific environment variable parsing and validation with Zod.

src/services/musicbrainz

MusicBrainz WS/2 client — User-Agent, rate limiter, response cache, retry, domain types.

src/services/cover-art

Cover Art Archive client — maps a 404 to an empty image set, follows the release-group redirect.

src/mcp-server/tools

Tool definitions (*.tool.ts). Ten read-only tools across search, lookup, browse, and cover art.

src/mcp-server/resources

Resource definitions. The musicbrainz://{entity_type}/{mbid} entity mirror.

tests/

Unit and integration tests mirroring src/.

Development guide

See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic

  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage

  • Register new tools and resources via the barrels in src/mcp-server/*/definitions/index.ts

  • Route every upstream call through the services, never a direct fetch(), so the User-Agent, rate limiter, and cache apply

  • Wrap external API data: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

MusicBrainz core entity data is CC0. The server reads only that core metadata and never fetches annotation text, which carries a different license. Cover art comes from the Cover Art Archive, a joint project of MusicBrainz and the Internet Archive; image URLs are linked, never rehosted, and each image's copyright stays with its rights holders. Cite MusicBrainz and the Cover Art Archive in downstream use.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    An MCP server that provides live access to MusicBrainz metadata and Cover Art Archive images, with optional OAuth-based submission of tags, ratings, and collection edits.
    9
    638 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    An MCP server for the Last.fm API, exposing artist, album, track, chart, and user data as read-only tools. Supports optional writes, auth, and experimental methods over stdio or HTTP.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables searching music artists and releases, and retrieving artist biographies, discographies, release track listings, credits, and metadata through the MusicBrainz API.
    14 npm
    MIT