{"name":"BeatBrain","version":"1.0.0","tools":[{"name":"play_music","description":"Start a BeatBrain music session. Interprets context and plans a set of tracks from the user's connected streaming service.\n\nIMPORTANT: If the user has multiple streaming services connected (e.g. Spotify + Tidal), you MUST pass the \"service\" parameter to select which one to use. Without it, BeatBrain picks the most recently active connection, which may not be what the user wants.\n\nFor Tidal: pass service: \"tidal\". The response will include a deep_link (not a web_player_url) — send it directly to the user. There is no BeatBrain web player for Tidal.\nFor Deezer: pass service: \"deezer\". The response will include a deep_link (not a web_player_url) — send it directly to the user. There is no BeatBrain web player for Deezer.\nFor Apple Music: pass service: \"apple_music\". Returns a web_player_url for the BeatBrain Web Player.\nFor Spotify: pass service: \"spotify\" (or omit — Spotify is the default). Returns planned tracks and a session_id.\n'play_music' auto-starts playback by default. For explicit orchestration, pass autoplay: false and then call start_playback.\n\nExample: play_music({ prompt: \"chill coding vibes\", end_user_id: \"user123\", track_count: 12, service: \"tidal\", autoplay: false })\nReturns for Tidal: { session_id, deep_link: \"https://listen.tidal.com/playlist/...\", service: \"tidal\" }\nReturns for Deezer: { session_id, deep_link: \"https://www.deezer.com/playlist/...\", service: \"deezer\" }\nReturns for Spotify/Apple Music: { session_id, set: { tracks: [...] }, playback: \"not_started|started\" }","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"Natural language description of the desired music. Examples: \"chill coding vibes at 2am\", \"high energy workout mix\", \"jazz for a dinner party\", \"90s hip hop road trip\""},"end_user_id":{"type":"string","description":"Identifies the human user whose streaming service will be used for playback"},"service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Which streaming service to use. ALWAYS specify this when the user has multiple services connected or asks for a specific one. \"spotify\" for Spotify, \"apple_music\" for Apple Music, \"tidal\" for Tidal, \"deezer\" for Deezer. If omitted, defaults to most recently active service (usually Spotify). Alias: \"streaming_service\" also accepted."},"streaming_service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Alias for \"service\". Use either one."},"energy":{"type":"number","description":"Energy level 0.0 (ambient) to 1.0 (peak). Default: inferred from prompt."},"objective":{"type":"object","description":"Optional objective envelope (targets, constraints, weights) produced by compile_objective"},"planning_mode":{"type":"string","enum":["balanced","explore","safe"],"description":"Optional high-level planning mode hint"},"determinism_seed":{"type":"integer","description":"Optional seed for deterministic orchestration controls"},"genre_hints":{"type":"array","items":{"type":"string"},"description":"Preferred genres. Use underscores: [\"indie_rock\", \"dream_pop\"]"},"track_count":{"type":"integer","description":"Number of tracks (default: 12, max: 30)"},"sensors":{"type":"object","description":"Optional real-time signals: { heart_rate, stress_level, ambient_noise_db, device_type, people_count, location_type, conversation_mood }"},"calendar":{"type":"object","description":"Optional schedule signals: { is_meeting, day_of_week, next_event_in_minutes, season }"},"psychological_state":{"type":"object","description":"Optional psychological-state snapshot: { arousal, valence, dominance, confidence, sources, captured_at }"},"device_id":{"type":"string","description":"Spotify device ID to play on. Use get_devices to list available devices. If omitted, plays on the user's active device."},"autoplay":{"type":"boolean","description":"Start playback immediately. Default: true. Set autoplay: false to plan first and call start_playback explicitly."},"skills":{"type":"array","items":{"type":"string"},"description":"Intelligence skills to activate. Each modifies scoring, energy curves, interpretation, or search. Examples: [\"deep-focus\"], [\"party-architect\", \"harmonic-flow\"], [\"sommelier\"]"},"skill_config":{"type":"object","description":"Per-skill configuration overrides. Keys are skill IDs, values are config objects. Example: { \"vinyl-curator\": { \"target_decade\": \"70s\", \"deep_cuts_only\": true } }"}},"required":["prompt","end_user_id"]}},{"name":"start_playback","description":"Start playback for an already planned session. Use after play_music when you need explicit two-step orchestration.\n\nExample: start_playback({ end_user_id: \"user123\", session_id: \"sess_abc\" })\nReturns: { status: \"playing|needs_device|playlist_ready\", ... }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"Identifies the human user whose connected service should be used"},"session_id":{"type":"string","description":"Session ID returned by play_music. If provided, track_uris are optional."},"track_uris":{"type":"array","items":{"type":"string"},"description":"Optional explicit track URIs to play. If omitted, playback uses session tracks from session_id."},"device_id":{"type":"string","description":"Optional Spotify device ID to target playback"},"service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Optional service override. Defaults to the user's latest active connection."}},"required":["end_user_id"]}},{"name":"search_tracks","description":"Search for tracks using BeatBrain's intelligence. Searches the user's connected streaming service, enriches results with cultural metadata, and scores them with a 16-dimension fitness algorithm.\n\nExample: search_tracks({ prompt: \"upbeat indie for a road trip\", end_user_id: \"user123\", limit: 10 })\nReturns: { tracks: [{ spotify_uri, title, artist, fit_score, genre, energy }] }","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"Natural language search context"},"end_user_id":{"type":"string","description":"User whose streaming service to search"},"mood":{"type":"string","description":"Mood keyword: happy, sad, energetic, chill, etc."},"activity":{"type":"string","description":"Activity: workout, coding, driving, cooking, etc."},"genre_hints":{"type":"array","items":{"type":"string"},"description":"Genre preferences"},"energy":{"type":"number","description":"Target energy 0-1"},"limit":{"type":"integer","description":"Max results (default: 20)"},"include_explanation":{"type":"boolean","description":"Include per-track scoring explanation"}},"required":["end_user_id"]}},{"name":"plan_set","description":"Plan a complete music set with energy arcs, harmonic sequencing, and genre flow. Uses beam search to find the optimal track sequence from the BeatBrain catalog + the user's streaming service. Returns track URIs ready for playback.\n\nExample: plan_set({ prompt: \"sunset beach vibes that builds to a peak\", end_user_id: \"user123\", track_count: 15, skills: [\"harmonic-flow\"] })\nReturns: { set: { tracks: [...], energy_arc: [...], total_duration_ms }, scene: {...} }","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"Natural language context for the set"},"end_user_id":{"type":"string","description":"User whose streaming service to use"},"track_count":{"type":"integer","description":"Number of tracks (default: 12, max: 30)"},"energy_curve":{"type":"string","enum":["building","sustaining","declining","wave","peak_valley"],"description":"Energy arc shape. building=gradual ramp up, wave=oscillating, peak_valley=build to middle then wind down"},"genre_hints":{"type":"array","items":{"type":"string"}},"avoid_genres":{"type":"array","items":{"type":"string"}},"play_history":{"type":"array","items":{"type":"string"},"description":"Spotify IDs to avoid repeats"},"sensors":{"type":"object","description":"Real-time sensor signals"},"calendar":{"type":"object","description":"Calendar/schedule signals"},"psychological_state":{"type":"object","description":"Optional psychological-state snapshot: { arousal, valence, dominance, confidence, sources, captured_at }"},"objective":{"type":"object","description":"Optional objective envelope (targets, constraints, weights) produced by compile_objective"},"planning_mode":{"type":"string","enum":["balanced","explore","safe"],"description":"Optional high-level planning mode hint"},"determinism_seed":{"type":"integer","description":"Optional seed for deterministic orchestration controls"},"include_explanation":{"type":"boolean","description":"Include per-track explanations"},"skills":{"type":"array","items":{"type":"string"},"description":"Intelligence skills to activate. Each modifies scoring, energy curves, interpretation, or search. Examples: [\"deep-focus\"], [\"sommelier\", \"harmonic-flow\"]"},"skill_config":{"type":"object","description":"Per-skill configuration overrides. Keys are skill IDs, values are config objects."}},"required":["prompt","end_user_id"]}},{"name":"compile_objective","description":"Compile natural-language context into a structured objective envelope (targets, constraints, weights) that downstream tools can use.\n\nExample: compile_objective({ prompt: \"late-night focus with low vocals\", end_user_id: \"user123\" })\nReturns: { objective: { targets, constraints, weights, mode }, scene }","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"Natural language objective prompt"},"end_user_id":{"type":"string","description":"User ID for personalization context"},"mood":{"type":"string"},"activity":{"type":"string"},"energy":{"type":"number"},"genre_hints":{"type":"array","items":{"type":"string"}},"avoid_genres":{"type":"array","items":{"type":"string"}},"sensors":{"type":"object"},"calendar":{"type":"object"},"planning_mode":{"type":"string","enum":["balanced","explore","safe"]}},"required":["end_user_id"]}},{"name":"query_candidates","description":"Query candidate tracks from BeatBrain search, optionally guided by a compiled objective envelope.\n\nExample: query_candidates({ end_user_id: \"user123\", prompt: \"afro house sunset\", objective: {...}, limit: 60 })\nReturns: { candidates: [...], scene }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User ID for retrieval context"},"prompt":{"type":"string","description":"Optional fallback prompt for candidate retrieval"},"objective":{"type":"object","description":"Structured objective envelope from compile_objective"},"limit":{"type":"integer","description":"Max candidates to return (default 50, max 100)"},"include_explanation":{"type":"boolean","description":"Include candidate-level explanations"}},"required":["end_user_id"]}},{"name":"score_candidates","description":"Score external or queried candidates against a structured objective.\n\nExample: score_candidates({ objective: {...}, candidates: [...] })\nReturns: { scored_candidates: [...], accepted_count, rejected_count }","inputSchema":{"type":"object","properties":{"objective":{"type":"object","description":"Structured objective envelope"},"candidates":{"type":"array","items":{"type":"object"},"description":"Candidate tracks to score"}},"required":["objective","candidates"]}},{"name":"sequence_tracks","description":"Plan an ordered sequence from scored candidates using target energy progression.\n\nExample: sequence_tracks({ objective: {...}, candidates: [...], track_count: 12 })\nReturns: { sequence: [...], summary }","inputSchema":{"type":"object","properties":{"objective":{"type":"object","description":"Structured objective envelope"},"candidates":{"type":"array","items":{"type":"object"},"description":"Scored or unscored candidate tracks"},"track_count":{"type":"integer","description":"Number of tracks in output sequence (default 12)"}},"required":["candidates"]}},{"name":"simulate_plan","description":"Run an end-to-end dry run of candidate query, scoring, and sequencing to inspect planning diagnostics before playback.\n\nExample: simulate_plan({ end_user_id: \"user123\", prompt: \"indie coding at night\", objective: {...} })\nReturns: { diagnostics, simulated_plan }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User ID for personalization context"},"prompt":{"type":"string","description":"Optional prompt used during candidate query"},"objective":{"type":"object","description":"Structured objective envelope"},"planning_mode":{"type":"string","enum":["balanced","explore","safe"]},"track_count":{"type":"integer","description":"Number of tracks to simulate (default 12)"}},"required":["end_user_id"]}},{"name":"control_playback","description":"Control playback on the user's streaming service. Supports: pause, resume, skip, previous, seek, volume, shuffle, repeat, transfer.\nNote: Only available for services with remote playback (Spotify). For Apple Music, use playlist management instead.\n\nUse \"transfer\" with a device_id to move playback to a different device (e.g., from Echo Show to iPhone).\n\nExample: control_playback({ end_user_id: \"user123\", action: \"skip\" })\nExample: control_playback({ end_user_id: \"user123\", action: \"volume\", value: 80 })\nExample: control_playback({ end_user_id: \"user123\", action: \"transfer\", device_id: \"abc123\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User whose playback to control"},"action":{"type":"string","enum":["pause","resume","skip","previous","seek","volume","shuffle","repeat","transfer"],"description":"Playback action"},"value":{"type":["number","string","boolean"],"description":"Action value: seek=ms, volume=0-100, shuffle=true/false, repeat=off/track/context"},"device_id":{"type":"string","description":"Target device ID (required for \"transfer\" action, optional otherwise)"}},"required":["end_user_id","action"]}},{"name":"report_feedback","description":"Report user feedback on music. Feeds BeatBrain's learning engine to improve future recommendations.\n\nSimple format: report_feedback({ end_user_id: \"user123\", signal_type: \"like\" })\nFull format: report_feedback({ end_user_id: \"user123\", signals: [{ type: \"like\", track_id: \"spotify_id\" }] })\nsession_id is optional — BeatBrain will find the most recent session automatically.","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User whose feedback to report"},"session_id":{"type":"string","description":"Session ID (optional — uses latest session if omitted)"},"signal_type":{"type":"string","enum":["like","dislike","skip","save","volume_change","time_to_skip","re_request","session_rating","track_complete"],"description":"Simple feedback type (alternative to signals array)"},"track_id":{"type":"string","description":"Spotify track ID (for simple format)"},"signals":{"type":"array","description":"Full signals array (alternative to signal_type)","items":{"type":"object","properties":{"type":{"type":"string","enum":["like","dislike","skip","volume_change","time_to_skip","re_request","session_rating","track_complete"]},"track_id":{"type":"string","description":"Spotify track ID"},"value":{"type":"number","description":"Signal value (depends on type)"}},"required":["type"]}},"context":{"type":"object","description":"Current context: { activity, location_type, device_type, time_of_day }"}},"required":["end_user_id"]}},{"name":"interpret_context","description":"Convert natural language, sensor data, calendar info, and environmental signals into structured musical parameters. Shows what BeatBrain would interpret from a given context.\n\nExample: interpret_context({ prompt: \"focus mode\", sensors: { heart_rate: 62, location_type: \"office\" } })\nReturns: { scene: { genres: [\"ambient\", \"lo_fi\"], energy: 0.3, instrumental_only: true } }","inputSchema":{"type":"object","properties":{"prompt":{"type":"string","description":"Natural language context"},"mood":{"type":"string"},"activity":{"type":"string"},"energy":{"type":"number"},"sensors":{"type":"object","description":"{ heart_rate, stress_level, ambient_noise_db, device_type, people_count, location_type, conversation_mood, latitude, longitude }"},"calendar":{"type":"object","description":"{ is_meeting, day_of_week, next_event_in_minutes, season }"},"psychological_state":{"type":"object","description":"Optional psychological-state snapshot: { arousal, valence, dominance, confidence, sources, captured_at }"}}}},{"name":"register_agent","description":"Register your AI agent with BeatBrain. If you already have an API key, this creates a sub-agent identity under your key. If you don't have a key yet, provide an email and this will generate a new API key for you (sandbox tier, 50 req/hr).\n\nWithout API key (self-provisioning):\n  register_agent({ name: \"Claude Music\", email: \"dev@example.com\" })\n  Returns: { agent_id, api_key, tier: \"sandbox\" }\n\nWith existing API key:\n  register_agent({ name: \"Claude Music\", description: \"Anthropic's music assistant\" })\n  Returns: { id, name, created_at }","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Agent name (required)"},"email":{"type":"string","description":"Developer email — required if you do not have an API key yet. Used to create your account."},"description":{"type":"string","description":"What your agent does"},"capabilities":{"type":"array","items":{"type":"string"},"description":"Agent capabilities: [\"music_playback\", \"context_sensing\", \"user_preferences\"]"},"default_streaming_service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Default streaming service for users of this agent"}},"required":["name"]}},{"name":"get_agent","description":"Get your agent's profile, including the contextual taste genome summary showing learned preferences across different activities and times.\n\nExample: get_agent({})\nReturns: { agent_id, name, taste_genome: { global: {...}, contexts: { working: {...}, driving: {...} } } }","inputSchema":{"type":"object","properties":{"include_taste_genome":{"type":"boolean","description":"Include full contextual taste genome (default: true)"}}}},{"name":"get_recommendations","description":"Get personalized track recommendations based on seed tracks, artists, or context. Uses Spotify's recommendation engine enhanced with BeatBrain's scoring.\n\nExample: get_recommendations({ seed_tracks: [\"4uLU6hMCjMI75M1A2tKUQC\"], end_user_id: \"user123\" })\nReturns: { tracks: [{ spotify_uri, title, artist, fit_score }] }","inputSchema":{"type":"object","properties":{"seed_tracks":{"type":"array","items":{"type":"string"},"description":"Spotify track IDs"},"seed_artists":{"type":"array","items":{"type":"string"},"description":"Spotify artist IDs"},"prompt":{"type":"string","description":"Context for recommendations"},"end_user_id":{"type":"string"},"limit":{"type":"integer","description":"Max results (default: 20)"}},"required":["end_user_id"]}},{"name":"now_playing","description":"Get current playback state from the user's streaming service. Shows what's playing, progress, device, and session info.\nFor Spotify: real-time playback state. For Apple Music: last played track from history (not real-time).\n\nWhen session_id is provided, BeatBrain automatically monitors remaining tracks and plans + queues continuation tracks when ≤3 remain — the music never stops. The response includes tracks_remaining and continuation_status.\n\nExample: now_playing({ end_user_id: \"user123\", session_id: \"sess-abc\" })\nReturns: { is_playing: true, track: { name, artist, album_art_url }, progress_ms, device: {...}, session: { tracks_remaining: 5, continuation_status: \"idle\" } }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User to check playback for"},"session_id":{"type":"string","description":"Optional session ID — enables automatic set continuation when tracks run low"}},"required":["end_user_id"]}},{"name":"connect_streaming_service","description":"Initiate streaming service connection for a user. Returns an authorization URL that the user must visit once to grant access.\n\nSupported services:\n- spotify: Full remote playback control (play, pause, skip, volume, device transfer) + BeatBrain Web Player\n- apple_music: Playlist management + BeatBrain Web Player (live DJ experience with real-time vibe switching)\n- tidal: Playlist management + deep links to Tidal app/web player. No embedded BeatBrain web player (Tidal SDK limitation). Agent sends Tidal link directly.\n- deezer: Connection wired but playback not yet functional (pending developer app approval). Once approved: playlist management + deep links to Deezer app/web player.\n\nIf the user is already connected with all required scopes, returns { already_connected: true }.\nIf scopes are missing (e.g. after an update), automatically triggers re-authorization.\nUse force: true to always generate a new auth URL regardless of current connection state.\n\nExample: connect_streaming_service({ service: \"spotify\", end_user_id: \"user123\" })\nExample: connect_streaming_service({ service: \"apple_music\", end_user_id: \"user123\" })\nExample: connect_streaming_service({ service: \"tidal\", end_user_id: \"user123\" })\nExample: connect_streaming_service({ service: \"deezer\", end_user_id: \"user123\" })\nReturns: { auth_url: \"...\", message: \"Send this URL to the user\" }","inputSchema":{"type":"object","properties":{"service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Which streaming service to connect"},"end_user_id":{"type":"string","description":"User to connect for"},"redirect_uri":{"type":"string","description":"Optional custom redirect URI"},"force":{"type":"boolean","description":"Force re-authorization even if already connected. Use when scopes need updating or user requests re-auth."}},"required":["service","end_user_id"]}},{"name":"update_context","description":"Smooth vibe transition — changes the mood, genre, or energy without interrupting the current song. BeatBrain auto-discovers the active session, plans new tracks for the updated context, and replaces all upcoming tracks in the session playlist while the current track keeps playing.\n\nExample: update_context({ end_user_id: \"user123\", prompt: \"switch to something more upbeat\", energy: 0.8 })\nsession_id is optional — BeatBrain auto-discovers the active session. Only falls back to creating a new session if no active playlist exists.","inputSchema":{"type":"object","properties":{"session_id":{"type":"string","description":"Session ID (optional — auto-discovered from active session)"},"end_user_id":{"type":"string","description":"User whose context to update"},"prompt":{"type":"string","description":"New context/mood/activity description"},"mood":{"type":"string"},"activity":{"type":"string"},"energy":{"type":"number"},"sensors":{"type":"object"},"calendar":{"type":"object"},"psychological_state":{"type":"object","description":"Optional psychological-state snapshot: { arousal, valence, dominance, confidence, sources, captured_at }"},"queue_strategy":{"type":"string","enum":["insert_next","append_end","replace_upcoming"],"description":"Queue placement mode. insert_next = place directly after the current track. append_end = add to the end of the queue. replace_upcoming = keep current track and replace everything after it. For update_context, prefer replace_upcoming (default)."},"wait_for_apply":{"type":"boolean","description":"When false, returns immediately with operation_id and applies the context update asynchronously. Default: true."},"operation_id":{"type":"string","description":"Optional caller-provided operation ID for async update_context tracking/idempotency."},"device_id":{"type":"string","description":"Target device for playback"}},"required":["end_user_id"]}},{"name":"get_operation_status","description":"Get status for an asynchronous MCP operation (for example update_context with wait_for_apply: false).\n\nExample: get_operation_status({ end_user_id: \"user123\", operation_id: \"op_abc123\" })\nReturns: { operation_id, status: \"in_progress|completed|failed\", result?, error? }","inputSchema":{"type":"object","properties":{"operation_id":{"type":"string","description":"Operation ID returned by update_context"},"session_id":{"type":"string","description":"Optional session ID to scope the lookup"},"end_user_id":{"type":"string","description":"User whose recent session should be searched (if session_id omitted)"}},"required":["operation_id"]}},{"name":"get_taste_genome","description":"Retrieve the contextual taste profile for a user. Shows learned preferences across different activities, times of day, and locations.\n\nExample: get_taste_genome({ end_user_id: \"user123\" })\nReturns: { global: { genre_affinities: {...} }, contexts: { working: {...}, driving: {...} } }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string"}},"required":["end_user_id"]}},{"name":"resolve_tracks","description":"Resolve BeatBrain catalog tracks to playable URIs on the user's connected streaming service (Spotify, Apple Music, Tidal). Uses ISRC, service IDs, and fuzzy search.\n\nExample: resolve_tracks({ tracks: [{ id: \"abc\", title: \"Song\", artist: \"Artist\" }], end_user_id: \"user123\" })\nReturns: { results: [{ id, resolved, uri, confidence, method }], service, resolved_count }","inputSchema":{"type":"object","properties":{"tracks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"artist":{"type":"string"},"isrc":{"type":"string"},"external_ids":{"type":"object"}},"required":["id"]},"description":"Tracks to resolve"},"end_user_id":{"type":"string","description":"User whose streaming service to resolve against"},"target_service":{"type":"string","description":"Target service for resolution (default: spotify)"}},"required":["tracks","end_user_id"]}},{"name":"enrich_track","description":"On-demand enrichment for any track. Uses the full knowledge fusion pipeline (GPT-4o, MusicBrainz, Last.fm, Discogs, Wikidata) to deeply understand a track.\n\nExample: enrich_track({ title: \"Bohemian Rhapsody\", artist: \"Queen\" })\nReturns: { enrichment: { genre_tags, era, mood_tags, ... }, sources_used, external_ids }","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"Track title"},"artist":{"type":"string","description":"Artist name"},"isrc":{"type":"string","description":"ISRC for exact identification"},"spotify_id":{"type":"string","description":"Spotify ID for cross-service resolution"}},"required":["title","artist"]}},{"name":"list_skills","description":"List available intelligence skills that modify how BeatBrain interprets context and selects tracks.\n\nExample: list_skills({ category: \"focus\" })\nReturns: { skills: [{ id, name, description, category }] }","inputSchema":{"type":"object","properties":{"category":{"type":"string","description":"Filter by category (optional)"}}}},{"name":"install_skill","description":"Install a skill on an agent to modify its music intelligence behavior.\n\nExample: install_skill({ skill_id: \"deep-focus\", agent_id: \"agent123\" })\nReturns: { installed: true }","inputSchema":{"type":"object","properties":{"skill_id":{"type":"string","description":"Skill ID to install"},"agent_id":{"type":"string","description":"Agent to install on"},"config":{"type":"object","description":"Skill configuration overrides"}},"required":["skill_id","agent_id"]}},{"name":"plan_transition","description":"Plan an optimal transition between two specific tracks. Returns timing, EQ hints, FX suggestions, and harmonic analysis.\n\nExample: plan_transition({ from_track_id: \"abc\", to_track_id: \"xyz\" })\nReturns: { transition: { start_ms, duration_ms, curve, score, eq_hint, fx }, harmonic: { score, type } }","inputSchema":{"type":"object","properties":{"from_track_id":{"type":"string","description":"Source track ID"},"to_track_id":{"type":"string","description":"Target track ID"},"style":{"type":"string","description":"Transition style: smooth, cut, echo, etc."}},"required":["from_track_id","to_track_id"]}},{"name":"analyze_track","description":"Get full analysis for a single track. Returns enrichment data, audio features, score breakdown, and cultural context.\n\nExample: analyze_track({ track_id: \"abc123\" })\nReturns: { track: { title, artist, genre, energy, ... }, enrichment: {...}, score_breakdown: [...] }","inputSchema":{"type":"object","properties":{"track_id":{"type":"string","description":"Track ID to analyze"}},"required":["track_id"]}},{"name":"get_catalog_stats","description":"Get BeatBrain catalog statistics including total tracks, genre distribution, and enrichment coverage.\n\nExample: get_catalog_stats()\nReturns: { total_tracks, enriched_tracks, genres: { electronic: 2340, hip_hop: 1820, ... } }","inputSchema":{"type":"object","properties":{}}},{"name":"get_trending_tracks","description":"Get tracks currently trending across all BeatBrain agents and users.\n\nExample: get_trending_tracks({ context: \"workout\", limit: 10 })\nReturns: { trending: [{ trackId, momentumScore, signalCount }] }","inputSchema":{"type":"object","properties":{"context":{"type":"string","description":"Filter by context (workout, driving, party, relaxing, etc.)"},"limit":{"type":"number","description":"Max results (default 20)","default":20}}}},{"name":"get_collaborative_recommendations","description":"Get collaborative recommendations based on what other users liked in similar contexts.\n\"Users who liked these tracks in this context also liked...\"\n\nExample: get_collaborative_recommendations({ track_ids: [\"track1\", \"track2\"], context: \"workout\" })\nReturns: { recommendations: [{ trackId, score, cooccurrenceCount, reason }] }","inputSchema":{"type":"object","properties":{"track_ids":{"type":"array","items":{"type":"string"},"description":"Seed track IDs"},"context":{"type":"string","description":"Context key for filtering"},"limit":{"type":"number","description":"Max results","default":20}},"required":["track_ids"]}},{"name":"get_catalog_health","description":"Get catalog health and quality assurance metrics including coverage gaps, enrichment quality, and recent issues.\n\nExample: get_catalog_health()\nReturns: { health: { totalTracks, gaps, qualityScores }, recent_quality_issues: [...] }","inputSchema":{"type":"object","properties":{"refresh":{"type":"boolean","description":"Force fresh computation (default: use cache)","default":false}}}},{"name":"submit_user_profile","description":"Send a narrative description of a user to seed their taste profile before any listening happens. Use this for \"initial download\" — tell BeatBrain about the user's age, lifestyle, recent concerts, preferences, etc.\n\nExample: submit_user_profile({ end_user_id: \"sarah\", narrative: \"Sarah is ~35, married, has a 7yo daughter, developer who works a lot, runner, went to Third Eye Blind concert last month\" })\nReturns: { profile_updated: true, fields_updated: [\"genre_affinities\", \"artist_tiers\", \"temporal_patterns\"] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User to create profile for"},"narrative":{"type":"string","description":"Natural language description of the user: age, lifestyle, concerts, preferences, etc."},"structured_data":{"type":"object","description":"Optional structured data: { age, lifestyle, recent_concerts, preferences, favorite_artists }"}},"required":["end_user_id","narrative"]}},{"name":"check_connection_status","description":"Check if a user's streaming service (Spotify, Apple Music, Tidal, or Deezer) is already connected and has valid tokens. Returns connection status for all supported services including capabilities per service.\n\nFor Spotify: returns scopes granted so you can tell if re-authorization is needed (e.g. missing playlist-modify-private).\nFor Apple Music: returns connection status, storefront, and capability flags (playlist management only, no remote playback).\nFor Tidal: returns connection status and capability flags (playlist management + deep links, no remote playback, no embedded web player, no recently-played polling).\nFor Deezer: returns connection status and capability flags (playlist management + deep links, no remote playback, no embedded web player, has recently-played via listening_history).\n\nNote: connect_streaming_service now automatically checks scopes, so you typically don't need to call this first. But it's useful if the user asks \"am I connected?\" or you want to check scope details.\n\nExample: check_connection_status({ end_user_id: \"sarah\" })\nReturns: { connections: [{ service: \"spotify\", connected: true, capabilities: {...} }, { service: \"apple_music\", connected: false, capabilities: {...} }, { service: \"tidal\", connected: false, capabilities: {...} }, { service: \"deezer\", connected: false, capabilities: {...} }] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User to check connections for"},"service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Check a specific service (default: all connected services)"}},"required":["end_user_id"]}},{"name":"get_devices","description":"List available playback devices and get a smart recommendation for which device to use based on context. ALWAYS pass the user's activity/context so BeatBrain can recommend the right device (e.g. phone for running, speaker for cooking, car audio for driving). Returns a recommended device with reasoning.\n\nExample: get_devices({ end_user_id: \"sarah\", context: { activity: \"running\" } })\nReturns: { devices: [...], recommended: { device_id: \"abc123\", device_name: \"Sarah's iPhone\", device_type: \"Smartphone\", reason: \"Mobile device is best for running\" } }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User whose devices to list"},"context":{"type":"object","description":"Context for smart device recommendation. Pass activity and/or location so BeatBrain picks the right device.","properties":{"activity":{"type":"string","description":"Current activity: running, workout, driving, cooking, working, coding, studying, relaxing, party, dinner, etc."},"location":{"type":"string","description":"Current location: home, gym, car, office, kitchen, outdoor, etc."},"device_type_hint":{"type":"string","description":"Explicit device preference from user: headphones, speaker, phone, etc."},"prompt":{"type":"string","description":"The original user prompt for additional context clues"}}}},"required":["end_user_id"]}},{"name":"queue_tracks","description":"Add specific songs by name with explicit queue strategy control. Resolves track titles + artists to playable URIs, then applies queue placement and logs the selections so BeatBrain learns from them.\n\nQueue strategy guidance:\n- insert_next (default): \"play X next\", \"up next\", \"right after this\"\n- append_end: \"add this later\", \"save for later\", \"at the end\"\n- replace_upcoming: \"replace what's coming\", broad vibe pivots, or hard course-corrections\n\nExample: queue_tracks({ end_user_id: \"sarah\", tracks: [{ title: \"Confessions Part II\", artist: \"Usher\" }, { title: \"Hey Ma\", artist: \"Cam'ron\" }] })\nReturns: { status: \"queued\", queued: [{ title, artist, uri }], failed: [], tracks_added: 2, learned: true }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"User ID"},"tracks":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Song title"},"artist":{"type":"string","description":"Artist name"}},"required":["title","artist"]},"description":"Tracks to queue, in order. Will be resolved to Spotify."},"device_id":{"type":"string","description":"Optional: target a specific device for queuing"},"queue_strategy":{"type":"string","enum":["insert_next","append_end","replace_upcoming"],"description":"Queue placement mode. insert_next = place directly after the current track. append_end = add to the end of the queue. replace_upcoming = keep current track and replace everything after it."}},"required":["end_user_id","tracks"]}},{"name":"get_session_details","description":"Get details about the current or a specific music session — including the full planned track list, energy arc, scene context, and genres. Use this to answer questions like \"what's in the queue?\", \"is it all one artist?\", \"what's coming up next?\", or to review what was planned.\n\nIf no session_id is provided, returns the most recent session for the user.\n\nExample: get_session_details({ end_user_id: \"sarah\" })\nReturns: { session_id, prompt, tracks: [{ position, name, artist, energy, fit_score }], energy_arc, scene_tags, genres, created_at }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user whose session to retrieve"},"session_id":{"type":"string","description":"Optional: specific session ID. If omitted, returns the most recent session."}},"required":["end_user_id"]}},{"name":"get_session_health","description":"Get real-time session health telemetry — engagement score, skip rate, skip streak, and alerts.\n\nPoll this alongside now_playing to detect when the listener is disengaging. Returns actionable alerts with suggested responses:\n- skip_streak (warning/critical): \"The listener has skipped 3+ tracks in a row\"\n- low_engagement (warning): \"Session engagement is very low\"\n- disengaging (info): \"Engagement is declining\"\n- recovery (info): \"Session is going great!\"\n\nUse the suggested_action in alerts to guide your response. For example, if you see a skip_streak alert, proactively ask if the user wants a vibe change.\n\nExample: get_session_health({ session_id: \"abc-123\" })\nReturns: { health: { engagement_score, skip_rate, skip_streak, trend }, alert: { alert_type, message, suggested_action } }","inputSchema":{"type":"object","properties":{"session_id":{"type":"string","description":"The session to check health for."},"end_user_id":{"type":"string","description":"The user whose active session to check (if no session_id provided)."}},"required":[]}},{"name":"preview_queue","description":"Preview the upcoming tracks in the session queue. Use this to:\n- Show the user what's coming up next\n- Decide if you want to veto/remove any upcoming tracks\n- Check genre/energy variety in the queue\n\nReturns the next N tracks with title, artist, energy, genre, and any explanations.\n\nExample: preview_queue({ session_id: \"abc-123\", limit: 5 })\nReturns: { current_track, upcoming_tracks: [{ queue_position, title, artist, energy, genre }], total_remaining }","inputSchema":{"type":"object","properties":{"session_id":{"type":"string","description":"The session to preview."},"end_user_id":{"type":"string","description":"The user whose active session to preview (if no session_id provided)."},"limit":{"type":"number","description":"Number of upcoming tracks to return (default: 5)."}},"required":[]}},{"name":"edit_queue","description":"Edit the upcoming track queue — remove, reorder, or replace specific tracks.\n\nThis gives you fine-grained control over the set without triggering a full replan. Perfect for:\n- Removing a track the user won't like: edit_queue({ actions: [{ action: \"remove\", queue_position: 2 }] })\n- Moving a track sooner: edit_queue({ actions: [{ action: \"reorder\", queue_position: 5, new_position: 1 }] })\n- Replacing a track: edit_queue({ actions: [{ action: \"replace\", queue_position: 3, replacement: { title: \"...\", artist: \"...\" } }] })\n\nqueue_position is 1-based (1 = next track to play).\n\nExample: edit_queue({ session_id: \"abc-123\", actions: [{ action: \"remove\", queue_position: 2 }] })","inputSchema":{"type":"object","properties":{"session_id":{"type":"string","description":"The session to edit."},"end_user_id":{"type":"string","description":"The user whose active session to edit (if no session_id provided)."},"actions":{"type":"array","description":"Queue edit actions to perform.","items":{"type":"object","properties":{"action":{"type":"string","enum":["remove","reorder","replace"],"description":"Type of edit."},"queue_position":{"type":"number","description":"1-based position in upcoming queue."},"track_id":{"type":"string","description":"Alternative to queue_position: target by track ID."},"new_position":{"type":"number","description":"For reorder: new 1-based position."},"replacement":{"type":"object","description":"For replace: new track info.","properties":{"title":{"type":"string"},"artist":{"type":"string"}}}},"required":["action"]}}},"required":["actions"]}},{"name":"adjust_session","description":"Make fine-grained adjustments to the active session without triggering a full replan.\n\nUnlike update_context (which replans everything), adjustments modify the session's parameters for the NEXT continuation set. Use this for incremental tweaks:\n\n- Bump energy: adjust_session({ adjustments: [{ type: \"energy\", value: 0.15 }] })\n- Lower energy: adjust_session({ adjustments: [{ type: \"energy\", value: -0.2 }] })\n- Block a genre: adjust_session({ adjustments: [{ type: \"genre_filter\", value: \"country\", action: \"add\" }] })\n- Switch to family-friendly: adjust_session({ adjustments: [{ type: \"content_rating\", value: \"family_friendly\" }] })\n- Change energy curve: adjust_session({ adjustments: [{ type: \"energy_curve\", value: \"building\" }] })\n- Block an artist: adjust_session({ adjustments: [{ type: \"avoid_artist\", value: \"Drake\" }] })\n- Prefer an artist: adjust_session({ adjustments: [{ type: \"prefer_artist\", value: \"Kendrick Lamar\" }] })\n- Set BPM range: adjust_session({ adjustments: [{ type: \"bpm_range\", value: [120, 140] }] })\n\nMultiple adjustments can be made in one call.","inputSchema":{"type":"object","properties":{"session_id":{"type":"string","description":"The session to adjust."},"end_user_id":{"type":"string","description":"The user whose active session to adjust (if no session_id provided)."},"adjustments":{"type":"array","description":"Adjustments to apply.","items":{"type":"object","properties":{"type":{"type":"string","enum":["energy","genre_filter","bpm_range","content_rating","energy_curve","avoid_artist","prefer_artist"],"description":"Type of adjustment."},"value":{"description":"Adjustment value. Varies by type: energy = float delta (-1 to 1), genre_filter = genre string, bpm_range = [min, max], content_rating = \"any\"|\"clean\"|\"family_friendly\", energy_curve = \"building\"|\"sustaining\"|\"peak_valley\"|\"declining\"|\"wave\", avoid/prefer_artist = artist name."},"action":{"type":"string","enum":["add","remove"],"description":"For genre_filter: add to avoid list or remove from it."}},"required":["type","value"]}}},"required":["adjustments"]}},{"name":"explain_track","description":"Get a rich, human-readable explanation for why a specific track was selected.\n\nReturns:\n- summary: One-sentence explanation\n- detailed_reasons: Specific scoring factors\n- situation_context: How the MSKG situation informed selection\n- taste_alignment: How user taste influenced the choice\n- conversation_hook: A suggested message to engage the user about this track\n\nUse conversation_hook to proactively engage: \"I picked this song because...\"\n\nExample: explain_track({ track: { title: \"Redbone\", artist: \"Childish Gambino\" }, scene_tags: [\"dinner_party\"] })","inputSchema":{"type":"object","properties":{"track":{"type":"object","description":"Track info (title, artist, genres, lyrical_themes, era, etc.)","properties":{"title":{"type":"string"},"artist":{"type":"string"},"genres":{"type":"string"},"lyrical_themes":{"type":"array","items":{"type":"string"}},"era":{"type":"object"}},"required":["title","artist"]},"scene_tags":{"type":"array","items":{"type":"string"},"description":"Scene tags from the current session context."},"scoring_breakdown":{"type":"object","description":"Optional: score breakdown from the set planner."},"position":{"type":"number","description":"Optional: position in the set (0-indexed)."},"total_tracks":{"type":"number","description":"Optional: total tracks in the set."}},"required":["track"]}},{"name":"get_song_dna","description":"Get a track's pre-computed \"Song DNA\" — social acceptability, recognizability, party readiness, background suitability, workout energy, emotional depth, and per-situation acceptability scores.\n\nUseful for understanding WHY a track fits or doesn't fit a situation, and for comparing tracks on contextual dimensions beyond basic genre/energy.\n\nExample: get_song_dna({ track_id: \"uuid-here\" })","inputSchema":{"type":"object","properties":{"track_id":{"type":"string","description":"The track's UUID from the catalog."}},"required":["track_id"]}},{"name":"get_track_quality","description":"Get aggregated quality signals for a track — completion rate, quality score, total plays, skips, likes, and per-situation quality breakdowns.\n\nUse this to check if a track has been well-received historically before including it in a set.\n\nExample: get_track_quality({ track_id: \"uuid-here\" })","inputSchema":{"type":"object","properties":{"track_id":{"type":"string","description":"The track's UUID from the catalog."}},"required":["track_id"]}},{"name":"get_agent_profile","description":"Get the agent's learned personality profile — curation style, energy bias, diversity preference, weight adjustments, situation-specific preferences, and communication settings.\n\nThe agent profile evolves from session outcomes. High-engagement sessions reinforce the agent's style; low-engagement sessions nudge adaptation.\n\nExample: get_agent_profile()","inputSchema":{"type":"object","properties":{}}},{"name":"get_learning_insights","description":"Get meta-learning insights — what scoring weight configurations have led to the best engagement for specific situations.\n\nReturns the top-performing weight configs that can inform how to set up future sessions.\n\nExample: get_learning_insights({ situation: \"dinner_party_casual\" })","inputSchema":{"type":"object","properties":{"situation":{"type":"string","description":"Optional situation slug to filter insights for."}}}},{"name":"process_knowledge_learning","description":"Trigger processing of the knowledge feedback queue. This processes accumulated situational feedback (skips, dislikes in specific situations) and updates the Music Situation Knowledge Graph with learned theme-situation conflicts.\n\nCall periodically or after a batch of feedback events.\n\nExample: process_knowledge_learning()","inputSchema":{"type":"object","properties":{}}},{"name":"predict_music_context","description":"Predict what music a user will want based on their learned patterns + current context signals. Returns predictions with confidence scores and suggested prompts.\n\nUses the Predictive Context Engine which learns from:\n- Temporal patterns (time of day, day of week)\n- Activity patterns (wearable data → music preferences)\n- Calendar patterns (event type → music)\n- Weather patterns (conditions → mood)\n- Detected routines (recurring daily patterns)\n\nUse this proactively to suggest music BEFORE the user asks.\n\nExample: predict_music_context({ end_user_id: \"user_123\", signals: { activity: \"workout\", weather: { condition: \"sunny\", temperature: 75 } } })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The end user identifier."},"signals":{"type":"object","description":"Current context signals (all optional).","properties":{"time":{"type":"string","description":"ISO 8601 timestamp"},"weather":{"type":"object","properties":{"condition":{"type":"string"},"temperature":{"type":"number"}}},"activity":{"type":"string"},"calendarEvent":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"},"minutesUntil":{"type":"number"}}},"socialContext":{"type":"string","description":"alone, friends, partner, family"}}}},"required":["end_user_id"]}},{"name":"get_shared_context","description":"Get the shared user context across all agents serving this user. Includes recently played tracks, active sessions, global avoid lists, and recent session history.\n\nEssential for multi-agent coordination — ensures agents don't repeat tracks another agent just played.\n\nExample: get_shared_context({ end_user_id: \"user_123\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The end user identifier."}},"required":["end_user_id"]}},{"name":"route_to_best_agent","description":"Given a context, find the best-suited agent to handle a music request. Returns the recommended agent, alternatives, and any conflicts (e.g., another agent already has an active session).\n\nUseful in multi-agent setups where specialized agents handle different situations (workout agent, dinner party agent, etc.).\n\nExample: route_to_best_agent({ end_user_id: \"user_123\", context: { situation: \"workout_hiit\", activity: \"running\" } })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The end user identifier."},"context":{"type":"object","description":"Current context for routing.","properties":{"situation":{"type":"string"},"activity":{"type":"string"},"calendar_event_type":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}}},"required":["end_user_id"]}},{"name":"get_embedding_stats","description":"Get statistics about the learned audio embedding system. Shows coverage, model version, and training data volume.\n\nExample: get_embedding_stats()","inputSchema":{"type":"object","properties":{}}},{"name":"get_listening_stats","description":"Get a user's listening statistics — total sessions, tracks played, hours listened, top genres, top artists, skip rate, new artist discoveries, most active day/time.\n\nReturns Wrapped-style insights for any time range.\n\nExample: get_listening_stats({ end_user_id: \"user-123\", time_range: \"this_week\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"time_range":{"type":"string","enum":["this_week","this_month","all_time"],"description":"Time range for stats. Default: this_week."}},"required":["end_user_id"]}},{"name":"share_song","description":"Get a shareable link and formatted message for a track. Resolves the track to a streaming URL on the user's connected service. Returns the data so your agent can present it to the user — the user then shares however they want (copy/paste, native share, etc.).\n\nExample: share_song({ end_user_id: \"user-123\", track: { title: \"Redbone\", artist: \"Childish Gambino\" } })\nReturns: { track: \"Redbone\", artist: \"Childish Gambino\", streaming_url: \"https://open.spotify.com/track/...\", formatted_message: \"Check out Redbone by Childish Gambino\\nhttps://...\" }\n\nOmit the track field to get a link for whatever is currently playing.","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"track":{"type":"object","properties":{"title":{"type":"string"},"artist":{"type":"string"}},"description":"Track to share. If omitted, shares the currently playing track."}},"required":["end_user_id"]}},{"name":"share_set","description":"Get a shareable summary of the current session's tracklist. Returns the full track list, context label, and playlist URL (if available) so your agent can present it to the user to share however they want.\n\nExample: share_set({ end_user_id: \"user-123\" })\nReturns: { tracks: [...], context_label: \"chill coding vibes\", track_count: 8, playlist_url: \"https://open.spotify.com/playlist/...\", formatted_message: \"...\" }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."}},"required":["end_user_id"]}},{"name":"get_lyrics","description":"Look up lyrics for a song via Musixmatch/Genius. Also supports identifying a song from a lyric snippet.\n\nExample: get_lyrics({ track: { title: \"Redbone\", artist: \"Childish Gambino\" } })\nExample: get_lyrics({ lyrics_snippet: \"I got my mind on my money\" })","inputSchema":{"type":"object","properties":{"track":{"type":"object","properties":{"title":{"type":"string"},"artist":{"type":"string"}},"description":"Track to look up lyrics for."},"lyrics_snippet":{"type":"string","description":"Lyric snippet to search for (song identification)."}}}},{"name":"get_concert_alerts","description":"Check for upcoming concerts by a user's favorite artists near their location, powered by Bandsintown. Can also look up events for a specific artist.\n\nExample: get_concert_alerts({ end_user_id: \"user-123\" })\nExample: get_concert_alerts({ end_user_id: \"user-123\", artist: \"Tyler the Creator\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"artist":{"type":"string","description":"Optional specific artist to check. If omitted, checks all favorites."}},"required":["end_user_id"]}},{"name":"get_milestones","description":"Get a user's milestone status — session count, listening hours, artist discoveries, account age. Useful for celebrating achievements.\n\nExample: get_milestones({ end_user_id: \"user-123\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."}},"required":["end_user_id"]}},{"name":"toggle_dj_commentary","description":"Toggle DJ commentary mode for a user. When enabled, BeatBrain generates occasional micro-narration between songs — commentary on transitions, deep cuts, and genre switches. Commentary text is returned as an optional field in now_playing and get_session_health responses (e.g. \"commentary\": \"Genre switch — from jazz to electronic\"), so your agent can present it however you want.\n\nExample: toggle_dj_commentary({ end_user_id: \"user-123\", enabled: true })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"enabled":{"type":"boolean","description":"Enable (true) or disable (false) commentary."}},"required":["end_user_id","enabled"]}},{"name":"get_passive_listening_insights","description":"Get insights from a user's organic listening outside of BeatBrain sessions (detected via Spotify recently-played sync). Shows what artists and tracks the user has been listening to on their own.\n\nExample: get_passive_listening_insights({ end_user_id: \"user-123\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."}},"required":["end_user_id"]}},{"name":"explore_music","description":"Look up real music knowledge — similar artists, artist deep dives, genre landscapes, similar tracks, or personalized recommendations. Powered by Last.fm + Soundcharts with audience-backed data, chart placements, and streaming stats.\n\nIntents:\n- \"similar_artists\": Find artists similar to a given artist (query = artist name)\n- \"artist_deep_dive\": Full profile — bio, stats, top tracks, similar artists, chart entries (query = artist name)\n- \"genre_explore\": Top artists and essential tracks for a genre (query = genre name)\n- \"track_similar\": Find tracks similar to a given track (query = \"track by artist\")\n- \"recommend_for_user\": Personalized recommendations based on the user's taste profile (query can be empty)\n\nExample: explore_music({ intent: \"artist_deep_dive\", query: \"Khruangbin\" })\nExample: explore_music({ intent: \"similar_artists\", query: \"Tyler the Creator\" })\nExample: explore_music({ intent: \"genre_explore\", query: \"shoegaze\" })\nExample: explore_music({ intent: \"recommend_for_user\", end_user_id: \"user-123\" })","inputSchema":{"type":"object","properties":{"intent":{"type":"string","enum":["similar_artists","artist_deep_dive","genre_explore","track_similar","recommend_for_user"],"description":"What kind of music knowledge lookup to perform."},"query":{"type":"string","description":"Artist name, genre, or \"track by artist\" to look up. For recommend_for_user, can be empty."},"end_user_id":{"type":"string","description":"User identifier (required for recommend_for_user, optional for others — used to personalize results)."}},"required":["intent","query"]}},{"name":"get_session_history","description":"Get a user's past music sessions — what they listened to, when, and what vibes. Enables patterns like \"play something like last Tuesday's set\" or \"what did I listen to this week?\"\n\nExample: get_session_history({ end_user_id: \"user-123\", limit: 5 })\nReturns: { sessions: [{ session_id, context_label, prompt, created_at, track_count, tracks: [...] }] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"limit":{"type":"integer","description":"Number of sessions to return (default: 10, max: 50)."},"offset":{"type":"integer","description":"Pagination offset (default: 0)."}},"required":["end_user_id"]}},{"name":"get_user_memories","description":"Retrieve a user's stored memories — personal facts, music preferences, routines, relationships, personality traits, session insights, and context associations. Enables personalized conversation and music selection based on deep user knowledge.\n\nOptionally pass a semantic_query to find memories most relevant to a specific topic (e.g. \"beach vacation music\" surfaces memories about the user's beach preferences).\n\nExample: get_user_memories({ end_user_id: \"user-123\", limit: 20 })\nExample: get_user_memories({ end_user_id: \"user-123\", category: \"music_preference\", semantic_query: \"workout energy\" })\nReturns: { memories: [{ category, content, confidence, importance, created_at }] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"category":{"type":"string","enum":["personal_fact","music_preference","music_dislike","routine","relationship","session_insight","context_association","personality_trait","conversation_summary","taste_profile"],"description":"Optional category filter."},"semantic_query":{"type":"string","description":"Optional natural-language query for semantic (embedding) search against memories."},"limit":{"type":"integer","description":"Max memories to return (default: 20, max: 60)."}},"required":["end_user_id"]}},{"name":"get_user_personality","description":"Get a synthesized view of a user's personality, routines, relationships, and life context as extracted from conversations. Useful for deeply personalizing tone, recommendations, and proactive suggestions.\n\nExample: get_user_personality({ end_user_id: \"user-123\" })\nReturns: { traits: [...], routines: [...], relationships: [...], personal_facts: [...], context_associations: [...] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."}},"required":["end_user_id"]}},{"name":"get_session_episodes","description":"Get GPT-generated episodic summaries of past listening sessions — what was played, how the user responded, and patterns worth remembering. These are richer than raw session history and include engagement insights.\n\nExample: get_session_episodes({ end_user_id: \"user-123\", limit: 5 })\nReturns: { episodes: [{ content, engagement_score, created_at }] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"limit":{"type":"integer","description":"Max episodes to return (default: 10, max: 30)."},"semantic_query":{"type":"string","description":"Optional semantic search to find episodes matching a context (e.g. \"cooking dinner\")."}},"required":["end_user_id"]}},{"name":"get_user_context","description":"Get the full composed user context — the same rich profile, personality, music DNA, session history, and optionally semantic matches that BeatBrain uses internally. This is the \"everything you need to know about this user\" endpoint.\n\nReturns a structured, versioned payload with sections: profile, personality, music_dna, sessions, and semantic_matches.\n\nExample: get_user_context({ end_user_id: \"user-123\" })\nExample: get_user_context({ end_user_id: \"user-123\", semantic_query: \"cooking dinner\" })\nReturns: { version: 1, profile: {...}, personality: {...}, music_dna: {...}, sessions: {...}, semantic_matches: [...] }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"semantic_query":{"type":"string","description":"Optional query to find semantically relevant memories for the current context."}},"required":["end_user_id"]}},{"name":"get_quality_metrics","description":"Get personalization quality metrics — compares engagement in sessions where memory/taste/context was used vs not. Useful for understanding whether personalization is improving user experience.\n\nExample: get_quality_metrics({ day_window: 30 })\nReturns: { total_sessions, memory_hit_rate, avg_engagement_with_memory, avg_engagement_without_memory, avg_skip_rate_with_context, avg_skip_rate_without_context }","inputSchema":{"type":"object","properties":{"day_window":{"type":"integer","description":"Number of days to look back (default: 30, max: 90)."},"agent_id":{"type":"string","description":"Optional agent ID filter for multi-agent analytics."}},"required":[]}},{"name":"get_share_link","description":"Generate a shareable link and formatted text for a track or the currently playing track. Returns the streaming URL for the user's connected service so the agent can present it to the user to share however they want (copy/paste, native share, etc.).\n\nExample: get_share_link({ end_user_id: \"user-123\", track: { title: \"Redbone\", artist: \"Childish Gambino\" } })\nExample: get_share_link({ end_user_id: \"user-123\" })  // shares currently playing\nReturns: { track, artist, streaming_url, formatted_message }","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"track":{"type":"object","properties":{"title":{"type":"string"},"artist":{"type":"string"}},"description":"Track to get a link for. If omitted, uses the currently playing track."}},"required":["end_user_id"]}},{"name":"schedule_session","description":"Schedule a music session to start at a future time. BeatBrain will plan and start playback automatically at the scheduled time. Returns a schedule_id for management.\n\nExample: schedule_session({ end_user_id: \"user-123\", prompt: \"morning workout mix\", start_at: \"2026-02-19T07:00:00Z\", service: \"spotify\" })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"prompt":{"type":"string","description":"Natural language description of the desired music."},"start_at":{"type":"string","description":"ISO 8601 datetime when the session should start."},"service":{"type":"string","enum":["spotify","apple_music","tidal","deezer"],"description":"Which streaming service to use."},"webhook_url":{"type":"string","description":"Optional URL to notify when the session starts."}},"required":["end_user_id","prompt","start_at"]}},{"name":"save_to_library","description":"Save a track to the user's streaming service library (liked songs / saved tracks). Works for Spotify and Apple Music. Can save the currently playing track or a track specified by name.\n\nExample: save_to_library({ end_user_id: \"user-123\" })  // saves currently playing\nExample: save_to_library({ end_user_id: \"user-123\", track: { title: \"Redbone\", artist: \"Childish Gambino\" } })","inputSchema":{"type":"object","properties":{"end_user_id":{"type":"string","description":"The user identifier."},"track":{"type":"object","properties":{"title":{"type":"string"},"artist":{"type":"string"}},"description":"Track to save. If omitted, saves the currently playing track."},"track_id":{"type":"string","description":"Spotify track ID or Apple Music track ID (alternative to track name)."}},"required":["end_user_id"]}}],"resources":[{"uri":"beatbrain://agent/{id}/profile","name":"Agent Profile","description":"Agent identity, contextual taste genome, Spotify connection, and session history summary","mimeType":"application/json"},{"uri":"beatbrain://session/{id}/state","name":"Session State","description":"Current session state: active scene, playback status, track list, energy arc, and Spotify playback state","mimeType":"application/json"},{"uri":"beatbrain://services/status","name":"Services Status","description":"Streaming services connection status (Spotify, Apple Music, Tidal, Deezer)","mimeType":"application/json"}]}