# How Music Assistant's Provider System Works: Architecture and Supported Types

> Explore the Music Assistant provider system architecture. Learn how integrations inherit from a base Provider class and register via manifest.json to supply music, playback, and metadata.

- Repository: [Music Assistant/server](https://github.com/music-assistant/server)
- Tags: architecture
- Published: 2026-06-14

---

**Music Assistant uses a unified provider system where every integration inherits from a base `Provider` class, declares its capabilities via the `ProviderFeature` enum, and registers through a [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json) file to supply music catalogues, playback devices, metadata, or plugins.**

The `music-assistant/server` repository implements a modular architecture that separates streaming services, hardware controllers, and metadata sources into distinct provider types. Understanding how this provider system works is essential for developers extending Music Assistant or troubleshooting why a specific integration behaves differently than expected.

## The Provider Base Class and Core Architecture

Every integration in Music Assistant begins with the **`Provider`** class defined in [`music_assistant/models/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/provider.py). This base class stores three critical references: the provider's **manifest**, its runtime **configuration**, and a handle to the core `MusicAssistant` instance.

The base class maintains a private set called `self._supported_features` that contains `ProviderFeature` enum values declaring what the integration can do. Developers query these capabilities through two helper methods:

- **`supports_feature()`** – Returns a boolean indicating feature availability.
- **`check_feature()`** – Raises an exception if the feature is unsupported.

When Music Assistant starts, the core reads each provider's [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json) to build a `ProviderManifest` object. This manifest specifies the `type` (via the `ProviderType` enum), a unique `domain` identifier (e.g., `spotify` or `sonos`), and the development `stage` (`stable` or `beta`). The system then instantiates the provider class, injects the manifest and config, and registers the instance in the global `mass.providers` registry.

## Five Provider Types Supported in Music Assistant

Music Assistant subclasses the base `Provider` into five concrete families, each identified by a `ProviderType` enum entry. Here is how they function according to the source:

- **MusicProvider** – Defined in [`music_assistant/models/music_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/music_provider.py). These providers supply music catalogues, handle library synchronization, implement search functionality, and return playback details. Typical implementations include Spotify, Tidal, YouTube Music, Plex, and Subsonic.

- **PlayerProvider** – Defined in [`music_assistant/models/player_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/player_provider.py). These control playback devices such as speakers and media players, optionally supporting grouping features like Sonos zones or MPD clients.

- **MetadataProvider** – Defined in [`music_assistant/models/metadata_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/metadata_provider.py). These offer supplemental metadata not present in the core music catalogue, including album artwork, lyrics, and advanced track tags from sources like MusicBrainz, TheAudioDB, and LRCLib.

- **AudioAnalysisProvider** – Defined in [`music_assistant/models/audio_analysis_provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/audio_analysis_provider.py). These perform computational audio tasks such as loudness detection, acoustic fingerprinting, and similarity matching. Examples include SonicSimilarity and SmartFades.

- **PluginProvider** – Defined in [`music_assistant/models/plugin.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/plugin.py). These implement optional, non-core features that extend Music Assistant's functionality, such as smart playlist generation, scrobbling to Last.fm, or recommendation engines.

## Provider Registration and Manifest System

Providers declare themselves to the core through a **[`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json)** file located in each provider's folder. When Music Assistant boots, it parses these manifests to construct `ProviderManifest` objects without instantiating the provider code.

The registration flow follows these steps:

1. The core discovers [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json) files across the `providers/` directory.
2. It validates the `domain` uniqueness and maps the `type` field to the `ProviderType` enum.
3. Upon user activation, the core imports the provider module, instantiates the class, and calls `loaded_in_mass()`.
4. The provider becomes accessible via `mass.providers.get_by_domain("domain_name")`.

## Feature Detection and Capability Checking

Providers advertise functionality through the **`ProviderFeature`** enum. Common features include `SEARCH`, `LIBRARY_ARTISTS`, `LIBRARY_ALBUMS`, and `PLAYLIST_CREATE`.

Before invoking provider-specific logic, the core guards calls using feature detection:

```python
spotify = self.mass.providers.get_by_domain("spotify")
if spotify and spotify.supports_feature(ProviderFeature.SEARCH):
    results = await spotify.search("beatles", [MediaType.ARTIST, MediaType.TRACK])

```

If a provider receives a call for an unsupported feature, it raises **`NotImplementedError`**. The core catches this exception and either falls back to alternative providers or returns a default implementation, ensuring the system remains stable even when specific providers lack certain capabilities.

## Provider Lifecycle Management

Providers support dynamic configuration changes without requiring a full server restart. The lifecycle hooks in [`music_assistant/models/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/provider.py) manage this state:

- **`loaded_in_mass()`** – Called immediately after registration. Providers perform async initialization here, such as establishing API sessions or discovering network devices.

- **`update_config()`** – Invoked when a user changes settings via the configuration UI. This updates the stored configuration, optionally reloads the provider, and reapplies logging levels.

- **`unload()`** and **`unload_with_error()`** – Clean up resources when a provider is disabled or encounters a fatal error. This includes closing HTTP sessions, stopping background tasks, and removing player registrations.

## Implementation Examples

### Creating a Minimal Music Provider

To implement a new streaming integration, subclass `MusicProvider` and declare supported features:

```python

# my_provider/provider.py

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

class MyProvider(MusicProvider):
    async def search(self, query: str, media_types: list[MediaType], limit: int = 5):
        # Implement provider-specific search logic

        results = await self._api.search(query, limit)
        return results

    async def get_library_artists(self):
        # Return an async generator of Artist objects

        for artist in await self._api.get_artists():
            yield artist

# Register supported features

SUPPORTED_FEATURES = {
    ProviderFeature.SEARCH,
    ProviderFeature.LIBRARY_ARTISTS,
    ProviderFeature.LIBRARY_ALBUMS,
}

```

### Accessing Providers from Core Logic

Other components interact with providers through the registry:

```python

# Inside a core controller or other provider

player_provider = self.mass.providers.get_by_domain("sonos")
if player_provider:
    await player_provider.on_player_enabled(player_id)

```

## Summary

- **Base Architecture:** All providers inherit from `Provider` in [`music_assistant/models/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/provider.py), storing manifests and configuration while exposing `supports_feature()` for capability checks.
- **Five Types:** Music Assistant supports **MusicProvider**, **PlayerProvider**, **MetadataProvider**, **AudioAnalysisProvider**, and **PluginProvider**, each defined in corresponding files under `music_assistant/models/`.
- **Registration:** Providers declare themselves via [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json), which the core parses to build `ProviderManifest` objects before instantiation.
- **Lifecycle:** Async hooks including `loaded_in_mass()`, `update_config()`, and `unload()` manage initialization, dynamic reconfiguration, and cleanup.

## Frequently Asked Questions

### What is the difference between a MusicProvider and a PlayerProvider?

A **MusicProvider** supplies audio content and metadata from sources like Spotify or Plex, handling search and library sync. A **PlayerProvider** controls physical or virtual playback devices such as Sonos speakers or MPD instances, managing volume, transport controls, and grouping.

### How does Music Assistant check if a provider supports a specific feature?

The core calls `provider.supports_feature(ProviderFeature.SOME_FEATURE)` before invoking capability-specific methods. If a provider receives a call for an unsupported feature, it raises `NotImplementedError`, which the core catches to handle gracefully or fall back to alternatives.

### Can providers be reloaded without restarting Music Assistant?

Yes. When configuration changes occur, the core invokes `provider.update_config()` to apply new settings. For major changes, the system may call `unload()` followed by re-instantiation and `loaded_in_mass()`, allowing providers to reinitialize without a full server restart.

### What files are required to create a custom provider?

You need a **[`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json)** declaring the `domain`, `type`, and `stage`, and a **[`provider.py`](https://github.com/music-assistant/server/blob/main/provider.py)** containing a class that inherits from the appropriate base (e.g., `MusicProvider`). Optional [`__init__.py`](https://github.com/music-assistant/server/blob/main/__init__.py) files and dependency directories follow standard Python package structure within the `providers/` directory.