From media-assistant-ops
Shared reference for the Music Assistant local API — base URL, auth, the WebSocket command bus, the DSP/EQ schema, and the data-storage layout this plugin uses. Load when another skill in this plugin needs to know how to talk to the server, what DSP shape to send, or where to read/write files.
npx claudepluginhub danielrosehill/claude-code-plugins --plugin media-assistant-opsThis skill uses the workspace's default tool permissions.
Music Assistant (MA) runs as a Home Assistant add-on or standalone container. It exposes a local HTTP + WebSocket API on port **8095** by default.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Music Assistant (MA) runs as a Home Assistant add-on or standalone container. It exposes a local HTTP + WebSocket API on port 8095 by default.
http://<LAN_IP>:8095/api-docsThe MA API surface evolves between releases. When a call 4xx/404s, fetch /api-docs from the user's running server first — it's always the source of truth for that install.
http://<LAN_IP>:8095ws://<LAN_IP>:8095/wsPrefer the LAN address when both are available.
Long-lived API key as a Bearer token:
Authorization: Bearer <API_KEY>
For WebSocket, the first frame after connect is an auth message:
{"type": "auth", "token": "<API_KEY>"}
MA's primary API is a JSON-RPC-style command bus available over both HTTP (POST /api) and WebSocket. Each call looks like:
{"command": "<command_name>", "args": { ... }, "message_id": "<uuid>"}
Verbatim commands worth knowing (subject to version):
config/players/get — fetch a player_config by player_idconfig/players/save — write a player_config (this is how DSP is updated)players/cmd/play, players/cmd/pause, players/cmd/stop, players/cmd/next, players/cmd/previousplayers/cmd/volume_set (args: { "player_id": "...", "volume_level": 0-100 })players/cmd/power (args: { "player_id": "...", "powered": true|false })players/all — list playersmusic/library/... — library queriesIf you're unsure of the exact command name on the user's MA version, hit http://<LAN_IP>:8095/api-docs and grep for the keyword.
Per the official DSP docs, the parametric EQ supports:
peaking (Peak / Bell), high_shelf, low_shelf, high_pass, low_pass, notch, all_pass.The DSP block lives inside the player_config under a dsp key. Canonical shape this plugin emits:
{
"dsp": {
"enabled": true,
"preamp_gain_db": -2.0,
"per_channel": false,
"bands": [
{"type": "peaking", "frequency": 2500, "gain_db": 3.0, "q": 1.0, "enabled": true},
{"type": "high_pass", "frequency": 70, "q": 0.7, "enabled": true}
]
}
}
Notes:
gain_db is omitted for filters where it doesn't apply (high_pass, low_pass, notch, all_pass).q is meaningful for peaking and the pass/notch filters.frequency is integer Hz.gain vs gain_db, freq vs frequency) — when a save fails, fetch /api-docs and adapt.DSP only applies to MA-native player flows (snapcast / built-in players). Hardware players that handle their own decoding may not expose a dsp key in their player_config.
Tone Controls (separate, simpler bass/treble) live alongside DSP per the docs at https://www.music-assistant.io/dsp/tonecontrols/.
DATA_ROOT="${CLAUDE_USER_DATA:-${XDG_DATA_HOME:-$HOME/.local/share}/claude-plugins}/media-assistant-ops"
$DATA_ROOT/
├── config.json # { lan_url, wan_url, api_key, port }
├── data/
│ ├── players-snapshot.json # raw players/all response from onboarding
│ ├── players-snapshot.md # human-readable roster
│ ├── library-snapshot.json
│ ├── library-snapshot.md
│ └── dsp-presets/
│ └── <player-slug>/
│ └── <preset-name>.json
└── state/
└── last-dsp-<player-slug>.json # rollback snapshot before any DSP change
Never write plugin data under ~/.claude/ or inside the plugin install directory.
DATA_ROOT="${CLAUDE_USER_DATA:-${XDG_DATA_HOME:-$HOME/.local/share}/claude-plugins}/media-assistant-ops"
CONFIG="$DATA_ROOT/config.json"
[ -f "$CONFIG" ] || { echo "Run /media-assistant-ops:onboard first"; exit 1; }
LAN_URL=$(jq -r '.lan_url' "$CONFIG")
API_KEY=$(jq -r '.api_key' "$CONFIG")
curl -sS -X POST "$LAN_URL/api" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"command":"config/players/get","args":{"player_id":"'"$PLAYER_ID"'"}}'