# How to Implement ProviderFeature Flags in a New Music Assistant Provider

> Learn how to implement ProviderFeature flags in Music Assistant providers. Define capabilities in manifest json, accept supported features in the constructor, and guard methods with runtime checks.

- Repository: [Music Assistant/server](https://github.com/music-assistant/server)
- Tags: how-to-guide
- Published: 2026-06-13

---

**Music Assistant providers declare capabilities through the `ProviderFeature` enum by listing supported flags in [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json), accepting a `supported_features` set in the constructor, and guarding optional methods with runtime checks against this set.**

The `music-assistant/server` repository uses **feature flags** to determine which providers support specific operations like browsing, searching, or library synchronization. When creating a new provider, you must implement **ProviderFeature flags** to advertise capabilities to the core system, ensuring the Music Assistant only invokes your code for operations you actually support.

## Understand the ProviderFeature Enum

The `ProviderFeature` enum is defined in the separate `music-assistant/models` repository within [`music_assistant_models/enums.py`](https://github.com/music-assistant/server/blob/main/music_assistant_models/enums.py). It declares granular capabilities such as `BROWSE`, `SEARCH`, `LIBRARY_TRACKS`, `LIBRARY_ALBUMS`, and `ARTIST_TOPTRACKS`. Each flag represents a contract—if your provider includes a flag in its supported set, the core expects the corresponding method to be implemented. Import the enum in your provider code:

```python
from music_assistant_models.enums import ProviderFeature

```

## Declare Feature Support in the Manifest

Every provider must include a [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json) file that serves as the canonical capability declaration. The core loads this manifest at startup via [`music_assistant/helpers/util.py`](https://github.com/music-assistant/server/blob/main/music_assistant/helpers/util.py) → `load_manifest()` and converts the array into a `frozenset[ProviderFeature]` passed to your constructor.

Example from [`music_assistant/providers/zvuk_music/manifest.json`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/zvuk_music/manifest.json):

```json
{
  "type": "music",
  "name": "ZVuk",
  "supported_features": [
    "BROWSE",
    "SEARCH",
    "LIBRARY_TRACKS",
    "LIBRARY_ALBUMS",
    "LIBRARY_ARTISTS",
    "ARTIST_ALBUMS",
    "ARTIST_TOPTRACKS"
  ]
}

```

The values must match the `ProviderFeature` member names exactly. Case sensitivity matters—`browse` will not match `BROWSE`.

## Accept the Feature Set in the Provider Class

When the core instantiates your provider, it passes the populated feature set as the `supported_features` parameter. The base class `Provider` in [`music_assistant/models/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/provider.py) stores this in `self._supported_features`.

Example implementation in [`music_assistant/providers/zvuk_music/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/zvuk_music/provider.py):

```python
class ZVukMusicProvider(Provider):
    def __init__(self, mass, manifest, config, supported_features):
        # Base class stores the set in self._supported_features

        super().__init__(mass, manifest, config, supported_features)
        # Keep a direct reference for convenience in method guards

        self.supported_features = supported_features

```

## Guard Optional Functionality with Runtime Checks

Any method implementing an optional capability must verify the flag exists before executing. This pattern appears throughout existing providers like Spotify and YouTube Music.

Example guard implementation:

```python
async def get_browse_items(self, **kwargs):
    """Return browse items only if the provider advertises BROWSE support."""
    if ProviderFeature.BROWSE not in self.supported_features:
        raise NotImplementedError("Browse not supported")
    # ... actual browse logic ...

```

Apply this check to all optional methods to prevent crashes when the core queries capabilities.

## Complete Implementation Example

Below is a skeleton showing how to integrate ProviderFeature flags into a new provider:

```python

# music_assistant/providers/my_provider/provider.py

from music_assistant_models.enums import ProviderFeature
from music_assistant.models.provider import Provider

class MyProvider(Provider):
    def __init__(self, mass, manifest, config, supported_features):
        super().__init__(mass, manifest, config, supported_features)
        self.supported_features = supported_features
    
    async def search(self, query: str, media_types: list, limit: int = 10):
        if ProviderFeature.SEARCH not in self.supported_features:
            return []
        # ... search implementation ...

    
    async def get_library_tracks(self):
        if ProviderFeature.LIBRARY_TRACKS not in self.supported_features:
            raise NotImplementedError("Library tracks not supported")
        # ... track retrieval logic ...

```

Corresponding [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json):

```json
{
  "type": "music",
  "name": "My Provider",
  "supported_features": [
    "SEARCH",
    "LIBRARY_TRACKS"
  ]
}

```

## Test Feature Discovery

The core discovers providers via [`music_assistant/models/provider.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/provider.py) → `load_providers()`. To verify your flags work correctly, write unit tests that instantiate your provider with specific flags and assert inclusion in `MusicAssistant.get_providers_supporting_feature()`. Reference the existing test patterns in [`tests/test_cross_type_features.py`](https://github.com/music-assistant/server/blob/main/tests/test_cross_type_features.py) for the standard verification approach.

## Summary

- **Import** `ProviderFeature` from `music_assistant_models.enums` to access capability constants.
- **Declare** supported features in your provider's [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json) using exact enum member names.
- **Accept** the `supported_features` set in your provider's `__init__` and forward it to the base `Provider` class.
- **Guard** every optional method with `if ProviderFeature.FLAG not in self.supported_features:` to prevent invalid calls.
- **Reference** existing providers in `music_assistant/providers/` (such as ZVuk Music, Spotify, or YouTube Music) for canonical implementation patterns.

## Frequently Asked Questions

### What happens if I omit a feature flag from my provider's manifest?

If you omit a flag from [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json), the core will not include that capability in the `supported_features` set passed to your constructor. Consequently, the Music Assistant UI will disable related functionality, and core methods like `get_providers_supporting_feature()` will exclude your provider from those operations, even if you implement the corresponding methods.

### Can I dynamically change ProviderFeature flags at runtime?

No. The `supported_features` set is populated once at provider initialization from the manifest and stored as a frozen set in the base class. To change capabilities, you must update [`manifest.json`](https://github.com/music-assistant/server/blob/main/manifest.json) and restart the Music Assistant server so the core reloads the provider configuration via `load_manifest()`.

### Where is the ProviderFeature enum defined?

The enum is defined in the `music-assistant/models` repository, specifically in [`music_assistant_models/enums.py`](https://github.com/music-assistant/server/blob/main/music_assistant_models/enums.py). This is a separate package from the main server. Import it using `from music_assistant_models.enums import ProviderFeature` to ensure compatibility with the core's type checking.

### Do I need to implement all methods for a feature flag I declare?

Yes. If you declare a flag like `BROWSE` or `SEARCH` in your manifest, the core expects the corresponding methods (such as `get_browse_items()` or `search()`) to be available and functional. While you should guard these methods with runtime checks against `self.supported_features`, declaring a feature without implementing its interface will raise `NotImplementedError` or similar exceptions when the core attempts to use those capabilities.