gabriel / musehub public
mcp.md markdown
976 lines 25.7 KB
bb9e42df docs: update README + add full MCP reference guide Gabriel Cardona <gabriel@tellurstori.com> 6d ago
1 # MuseHub MCP Reference
2
3 > Protocol version: **2025-03-26** | 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 ---
8
9 ## Table of Contents
10
11 1. [Architecture](#architecture)
12 2. [Transports](#transports)
13 3. [Authentication](#authentication)
14 4. [Tools — 27 total](#tools)
15 - [Read Tools (15)](#read-tools-15)
16 - [Write Tools (12)](#write-tools-12)
17 5. [Resources — 20 total](#resources)
18 - [Static Resources (5)](#static-resources-5)
19 - [Templated Resources (15)](#templated-resources-15)
20 6. [Prompts — 6 total](#prompts)
21 7. [Error Handling](#error-handling)
22 8. [Usage Patterns](#usage-patterns)
23 9. [Architecture Diagrams](#architecture-diagrams)
24
25 ---
26
27 ## Architecture
28
29 ```
30 MCP Client (Cursor, Claude Desktop, any SDK)
31
32 ├─ HTTP POST /mcp (production)
33 └─ stdio python -m musehub.mcp.stdio_server (local dev)
34
35 musehub/mcp/dispatcher.py ← async JSON-RPC 2.0 engine
36
37 ┌───────┼───────────────┐
38 │ │ │
39 tools/call resources/read prompts/get
40 │ │ │
41 Read executors Resource handlers Prompt assembler
42 (musehub_mcp_executor.py) (resources.py) (prompts.py)
43 Write executors
44 (mcp/write_tools/)
45
46 AsyncSession → Postgres
47 ```
48
49 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.
50
51 ---
52
53 ## Transports
54
55 ### HTTP Streamable — `POST /mcp`
56
57 The production transport. Accepts `application/json`.
58
59 ```http
60 POST /mcp HTTP/1.1
61 Content-Type: application/json
62 Authorization: Bearer <jwt>
63
64 {"jsonrpc":"2.0","id":1,"method":"tools/list"}
65 ```
66
67 **Batch requests** — send a JSON array; responses are returned as an array in the same order (notifications are filtered out):
68
69 ```http
70 POST /mcp
71 [
72 {"jsonrpc":"2.0","id":1,"method":"tools/list"},
73 {"jsonrpc":"2.0","id":2,"method":"resources/list"}
74 ]
75 ```
76
77 **Notifications** (no `id`) return `202 Accepted` with an empty body.
78
79 ### stdio — `python -m musehub.mcp.stdio_server`
80
81 The local dev and Cursor IDE transport. Reads newline-delimited JSON from `stdin`, writes JSON-RPC responses to `stdout`, logs to `stderr`.
82
83 **Cursor IDE integration** — create or update `.cursor/mcp.json` in your workspace:
84
85 ```json
86 {
87 "mcpServers": {
88 "musehub": {
89 "command": "python",
90 "args": ["-m", "musehub.mcp.stdio_server"],
91 "cwd": "/path/to/musehub"
92 }
93 }
94 }
95 ```
96
97 The stdio server runs without auth (trusted local process). Write tools are available unconditionally.
98
99 ---
100
101 ## Authentication
102
103 | Context | How |
104 |---------|-----|
105 | HTTP transport — read tools + public resources | No auth required |
106 | HTTP transport — write tools | `Authorization: Bearer <jwt>` |
107 | HTTP transport — private repo resources | `Authorization: Bearer <jwt>` |
108 | stdio transport | No auth (trusted process) |
109
110 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.
111
112 Attempting a write tool without a valid token returns a JSON-RPC error (`code: -32001`, `message: "Authentication required for write tools"`).
113
114 ---
115
116 ## Tools
117
118 All 27 tools use `server_side: true`. The JSON-RPC envelope is always a success response — errors are represented inside the content block via `isError: true`.
119
120 ### Calling a tool
121
122 ```json
123 {
124 "jsonrpc": "2.0",
125 "id": 1,
126 "method": "tools/call",
127 "params": {
128 "name": "musehub_browse_repo",
129 "arguments": { "repo_id": "abc123" }
130 }
131 }
132 ```
133
134 Response:
135
136 ```json
137 {
138 "jsonrpc": "2.0",
139 "id": 1,
140 "result": {
141 "content": [{ "type": "text", "text": "{\"name\":\"my-song\", ...}" }],
142 "isError": false
143 }
144 }
145 ```
146
147 ---
148
149 ### Read Tools (15)
150
151 #### `musehub_browse_repo`
152
153 Orientation snapshot for a repo: metadata, default branch, recent commits, top-level file list.
154
155 | Parameter | Type | Required | Description |
156 |-----------|------|----------|-------------|
157 | `repo_id` | string | yes | Repository UUID |
158
159 ---
160
161 #### `musehub_list_branches`
162
163 All branches with their head commit IDs and timestamps.
164
165 | Parameter | Type | Required | Description |
166 |-----------|------|----------|-------------|
167 | `repo_id` | string | yes | Repository UUID |
168
169 ---
170
171 #### `musehub_list_commits`
172
173 Paginated commit history, newest first.
174
175 | Parameter | Type | Required | Description |
176 |-----------|------|----------|-------------|
177 | `repo_id` | string | yes | Repository UUID |
178 | `branch` | string | no | Branch name filter |
179 | `limit` | integer | no | Max commits (default 20) |
180
181 ---
182
183 #### `musehub_read_file`
184
185 Metadata for a single artifact (MIDI, MP3, WebP, etc.) at a given commit.
186
187 | Parameter | Type | Required | Description |
188 |-----------|------|----------|-------------|
189 | `repo_id` | string | yes | Repository UUID |
190 | `path` | string | yes | File path within the repo |
191 | `commit_id` | string | no | Commit SHA (defaults to HEAD) |
192
193 ---
194
195 #### `musehub_get_analysis`
196
197 13-dimension musical analysis for a repo at a given ref.
198
199 | Parameter | Type | Required | Description |
200 |-----------|------|----------|-------------|
201 | `repo_id` | string | yes | Repository UUID |
202 | `ref` | string | no | Branch, tag, or commit SHA |
203 | `mode` | string | no | `"overview"` (default), `"commits"`, or `"objects"` |
204
205 ---
206
207 #### `musehub_search`
208
209 Keyword/path search over commits and file paths within a repo.
210
211 | Parameter | Type | Required | Description |
212 |-----------|------|----------|-------------|
213 | `repo_id` | string | yes | Repository UUID |
214 | `query` | string | yes | Search terms |
215
216 ---
217
218 #### `musehub_get_context`
219
220 Full AI context document for a repo — combines metadata, analysis, recent activity, and usage hints into a single structured payload.
221
222 | Parameter | Type | Required | Description |
223 |-----------|------|----------|-------------|
224 | `repo_id` | string | yes | Repository UUID |
225
226 ---
227
228 #### `musehub_get_commit`
229
230 Single commit detail with the full snapshot manifest (all file paths and content hashes at that point in history).
231
232 | Parameter | Type | Required | Description |
233 |-----------|------|----------|-------------|
234 | `repo_id` | string | yes | Repository UUID |
235 | `commit_id` | string | yes | Commit SHA |
236
237 ---
238
239 #### `musehub_compare`
240
241 Musical diff between two refs — returns per-dimension change scores (harmony, rhythm, groove, key, tempo) and a list of changed file paths.
242
243 | Parameter | Type | Required | Description |
244 |-----------|------|----------|-------------|
245 | `repo_id` | string | yes | Repository UUID |
246 | `base_ref` | string | yes | Base branch, tag, or commit SHA |
247 | `head_ref` | string | yes | Head branch, tag, or commit SHA |
248
249 ---
250
251 #### `musehub_list_issues`
252
253 Issues with optional state, label, and assignee filters.
254
255 | Parameter | Type | Required | Description |
256 |-----------|------|----------|-------------|
257 | `repo_id` | string | yes | Repository UUID |
258 | `state` | string | no | `"open"` (default) or `"closed"` |
259 | `label` | string | no | Label name filter |
260 | `assignee` | string | no | Assignee username filter |
261
262 ---
263
264 #### `musehub_get_issue`
265
266 Single issue with its full comment thread.
267
268 | Parameter | Type | Required | Description |
269 |-----------|------|----------|-------------|
270 | `repo_id` | string | yes | Repository UUID |
271 | `issue_number` | integer | yes | Issue number |
272
273 ---
274
275 #### `musehub_list_prs`
276
277 Pull requests with optional state and base branch filters.
278
279 | Parameter | Type | Required | Description |
280 |-----------|------|----------|-------------|
281 | `repo_id` | string | yes | Repository UUID |
282 | `state` | string | no | `"open"` (default), `"closed"`, or `"merged"` |
283 | `base` | string | no | Target branch filter |
284
285 ---
286
287 #### `musehub_get_pr`
288
289 Single PR with all inline comments and reviews.
290
291 | Parameter | Type | Required | Description |
292 |-----------|------|----------|-------------|
293 | `repo_id` | string | yes | Repository UUID |
294 | `pr_number` | integer | yes | Pull request number |
295
296 ---
297
298 #### `musehub_list_releases`
299
300 All releases for a repo with asset counts and timestamps.
301
302 | Parameter | Type | Required | Description |
303 |-----------|------|----------|-------------|
304 | `repo_id` | string | yes | Repository UUID |
305
306 ---
307
308 #### `musehub_search_repos`
309
310 Discover public repos by text query or musical attributes.
311
312 | Parameter | Type | Required | Description |
313 |-----------|------|----------|-------------|
314 | `query` | string | no | Text search query |
315 | `key` | string | no | Musical key filter (e.g. `"C major"`) |
316 | `tempo_min` | integer | no | Minimum BPM |
317 | `tempo_max` | integer | no | Maximum BPM |
318 | `tags` | array of strings | no | Tag filters |
319 | `limit` | integer | no | Max results (default 20) |
320
321 ---
322
323 ### Write Tools (12)
324
325 > All write tools require `Authorization: Bearer <jwt>` on the HTTP transport.
326
327 #### `musehub_create_repo`
328
329 Create a new repository.
330
331 | Parameter | Type | Required | Description |
332 |-----------|------|----------|-------------|
333 | `name` | string | yes | Repository name |
334 | `owner` | string | yes | Owner username |
335 | `owner_user_id` | string | yes | Owner user UUID |
336 | `description` | string | no | Short description |
337 | `visibility` | string | no | `"public"` (default) or `"private"` |
338 | `tags` | array of strings | no | Initial tags |
339 | `key_signature` | string | no | Musical key (e.g. `"G major"`) |
340 | `tempo_bpm` | integer | no | Tempo in BPM |
341 | `initialize` | boolean | no | Create initial commit (default `true`) |
342
343 ---
344
345 #### `musehub_fork_repo`
346
347 Fork an existing repository into the authenticated user's account.
348
349 | Parameter | Type | Required | Description |
350 |-----------|------|----------|-------------|
351 | `repo_id` | string | yes | Source repository UUID |
352 | `new_owner` | string | yes | Fork owner username |
353 | `new_owner_user_id` | string | yes | Fork owner user UUID |
354
355 ---
356
357 #### `musehub_create_issue`
358
359 Open a new issue.
360
361 | Parameter | Type | Required | Description |
362 |-----------|------|----------|-------------|
363 | `repo_id` | string | yes | Repository UUID |
364 | `title` | string | yes | Issue title |
365 | `body` | string | no | Issue description (Markdown) |
366 | `labels` | array of strings | no | Label names to apply |
367 | `assignee_id` | string | no | Assignee user UUID |
368
369 ---
370
371 #### `musehub_update_issue`
372
373 Update issue state or metadata.
374
375 | Parameter | Type | Required | Description |
376 |-----------|------|----------|-------------|
377 | `repo_id` | string | yes | Repository UUID |
378 | `issue_number` | integer | yes | Issue number |
379 | `state` | string | no | `"open"` or `"closed"` |
380 | `title` | string | no | New title |
381 | `body` | string | no | New body |
382 | `assignee_id` | string | no | New assignee UUID |
383 | `labels` | array of strings | no | Replace label set |
384
385 ---
386
387 #### `musehub_create_issue_comment`
388
389 Post a comment on an issue.
390
391 | Parameter | Type | Required | Description |
392 |-----------|------|----------|-------------|
393 | `repo_id` | string | yes | Repository UUID |
394 | `issue_number` | integer | yes | Issue number |
395 | `body` | string | yes | Comment body (Markdown) |
396
397 ---
398
399 #### `musehub_create_pr`
400
401 Open a pull request.
402
403 | Parameter | Type | Required | Description |
404 |-----------|------|----------|-------------|
405 | `repo_id` | string | yes | Repository UUID |
406 | `title` | string | yes | PR title |
407 | `from_branch` | string | yes | Source branch |
408 | `to_branch` | string | yes | Target branch |
409 | `body` | string | no | PR description (Markdown) |
410
411 ---
412
413 #### `musehub_merge_pr`
414
415 Merge an open pull request.
416
417 | Parameter | Type | Required | Description |
418 |-----------|------|----------|-------------|
419 | `repo_id` | string | yes | Repository UUID |
420 | `pr_number` | integer | yes | Pull request number |
421 | `merge_message` | string | no | Custom merge commit message |
422
423 ---
424
425 #### `musehub_create_pr_comment`
426
427 Post an inline comment on a PR. Supports general, track-level, and beat-range comments — mirroring the musical diff view in the web UI.
428
429 | Parameter | Type | Required | Description |
430 |-----------|------|----------|-------------|
431 | `repo_id` | string | yes | Repository UUID |
432 | `pr_number` | integer | yes | Pull request number |
433 | `body` | string | yes | Comment body (Markdown) |
434 | `target_type` | string | no | `"general"` (default), `"track"`, `"region"`, or `"note"` |
435 | `target_track` | string | no | Track name (when `target_type` is `"track"` or finer) |
436 | `target_beat_start` | number | no | Start beat position |
437 | `target_beat_end` | number | no | End beat position |
438
439 ---
440
441 #### `musehub_submit_pr_review`
442
443 Submit a formal review on a PR.
444
445 | Parameter | Type | Required | Description |
446 |-----------|------|----------|-------------|
447 | `repo_id` | string | yes | Repository UUID |
448 | `pr_number` | integer | yes | Pull request number |
449 | `state` | string | yes | `"approved"`, `"changes_requested"`, or `"commented"` |
450 | `body` | string | no | Review summary |
451
452 ---
453
454 #### `musehub_create_release`
455
456 Publish a release.
457
458 | Parameter | Type | Required | Description |
459 |-----------|------|----------|-------------|
460 | `repo_id` | string | yes | Repository UUID |
461 | `tag` | string | yes | Tag name (e.g. `"v1.0.0"`) |
462 | `title` | string | yes | Release title |
463 | `body` | string | no | Release notes (Markdown) |
464 | `commit_id` | string | no | Target commit SHA (defaults to HEAD) |
465 | `is_prerelease` | boolean | no | Mark as pre-release (default `false`) |
466
467 ---
468
469 #### `musehub_star_repo`
470
471 Star a repository.
472
473 | Parameter | Type | Required | Description |
474 |-----------|------|----------|-------------|
475 | `repo_id` | string | yes | Repository UUID |
476
477 ---
478
479 #### `musehub_create_label`
480
481 Create a label scoped to a repository.
482
483 | Parameter | Type | Required | Description |
484 |-----------|------|----------|-------------|
485 | `repo_id` | string | yes | Repository UUID |
486 | `name` | string | yes | Label name |
487 | `color` | string | yes | Hex color (e.g. `"#0075ca"`) |
488 | `description` | string | no | Label description |
489
490 ---
491
492 ## Resources
493
494 Resources are side-effect-free, cacheable, URI-addressable reads. All resources return `application/json`. They are read via the `resources/read` method.
495
496 ### Listing resources
497
498 ```json
499 {"jsonrpc":"2.0","id":1,"method":"resources/list"}
500 {"jsonrpc":"2.0","id":2,"method":"resources/templates/list"}
501 ```
502
503 ### Reading a resource
504
505 ```json
506 {
507 "jsonrpc": "2.0",
508 "id": 1,
509 "method": "resources/read",
510 "params": { "uri": "musehub://trending" }
511 }
512 ```
513
514 Response:
515
516 ```json
517 {
518 "jsonrpc": "2.0",
519 "id": 1,
520 "result": {
521 "contents": [{
522 "uri": "musehub://trending",
523 "mimeType": "application/json",
524 "text": "[{\"repo_id\":\"...\",\"name\":\"my-song\",...}]"
525 }]
526 }
527 }
528 ```
529
530 ---
531
532 ### Static Resources (5)
533
534 #### `musehub://trending`
535
536 Top 20 public repos ordered by star count. Anonymous-accessible.
537
538 **Returns:** array of repo summaries with `repo_id`, `name`, `owner`, `slug`, `description`, `visibility`, `clone_url`, `created_at`.
539
540 ---
541
542 #### `musehub://me`
543
544 Authenticated user's profile and their most recent 20 repos. Requires JWT.
545
546 **Returns:** `{ "user_id", "username", "repos": [...] }`
547
548 ---
549
550 #### `musehub://me/notifications`
551
552 Unread notifications for the authenticated user. Requires JWT.
553
554 **Returns:** `{ "notifications": [{ "id", "event_type", "read", "created_at" }] }`
555
556 ---
557
558 #### `musehub://me/starred`
559
560 Repos the authenticated user has starred. Requires JWT.
561
562 **Returns:** `{ "starred": [{ "repo_id", "name", "owner", "slug", "starred_at" }] }`
563
564 ---
565
566 #### `musehub://me/feed`
567
568 Activity feed for repos the authenticated user watches. Requires JWT.
569
570 **Returns:** `{ "feed": [...] }`
571
572 ---
573
574 ### Templated Resources (15)
575
576 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.
577
578 #### `musehub://repos/{owner}/{slug}`
579
580 Repo overview: metadata, visibility, default branch, tag list, description.
581
582 ---
583
584 #### `musehub://repos/{owner}/{slug}/branches`
585
586 All branches with their name, head commit ID, and last-updated timestamp.
587
588 ---
589
590 #### `musehub://repos/{owner}/{slug}/commits`
591
592 20 most recent commits on the default branch. Includes commit message, author, timestamp.
593
594 ---
595
596 #### `musehub://repos/{owner}/{slug}/commits/{commit_id}`
597
598 Single commit with its full snapshot manifest (all file paths and content hashes at that point).
599
600 ---
601
602 #### `musehub://repos/{owner}/{slug}/tree/{ref}`
603
604 File tree at a given ref. Returns all object paths and guessed MIME types.
605
606 ---
607
608 #### `musehub://repos/{owner}/{slug}/blob/{ref}/{path}`
609
610 Metadata for a single file at a given ref: path, content hash, MIME type, size.
611
612 ---
613
614 #### `musehub://repos/{owner}/{slug}/issues`
615
616 Open issues list with labels, assignees, and comment counts.
617
618 ---
619
620 #### `musehub://repos/{owner}/{slug}/issues/{number}`
621
622 Single issue with its full comment thread.
623
624 ---
625
626 #### `musehub://repos/{owner}/{slug}/pulls`
627
628 Open PRs with source/target branches and review counts.
629
630 ---
631
632 #### `musehub://repos/{owner}/{slug}/pulls/{number}`
633
634 Single PR with all inline comments and reviews (reviewer, state, body).
635
636 ---
637
638 #### `musehub://repos/{owner}/{slug}/releases`
639
640 All releases ordered newest first: tag, title, body, asset count, timestamp.
641
642 ---
643
644 #### `musehub://repos/{owner}/{slug}/releases/{tag}`
645
646 Single release matching a tag name, including the full release notes body.
647
648 ---
649
650 #### `musehub://repos/{owner}/{slug}/analysis/{ref}`
651
652 Musical analysis at a given ref: key, tempo, time signature, per-dimension scores (harmony, rhythm, groove, dynamics, orchestration, …).
653
654 ---
655
656 #### `musehub://repos/{owner}/{slug}/timeline`
657
658 Musical evolution timeline: commits, section events, and track events in chronological order.
659
660 ---
661
662 #### `musehub://users/{username}`
663
664 User profile and their 20 most recent public repos.
665
666 ---
667
668 ## Prompts
669
670 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.
671
672 ### Getting a prompt
673
674 ```json
675 {
676 "jsonrpc": "2.0",
677 "id": 1,
678 "method": "prompts/get",
679 "params": {
680 "name": "musehub/orientation"
681 }
682 }
683 ```
684
685 With arguments:
686
687 ```json
688 {
689 "jsonrpc": "2.0",
690 "id": 1,
691 "method": "prompts/get",
692 "params": {
693 "name": "musehub/contribute",
694 "arguments": {
695 "repo_id": "abc123",
696 "owner": "alice",
697 "slug": "my-song"
698 }
699 }
700 }
701 ```
702
703 ---
704
705 ### `musehub/orientation`
706
707 **Arguments:** none
708
709 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.
710
711 ---
712
713 ### `musehub/contribute`
714
715 **Arguments:** `repo_id`, `owner`, `slug`
716
717 End-to-end contribution workflow:
718
719 1. `musehub_get_context` — understand the repo
720 2. `musehub://repos/{owner}/{slug}/issues` — find open issues
721 3. `musehub_create_issue` — or create a new one
722 4. Make changes, push a commit
723 5. `musehub_create_pr` — open a PR
724 6. `musehub_submit_pr_review` — request review
725 7. `musehub_merge_pr` — merge when approved
726
727 ---
728
729 ### `musehub/compose`
730
731 **Arguments:** `repo_id`
732
733 Musical composition workflow:
734
735 1. `musehub_get_context` — understand existing tracks and structure
736 2. `musehub://repos/{owner}/{slug}/analysis/{ref}` — study the musical analysis
737 3. Compose new MIDI matching key/tempo/style
738 4. Push the commit
739 5. Verify the new analysis with `musehub_get_analysis`
740
741 ---
742
743 ### `musehub/review_pr`
744
745 **Arguments:** `repo_id`, `pr_id`
746
747 Musical PR review:
748
749 1. `musehub_get_pr` — read the PR metadata
750 2. `musehub_compare` — get per-dimension diff scores
751 3. `musehub://repos/{owner}/{slug}/analysis/{ref}` — compare analyses for base and head
752 4. `musehub_create_pr_comment` — post track/region-level comments
753 5. `musehub_submit_pr_review` — approve or request changes
754
755 ---
756
757 ### `musehub/issue_triage`
758
759 **Arguments:** `repo_id`
760
761 Triage open issues:
762
763 1. `musehub_list_issues` — list open issues
764 2. Categorise by type (bug, feature, discussion)
765 3. `musehub_create_label` — create missing labels
766 4. `musehub_update_issue` — apply labels, assign, close duplicates
767
768 ---
769
770 ### `musehub/release_prep`
771
772 **Arguments:** `repo_id`
773
774 Prepare a release:
775
776 1. `musehub_list_prs` — find merged PRs since the last release
777 2. `musehub_list_releases` — check the latest release tag
778 3. `musehub_get_analysis` — summarise musical changes
779 4. Draft release notes (Markdown)
780 5. `musehub_create_release` — publish
781
782 ---
783
784 ## Error Handling
785
786 ### JSON-RPC error codes
787
788 | Code | Meaning |
789 |------|---------|
790 | `-32700` | Parse error — request body is not valid JSON |
791 | `-32600` | Invalid request — not an object or array |
792 | `-32601` | Method not found |
793 | `-32602` | Invalid params — required argument missing or wrong type |
794 | `-32603` | Internal error — unexpected server exception |
795 | `-32001` | Authentication required — write tool called without valid JWT |
796
797 ### Tool errors
798
799 Tool execution errors are not JSON-RPC errors. The envelope is always a success response; the error is signalled inside the result:
800
801 ```json
802 {
803 "result": {
804 "content": [{ "type": "text", "text": "repo not found: abc123" }],
805 "isError": true
806 }
807 }
808 ```
809
810 ---
811
812 ## Usage Patterns
813
814 ### Pattern 1: Discover and explore
815
816 ```
817 1. resources/read musehub://trending → pick a repo
818 2. resources/read musehub://repos/{owner}/{slug} → orientation
819 3. tools/call musehub_get_context → full AI context
820 4. resources/read musehub://repos/{owner}/{slug}/analysis/{ref} → musical detail
821 ```
822
823 ### Pattern 2: Fix a bug, open a PR
824
825 ```
826 1. tools/call musehub_list_issues { repo_id, state: "open" }
827 2. tools/call musehub_get_issue { repo_id, issue_number }
828 3. tools/call musehub_browse_repo { repo_id }
829 4. tools/call musehub_read_file { repo_id, path }
830 5. -- compose fix, push commit --
831 6. tools/call musehub_create_pr { repo_id, title, from_branch, to_branch }
832 ```
833
834 ### Pattern 3: Full musical PR review
835
836 ```
837 1. tools/call musehub_get_pr { repo_id, pr_number }
838 2. tools/call musehub_compare { repo_id, base_ref, head_ref }
839 3. resources/read musehub://repos/{owner}/{slug}/analysis/{base_ref}
840 4. resources/read musehub://repos/{owner}/{slug}/analysis/{head_ref}
841 5. tools/call musehub_create_pr_comment {
842 repo_id, pr_number, body: "...",
843 target_type: "track", target_track: "Bass",
844 target_beat_start: 0, target_beat_end: 32
845 }
846 6. tools/call musehub_submit_pr_review { repo_id, pr_number, state: "approved" }
847 ```
848
849 ### Pattern 4: Publish a release
850
851 ```
852 1. tools/call musehub_list_releases { repo_id }
853 2. tools/call musehub_list_prs { repo_id, state: "closed" }
854 3. tools/call musehub_get_analysis { repo_id, ref: "main" }
855 4. tools/call musehub_create_release {
856 repo_id, tag: "v1.2.0", title: "Spring Drop",
857 body: "## What changed\n..."
858 }
859 ```
860
861 ---
862
863 ## Architecture Diagrams
864
865 ### Request flow
866
867 ```mermaid
868 flowchart TD
869 subgraph transports [Transports]
870 HTTP["POST /mcp\nHTTP Streamable"]
871 stdio["stdio\npython -m musehub.mcp.stdio_server"]
872 end
873
874 subgraph dispatcher [musehub/mcp/dispatcher.py]
875 D["handle_request()"]
876 D --> INIT["initialize"]
877 D --> TL["tools/list"]
878 D --> TC["tools/call"]
879 D --> RL["resources/list\nresources/templates/list"]
880 D --> RR["resources/read"]
881 D --> PL["prompts/list"]
882 D --> PG["prompts/get"]
883 end
884
885 subgraph execution [Execution Layer]
886 READ["Read executors\nmusehub_mcp_executor.py"]
887 WRITE["Write executors\nmcp/write_tools/"]
888 RES["Resource handlers\nmcp/resources.py"]
889 PROMPTS["Prompt assembler\nmcp/prompts.py"]
890 end
891
892 HTTP --> D
893 stdio --> D
894 TC --> READ
895 TC --> WRITE
896 RR --> RES
897 PG --> PROMPTS
898 READ --> DB[("AsyncSession / Postgres")]
899 WRITE --> DB
900 RES --> DB
901 ```
902
903 ### Tool catalogue structure
904
905 ```mermaid
906 classDiagram
907 class MUSEHUB_READ_TOOLS {
908 <<list of MCPToolDef — 15 tools>>
909 musehub_browse_repo
910 musehub_list_branches
911 musehub_list_commits
912 musehub_read_file
913 musehub_get_analysis
914 musehub_search
915 musehub_get_context
916 musehub_get_commit
917 musehub_compare
918 musehub_list_issues
919 musehub_get_issue
920 musehub_list_prs
921 musehub_get_pr
922 musehub_list_releases
923 musehub_search_repos
924 }
925 class MUSEHUB_WRITE_TOOLS {
926 <<list of MCPToolDef — 12 tools>>
927 musehub_create_repo
928 musehub_fork_repo
929 musehub_create_issue
930 musehub_update_issue
931 musehub_create_issue_comment
932 musehub_create_pr
933 musehub_merge_pr
934 musehub_create_pr_comment
935 musehub_submit_pr_review
936 musehub_create_release
937 musehub_star_repo
938 musehub_create_label
939 }
940 class MCPDispatcher {
941 +handle_request(raw, user_id)
942 +handle_batch(raw, user_id)
943 }
944
945 MCPDispatcher ..> MUSEHUB_READ_TOOLS : routes read calls
946 MCPDispatcher ..> MUSEHUB_WRITE_TOOLS : routes write calls (JWT required)
947 ```
948
949 ### Resource URI hierarchy
950
951 ```mermaid
952 flowchart TD
953 root["musehub://"]
954 root --> trending["trending"]
955 root --> me["me"]
956 root --> repos["repos/{owner}/{slug}"]
957 root --> users["users/{username}"]
958
959 me --> notifications["me/notifications"]
960 me --> starred["me/starred"]
961 me --> feed["me/feed"]
962
963 repos --> branches["…/branches"]
964 repos --> commits["…/commits"]
965 commits --> commit["…/commits/{commit_id}"]
966 repos --> tree["…/tree/{ref}"]
967 repos --> blob["…/blob/{ref}/{path}"]
968 repos --> issues["…/issues"]
969 issues --> issue["…/issues/{number}"]
970 repos --> pulls["…/pulls"]
971 pulls --> pull["…/pulls/{number}"]
972 repos --> releases["…/releases"]
973 releases --> release["…/releases/{tag}"]
974 repos --> analysis["…/analysis/{ref}"]
975 repos --> timeline["…/timeline"]
976 ```