/
/
/
1"""Setup flow for connecting an MCP client."""
2
3from __future__ import annotations
4
5from typing import TYPE_CHECKING
6
7from music_assistant.models.setup_flow import SetupFlowError
8
9from ._init_helpers import _dispatch_open_connect
10from .config import build_config_entries
11from .connect import mount_connect_wizard
12from .constants import (
13 CONF_EXTRA_ALLOWED_ORIGINS,
14 CONF_MOUNT_PATH,
15 CONF_TRUST_FORWARDED_PROTO,
16 DEFAULT_MOUNT_PATH,
17)
18from .tags import CONFIG_TO_TAG
19
20if TYPE_CHECKING:
21 from collections.abc import Callable
22
23 from music_assistant_models.config_entries import ConfigValueType
24
25 from music_assistant.models.setup_flow import SetupSession
26
27
28async def run_setup(session: SetupSession) -> None:
29 """
30 Open the Connect Wizard and finish after it generates a client configuration.
31
32 :param session: The setup session driving the flow.
33 """
34 values = _effective_values(session)
35 mount_path = str(values.get(CONF_MOUNT_PATH) or DEFAULT_MOUNT_PATH)
36 unmount: Callable[[], None] | None = None
37 instance_id = session.context.instance_id
38 provider = (
39 session.mass.get_provider(instance_id, return_unavailable=True) if instance_id else None
40 )
41 if provider is None:
42 unmount = await mount_connect_wizard(
43 session.mass,
44 mount_path,
45 enabled_tags_provider=lambda: [
46 str(tag) for key, tag in CONFIG_TO_TAG.items() if values.get(key)
47 ],
48 extra_origins_csv=str(values.get(CONF_EXTRA_ALLOWED_ORIGINS) or ""),
49 trust_forwarded_proto=bool(values.get(CONF_TRUST_FORWARDED_PROTO)),
50 )
51 try:
52 wizard_url = await _dispatch_open_connect(
53 session.mass,
54 values,
55 setup_callback_path=session.callback_path,
56 )
57 if wizard_url is None:
58 raise SetupFlowError("Unable to open the MCP Connect Wizard")
59 await session.external(wizard_url, step_id="connect")
60 finally:
61 if unmount is not None:
62 unmount()
63 await session.finish({})
64
65
66def _effective_values(session: SetupSession) -> dict[str, ConfigValueType]:
67 """Return stored option values overlaid on the MCP provider defaults."""
68 entries = build_config_entries(session.mass, DEFAULT_MOUNT_PATH)
69 values = {entry.key: entry.default_value for entry in entries}
70 values.update(session.context.values)
71 return values
72