BeatOS MCP facade — FastMCP server (mounted by beatos-http) + in-process stdio<->/mcp proxy launcher.
BeatOS MCP exhibits strong naming conventions, comprehensive tool descriptions, and well-structured schemas across 23 tools. All tools follow verb_noun naming (list_tracks, get_track, create_list, update_tracks, etc.). Tool descriptions are detailed and contextual, averaging 140-250 characters with clear guidance on prerequisites and when to use each tool. Input schemas are complete with JSON Schema types, descriptions, and appropriate constraints (enums, min/max bounds). Output schemas are documented in descriptions with pagination support and structured returns. Key strengths: batch operations (create_tracks, attach_assets, update_tracks with array support), clear field-to-field chaining (list_tracks returns track ids usable by get_track), and comprehensive error guidance embedded in descriptions (e.g., 'Use list_distinct_values first to discover values'). Weaknesses: some parameter descriptions could be more concise; no explicit dry-run or confirmation pattern for destructive operations (purge_tracks, delete_list); error handling relies on description text rather than explicit error response examples; missing per-item success/failure detail in batch operations.
Add one or more tracks to a list. Duplicates are silently skipped. Applies directly; recorded in Agent Actions.
Attach audio and/or cover assets to one or more tracks. Asset bytes are base64-encoded in the request. All specified tracks receive the same cover (if provided); audio files are matched to tracks by position. Applies directly; recorded in Agent Actions.
Create a new user list. Applies directly (your MCP client gates the call); recorded in BeatOS → Agent Actions. Returns {list_id, name}.
Create one or more tracks and optionally attach audio/cover assets. Asset bytes are base64-encoded in the request. Applies directly; recorded in Agent Actions with filenames and track titles.
Delete a user list (not system lists). Applies directly; recorded in Agent Actions.
Detach audio and/or cover assets from one or more tracks. Applies directly; recorded in Agent Actions.
Destructive operations (purge_tracks, delete_list) lack confirmation or dry-run patterns. No explicit error recovery or undo guidance in responses.
Batch operations (create_tracks, update_tracks, attach_assets) do not document per-item success/failure responses. If one track update fails in a batch of 500, the agent lacks clarity on which succeeded and which failed.
Error handling relies entirely on description text. No documented error response examples showing what LLMs should expect on invalid input, resource not found, or permission denied. Descriptions guide intent but not failure recovery.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 73 | 2026-07-28+ | v2 |
Export one track's metadata shaped for a platform's upload form. Returns {platform, fields:[{key,label,value,options,note}]}. Genre/mood are translated to the platform's vocabulary; multi-genre returns `options` (the platform is single-select). Identical output to the in-app export panel. Price tiers come from the track's own license tiers (set via set_license_tiers) when present; otherwise the platform template's default prices are used.
Fetch a single track by id, including its audio/cover assets. For listing without per-track detail, use list_tracks.
Enumerate distinct values + counts for one of producer/genre/mood/key. Returns {items: [{value, count}, ...]} ordered by count desc. Call this before filtering list_tracks so you use the user's actual spelling.
List platforms BeatOS can export metadata for (e.g. "netease"). Returns {platforms: [str, ...]}.
List all user + system lists. Returns {items: [{id, name, kind, position, created_at}, ...]}; no pagination.
List tracks in the BeatOS library with rich filtering. Default sort: created_at desc. Default limit: 50 (max 500). Returns {items, total, returned, limit, offset, hint?}. Use list_distinct_values first to discover what values exist for producer/genre/mood/key. Use get_track for full single-track detail including assets and description fields.
Merge metadata from one track into one or more other tracks. Source track is not modified; target tracks' scalar fields (title, bpm, key, description, is_free) are replaced; multi-value fields (producer, genre, mood) are unioned. Applies directly; recorded in Agent Actions.
Liveness check — returns pong and the BeatOS version.
PERMANENTLY delete tracks (and cascade their asset rows). Source audio files on disk are not touched. Irreversible — applies directly; recorded in BeatOS → Agent Actions.
Remove one or more tracks from a list. Applies directly; recorded in Agent Actions.
Reorder a list's tracks. Applies directly; recorded in Agent Actions.
Restore previously-trashed tracks. Applies directly; recorded in BeatOS → Agent Actions.
Search tracks with the same query syntax humans use in the BeatOS search box. Returns identical results to the in-app search. Returns {items, total, returned, limit, offset, hint?}. Use offset to page when total exceeds the returned count.
Set license tier pricing for one or more tracks. Tiers replace (not merge). Applies directly; recorded in Agent Actions.
Move tracks to trash (soft delete; reversible via restore_tracks). Applies directly; recorded in BeatOS → Agent Actions (with the affected tracks' titles).
Update a list's name or reorder its tracks. Applies directly; recorded in Agent Actions.
Update metadata on one or more tracks. 'ids' is a list of track ids. 'patch' maps fields to new values: scalar fields title, bpm, key, description, is_free take a plain value; multi-value fields producer, genre, mood take either a list (replace) or {"add": [...], "remove": [...]}. Only include fields you intend to change. Applies directly; recorded in Agent Actions.
The 'patch' parameter in update_tracks accepts an untyped object. Description documents the structure, but JSON Schema lacks explicit type definitions for the nested patch object properties. This forces LLMs to reason about structure from text alone.
list_distinct_values returns untyped items array in description ('{items: [{value, count}, ...]}'); JSON Schema could be more precise about nested field types.