Move the media server, downloader, library volume, and browser player to the
standalone hope-media-music product. Keep Hope's music tools as a thin HTTP
client of the LAN service on port 8094.
Use a stable voice-room player scope instead of ephemeral LiveKit room names.
The agent now owns the conversation handshake: fresh reported playback mutes
its input, joining pauses music, and the last participant leaving resumes only
music it paused. Peer failures remain non-fatal.
Also move the voice deploy workflow onto the active Unraid Gitea runner and
remove yt-dlp/ffmpeg/media health and volume dependencies from the image.
- web/media_server.py: FastAPI service owning the permanent library
(library.json + ./media volume), yt-dlp YouTube Music search, queued
download jobs with mp3 transcode (ffmpeg), per-room player desired
state, and an HTTPS proxy for external live-stream URLs.
- agent/media_mcp.py: Hope tools — search_music, play_song,
offer_song_choices, pause/resume/stop/skip/seek, now_playing,
list_library, add_stream.
- agent/agent.py: media toolset wiring + conversation rule (music
playing disables the agent mic; re-engaging pauses music).
- web UI: slide-out Music panel (search, suggestions, library, live
stream add, play/pause, ±10s, seek, volume) with a reconciling poller
and media_state data-channel reports.
- token server returns the minted room name; nginx serves /media/files
as static (native Range) and proxies /media/api to the media server.
- supervisord runs media-server; compose mounts ./media and adds
ffmpeg to the image.
- agent/web_mcp.py: stdio MCP server exposing web_search and web_scrape,
backed by the self-hosted Firecrawl stack on xNAS (no API key needed)
- agent.py: Agent now attaches mcp_servers built from config; EXTRA_MCP_SERVERS
env var allows adding arbitrary HTTP/SSE MCP servers as JSON
- Dockerfile: installs livekit-agents[mcp], copies web_mcp.py
- .env.example: WEB_MCP_ENABLED, FIRECRAWL_BASE, EXTRA_MCP_SERVERS documented