How Music Assistant's Provider Architecture (Music, Player, Metadata) Works

Music Assistant uses a modular provider architecture where all external integrations inherit from a common Provider base class and implement specialized interfaces for music libraries, playback devices, or metadata enrichment.

Music Assistant organizes every external integration through a hierarchical provider system defined in the music-assistant/server repository. This architecture categorizes integrations into three distinct provider types—MUSIC, PLAYER, and METADATA—each extending a shared foundation that handles configuration, logging, and feature declaration. Understanding this structure is essential for developing new integrations or troubleshooting existing ones.

The Three Provider Types

Music Assistant splits external services into three specialized domains, each with a dedicated abstract base class.

Music Provider

The Music Provider (music_assistant/models/music_provider.py) supplies catalogues of media items and synchronizes user libraries with Music Assistant. These providers handle artists, albums, tracks, playlists, radios, podcasts, and audiobooks.

Key responsibilities include:

  • Search and browse operations via search() and library methods like get_library_artists()
  • Library synchronization through the sync_library() method, which orchestrates full syncs for specific MediaType values
  • Stream detail handling for custom audio streams

The sync_library() method iterates over provider library methods, creates or updates database items, and tracks processed IDs using CACHE_CATEGORY_PREV_LIBRARY_IDS to detect deletions.

Player Provider

The Player Provider (music_assistant/models/player_provider.py) controls playback devices including speakers, smart displays, and media players. These providers manage device discovery, grouping, and lifecycle events.

Core functionality includes:

  • Device discovery via discover_players()
  • Exposing a players property that returns all Player objects belonging to the provider
  • Lifecycle callbacks: on_player_enabled() and on_player_disabled()
  • Optional group player creation when ProviderFeature.CREATE_GROUP_PLAYER is declared

Metadata Provider

The Metadata Provider (music_assistant/models/metadata_provider.py) enriches existing media items with supplementary information such as cover art, descriptions, similar items, and recommendations.

These providers operate on a priority basis:

  • Each provider declares a priority attribute
  • Music Assistant queries providers in priority order until one returns a non-None result
  • Typical methods include get_album_metadata(), get_similar_tracks(), and get_top_tracks()

The Common Provider Base Class

All provider types inherit from the Provider class in music_assistant/models/provider.py. This base implements shared infrastructure:

Configuration Handling Each provider receives a ProviderConfig object during instantiation and can react to changes via update_config().

Feature Declaration Providers expose capabilities through a supported_features set containing ProviderFeature enum values (defined in music_assistant/constants.py). The base class provides supports_feature() and check_feature() methods for runtime capability checks.

Logging Providers receive a dedicated logger whose level is automatically configured based on the provider's settings via _set_log_level_from_config().

Lifecycle Hooks The base class defines loaded_in_mass(), unload(), and async initialization hooks for startup and cleanup operations.

How the Provider System Functions

The architecture follows a strict discovery and enforcement pattern:

  1. Discovery & Registration During startup, Music Assistant scans providers/ directories for manifest.json files. Each manifest declares the provider's type (ProviderType.MUSIC, PLAYER, or METADATA), domain, and implemented features.

  2. Instantiation For each manifest, the system creates an instance of the appropriate concrete class, passing the global MusicAssistant object, manifest, config, and optional supported features to the constructor.

  3. Feature Enforcement Core actions are guarded by feature checks. For example, MusicProvider.get_similar_tracks() is only invoked if the provider declares ProviderFeature.SIMILAR_TRACKS. Missing features raise NotImplementedError in the base implementation.

  4. Library Synchronization For music providers, the sync_library() method orchestrates full synchronizations by iterating over library methods, updating database records, and comparing cached IDs against current sets to detect removals.

  5. Metadata Enrichment When enrichment is needed, Music Assistant iterates over registered metadata providers by priority, stopping at the first successful result.

Implementation Examples

Declaring a Music Provider


# my_music_provider/__init__.py

from music_assistant.models.music_provider import MusicProvider
from music_assistant.constants import ProviderFeature

class MyMusicProvider(MusicProvider):
    async def search(self, query: str, media_types: list[MediaType], limit: int = 5):
        # Implementation of your service's search endpoint

        pass

    async def get_library_artists(self):
        # Yield Artist objects from the remote service

        pass

# manifest.json (placed next to the package)

{
  "domain": "my_music",
  "name": "My Music Service",
  "type": "music",
  "stage": "stable",
  "features": [
    "SEARCH",
    "LIBRARY_ARTISTS",
    "LIBRARY_ALBUMS",
    "LIBRARY_TRACKS"
  ]
}

Using Metadata Providers for Album Art

async def enrich_album(album: Album) -> Album:
    # Iterate over all metadata providers by priority

    for prov in mass.providers.get_by_type("metadata"):
        try:
            md = await prov.get_album_metadata(album)
            if md:
                album.metadata = md
                break
        except NotImplementedError:
            continue
    return album

Summary

  • Music Assistant's provider architecture centers on three specialized types: MusicProvider, PlayerProvider, and MetadataProvider.
  • All providers inherit from the common Provider base class in music_assistant/models/provider.py, which handles configuration, logging, and feature checks.
  • Features are declared via the ProviderFeature enum and enforced at runtime using supports_feature() and check_feature().
  • Music providers synchronize libraries using sync_library() and track deletions via cache categories like CACHE_CATEGORY_PREV_LIBRARY_IDS.
  • Player providers manage device lifecycles through discover_players() and the players property, with optional group player support.
  • Metadata providers enrich content based on priority ordering, with the first successful result winning.
  • New integrations require only a concrete subclass, a manifest JSON file, and proper feature declaration.

Frequently Asked Questions

What is the difference between a Music Provider and a Metadata Provider in Music Assistant?

A Music Provider supplies the actual catalog of media items (artists, albums, tracks) and handles library synchronization, while a Metadata Provider only enriches existing items with supplemental data like cover art, descriptions, or recommendations. Music providers are the source of truth for media existence, whereas metadata providers enhance information about items already in the system.

How does Music Assistant determine which provider method to call?

Music Assistant checks the supported_features set exposed by each provider instance. Before calling methods like get_similar_tracks() or create_group_player(), the core code verifies that the provider declares the corresponding ProviderFeature enum value. If the feature is missing, the system either skips the call or catches the NotImplementedError raised by the base class.

What files must I create to implement a new provider in Music Assistant?

You must create a Python class inheriting from the appropriate base (MusicProvider, PlayerProvider, or MetadataProvider) and place it in the providers/ directory. Additionally, you need a manifest.json file declaring the provider's domain, type, and features. The base class in music_assistant/models/provider.py handles configuration and logging automatically.

How does the Metadata Provider priority system work?

Each Metadata Provider declares a priority attribute. When Music Assistant needs enrichment data (such as album artwork), it queries providers in descending order of priority. The first provider that returns a non-None result wins, and subsequent providers are skipped. This allows high-priority sources (like local databases) to override lower-priority remote services.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →