gabriel / musehub public
mcp.md markdown
1332 lines 40.9 KB
c0f0b481 release: merge dev → main (#5) Gabriel Cardona <cgcardona@gmail.com> 5d ago
1 # MuseHub MCP Reference
2
3 > Protocol version: **2025-11-25** | Implementation: pure-Python async, no external MCP SDK
4
5 MuseHub treats AI agents as first-class citizens. The MCP integration gives agents complete capability parity with the web UI: they can browse, search, compose, review, and publish — over a standard protocol that every major agent runtime supports.
6
7 MCP 2025-11-25 adds the full **Streamable HTTP transport** (`GET /mcp` SSE push channel, session management, Origin security) and **Elicitation** (server-initiated user input via form and URL modes), enabling real-time interactive tool calls that interview users mid-execution.
8
9 ---
10
11 ## Table of Contents
12
13 1. [Architecture](#architecture)
14 2. [Transports](#transports)
15 3. [Authentication](#authentication)
16 4. [Session Management](#session-management)
17 5. [Elicitation](#elicitation)
18 6. [Tools — 32 total](#tools)
19 - [Read Tools (15)](#read-tools-15)
20 - [Write Tools (12)](#write-tools-12)
21 - [Elicitation-Powered Tools (5)](#elicitation-powered-tools-5)
22 7. [Resources — 20 total](#resources)
23 - [Static Resources (5)](#static-resources-5)
24 - [Templated Resources (15)](#templated-resources-15)
25 8. [Prompts — 8 total](#prompts)
26 9. [Error Handling](#error-handling)
27 10. [Usage Patterns](#usage-patterns)
28 11. [Architecture Diagrams](#architecture-diagrams)
29
30 ---
31
32 ## Architecture
33
34 ```
35 MCP Client (Cursor, Claude Desktop, any SDK)
36
37 ├─ HTTP POST /mcp (all client→server)
38 ├─ HTTP GET /mcp (SSE push, server→client)
39 ├─ HTTP DELETE /mcp (session termination)
40 └─ stdio python -m musehub.mcp.stdio_server (local dev)
41
42 musehub/api/routes/mcp.py ← Streamable HTTP transport (2025-11-25)
43
44 musehub/mcp/dispatcher.py ← async JSON-RPC 2.0 engine
45
46 ┌───────┼───────────────┬────────────────┐
47 │ │ │ │
48 tools/call resources/read prompts/get notifications/*
49 │ │ │ │
50 Read executors Resource handlers Prompt Session/Elicitation
51 (musehub_mcp_executor.py) (resources.py) assembler (session.py)
52 Write executors (context.py)
53 Elicitation tools
54 (mcp/write_tools/elicitation_tools.py)
55
56 AsyncSession → Postgres
57 ```
58
59 The dispatcher speaks JSON-RPC 2.0 directly. The HTTP envelope is always `200 OK` — tool errors are signalled via `isError: true` on the content block, not via HTTP status codes. Notifications (no `id` field) return `202 Accepted` with an empty body. Elicitation-powered tools return `text/event-stream` so the server can push `elicitation/create` events mid-call.
60
61 ---
62
63 ## Transports
64
65 ### HTTP Streamable — Full 2025-11-25 Transport
66
67 #### `POST /mcp`
68
69 The production transport. Accepts `application/json`. Returns `application/json` for most requests, or `text/event-stream` for elicitation-powered tool calls.
70
71 ```http
72 POST /mcp HTTP/1.1
73 Content-Type: application/json
74 Authorization: Bearer <jwt>
75 Mcp-Session-Id: <session-id> ← required after initialize
76 MCP-Protocol-Version: 2025-11-25 ← optional; validated if present
77
78 {"jsonrpc":"2.0","id":1,"method":"tools/list"}
79 ```
80
81 **Batch requests** — send a JSON array; responses are returned as an array in the same order (notifications are filtered out):
82
83 ```http
84 POST /mcp
85 [
86 {"jsonrpc":"2.0","id":1,"method":"tools/list"},
87 {"jsonrpc":"2.0","id":2,"method":"resources/list"}
88 ]
89 ```
90
91 **Notifications** (no `id`) return `202 Accepted` with an empty body.
92
93 #### `GET /mcp` — SSE Push Channel
94
95 Persistent server-to-client event stream. Required for receiving elicitation requests and progress notifications outside of an active tool call.
96
97 ```http
98 GET /mcp HTTP/1.1
99 Accept: text/event-stream
100 Mcp-Session-Id: <session-id>
101 Last-Event-ID: <last-seen-event-id> ← optional; triggers replay
102 ```
103
104 Returns `text/event-stream`. Server pushes:
105 - `notifications/progress` — tool progress updates
106 - `elicitation/create` — server-initiated user input requests
107 - `notifications/elicitation/complete` — URL-mode OAuth completion signals
108 - `: heartbeat` — comment every 15 s to keep proxies alive
109
110 #### `DELETE /mcp` — Session Termination
111
112 ```http
113 DELETE /mcp HTTP/1.1
114 Mcp-Session-Id: <session-id>
115 ```
116
117 Returns `200 OK`. Closes all open SSE streams and cancels pending elicitation Futures for the session.
118
119 ### stdio — `python -m musehub.mcp.stdio_server`
120
121 The local dev and Cursor IDE transport. Reads newline-delimited JSON from `stdin`, writes JSON-RPC responses to `stdout`, logs to `stderr`.
122
123 **Cursor IDE integration** — create or update `.cursor/mcp.json` in your workspace:
124
125 ```json
126 {
127 "mcpServers": {
128 "musehub": {
129 "command": "python",
130 "args": ["-m", "musehub.mcp.stdio_server"],
131 "cwd": "/path/to/musehub"
132 }
133 }
134 }
135 ```
136
137 The stdio server runs without auth (trusted local process). Write tools are available unconditionally.
138
139 ---
140
141 ## Authentication
142
143 | Context | How |
144 |---------|-----|
145 | HTTP transport — read tools + public resources | No auth required |
146 | HTTP transport — write / elicitation tools | `Authorization: Bearer <jwt>` |
147 | HTTP transport — private repo resources | `Authorization: Bearer <jwt>` |
148 | stdio transport | No auth (trusted process) |
149
150 The JWT is the same token issued by the MuseHub auth endpoints (`POST /api/v1/auth/token`). The `sub` claim is used as the acting `user_id` for all write operations.
151
152 Attempting a write tool without a valid token returns a JSON-RPC error (`code: -32001`, `message: "Authentication required for write tools"`).
153
154 ---
155
156 ## Session Management
157
158 Session management is required for elicitation and the GET /mcp SSE push channel.
159
160 **Creating a session:**
161
162 ```http
163 POST /mcp
164 {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{"elicitation":{"form":{},"url":{}}}}}
165 ```
166
167 Response includes:
168 ```http
169 Mcp-Session-Id: <cryptographically-secure-session-id>
170 ```
171
172 **Using the session:** include `Mcp-Session-Id` in all subsequent requests. Sessions expire after 1 hour of inactivity.
173
174 **Ending a session:** `DELETE /mcp` with the `Mcp-Session-Id` header.
175
176 **Security:** All requests are validated against an Origin allowlist (`localhost` always permitted; production: `musehub.app`). Requests from unlisted Origins are rejected with `403 Forbidden`.
177
178 ---
179
180 ## Elicitation
181
182 Elicitation is a MCP 2025-11-25 feature that allows the server to request structured input from the user *mid-tool-call*. MuseHub supports both modes:
183
184 ### Form Mode
185
186 The server sends an `elicitation/create` request with a restricted JSON Schema object describing the fields to collect. The client shows a form to the user, then sends the response back via `POST /mcp`.
187
188 ```
189 Agent MuseHub MCP
190 │ │
191 │ POST tools/call │
192 │ (musehub_compose_with_preferences)
193 │──────────────────────────►│
194 │ │ opens SSE stream
195 │◄──────────────────────────│
196 │ SSE: elicitation/create │
197 │ {mode:"form", schema:{ │
198 │ key, tempo, mood, ...}}│
199 │◄──────────────────────────│
200 │ [user fills form] │
201 │ POST elicitation result │
202 │ {action:"accept", │
203 │ content:{key:"Dm",...}} │
204 │──────────────────────────►│
205 │ │ tool continues
206 │ SSE: tools/call response │
207 │◄──────────────────────────│
208 ```
209
210 ### URL Mode
211
212 The server sends an `elicitation/create` request with `mode:"url"` directing the user to a MuseHub OAuth page. After the user completes the flow, the callback fires `notifications/elicitation/complete` into the agent's SSE stream.
213
214 ```
215 Agent MuseHub MCP Browser
216 │ │ │
217 │ POST musehub_connect_ │ │
218 │ streaming_platform │ │
219 │──────────────────────────►│ │
220 │ SSE: elicitation/create │ │
221 │ {mode:"url", url:"https://musehub.app/mcp/connect/spotify?..."}
222 │◄──────────────────────────│ │
223 │ [client opens URL] │──────────────────────►│
224 │ │ User authorises OAuth│
225 │ │◄──────────────────────│
226 │ SSE: notifications/ │ │
227 │ elicitation/complete │ │
228 │◄──────────────────────────│ │
229 │ SSE: tools/call response │ │
230 │◄──────────────────────────│ │
231 ```
232
233 ### Elicitation Schemas
234
235 MuseHub provides five musical form schemas:
236
237 | Schema key | Fields |
238 |------------|--------|
239 | `compose_preferences` | `key` (24 options), `tempo_bpm`, `time_signature`, `mood` (10 options), `genre` (10 options), `reference_artist`, `duration_bars`, `include_modulation` |
240 | `repo_creation` | `daw` (10 options), `primary_genre`, `key_signature`, `tempo_bpm`, `is_collab`, `collaborator_handles`, `initial_readme` |
241 | `pr_review_focus` | `dimension_focus` (all/melodic/harmonic/rhythmic/structural/dynamic), `review_depth` (quick/standard/thorough), `check_harmonic_tension`, `check_rhythmic_consistency`, `reviewer_note` |
242 | `release_metadata` | `tag`, `title`, `release_notes`, `is_prerelease`, `highlight` |
243 | `platform_connect_confirm` | `platform` (8 streaming services), `confirm` |
244
245 ---
246
247 ## Tools
248
249 All 32 tools use `server_side: true`. The JSON-RPC envelope is always a success response — errors are represented inside the content block via `isError: true`.
250
251 ### Calling a tool
252
253 ```json
254 {
255 "jsonrpc": "2.0",
256 "id": 1,
257 "method": "tools/call",
258 "params": {
259 "name": "musehub_browse_repo",
260 "arguments": { "repo_id": "abc123" }
261 }
262 }
263 ```
264
265 Response:
266
267 ```json
268 {
269 "jsonrpc": "2.0",
270 "id": 1,
271 "result": {
272 "content": [{ "type": "text", "text": "{\"name\":\"my-song\", ...}" }],
273 "isError": false
274 }
275 }
276 ```
277
278 ---
279
280 ### Read Tools (15)
281
282 #### `musehub_browse_repo`
283
284 Orientation snapshot for a repo: metadata, default branch, recent commits, top-level file list.
285
286 | Parameter | Type | Required | Description |
287 |-----------|------|----------|-------------|
288 | `repo_id` | string | yes | Repository UUID |
289
290 ---
291
292 #### `musehub_list_branches`
293
294 All branches with their head commit IDs and timestamps.
295
296 | Parameter | Type | Required | Description |
297 |-----------|------|----------|-------------|
298 | `repo_id` | string | yes | Repository UUID |
299
300 ---
301
302 #### `musehub_list_commits`
303
304 Paginated commit history, newest first.
305
306 | Parameter | Type | Required | Description |
307 |-----------|------|----------|-------------|
308 | `repo_id` | string | yes | Repository UUID |
309 | `branch` | string | no | Branch name filter |
310 | `limit` | integer | no | Max commits (default 20) |
311
312 ---
313
314 #### `musehub_read_file`
315
316 Metadata for a single artifact (MIDI, MP3, WebP, etc.) at a given commit.
317
318 | Parameter | Type | Required | Description |
319 |-----------|------|----------|-------------|
320 | `repo_id` | string | yes | Repository UUID |
321 | `path` | string | yes | File path within the repo |
322 | `commit_id` | string | no | Commit SHA (defaults to HEAD) |
323
324 ---
325
326 #### `musehub_get_analysis`
327
328 13-dimension musical analysis for a repo at a given ref.
329
330 | Parameter | Type | Required | Description |
331 |-----------|------|----------|-------------|
332 | `repo_id` | string | yes | Repository UUID |
333 | `ref` | string | no | Branch, tag, or commit SHA |
334 | `mode` | string | no | `"overview"` (default), `"commits"`, or `"objects"` |
335
336 ---
337
338 #### `musehub_search`
339
340 Keyword/path search over commits and file paths within a repo.
341
342 | Parameter | Type | Required | Description |
343 |-----------|------|----------|-------------|
344 | `repo_id` | string | yes | Repository UUID |
345 | `query` | string | yes | Search terms |
346
347 ---
348
349 #### `musehub_get_context`
350
351 Full AI context document for a repo — combines metadata, analysis, recent activity, and usage hints into a single structured payload.
352
353 | Parameter | Type | Required | Description |
354 |-----------|------|----------|-------------|
355 | `repo_id` | string | yes | Repository UUID |
356
357 ---
358
359 #### `musehub_get_commit`
360
361 Single commit detail with the full snapshot manifest (all file paths and content hashes at that point in history).
362
363 | Parameter | Type | Required | Description |
364 |-----------|------|----------|-------------|
365 | `repo_id` | string | yes | Repository UUID |
366 | `commit_id` | string | yes | Commit SHA |
367
368 ---
369
370 #### `musehub_compare`
371
372 Musical diff between two refs — returns per-dimension change scores (harmony, rhythm, groove, key, tempo) and a list of changed file paths.
373
374 | Parameter | Type | Required | Description |
375 |-----------|------|----------|-------------|
376 | `repo_id` | string | yes | Repository UUID |
377 | `base_ref` | string | yes | Base branch, tag, or commit SHA |
378 | `head_ref` | string | yes | Head branch, tag, or commit SHA |
379
380 ---
381
382 #### `musehub_list_issues`
383
384 Issues with optional state, label, and assignee filters.
385
386 | Parameter | Type | Required | Description |
387 |-----------|------|----------|-------------|
388 | `repo_id` | string | yes | Repository UUID |
389 | `state` | string | no | `"open"` (default) or `"closed"` |
390 | `label` | string | no | Label name filter |
391 | `assignee` | string | no | Assignee username filter |
392
393 ---
394
395 #### `musehub_get_issue`
396
397 Single issue with its full comment thread.
398
399 | Parameter | Type | Required | Description |
400 |-----------|------|----------|-------------|
401 | `repo_id` | string | yes | Repository UUID |
402 | `issue_number` | integer | yes | Issue number |
403
404 ---
405
406 #### `musehub_list_prs`
407
408 Pull requests with optional state and base branch filters.
409
410 | Parameter | Type | Required | Description |
411 |-----------|------|----------|-------------|
412 | `repo_id` | string | yes | Repository UUID |
413 | `state` | string | no | `"open"` (default), `"closed"`, or `"merged"` |
414 | `base` | string | no | Target branch filter |
415
416 ---
417
418 #### `musehub_get_pr`
419
420 Single PR with all inline comments and reviews.
421
422 | Parameter | Type | Required | Description |
423 |-----------|------|----------|-------------|
424 | `repo_id` | string | yes | Repository UUID |
425 | `pr_number` | integer | yes | Pull request number |
426
427 ---
428
429 #### `musehub_list_releases`
430
431 All releases for a repo with asset counts and timestamps.
432
433 | Parameter | Type | Required | Description |
434 |-----------|------|----------|-------------|
435 | `repo_id` | string | yes | Repository UUID |
436
437 ---
438
439 #### `musehub_search_repos`
440
441 Discover public repos by text query or musical attributes.
442
443 | Parameter | Type | Required | Description |
444 |-----------|------|----------|-------------|
445 | `query` | string | no | Text search query |
446 | `key` | string | no | Musical key filter (e.g. `"C major"`) |
447 | `tempo_min` | integer | no | Minimum BPM |
448 | `tempo_max` | integer | no | Maximum BPM |
449 | `tags` | array of strings | no | Tag filters |
450 | `limit` | integer | no | Max results (default 20) |
451
452 ---
453
454 ### Write Tools (12)
455
456 > All write tools require `Authorization: Bearer <jwt>` on the HTTP transport.
457
458 #### `musehub_create_repo`
459
460 Create a new repository.
461
462 | Parameter | Type | Required | Description |
463 |-----------|------|----------|-------------|
464 | `name` | string | yes | Repository name |
465 | `owner` | string | yes | Owner username |
466 | `owner_user_id` | string | yes | Owner user UUID |
467 | `description` | string | no | Short description |
468 | `visibility` | string | no | `"public"` (default) or `"private"` |
469 | `tags` | array of strings | no | Initial tags |
470 | `key_signature` | string | no | Musical key (e.g. `"G major"`) |
471 | `tempo_bpm` | integer | no | Tempo in BPM |
472 | `initialize` | boolean | no | Create initial commit (default `true`) |
473
474 ---
475
476 #### `musehub_fork_repo`
477
478 Fork an existing repository into the authenticated user's account.
479
480 | Parameter | Type | Required | Description |
481 |-----------|------|----------|-------------|
482 | `repo_id` | string | yes | Source repository UUID |
483 | `new_owner` | string | yes | Fork owner username |
484 | `new_owner_user_id` | string | yes | Fork owner user UUID |
485
486 ---
487
488 #### `musehub_create_issue`
489
490 Open a new issue.
491
492 | Parameter | Type | Required | Description |
493 |-----------|------|----------|-------------|
494 | `repo_id` | string | yes | Repository UUID |
495 | `title` | string | yes | Issue title |
496 | `body` | string | no | Issue description (Markdown) |
497 | `labels` | array of strings | no | Label names to apply |
498 | `assignee_id` | string | no | Assignee user UUID |
499
500 ---
501
502 #### `musehub_update_issue`
503
504 Update issue state or metadata.
505
506 | Parameter | Type | Required | Description |
507 |-----------|------|----------|-------------|
508 | `repo_id` | string | yes | Repository UUID |
509 | `issue_number` | integer | yes | Issue number |
510 | `state` | string | no | `"open"` or `"closed"` |
511 | `title` | string | no | New title |
512 | `body` | string | no | New body |
513 | `assignee_id` | string | no | New assignee UUID |
514 | `labels` | array of strings | no | Replace label set |
515
516 ---
517
518 #### `musehub_create_issue_comment`
519
520 Post a comment on an issue.
521
522 | Parameter | Type | Required | Description |
523 |-----------|------|----------|-------------|
524 | `repo_id` | string | yes | Repository UUID |
525 | `issue_number` | integer | yes | Issue number |
526 | `body` | string | yes | Comment body (Markdown) |
527
528 ---
529
530 #### `musehub_create_pr`
531
532 Open a pull request.
533
534 | Parameter | Type | Required | Description |
535 |-----------|------|----------|-------------|
536 | `repo_id` | string | yes | Repository UUID |
537 | `title` | string | yes | PR title |
538 | `from_branch` | string | yes | Source branch |
539 | `to_branch` | string | yes | Target branch |
540 | `body` | string | no | PR description (Markdown) |
541
542 ---
543
544 #### `musehub_merge_pr`
545
546 Merge an open pull request.
547
548 | Parameter | Type | Required | Description |
549 |-----------|------|----------|-------------|
550 | `repo_id` | string | yes | Repository UUID |
551 | `pr_number` | integer | yes | Pull request number |
552 | `merge_message` | string | no | Custom merge commit message |
553
554 ---
555
556 #### `musehub_create_pr_comment`
557
558 Post an inline comment on a PR. Supports general, track-level, and beat-range comments — mirroring the musical diff view in the web UI.
559
560 | Parameter | Type | Required | Description |
561 |-----------|------|----------|-------------|
562 | `repo_id` | string | yes | Repository UUID |
563 | `pr_number` | integer | yes | Pull request number |
564 | `body` | string | yes | Comment body (Markdown) |
565 | `target_type` | string | no | `"general"` (default), `"track"`, `"region"`, or `"note"` |
566 | `target_track` | string | no | Track name (when `target_type` is `"track"` or finer) |
567 | `target_beat_start` | number | no | Start beat position |
568 | `target_beat_end` | number | no | End beat position |
569
570 ---
571
572 #### `musehub_submit_pr_review`
573
574 Submit a formal review on a PR.
575
576 | Parameter | Type | Required | Description |
577 |-----------|------|----------|-------------|
578 | `repo_id` | string | yes | Repository UUID |
579 | `pr_number` | integer | yes | Pull request number |
580 | `state` | string | yes | `"approved"`, `"changes_requested"`, or `"commented"` |
581 | `body` | string | no | Review summary |
582
583 ---
584
585 #### `musehub_create_release`
586
587 Publish a release.
588
589 | Parameter | Type | Required | Description |
590 |-----------|------|----------|-------------|
591 | `repo_id` | string | yes | Repository UUID |
592 | `tag` | string | yes | Tag name (e.g. `"v1.0.0"`) |
593 | `title` | string | yes | Release title |
594 | `body` | string | no | Release notes (Markdown) |
595 | `commit_id` | string | no | Target commit SHA (defaults to HEAD) |
596 | `is_prerelease` | boolean | no | Mark as pre-release (default `false`) |
597
598 ---
599
600 #### `musehub_star_repo`
601
602 Star a repository.
603
604 | Parameter | Type | Required | Description |
605 |-----------|------|----------|-------------|
606 | `repo_id` | string | yes | Repository UUID |
607
608 ---
609
610 #### `musehub_create_label`
611
612 Create a label scoped to a repository.
613
614 | Parameter | Type | Required | Description |
615 |-----------|------|----------|-------------|
616 | `repo_id` | string | yes | Repository UUID |
617 | `name` | string | yes | Label name |
618 | `color` | string | yes | Hex color (e.g. `"#0075ca"`) |
619 | `description` | string | no | Label description |
620
621 ---
622
623 ### Elicitation-Powered Tools (5)
624
625 > All elicitation tools require `Authorization: Bearer <jwt>`, an active session (`Mcp-Session-Id`), and a client that declared elicitation capability during `initialize`. They degrade gracefully for stateless clients, returning an `elicitation_unavailable` error that includes instructions for the non-interactive equivalent.
626
627 #### `musehub_compose_with_preferences` _(form elicitation)_
628
629 Interview the user about a composition, then return a complete musical plan.
630
631 **Elicits:** key, tempo (BPM), time signature, mood, genre, reference artist, duration (bars), key modulation preference.
632
633 **Returns:** chord progressions per section, structural form (intro/verse/chorus/bridge/outro), harmonic tension profile, texture guidance, and a step-by-step Muse project workflow.
634
635 | Parameter | Type | Required | Description |
636 |-----------|------|----------|-------------|
637 | `repo_id` | string | no | Optional target repo to scaffold the plan into |
638
639 ---
640
641 #### `musehub_review_pr_interactive` _(form elicitation)_
642
643 Interactive PR review: collect the reviewer's focus before running the divergence analysis.
644
645 **Elicits:** dimension focus (all/melodic/harmonic/rhythmic/structural/dynamic), review depth (quick/standard/thorough), harmonic tension check, rhythmic consistency check, reviewer note.
646
647 **Returns:** per-dimension divergence scores, findings list, and a recommendation (APPROVE / REQUEST_CHANGES / COMMENT).
648
649 | Parameter | Type | Required | Description |
650 |-----------|------|----------|-------------|
651 | `repo_id` | string | yes | Repository UUID |
652 | `pr_id` | string | yes | Pull request UUID |
653
654 ---
655
656 #### `musehub_connect_streaming_platform` _(URL elicitation)_
657
658 OAuth-connect a streaming platform account for agent-triggered release distribution.
659
660 **Elicits (form, if platform not supplied):** platform name, confirm checkbox.
661 **Elicits (URL):** directs user to `GET /musehub/ui/mcp/connect/{platform}?elicitation_id=...` OAuth start page.
662
663 **Supported platforms:** Spotify, SoundCloud, Bandcamp, YouTube Music, Apple Music, TIDAL, Amazon Music, Deezer.
664
665 | Parameter | Type | Required | Description |
666 |-----------|------|----------|-------------|
667 | `platform` | string | no | Platform name (elicited if omitted) |
668 | `repo_id` | string | no | Repository context for distribution |
669
670 ---
671
672 #### `musehub_connect_daw_cloud` _(URL elicitation)_
673
674 OAuth-connect a cloud DAW or mastering service for cloud renders and exports.
675
676 **Elicits (form, if service not supplied):** service name, confirm checkbox.
677 **Elicits (URL):** directs user to `GET /musehub/ui/mcp/connect/daw/{service}?elicitation_id=...`.
678
679 **Supported services:** LANDR (AI mastering + distribution), Splice (sample sync + backup), Soundtrap, BandLab, Audiotool.
680
681 | Parameter | Type | Required | Description |
682 |-----------|------|----------|-------------|
683 | `service` | string | no | Service name (elicited if omitted) |
684
685 ---
686
687 #### `musehub_create_release_interactive` _(chained form + URL elicitation)_
688
689 Two-phase interactive release creator:
690
691 1. **Form elicitation:** collects tag, title, release notes, changelog highlight, and pre-release flag.
692 2. **URL elicitation (optional):** offers Spotify connection OAuth for immediate distribution.
693
694 | Parameter | Type | Required | Description |
695 |-----------|------|----------|-------------|
696 | `repo_id` | string | yes | Repository to create the release in |
697
698 ---
699
700 ## Resources
701
702 Resources are side-effect-free, cacheable, URI-addressable reads. All resources return `application/json`. They are read via the `resources/read` method.
703
704 ### Listing resources
705
706 ```json
707 {"jsonrpc":"2.0","id":1,"method":"resources/list"}
708 {"jsonrpc":"2.0","id":2,"method":"resources/templates/list"}
709 ```
710
711 ### Reading a resource
712
713 ```json
714 {
715 "jsonrpc": "2.0",
716 "id": 1,
717 "method": "resources/read",
718 "params": { "uri": "musehub://trending" }
719 }
720 ```
721
722 Response:
723
724 ```json
725 {
726 "jsonrpc": "2.0",
727 "id": 1,
728 "result": {
729 "contents": [{
730 "uri": "musehub://trending",
731 "mimeType": "application/json",
732 "text": "[{\"repo_id\":\"...\",\"name\":\"my-song\",...}]"
733 }]
734 }
735 }
736 ```
737
738 ---
739
740 ### Static Resources (5)
741
742 #### `musehub://trending`
743
744 Top 20 public repos ordered by star count. Anonymous-accessible.
745
746 **Returns:** array of repo summaries with `repo_id`, `name`, `owner`, `slug`, `description`, `visibility`, `clone_url`, `created_at`.
747
748 ---
749
750 #### `musehub://me`
751
752 Authenticated user's profile and their most recent 20 repos. Requires JWT.
753
754 **Returns:** `{ "user_id", "username", "repos": [...] }`
755
756 ---
757
758 #### `musehub://me/notifications`
759
760 Unread notifications for the authenticated user. Requires JWT.
761
762 **Returns:** `{ "notifications": [{ "id", "event_type", "read", "created_at" }] }`
763
764 ---
765
766 #### `musehub://me/starred`
767
768 Repos the authenticated user has starred. Requires JWT.
769
770 **Returns:** `{ "starred": [{ "repo_id", "name", "owner", "slug", "starred_at" }] }`
771
772 ---
773
774 #### `musehub://me/feed`
775
776 Activity feed for repos the authenticated user watches. Requires JWT.
777
778 **Returns:** `{ "feed": [...] }`
779
780 ---
781
782 ### Templated Resources (15)
783
784 All templated resources follow RFC 6570 Level 1. `{owner}` and `{slug}` are resolved to a `repo_id` by the dispatcher — agents use human-readable names, not UUIDs.
785
786 #### `musehub://repos/{owner}/{slug}`
787
788 Repo overview: metadata, visibility, default branch, tag list, description.
789
790 ---
791
792 #### `musehub://repos/{owner}/{slug}/branches`
793
794 All branches with their name, head commit ID, and last-updated timestamp.
795
796 ---
797
798 #### `musehub://repos/{owner}/{slug}/commits`
799
800 20 most recent commits on the default branch. Includes commit message, author, timestamp.
801
802 ---
803
804 #### `musehub://repos/{owner}/{slug}/commits/{commit_id}`
805
806 Single commit with its full snapshot manifest (all file paths and content hashes at that point).
807
808 ---
809
810 #### `musehub://repos/{owner}/{slug}/tree/{ref}`
811
812 File tree at a given ref. Returns all object paths and guessed MIME types.
813
814 ---
815
816 #### `musehub://repos/{owner}/{slug}/blob/{ref}/{path}`
817
818 Metadata for a single file at a given ref: path, content hash, MIME type, size.
819
820 ---
821
822 #### `musehub://repos/{owner}/{slug}/issues`
823
824 Open issues list with labels, assignees, and comment counts.
825
826 ---
827
828 #### `musehub://repos/{owner}/{slug}/issues/{number}`
829
830 Single issue with its full comment thread.
831
832 ---
833
834 #### `musehub://repos/{owner}/{slug}/pulls`
835
836 Open PRs with source/target branches and review counts.
837
838 ---
839
840 #### `musehub://repos/{owner}/{slug}/pulls/{number}`
841
842 Single PR with all inline comments and reviews (reviewer, state, body).
843
844 ---
845
846 #### `musehub://repos/{owner}/{slug}/releases`
847
848 All releases ordered newest first: tag, title, body, asset count, timestamp.
849
850 ---
851
852 #### `musehub://repos/{owner}/{slug}/releases/{tag}`
853
854 Single release matching a tag name, including the full release notes body.
855
856 ---
857
858 #### `musehub://repos/{owner}/{slug}/analysis/{ref}`
859
860 Musical analysis at a given ref: key, tempo, time signature, per-dimension scores (harmony, rhythm, groove, dynamics, orchestration, …).
861
862 ---
863
864 #### `musehub://repos/{owner}/{slug}/timeline`
865
866 Musical evolution timeline: commits, section events, and track events in chronological order.
867
868 ---
869
870 #### `musehub://users/{username}`
871
872 User profile and their 20 most recent public repos.
873
874 ---
875
876 ## Prompts
877
878 Prompts teach agents how to chain tools and resources to accomplish multi-step goals. They return a structured list of `role`/`content` messages that frame the task for the agent.
879
880 ### Getting a prompt
881
882 ```json
883 {
884 "jsonrpc": "2.0",
885 "id": 1,
886 "method": "prompts/get",
887 "params": {
888 "name": "musehub/orientation"
889 }
890 }
891 ```
892
893 With arguments:
894
895 ```json
896 {
897 "jsonrpc": "2.0",
898 "id": 1,
899 "method": "prompts/get",
900 "params": {
901 "name": "musehub/contribute",
902 "arguments": {
903 "repo_id": "abc123",
904 "owner": "alice",
905 "slug": "my-song"
906 }
907 }
908 }
909 ```
910
911 ---
912
913 ### `musehub/orientation`
914
915 **Arguments:** none
916
917 The essential first read for any new agent. Explains MuseHub's model (repos, commits, branches, musical analysis), the `musehub://` URI scheme, which tools to use for reads vs. writes, and how to authenticate.
918
919 ---
920
921 ### `musehub/contribute`
922
923 **Arguments:** `repo_id`, `owner`, `slug`
924
925 End-to-end contribution workflow:
926
927 1. `musehub_get_context` — understand the repo
928 2. `musehub://repos/{owner}/{slug}/issues` — find open issues
929 3. `musehub_create_issue` — or create a new one
930 4. Make changes, push a commit
931 5. `musehub_create_pr` — open a PR
932 6. `musehub_submit_pr_review` — request review
933 7. `musehub_merge_pr` — merge when approved
934
935 ---
936
937 ### `musehub/compose`
938
939 **Arguments:** `repo_id`
940
941 Musical composition workflow:
942
943 1. `musehub_get_context` — understand existing tracks and structure
944 2. `musehub://repos/{owner}/{slug}/analysis/{ref}` — study the musical analysis
945 3. Compose new MIDI matching key/tempo/style
946 4. Push the commit
947 5. Verify the new analysis with `musehub_get_analysis`
948
949 ---
950
951 ### `musehub/review_pr`
952
953 **Arguments:** `repo_id`, `pr_id`
954
955 Musical PR review:
956
957 1. `musehub_get_pr` — read the PR metadata
958 2. `musehub_compare` — get per-dimension diff scores
959 3. `musehub://repos/{owner}/{slug}/analysis/{ref}` — compare analyses for base and head
960 4. `musehub_create_pr_comment` — post track/region-level comments
961 5. `musehub_submit_pr_review` — approve or request changes
962
963 ---
964
965 ### `musehub/issue_triage`
966
967 **Arguments:** `repo_id`
968
969 Triage open issues:
970
971 1. `musehub_list_issues` — list open issues
972 2. Categorise by type (bug, feature, discussion)
973 3. `musehub_create_label` — create missing labels
974 4. `musehub_update_issue` — apply labels, assign, close duplicates
975
976 ---
977
978 ### `musehub/release_prep`
979
980 **Arguments:** `repo_id`
981
982 Prepare a release:
983
984 1. `musehub_list_prs` — find merged PRs since the last release
985 2. `musehub_list_releases` — check the latest release tag
986 3. `musehub_get_analysis` — summarise musical changes
987 4. Draft release notes (Markdown)
988 5. `musehub_create_release` — publish
989
990 ---
991
992 ### `musehub/onboard` _(MCP 2025-11-25)_
993
994 **Arguments:** `username` (optional)
995
996 Interactive artist onboarding using elicitation. Requires a client with session + elicitation capability:
997
998 1. `musehub_create_repo` — scaffold the first project repo
999 2. `musehub_compose_with_preferences` — elicits key, tempo, mood, genre; returns composition plan
1000 3. `musehub_connect_daw_cloud` — URL elicitation: OAuth-connect LANDR/Splice/Soundtrap
1001 4. Guides through first commit, collaboration invite, and activity feed
1002
1003 ---
1004
1005 ### `musehub/release_to_world` _(MCP 2025-11-25)_
1006
1007 **Arguments:** `repo_id`
1008
1009 Full elicitation-powered release and distribution pipeline:
1010
1011 1. `musehub_create_release_interactive` — form: collect tag, title, notes, highlight; URL: optional Spotify connect
1012 2. `musehub_connect_streaming_platform` — URL elicitation for each target platform
1013 3. `musehub_connect_daw_cloud` — optional cloud mastering via LANDR
1014 4. Post announcement issue and notify followers
1015
1016 ---
1017
1018 ## Error Handling
1019
1020 ### JSON-RPC error codes
1021
1022 | Code | Meaning |
1023 |------|---------|
1024 | `-32700` | Parse error — request body is not valid JSON |
1025 | `-32600` | Invalid request — not an object or array |
1026 | `-32601` | Method not found |
1027 | `-32602` | Invalid params — required argument missing or wrong type |
1028 | `-32603` | Internal error — unexpected server exception |
1029 | `-32001` | Authentication required — write tool called without valid JWT |
1030
1031 ### Tool errors
1032
1033 Tool execution errors are not JSON-RPC errors. The envelope is always a success response; the error is signalled inside the result:
1034
1035 ```json
1036 {
1037 "result": {
1038 "content": [{ "type": "text", "text": "repo not found: abc123" }],
1039 "isError": true
1040 }
1041 }
1042 ```
1043
1044 ---
1045
1046 ## Usage Patterns
1047
1048 ### Pattern 1: Discover and explore
1049
1050 ```
1051 1. resources/read musehub://trending → pick a repo
1052 2. resources/read musehub://repos/{owner}/{slug} → orientation
1053 3. tools/call musehub_get_context → full AI context
1054 4. resources/read musehub://repos/{owner}/{slug}/analysis/{ref} → musical detail
1055 ```
1056
1057 ### Pattern 2: Fix a bug, open a PR
1058
1059 ```
1060 1. tools/call musehub_list_issues { repo_id, state: "open" }
1061 2. tools/call musehub_get_issue { repo_id, issue_number }
1062 3. tools/call musehub_browse_repo { repo_id }
1063 4. tools/call musehub_read_file { repo_id, path }
1064 5. -- compose fix, push commit --
1065 6. tools/call musehub_create_pr { repo_id, title, from_branch, to_branch }
1066 ```
1067
1068 ### Pattern 3: Full musical PR review (elicitation-powered)
1069
1070 ```
1071 1. tools/call musehub_review_pr_interactive { repo_id, pr_id }
1072 → elicitation: "Focus on harmonic divergence, thorough depth"
1073 → returns: per-dimension scores, findings, APPROVE/REQUEST_CHANGES recommendation
1074 ```
1075
1076 Or stateless:
1077
1078 ```
1079 1. tools/call musehub_get_pr { repo_id, pr_id }
1080 2. tools/call musehub_compare { repo_id, base_ref, head_ref }
1081 3. tools/call musehub_create_pr_comment { repo_id, pr_id, body, target_type: "track", ... }
1082 4. tools/call musehub_submit_pr_review { repo_id, pr_id, event: "APPROVE" }
1083 ```
1084
1085 ### Pattern 4: Compose with preferences (elicitation-powered)
1086
1087 ```
1088 1. POST initialize → Mcp-Session-Id: <id>
1089 2. GET /mcp (SSE) → open push channel
1090 3. tools/call musehub_compose_with_preferences { repo_id }
1091 → SSE: elicitation/create { mode: "form", schema: compose_preferences }
1092 → [user selects key: "D minor", tempo: 95, mood: "melancholic", genre: "neo-soul"]
1093 → POST elicitation result { action: "accept", content: { key: "D minor", ... } }
1094 → SSE: tools/call response { composition_plan: { ... } }
1095 ```
1096
1097 ### Pattern 5: Publish a release (elicitation-powered)
1098
1099 ```
1100 1. tools/call musehub_create_release_interactive { repo_id }
1101 → elicitation (form): tag, title, release notes, highlight
1102 → elicitation (URL, optional): Spotify OAuth
1103 → creates release + returns distribution guidance
1104 ```
1105
1106 Or stateless:
1107
1108 ```
1109 1. tools/call musehub_list_releases { repo_id }
1110 2. tools/call musehub_list_prs { repo_id, state: "closed" }
1111 3. tools/call musehub_get_analysis { repo_id, dimension: "overview" }
1112 4. tools/call musehub_create_release {
1113 repo_id, tag: "v1.2.0", title: "Spring Drop",
1114 body: "## What changed\n..."
1115 }
1116 ```
1117
1118 ### Pattern 6: Connect and distribute (URL elicitation)
1119
1120 ```
1121 1. tools/call musehub_connect_streaming_platform { platform: "Spotify" }
1122 → SSE: elicitation/create { mode: "url", url: "https://musehub.app/musehub/ui/mcp/connect/spotify?elicitation_id=..." }
1123 → [user clicks through OAuth in browser]
1124 → SSE: notifications/elicitation/complete { action: "accept" }
1125 → returns: { platform: "Spotify", status: "connected" }
1126 ```
1127
1128 ---
1129
1130 ## Architecture Diagrams
1131
1132 ### Request flow
1133
1134 ```mermaid
1135 flowchart TD
1136 subgraph transports [Transports — MCP 2025-11-25]
1137 POST["POST /mcp\nJSON + SSE stream"]
1138 GET["GET /mcp\nSSE push channel"]
1139 DEL["DELETE /mcp\nSession termination"]
1140 stdio["stdio\npython -m musehub.mcp.stdio_server"]
1141 end
1142
1143 subgraph session [Session Layer]
1144 SID["Mcp-Session-Id"]
1145 ORIGIN["Origin validation"]
1146 SSE_Q["asyncio.Queue\nSSE queues"]
1147 FUTURES["asyncio.Future\nelicitation registry"]
1148 end
1149
1150 subgraph dispatcher [musehub/mcp/dispatcher.py]
1151 D["handle_request()"]
1152 D --> INIT["initialize"]
1153 D --> TL["tools/list"]
1154 D --> TC["tools/call"]
1155 D --> RL["resources/list"]
1156 D --> RR["resources/read"]
1157 D --> PL["prompts/list"]
1158 D --> PG["prompts/get"]
1159 D --> NC["notifications/cancelled"]
1160 D --> NEC["notifications/elicitation/complete"]
1161 end
1162
1163 subgraph execution [Execution Layer]
1164 READ["Read executors\nmusehub_mcp_executor.py"]
1165 WRITE["Write executors\nmcp/write_tools/"]
1166 ELICIT["Elicitation tools\nelicitation_tools.py"]
1167 CTX["ToolCallContext\ncontext.py"]
1168 RES["Resource handlers\nresources.py"]
1169 PROMPTS["Prompt assembler\nprompts.py"]
1170 end
1171
1172 POST --> ORIGIN
1173 POST --> SID
1174 SID --> D
1175 GET --> SSE_Q
1176 DEL --> SID
1177 stdio --> D
1178 TC --> READ
1179 TC --> WRITE
1180 TC --> ELICIT
1181 ELICIT --> CTX
1182 CTX --> SSE_Q
1183 CTX --> FUTURES
1184 RR --> RES
1185 PG --> PROMPTS
1186 NC --> FUTURES
1187 NEC --> FUTURES
1188 READ --> DB[("AsyncSession / Postgres")]
1189 WRITE --> DB
1190 RES --> DB
1191 ```
1192
1193 ### Tool catalogue structure
1194
1195 ```mermaid
1196 classDiagram
1197 class MUSEHUB_READ_TOOLS {
1198 <<list of MCPToolDef — 15 tools>>
1199 musehub_browse_repo
1200 musehub_list_branches
1201 musehub_list_commits
1202 musehub_read_file
1203 musehub_get_analysis
1204 musehub_search
1205 musehub_get_context
1206 musehub_get_commit
1207 musehub_compare
1208 musehub_list_issues
1209 musehub_get_issue
1210 musehub_list_prs
1211 musehub_get_pr
1212 musehub_list_releases
1213 musehub_search_repos
1214 }
1215 class MUSEHUB_WRITE_TOOLS {
1216 <<list of MCPToolDef — 12 tools>>
1217 musehub_create_repo
1218 musehub_fork_repo
1219 musehub_create_issue
1220 musehub_update_issue
1221 musehub_create_issue_comment
1222 musehub_create_pr
1223 musehub_merge_pr
1224 musehub_create_pr_comment
1225 musehub_submit_pr_review
1226 musehub_create_release
1227 musehub_star_repo
1228 musehub_create_label
1229 }
1230 class MUSEHUB_ELICITATION_TOOLS {
1231 <<list of MCPToolDef — 5 tools — MCP 2025-11-25>>
1232 musehub_compose_with_preferences
1233 musehub_review_pr_interactive
1234 musehub_connect_streaming_platform
1235 musehub_connect_daw_cloud
1236 musehub_create_release_interactive
1237 }
1238 class MCPDispatcher {
1239 +handle_request(raw, user_id, session)
1240 +handle_batch(raw, user_id, session)
1241 }
1242
1243 MCPDispatcher ..> MUSEHUB_READ_TOOLS : routes read calls
1244 MCPDispatcher ..> MUSEHUB_WRITE_TOOLS : routes write calls (JWT required)
1245 MCPDispatcher ..> MUSEHUB_ELICITATION_TOOLS : routes interactive calls (session required)
1246 ```
1247
1248 ### Resource URI hierarchy
1249
1250 ```mermaid
1251 flowchart TD
1252 root["musehub://"]
1253 root --> trending["trending"]
1254 root --> me["me"]
1255 root --> repos["repos/{owner}/{slug}"]
1256 root --> users["users/{username}"]
1257
1258 me --> notifications["me/notifications"]
1259 me --> starred["me/starred"]
1260 me --> feed["me/feed"]
1261
1262 repos --> branches["…/branches"]
1263 repos --> commits["…/commits"]
1264 commits --> commit["…/commits/{commit_id}"]
1265 repos --> tree["…/tree/{ref}"]
1266 repos --> blob["…/blob/{ref}/{path}"]
1267 repos --> issues["…/issues"]
1268 issues --> issue["…/issues/{number}"]
1269 repos --> pulls["…/pulls"]
1270 pulls --> pull["…/pulls/{number}"]
1271 repos --> releases["…/releases"]
1272 releases --> release["…/releases/{tag}"]
1273 repos --> analysis["…/analysis/{ref}"]
1274 repos --> timeline["…/timeline"]
1275 ```
1276
1277 ### Elicitation sequence (form mode)
1278
1279 ```mermaid
1280 sequenceDiagram
1281 participant Agent
1282 participant MCP as POST /mcp
1283 participant Session as Session Store
1284 participant Tool as Elicitation Tool
1285
1286 Agent->>MCP: POST initialize {capabilities: {elicitation: {form:{}, url:{}}}}
1287 MCP-->>Agent: 200 OK, Mcp-Session-Id: abc123
1288
1289 Agent->>MCP: GET /mcp (Accept: text/event-stream, Mcp-Session-Id: abc123)
1290 MCP-->>Agent: 200 text/event-stream (SSE channel open)
1291
1292 Agent->>MCP: POST tools/call musehub_compose_with_preferences
1293 Note over MCP: tool needs elicitation → SSE response
1294 MCP->>Session: create_pending_elicitation("elicit-1")
1295 MCP-->>Agent: 200 text/event-stream (POST SSE open)
1296 MCP-->>Agent: SSE: elicitation/create {mode:"form", schema:{key,tempo,mood,...}}
1297
1298 Note over Agent: Shows form UI to user
1299
1300 Agent->>MCP: POST {jsonrpc:"2.0", id:"elicit-1", result:{action:"accept", content:{key:"Dm",...}}}
1301 MCP->>Session: resolve_elicitation("elicit-1", {action:"accept", content:...})
1302 MCP-->>Agent: 202 Accepted
1303
1304 Note over Tool: Future resolved, tool continues
1305
1306 MCP-->>Agent: SSE: tools/call response {composition_plan: {...}}
1307 Note over MCP: SSE stream closes
1308 ```
1309
1310 ### Elicitation sequence (URL mode)
1311
1312 ```mermaid
1313 sequenceDiagram
1314 participant Agent
1315 participant MCP as POST /mcp
1316 participant Browser as User's Browser
1317 participant UI as MuseHub UI /mcp/connect/...
1318
1319 Agent->>MCP: POST tools/call musehub_connect_streaming_platform {platform:"Spotify"}
1320 MCP-->>Agent: SSE: elicitation/create {mode:"url", url:"https://musehub.app/musehub/ui/mcp/connect/spotify?elicitation_id=xyz"}
1321
1322 Agent->>Browser: opens URL
1323 Browser->>UI: GET /musehub/ui/mcp/connect/spotify?elicitation_id=xyz
1324 UI-->>Browser: confirmation page
1325
1326 Browser->>UI: user clicks "Connect Spotify"
1327 UI->>UI: resolve_elicitation(session, "xyz", {action:"accept"})
1328 UI-->>Browser: callback page (auto-close tab)
1329
1330 MCP-->>Agent: SSE: notifications/elicitation/complete {elicitationId:"xyz", action:"accept"}
1331 MCP-->>Agent: SSE: tools/call response {platform:"Spotify", status:"connected"}
1332 ```