Music Assistant Provider Types: MusicProvider, PlayerProvider, and MetadataProvider Explained

Music Assistant defines three distinct provider types—MusicProvider, PlayerProvider, and MetadataProvider—that inherit from a common base class to modularize music sources, playback devices, and metadata enrichment.

The Music Assistant server architecture revolves around a pluggable provider system that separates concerns between content discovery, device control, and data enhancement. Each provider type implements a specific contract defined in the music_assistant/models/ directory, allowing developers to extend functionality without modifying core server code. Understanding these Music Assistant provider types is essential for building custom integrations or contributing to the ecosystem.

The Three Core Provider Types

Music Assistant organizes extensions into three categories based on their primary function. Each category has a dedicated abstract base class that defines the required interface and optional feature hooks.

MusicProvider: Content and Library Management

The MusicProvider class handles music catalogue access, search operations, and library synchronization. Located in music_assistant/models/music_provider.py, this provider type supplies tracks, albums, artists, playlists, radios, podcasts, and audiobooks to the system.

Key responsibilities include:

  • Library synchronization via sync_library(), which orchestrates full imports of media items into Music Assistant's central SQLite database
  • Search functionality through search() methods that return structured results across media types
  • Streaming support for generating playable audio streams
  • Media item CRUD operations for creating, updating, and deleting library entries

The class uses helper methods like _sync_library_artists() and _sync_library_albums() to perform per-item upserts, genre synchronization, and deletion handling during sync operations.

PlayerProvider: Device Discovery and Control

The PlayerProvider class manages physical or virtual playback devices. Defined in music_assistant/models/player_provider.py, this provider type handles device discovery, grouping, and lifecycle management.

Key capabilities include:

  • Player discovery via discover_players(), though many implementations rely on mDNS/UPnP and use this as a no-op entry point
  • Enable/disable hooks through on_player_enabled() and on_player_disabled() callbacks that register or unregister devices with the central controller
  • Group management for creating and removing player groups
  • Feature declaration indicating support for advanced capabilities like gapless playback or volume normalization

The on_player_enabled() hook typically schedules discovery calls using self.mass.call_later(), while on_player_disabled() ensures clean unregistration from the player controller.

MetadataProvider: Data Enrichment and Recommendations

The MetadataProvider class supplies supplementary metadata and recommendation services. Found in music_assistant/models/metadata_provider.py, this provider type enhances media items with external data.

Core functions include:

  • Artist and album metadata retrieval via get_artist_metadata() and get_album_metadata()
  • Image resolution through resolve_image() for fetching high-quality artwork
  • Recommendation engines using get_similar_tracks() to suggest related content
  • Default implementations that return None or empty lists, allowing selective override of specific methods

Concrete implementations might fetch data from Last.fm, Discogs, or MusicBrainz to enrich the local library without disrupting core playback functionality.

The Provider Base Class and Shared Architecture

All three provider types inherit from the abstract Provider class in music_assistant/models/provider.py. This base class supplies shared functionality including configuration handling, logging infrastructure, and lifecycle management.

Lifecycle Management

Every provider follows a standardized initialization pattern:

  1. __init__ sets up logging, internal caches, and stores the manifest and configuration objects
  2. loaded_in_mass triggers after instantiation, allowing asynchronous initialization and registration with the MusicAssistant core
  3. unload enables graceful shutdown and resource cleanup without server restart
  4. update_config supports runtime reconfiguration, applying new settings without reloading the provider module

Feature Gating with ProviderFeature

The base class implements feature gating through the ProviderFeature enum. Providers declare supported features in their manifest (e.g., ProviderFeature.SEARCH, ProviderFeature.LIBRARY_TRACKS_EDIT), and the base class validates these flags before invoking optional methods. This ensures the core only calls methods the provider actually implements.

Accessing Core Services

Providers communicate with the Music Assistant core through self.mass, the shared MusicAssistant instance. This object provides access to:

  • Caching layer via self.mass.cache
  • Music controller through self.mass.music
  • Player controller via self.mass.players
  • Task scheduling using self.mass.call_later() and self.mass.create_task()

Implementing Custom Providers

Developers create extensions by subclassing the appropriate provider type and including a manifest.json file specifying the domain, name, type (music, player, or metadata), and supported features.

Creating a Music Provider


# my_custom_provider/__init__.py

from music_assistant.models.music_provider import MusicProvider
from music_assistant_models.enums import ProviderFeature, MediaType

class MyCustomMusicProvider(MusicProvider):
    """A stub provider that only supports searching."""
    
    async def search(self, search_query: str, media_types: list[MediaType], limit: int = 5):
        # Pretend we queried an external API and return dummy results

        return SearchResults(
            artists=[],
            albums=[],
            tracks=[],
            playlists=[],
            radios=[],
            podcasts=[],
        )

# manifest.json (placed next to __init__.py)

{
  "domain": "mycustom",
  "name": "My Custom Music",
  "type": "music",
  "stage": "stable",
  "features": ["SEARCH"]
}

Implementing a Player Provider


# my_player_provider/__init__.py

from music_assistant.models.player_provider import PlayerProvider

class MyMDNSPlayerProvider(PlayerProvider):
    async def discover_players(self):
        # Use zeroconf to find "_myplayer._tcp.local." services

        await self.mass.run_provider_discovery(self.instance_id)

Building a Metadata Provider


# my_metadata_provider/__init__.py

from music_assistant.models.metadata_provider import MetadataProvider

class MyCoverArtProvider(MetadataProvider):
    async def resolve_image(self, path: str):
        # Assume `path` is a MusicBrainz ID – retrieve the image URL

        url = f"https://coverartarchive.org/release/{path}/front-500.jpg"
        return url

Key Source Files and Implementation Details

Understanding the provider architecture requires familiarity with these specific files in the music-assistant/server repository:

File Role
music_assistant/models/provider.py Base Provider class with config handling, logging, and lifecycle hooks
music_assistant/models/music_provider.py MusicProvider implementation with library sync and search contracts
music_assistant/models/player_provider.py PlayerProvider definition for device discovery and management
music_assistant/models/metadata_provider.py MetadataProvider interface for enrichment and recommendations
music_assistant/__main__.py Server entrypoint that instantiates the core and loads provider manifests
music_assistant/constants.py Global constants and configuration keys used across providers

Summary

  • MusicProvider handles content catalogues, library synchronization, and audio streaming through methods like sync_library() and search().
  • PlayerProvider manages playback devices and groups via discover_players() and lifecycle hooks on_player_enabled()/on_player_disabled().
  • MetadataProvider enriches media items with external data using get_artist_metadata(), resolve_image(), and recommendation methods.
  • All providers inherit from the base Provider class in music_assistant/models/provider.py, sharing configuration management, logging, and feature gating capabilities.
  • The MusicAssistant core (self.mass) provides providers with access to controllers, caching, and task scheduling utilities.

Frequently Asked Questions

What is the difference between a MusicProvider and a PlayerProvider in Music Assistant?

A MusicProvider supplies audio content and metadata from external sources like Spotify or local files, handling library synchronization and search. A PlayerProvider manages the physical or virtual devices that actually play the audio, handling discovery, grouping, and device-specific control commands. While MusicProviders deal with "what" to play, PlayerProviders handle "where" it plays.

How does Music Assistant handle provider configuration and lifecycle management?

Providers follow a standardized lifecycle defined in the base Provider class. The __init__ method receives configuration and manifest data, loaded_in_mass() triggers asynchronous initialization, and unload() enables graceful shutdown. The update_config() method allows runtime reconfiguration without restarting the server, checking feature support against declared ProviderFeature flags before invoking optional methods.

Can a single provider implementation serve multiple provider types?

No, each provider implementation must inherit from a specific base class—MusicProvider, PlayerProvider, or MetadataProvider—and declare its type in the manifest.json file using the type field ("music", "player", or "metadata"). While providers cannot hybridize types, they can communicate with other provider types through the shared MusicAssistant instance (self.mass) to coordinate behavior.

What methods are required when implementing a MetadataProvider?

No methods are strictly required because MetadataProvider provides default implementations that return None or empty lists. Developers typically override specific methods based on their data source, such as get_artist_metadata() for biographical data, resolve_image() for artwork URLs, or get_similar_tracks() for recommendation engines. This selective implementation allows lightweight providers that only enhance specific media types.

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 →