# MuseHub MCP Reference > Protocol version: **2025-11-25** | Implementation: pure-Python async, no external MCP SDK 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. 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. --- ## Table of Contents 1. [Architecture](#architecture) 2. [Transports](#transports) 3. [Authentication](#authentication) 4. [Session Management](#session-management) 5. [Elicitation](#elicitation) 6. [Tools — 40 total](#tools) - [Read Tools (20)](#read-tools-20) - [Write Tools (22)](#write-tools-22) - [Elicitation-Powered Tools (5)](#elicitation-powered-tools-5) 7. [Resources — 29 total](#resources) - [Static Resources (12)](#static-resources-12) - [Templated Resources (17)](#templated-resources-17) 8. [Prompts — 10 total](#prompts) 9. [Error Handling](#error-handling) 10. [Usage Patterns](#usage-patterns) 11. [Architecture Diagrams](#architecture-diagrams) --- ## Architecture ``` MCP Client (Cursor, Claude Desktop, any SDK) │ ├─ HTTP POST /mcp (all client→server) ├─ HTTP GET /mcp (SSE push, server→client) ├─ HTTP DELETE /mcp (session termination) └─ stdio python -m musehub.mcp.stdio_server (local dev) │ musehub/api/routes/mcp.py ← Streamable HTTP transport (2025-11-25) │ musehub/mcp/dispatcher.py ← async JSON-RPC 2.0 engine │ ┌───────┼───────────────┬────────────────┐ │ │ │ │ tools/call resources/read prompts/get notifications/* │ │ │ │ Read executors Resource handlers Prompt Session/Elicitation (musehub_mcp_executor.py) (resources.py) assembler (session.py) Write executors (context.py) Elicitation tools (mcp/write_tools/elicitation_tools.py) │ AsyncSession → Postgres ``` 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. --- ## Transports ### HTTP Streamable — Full 2025-11-25 Transport #### `POST /mcp` The production transport. Accepts `application/json`. Returns `application/json` for most requests, or `text/event-stream` for elicitation-powered tool calls. ```http POST /mcp HTTP/1.1 Content-Type: application/json Authorization: MSign handle="..." ts=... sig="..." Mcp-Session-Id: ← required after initialize MCP-Protocol-Version: 2025-11-25 ← optional; validated if present {"jsonrpc":"2.0","id":1,"method":"tools/list"} ``` **Batch requests** — send a JSON array; responses are returned as an array in the same order (notifications are filtered out): ```http POST /mcp [ {"jsonrpc":"2.0","id":1,"method":"tools/list"}, {"jsonrpc":"2.0","id":2,"method":"resources/list"} ] ``` **Notifications** (no `id`) return `202 Accepted` with an empty body. #### `GET /mcp` — SSE Push Channel Persistent server-to-client event stream. Required for receiving elicitation requests and progress notifications outside of an active tool call. ```http GET /mcp HTTP/1.1 Accept: text/event-stream Mcp-Session-Id: Last-Event-ID: ← optional; triggers replay ``` Returns `text/event-stream`. Server pushes: - `notifications/progress` — tool progress updates - `elicitation/create` — server-initiated user input requests - `notifications/elicitation/complete` — URL-mode OAuth completion signals - `: heartbeat` — comment every 15 s to keep proxies alive #### `DELETE /mcp` — Session Termination ```http DELETE /mcp HTTP/1.1 Mcp-Session-Id: ``` Returns `200 OK`. Closes all open SSE streams and cancels pending elicitation Futures for the session. ### stdio — `python -m musehub.mcp.stdio_server` The local dev and Cursor IDE transport. Reads newline-delimited JSON from `stdin`, writes JSON-RPC responses to `stdout`, logs to `stderr`. **Cursor IDE integration** — create or update `.cursor/mcp.json` in your workspace: ```json { "mcpServers": { "musehub": { "command": "python", "args": ["-m", "musehub.mcp.stdio_server"], "cwd": "/path/to/musehub" } } } ``` The stdio server runs without auth (trusted local process). Write tools are available unconditionally. --- ## Authentication | Context | How | |---------|-----| | HTTP transport — read tools + public resources | No auth required | | HTTP transport — write / elicitation tools | `Authorization: MSign handle="..." ts=... sig="..."` | | HTTP transport — private repo resources | `Authorization: MSign handle="..." ts=... sig="..."` | | stdio transport | No auth (trusted process) | MuseHub uses Ed25519 / MSign request signing. Register your Ed25519 public key via `POST /api/auth/challenge` → `POST /api/auth/verify`. The `muse` CLI manages key registration and signs all requests automatically. The verified `handle` claim is used as the acting `user_id` for all write operations. Attempting a write tool without a valid MSign request returns a JSON-RPC error (`code: -32001`, `message: "Authentication required for write tools"`). --- ## Session Management Session management is required for elicitation and the GET /mcp SSE push channel. **Creating a session:** ```http POST /mcp {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{"elicitation":{"form":{},"url":{}}}}} ``` Response includes: ```http Mcp-Session-Id: ``` **Using the session:** include `Mcp-Session-Id` in all subsequent requests. Sessions expire after 1 hour of inactivity. **Ending a session:** `DELETE /mcp` with the `Mcp-Session-Id` header. **Security:** All requests are validated against an Origin allowlist (`localhost` always permitted; production: `musehub.ai`). Requests from unlisted Origins are rejected with `403 Forbidden`. --- ## Elicitation 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: ### Form Mode 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`. ``` Agent MuseHub MCP │ │ │ POST tools/call │ │ (musehub_review_proposal_interactive) │──────────────────────────►│ │ │ opens SSE stream │◄──────────────────────────│ │ SSE: elicitation/create │ │ {mode:"form", schema:{ │ │ dimension_focus, depth,│ │ reviewer_note, ...}} │ │◄──────────────────────────│ │ [user fills form] │ │ POST elicitation result │ │ {action:"accept", │ │ content:{dimension_focus│ │ :"harmonic",...}} │ │──────────────────────────►│ │ │ tool continues │ SSE: tools/call response │ │◄──────────────────────────│ ``` ### Elicitation Schemas MuseHub exposes two form schemas used by the interactive tools: | Schema key | Used by | Fields | |------------|---------|--------| | `proposal_review_focus` | `musehub_review_proposal_interactive` | `dimension_focus` (all/melodic/harmonic/rhythmic/structural/dynamic), `review_depth` (quick/standard/thorough), `check_harmonic_tension`, `check_rhythmic_consistency`, `reviewer_note` | | `release_metadata` | `musehub_create_release_interactive` | `tag`, `title`, `release_notes`, `is_prerelease`, `highlight` | --- ## Tools All 40 tools use `server_side: true`. The JSON-RPC envelope is always a success response — errors are represented inside the content block via `isError: true`. ### Repo identification: `repo_id` or `owner` + `slug` All repo-scoped tools accept either form. The dispatcher resolves `owner` + `slug` to a `repo_id` transparently — agents can use human-readable names without a prior lookup step: ```json { "repo_id": "abc-123-uuid" } // or equivalently: { "owner": "gabriel", "slug": "jazz-standards" } ``` ### Calling a tool ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "musehub_get_context", "arguments": { "owner": "gabriel", "slug": "jazz-standards" } } } ``` Response: ```json { "jsonrpc": "2.0", "id": 1, "result": { "content": [{ "type": "text", "text": "{\"name\":\"my-song\", ...}" }], "isError": false } } ``` --- ### Read Tools (21) #### `musehub_get_context` **Start here.** Full AI context document for a repo — domain plugin (scoped_id, dimensions, capabilities), branches, recent commits, and artifact inventory in a single call. Always call this before creating or modifying state. For computed analytics, follow up with `musehub_get_domain_insights`. For the full viewer payload, follow up with `musehub_get_view`. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | --- #### `musehub_list_branches` All branches with their head commit IDs and timestamps. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | --- #### `musehub_list_commits` Paginated commit history, newest first. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `branch` | string | no | Branch name filter | | `limit` | integer | no | Max commits (default 20) | --- #### `musehub_read_file` Metadata for a single artifact (MIDI, MP3, WebP, etc.) at a given commit. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `path` | string | yes | File path within the repo | | `commit_id` | string | no | Commit SHA (defaults to HEAD) | --- #### `musehub_search` Keyword/path search over commits and file paths within a repo. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `query` | string | yes | Search terms | | `mode` | string | no | `"path"` (default) or `"commit"` | --- #### `musehub_get_commit` Single commit detail with the full snapshot manifest (all file paths and content hashes at that point in history). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `commit_id` | string | yes | Commit SHA | --- #### `musehub_compare` Musical diff between two refs — returns per-dimension change scores (harmony, rhythm, groove, key, tempo) and a list of changed file paths. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `base_ref` | string | yes | Base branch, tag, or commit SHA | | `head_ref` | string | yes | Head branch, tag, or commit SHA | --- #### `musehub_list_issues` Issues with optional state, label, and assignee filters. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `state` | string | no | `"open"` (default) or `"closed"` | | `label` | string | no | Label name filter | | `assignee` | string | no | Assignee username filter | --- #### `musehub_get_issue` Single issue with its full comment thread. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `issue_number` | integer | yes | Issue number | --- #### `musehub_list_proposals` Proposals with optional state and base branch filters. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `state` | string | no | `"open"` (default), `"closed"`, or `"merged"` | | `base` | string | no | Target branch filter | --- #### `musehub_get_proposal` Single proposal with all inline comments and reviews. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `proposal_number` | integer | yes | Proposal number | --- #### `musehub_list_releases` All releases for a repo with asset counts and timestamps. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | --- #### `musehub_search_repos` Discover public repos by text query or musical attributes. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string | no | Text search query | | `key` | string | no | Musical key filter (e.g. `"C major"`) | | `tempo_min` | integer | no | Minimum BPM | | `tempo_max` | integer | no | Maximum BPM | | `tags` | array of strings | no | Tag filters | | `limit` | integer | no | Max results (default 20) | --- #### `musehub_list_domains` List all available domain plugins registered in MuseHub (e.g. MIDI, Genomics, Code). _No parameters required._ --- #### `musehub_get_domain` Full definition for a single domain plugin — scoped_id, version, dimension manifest, capabilities, and schema. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `domain_id` | string | yes | Domain plugin identifier (e.g. `"midi-v1"`) | --- #### `musehub_get_domain_insights` Computed analytics for a repo using its domain plugin — per-dimension scores, distribution stats, and trend data. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `ref` | string | no | Branch, tag, or commit SHA (defaults to HEAD) | --- #### `musehub_get_view` Full viewer payload — dimension slices, navigation strip, and the current state for each registered dimension. Use after `musehub_get_context` for the visual-layer detail. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `ref` | string | no | Branch, tag, or commit SHA (defaults to HEAD) | --- #### `musehub_whoami` Return the authenticated user's profile. Useful for confirming token identity before write operations. _No parameters required._ --- #### `musehub_list_labels` List all labels defined in a repository. Returns `label_id`, `name`, `color`, and `description` for each label. Use the `label_id` values with `musehub_update_label` and `musehub_delete_label`. No authentication required. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | --- #### `muse_pull` Pull latest commits from MuseHub into a local Muse working tree — equivalent of `muse pull` on the command line. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `branch` | string | no | Branch to pull (defaults to current) | --- #### `muse_remote` Inspect remote tracking configuration and get the clone URL for a repo — equivalent of `muse remote` on the command line. Returns `clone_url`, `clone_command`, and `visibility`. Pass `ref` to pin to a specific branch or tag. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `ref` | string | no | Branch or tag to reference in the clone command | --- ### Write Tools (22) > All write tools require a valid MSign request signature (`Authorization: MSign handle="..." ts=... sig="..."`) on the HTTP transport. #### `musehub_create_repo` Create a new repository. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `name` | string | yes | Repository name | | `owner` | string | yes | Owner username | | `owner_user_id` | string | yes | Owner user UUID | | `description` | string | no | Short description | | `visibility` | string | no | `"public"` (default) or `"private"` | | `tags` | array of strings | no | Initial tags | | `key_signature` | string | no | Musical key (e.g. `"G major"`) | | `tempo_bpm` | integer | no | Tempo in BPM | | `initialize` | boolean | no | Create initial commit (default `true`) | --- #### `musehub_create_issue` Open a new issue. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `title` | string | yes | Issue title | | `body` | string | no | Issue description (Markdown) | | `labels` | array of strings | no | Label names to apply | | `assignee_id` | string | no | Assignee user UUID | --- #### `musehub_update_issue` Update issue state or metadata. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Issue number | | `state` | string | no | `"open"` or `"closed"` | | `title` | string | no | New title | | `body` | string | no | New body | | `assignee_id` | string | no | New assignee UUID | | `labels` | array of strings | no | Replace label set | --- #### `musehub_create_issue_comment` Post a comment on an issue. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Issue number | | `body` | string | yes | Comment body (Markdown) | --- #### `musehub_create_proposal` Open a merge proposal. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `title` | string | yes | Proposal title | | `from_branch` | string | yes | Source branch | | `to_branch` | string | yes | Target branch | | `body` | string | no | Proposal description (Markdown) | --- #### `musehub_merge_proposal` Merge an open proposal. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `proposal_number` | integer | yes | Proposal number | | `merge_message` | string | no | Custom merge commit message | --- #### `musehub_create_proposal_comment` Post an inline comment on a proposal. Supports general, track-level, and beat-range comments — mirroring the musical diff view in the web UI. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `proposal_number` | integer | yes | Proposal number | | `body` | string | yes | Comment body (Markdown) | | `target_type` | string | no | `"general"` (default), `"track"`, `"region"`, or `"note"` | | `target_track` | string | no | Track name (when `target_type` is `"track"` or finer) | | `target_beat_start` | number | no | Start beat position | | `target_beat_end` | number | no | End beat position | --- #### `musehub_submit_proposal_review` Submit a formal review on a proposal. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `proposal_number` | integer | yes | Proposal number | | `state` | string | yes | `"approved"`, `"changes_requested"`, or `"commented"` | | `body` | string | no | Review summary | --- #### `musehub_create_release` Publish a release. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `tag` | string | yes | Tag name (e.g. `"v1.0.0"`) | | `title` | string | yes | Release title | | `body` | string | no | Release notes (Markdown) | | `commit_id` | string | no | Target commit SHA (defaults to HEAD) | | `is_prerelease` | boolean | no | Mark as pre-release (default `false`) | --- #### `musehub_create_label` Create a label scoped to a repository. Names must be unique within the repo; `color` must be a 7-character hex string starting with `#` (e.g. `"#d73a4a"`). Repos are pre-seeded with default labels (bug, enhancement, question, documentation, etc.) on creation. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `name` | string | yes | Label name (max 50 chars, unique per repo) | | `color` | string | yes | 7-char hex color starting with `#` (e.g. `"#d73a4a"`) | | `description` | string | no | Label description (max 200 chars) | --- #### `musehub_update_label` Partially update an existing label — rename it, change its colour, or update its description. Only the fields you provide are changed; omitted fields stay as-is. The new name must still be unique within the repository. Get `label_id` from `musehub_list_labels`. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `label_id` | string | yes | UUID of the label to update (from `musehub_list_labels`) | | `name` | string | no | New label name (max 50 chars, must be unique per repo) | | `color` | string | no | New 7-char hex color starting with `#` (e.g. `"#b60205"`) | | `description` | string | no | New description (max 200 chars; pass `""` to clear) | --- #### `musehub_delete_label` Permanently delete a label from a repository and remove it from every issue and proposal it is currently attached to. This operation is irreversible. Get `label_id` from `musehub_list_labels`. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `label_id` | string | yes | UUID of the label to delete (from `musehub_list_labels`) | --- #### `musehub_close_issue` Close an open issue. Idempotent — closing an already-closed issue returns the issue unchanged. Reverse with `musehub_reopen_issue`. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Per-repo issue number | --- #### `musehub_reopen_issue` Reopen a closed issue. Idempotent — reopening an already-open issue returns the issue unchanged. Reverse with `musehub_close_issue`. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Per-repo issue number | --- #### `musehub_assign_issue` Assign or unassign a collaborator on an issue. Pass `assignee=""` (empty string) to clear the current assignee. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Per-repo issue number | | `assignee` | string | yes | Username to assign, or empty string to unassign | --- #### `musehub_set_issue_labels` Bulk-replace the label list on an issue. The new list replaces all existing labels. Pass `labels=[]` to remove all labels. Use `musehub_remove_issue_label` to remove a single label without affecting others. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Per-repo issue number | | `labels` | array of strings | yes | Replacement label list (replaces all existing labels) | --- #### `musehub_remove_issue_label` Remove a single label from an issue. Idempotent — silently no-ops when the label is not present. Use `musehub_set_issue_labels` to replace the entire label list. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `issue_number` | integer | yes | Per-repo issue number | | `label` | string | yes | Label name to remove | --- #### `muse_push` Push a Muse mpack to MuseHub — equivalent of `muse push` on the command line. Accepts the full wire format: commits, snapshot manifests, and content-addressed objects in a single round-trip. Snapshots are stored idempotently — re-pushing an existing `snapshot_id` is a safe no-op. ```json { "name": "muse_push", "arguments": { "owner": "alice", "slug": "my-song", "branch": "main", "head_commit_id": "sha256:abc...", "commits": [ { "commit_id": "sha256:abc...", "parent_ids": ["sha256:parent..."], "message": "feat: add bridge section", "author": "alice", "timestamp": "2026-03-21T18:00:00Z", "snapshot_id": "sha256:snap..." } ], "snapshots": [ { "snapshot_id": "sha256:snap...", "manifest": { "tracks/piano.mid": "sha256:obj-piano...", "tracks/strings.mid": "sha256:obj-strings..." } } ], "objects": [ { "object_id": "sha256:obj-piano...", "path": "tracks/piano.mid", "size": 4096, "content_b64": "" } ] } } ``` **Fast-forward enforcement:** rejected with `HTTP 409 Conflict` if the push would create a non-linear history. Use `force: true` to override (destructive — use with care). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `branch` | string | yes | Target branch name | | `head_commit_id` | string | yes | SHA of the new branch tip | | `commits` | array | yes | List of `CommitInput` objects (see wire format) | | `snapshots` | array | no | List of `SnapshotInput` objects — `snapshot_id` + `manifest` dict | | `objects` | array | no | List of `ObjectInput` objects — content-addressed blobs | | `force` | boolean | no | Override fast-forward check (default: `false`) | --- #### `muse_config` Read or write per-repo Muse configuration values — equivalent of `muse config` on the command line. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | no | Repository UUID (or use `owner` + `slug`) | | `owner` | string | no | Owner username (use with `slug`) | | `slug` | string | no | Repository slug (use with `owner`) | | `key` | string | yes | Config key to read or write | | `value` | string | no | Value to set (omit to read the current value) | --- ### Elicitation-Powered Tools (5) > **Three execution paths — no session required for bypass or schema guide.** > > | Path | Requirements | Behaviour | > |------|-------------|-----------| > | **Elicitation** | Active session + elicitation capability declared | Interactive form / URL presented to user mid-call | > | **Bypass** | Supply bypass params (see each tool) | Returns result immediately; zero round-trips | > | **Schema guide** | No session, no bypass params | Returns `ok: true` with `mode: "schema_guide"` — a complete field guide for the next call | > > The bypass path makes all five tools usable in any headless agent, CI pipeline, or client that does not support MCP sessions. #### `musehub_review_proposal_interactive` _(form elicitation | bypass: `dimension`, `depth`)_ Deep musical proposal review, either interactively or from explicit parameters. **Elicitation path** — elicits: dimension focus, review depth, harmonic tension check, rhythmic consistency check, reviewer note. **Bypass path** — pass `dimension` and/or `depth` directly: ```json { "name": "musehub_review_proposal_interactive", "arguments": { "repo_id": "repo-uuid", "proposal_id": "proposal-uuid", "dimension": "harmonic", "depth": "thorough" } } ``` Either or both bypass params may be provided; missing values default to `"all"` and `"standard"` respectively. **Schema guide** (no session, no bypass params) — returns `dimension_options` and `depth_options` lists. **Returns:** per-dimension divergence scores, findings list (with harmonic tension and rhythmic checks), and a recommendation (APPROVE / REQUEST_CHANGES / COMMENT). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository UUID | | `proposal_id` | string | yes | Proposal UUID | | `dimension` | string | no | **Bypass:** one of `melodic`, `harmonic`, `rhythmic`, `structural`, `dynamic`, `all` | | `depth` | string | no | **Bypass:** one of `quick`, `standard`, `thorough` | --- #### `musehub_create_release_interactive` _(chained form + URL elicitation | bypass: `tag`)_ Two-phase interactive release creator, or direct release creation via bypass params. **Elicitation path:** 1. **Form:** collects tag, title, release notes, changelog highlight, and pre-release flag. 2. **URL (optional):** offers Spotify OAuth for immediate distribution. **Bypass path** — supply `tag` (required); `title` and `notes` are optional: ```json { "name": "musehub_create_release_interactive", "arguments": { "repo_id": "repo-uuid", "tag": "v1.2.0", "title": "Spring release", "notes": "New chord voicings, tempo map fixes." } } ``` **Schema guide** (no session, no `tag`) — returns field guide with required/optional labels. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `repo_id` | string | yes | Repository to create the release in | | `tag` | string | no | **Bypass:** semantic version tag (e.g. `v1.2.0`); triggers direct release creation | | `title` | string | no | **Bypass:** human-readable release title (defaults to `tag`) | | `notes` | string | no | **Bypass:** release notes / changelog body | --- ## Resources Resources are side-effect-free, cacheable, URI-addressable reads. All resources return `application/json`. They are read via the `resources/read` method. ### Listing resources ```json {"jsonrpc":"2.0","id":1,"method":"resources/list"} {"jsonrpc":"2.0","id":2,"method":"resources/templates/list"} ``` ### Reading a resource ```json { "jsonrpc": "2.0", "id": 1, "method": "resources/read", "params": { "uri": "musehub://trending" } } ``` Response: ```json { "jsonrpc": "2.0", "id": 1, "result": { "contents": [{ "uri": "musehub://trending", "mimeType": "application/json", "text": "[{\"repo_id\":\"...\",\"name\":\"my-song\",...}]" }] } } ``` --- ### Static Resources (12) #### `musehub://trending` Top 20 public repos ordered by star count. Anonymous-accessible. **Returns:** array of repo summaries with `repo_id`, `name`, `owner`, `slug`, `description`, `visibility`, `clone_url`, `created_at`. --- #### `musehub://me` Authenticated user's profile and their most recent 20 repos. Requires MSign auth. **Returns:** `{ "user_id", "username", "repos": [...] }` --- #### `musehub://me/notifications` Unread notifications for the authenticated user. Requires MSign auth. **Returns:** `{ "notifications": [{ "id", "event_type", "read", "created_at" }] }` --- #### `musehub://me/starred` Repos the authenticated user has starred. Requires MSign auth. **Returns:** `{ "starred": [{ "repo_id", "name", "owner", "slug", "starred_at" }] }` --- #### `musehub://me/feed` Activity feed for repos the authenticated user watches. Requires MSign auth. **Returns:** `{ "feed": [...] }` --- ### Templated Resources (17) 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. #### `musehub://repos/{owner}/{slug}` Repo overview: metadata, visibility, default branch, tag list, description. --- #### `musehub://repos/{owner}/{slug}/branches` All branches with their name, head commit ID, and last-updated timestamp. --- #### `musehub://repos/{owner}/{slug}/commits` 20 most recent commits on the default branch. Includes commit message, author, timestamp. --- #### `musehub://repos/{owner}/{slug}/commits/{commit_id}` Single commit with its full snapshot manifest (all file paths and content hashes at that point). --- #### `musehub://repos/{owner}/{slug}/tree/{ref}` File tree at a given ref. Returns all object paths and guessed MIME types. --- #### `musehub://repos/{owner}/{slug}/blob/{ref}/{path}` Metadata for a single file at a given ref: path, content hash, MIME type, size. --- #### `musehub://repos/{owner}/{slug}/issues` Open issues list with labels, assignees, and comment counts. --- #### `musehub://repos/{owner}/{slug}/issues/{number}` Single issue with its full comment thread. --- #### `musehub://repos/{owner}/{slug}/pulls` Open proposals with source/target branches and review counts. --- #### `musehub://repos/{owner}/{slug}/pulls/{number}` Single proposal with all inline comments and reviews (reviewer, state, body). --- #### `musehub://repos/{owner}/{slug}/releases` All releases ordered newest first: tag, title, body, asset count, timestamp. --- #### `musehub://repos/{owner}/{slug}/releases/{tag}` Single release matching a tag name, including the full release notes body. --- #### `musehub://repos/{owner}/{slug}/analysis/{ref}` Musical analysis at a given ref: key, tempo, time signature, per-dimension scores (harmony, rhythm, groove, dynamics, orchestration, …). --- #### `musehub://repos/{owner}/{slug}/timeline` Musical evolution timeline: commits, section events, and track events in chronological order. --- #### `musehub://users/{username}` User profile and their 20 most recent public repos. --- ## Prompts 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. ### Getting a prompt ```json { "jsonrpc": "2.0", "id": 1, "method": "prompts/get", "params": { "name": "musehub/orientation" } } ``` With arguments: ```json { "jsonrpc": "2.0", "id": 1, "method": "prompts/get", "params": { "name": "musehub/contribute", "arguments": { "repo_id": "abc123", "owner": "alice", "slug": "my-song" } } } ``` --- ### `musehub/orientation` **Arguments:** `caller_type` (optional: `"human"` or `"agent"`) The essential first read for any new agent or human. Explains MuseHub's model (repos, commits, branches, domain plugins, multidimensional state), the `musehub://` URI scheme, which tools to use for reads vs. writes, and how to authenticate. When `caller_type: "agent"` is passed, the response includes extended agent onboarding guidance — tool call sequencing, addressing scheme, and auth setup. --- ### `musehub/contribute` **Arguments:** `repo_id`, `owner`, `slug` End-to-end contribution workflow, including auth and push setup: 0. Confirm authentication and set up `muse remote` tracking 1. `musehub_get_context` — understand the repo 2. `musehub://repos/{owner}/{slug}/issues` — find open issues 3. `musehub_create_issue` — or create a new one 4. Make changes, push a commit via `muse_push` 5. `musehub_create_proposal` — open a proposal 6. `musehub_submit_proposal_review` — request review 7. `musehub_merge_proposal` — merge when approved --- ### `musehub/create` **Arguments:** `repo_id` Domain-agnostic creation workflow: 1. `musehub_get_context` — understand existing content and structure 2. `musehub://repos/{owner}/{slug}/analysis/{ref}` — study the domain-specific analysis 3. Create domain artifacts matching the repo's dimensional constraints 4. Push the commit via `muse_push` 5. Verify with `musehub_get_domain_insights` --- ### `musehub/review_proposaloposal` **Arguments:** `repo_id`, `proposal_id` Dimension-aware proposal review: get proposal → read domain insights → compare branches → submit review with dimension_ref-anchored comments. 1. `musehub_get_proposal` — read the proposal metadata 2. `musehub_compare` — get per-dimension diff scores 3. `musehub_create_proposal_comment` — post dimension-anchored comments 4. `musehub_submit_proposal_review` — approve or request changes --- ### `musehub/issue_triage` **Arguments:** `repo_id` Triage open issues: list → label → assign → link to milestones. 1. `musehub_list_issues` — list open issues 2. Categorise by type (bug, feature, discussion) 3. `musehub_create_label` — create missing labels 4. `musehub_update_issue` — apply labels, assign, close duplicates --- ### `musehub/release_prep` **Arguments:** `repo_id` Prepare a release: check merged proposals → write release notes → create release with version tag. 1. `musehub_list_proposals` — find merged proposals since the last release 2. `musehub_list_releases` — check the latest release tag 3. `musehub_get_domain_insights` — summarise domain-specific changes 4. Draft release notes (Markdown) 5. `musehub_create_release` — publish --- ### `musehub/onboard` _(MCP 2025-11-25)_ **Arguments:** `username` Interactive creator onboarding (MCP 2025-11-25 elicitation-aware). Guides a new MuseHub creator through: profile setup → domain selection (via `musehub_list_domains`) → first repo creation → initial state scaffold → optional cloud integration. Requires an active session with elicitation capability. --- ### `musehub/safe-to-merge` **Arguments:** `repo_id`, `proposal_id` Pre-merge safety audit for a merge proposal. Runs: risk score → symbol diff → breakage check → blast radius → CI status → reviews. Produces a structured merge recommendation: APPROVE, APPROVE WITH CAUTION, or BLOCK. 1. `musehub_proposal_risk` — overall risk score 2. `musehub_proposal_symbol_diff` — symbol-level changes 3. `musehub_proposal_breakage` — structural breakage check --- ### `musehub/pre-release-audit` **Arguments:** `repo_id` Full repository health audit before cutting a release. Runs: health score → hotspots → dead code → blast risk → open proposals → recent breakages. Produces a structured GO / GO WITH CAUTION / NO-GO release recommendation. 1. `musehub_intel_health_score` — overall health 2. `musehub_intel_hotspots` — high-churn symbols 3. `musehub_intel_dead` — dead code detection 4. `musehub_intel_blast_risk` — highest-impact symbols --- ### `musehub/agent-onboarding` **Arguments:** `repo_id`, `agent_id`, `queue` Onboarding guide for a new agent joining a multi-agent swarm on a MuseHub repository. Covers: authenticate → get context → survey swarm state → reserve symbols → claim task → commit with provenance → complete task. Teaches the read-reserve-edit-commit cycle and how to avoid conflicts with concurrent agents. 1. `musehub_coord_swarm` — survey active agents 2. `musehub_coord_tasks` — see available work 3. `musehub_coord_claim_task` — claim a task 4. `musehub_coord_reserve` — reserve symbols before editing --- ### `musehub/symbol-investigation` **Arguments:** `repo_id`, `address` Deep-dive symbol investigation workflow: find a symbol → read its body → compute blast radius → trace provenance → surface co-change partners → check for active reservations. Produces a structured investigation report suitable for deciding whether to edit the symbol or delegate to another agent. 1. `musehub_get_symbol` — read symbol body and metadata 2. `musehub_symbol_impact` — compute blast radius 3. `musehub_coord_reservations` — check for active reservations --- ## Error Handling ### JSON-RPC error codes | Code | Meaning | |------|---------| | `-32700` | Parse error — request body is not valid JSON | | `-32600` | Invalid request — not an object or array | | `-32601` | Method not found | | `-32602` | Invalid params — required argument missing or wrong type | | `-32603` | Internal error — unexpected server exception | | `-32001` | Authentication required — write tool called without a valid MSign request | ### Tool errors Tool execution errors are not JSON-RPC errors. The envelope is always a success response; the error is signalled inside the result: ```json { "result": { "content": [{ "type": "text", "text": "repo not found: abc123" }], "isError": true } } ``` --- ## Usage Patterns ### Pattern 1: Discover and explore ``` 1. resources/read musehub://trending → pick a repo 2. resources/read musehub://repos/{owner}/{slug} → orientation 3. tools/call musehub_get_context → full AI context 4. resources/read musehub://repos/{owner}/{slug}/analysis/{ref} → musical detail ``` ### Pattern 2: Fix a bug, open a proposal ``` 1. tools/call musehub_list_issues { owner, slug, state: "open" } 2. tools/call musehub_get_issue { owner, slug, issue_number } 3. tools/call musehub_get_context { owner, slug } 4. tools/call musehub_read_file { owner, slug, path } 5. -- compose fix, push commit via muse_push -- 6. tools/call musehub_create_proposal { owner, slug, title, from_branch, to_branch } ``` ### Pattern 3: Full musical proposal review (elicitation-powered) ``` 1. tools/call musehub_review_proposal_interactive { repo_id, proposal_id } → elicitation: "Focus on harmonic divergence, thorough depth" → returns: per-dimension scores, findings, APPROVE/REQUEST_CHANGES recommendation ``` Or stateless: ``` 1. tools/call musehub_get_proposal { repo_id, proposal_id } 2. tools/call musehub_compare { repo_id, base_ref, head_ref } 3. tools/call musehub_create_proposal_comment { repo_id, proposal_id, body, target_type: "track", ... } 4. tools/call musehub_submit_proposal_review { repo_id, proposal_id, event: "APPROVE" } ``` ### Pattern 4: Publish a release (elicitation-powered) ``` 1. tools/call musehub_create_release_interactive { repo_id } → elicitation (form): tag, title, release notes, highlight → creates release + returns release record ``` Or stateless: ``` 1. tools/call musehub_list_releases { owner, slug } 2. tools/call musehub_list_proposals { owner, slug, state: "closed" } 3. tools/call musehub_get_domain_insights { owner, slug } 4. tools/call musehub_create_release { owner, slug, tag: "v1.2.0", title: "Spring Drop", body: "## What changed\n..." } ``` --- ## Architecture Diagrams ### Request flow ```mermaid flowchart TD subgraph transports [Transports — MCP 2025-11-25] POST["POST /mcp\nJSON + SSE stream"] GET["GET /mcp\nSSE push channel"] DEL["DELETE /mcp\nSession termination"] stdio["stdio\npython -m musehub.mcp.stdio_server"] end subgraph session [Session Layer] SID["Mcp-Session-Id"] ORIGIN["Origin validation"] SSE_Q["asyncio.Queue\nSSE queues"] FUTURES["asyncio.Future\nelicitation registry"] end subgraph dispatcher [musehub/mcp/dispatcher.py] D["handle_request()"] D --> INIT["initialize"] D --> TL["tools/list"] D --> TC["tools/call"] D --> RL["resources/list"] D --> RR["resources/read"] D --> PL["prompts/list"] D --> PG["prompts/get"] D --> NC["notifications/cancelled"] D --> NEC["notifications/elicitation/complete"] end subgraph execution [Execution Layer] READ["Read executors\nmusehub_mcp_executor.py"] WRITE["Write executors\nmcp/write_tools/"] ELICIT["Elicitation tools\nelicitation_tools.py"] CTX["ToolCallContext\ncontext.py"] RES["Resource handlers\nresources.py"] PROMPTS["Prompt assembler\nprompts.py"] end POST --> ORIGIN POST --> SID SID --> D GET --> SSE_Q DEL --> SID stdio --> D TC --> READ TC --> WRITE TC --> ELICIT ELICIT --> CTX CTX --> SSE_Q CTX --> FUTURES RR --> RES PG --> PROMPTS NC --> FUTURES NEC --> FUTURES READ --> DB[("AsyncSession / Postgres")] WRITE --> DB RES --> DB ``` ### Tool catalogue structure ```mermaid classDiagram class MUSEHUB_READ_TOOLS { <> musehub_set_context musehub_get_context musehub_list_branches musehub_list_commits musehub_read_file musehub_search musehub_get_commit musehub_compare musehub_list_issues musehub_get_issue musehub_list_proposals musehub_get_proposal musehub_proposal_risk musehub_proposal_symbol_diff musehub_proposal_breakage musehub_list_releases musehub_search_repos musehub_list_domains musehub_get_domain musehub_get_domain_insights musehub_get_view musehub_whoami musehub_get_prompt musehub_list_symbols musehub_get_symbol musehub_symbol_impact musehub_symbol_clones musehub_intel_index_status musehub_intel_health_score musehub_intel_hotspots musehub_intel_dead musehub_intel_blast_risk musehub_coord_swarm musehub_coord_reservations musehub_coord_check_conflicts musehub_coord_tasks musehub_cross_repo_impact musehub_workspace_intel } class MUSEHUB_CLI_TOOLS { <> muse_pull muse_remote muse_push muse_config } class MUSEHUB_WRITE_TOOLS { <> musehub_create_repo musehub_create_issue musehub_update_issue musehub_create_issue_comment musehub_create_proposal musehub_merge_proposal musehub_create_proposal_comment musehub_submit_proposal_review musehub_create_release musehub_create_label musehub_publish_domain musehub_agent_notify musehub_agent_broadcast musehub_coord_claim_task musehub_coord_complete_task musehub_coord_fail_task musehub_coord_extend_reservation musehub_coord_reserve musehub_coord_release musehub_coord_enqueue } class MUSEHUB_ELICITATION_TOOLS { <> musehub_review_proposal_interactive musehub_create_release_interactive } class MCPDispatcher { +handle_request(raw, user_id, session) +handle_batch(raw, user_id, session) } MCPDispatcher ..> MUSEHUB_READ_TOOLS : routes read calls MCPDispatcher ..> MUSEHUB_CLI_TOOLS : routes Muse VCS calls MCPDispatcher ..> MUSEHUB_WRITE_TOOLS : routes write calls (MSign auth required) MCPDispatcher ..> MUSEHUB_ELICITATION_TOOLS : routes interactive calls (session required) ``` ### Resource URI hierarchy ```mermaid flowchart TD root["musehub://"] root --> trending["trending"] root --> me["me"] root --> repos["repos/{owner}/{slug}"] root --> users["users/{username}"] me --> notifications["me/notifications"] me --> starred["me/starred"] me --> feed["me/feed"] repos --> branches["…/branches"] repos --> commits["…/commits"] commits --> commit["…/commits/{commit_id}"] repos --> tree["…/tree/{ref}"] repos --> blob["…/blob/{ref}/{path}"] repos --> issues["…/issues"] issues --> issue["…/issues/{number}"] repos --> pulls["…/pulls"] pulls --> pull["…/pulls/{number}"] repos --> releases["…/releases"] releases --> release["…/releases/{tag}"] repos --> analysis["…/analysis/{ref}"] repos --> timeline["…/timeline"] ``` ### Elicitation sequence (form mode) ```mermaid sequenceDiagram participant Agent participant MCP as POST /mcp participant Session as Session Store participant Tool as Elicitation Tool Agent->>MCP: POST initialize {capabilities: {elicitation: {form:{}, url:{}}}} MCP-->>Agent: 200 OK, Mcp-Session-Id: abc123 Agent->>MCP: GET /mcp (Accept: text/event-stream, Mcp-Session-Id: abc123) MCP-->>Agent: 200 text/event-stream (SSE channel open) Agent->>MCP: POST tools/call musehub_review_proposal_interactive {repo_id, proposal_id} Note over MCP: tool needs elicitation → SSE response MCP->>Session: create_pending_elicitation("elicit-1") MCP-->>Agent: 200 text/event-stream (POST SSE open) MCP-->>Agent: SSE: elicitation/create {mode:"form", schema:{dimension_focus,review_depth,...}} Note over Agent: Shows form UI to user Agent->>MCP: POST {jsonrpc:"2.0", id:"elicit-1", result:{action:"accept", content:{dimension_focus:"harmonic",...}}} MCP->>Session: resolve_elicitation("elicit-1", {action:"accept", content:...}) MCP-->>Agent: 202 Accepted Note over Tool: Future resolved, tool continues MCP-->>Agent: SSE: tools/call response {scores: {...}, recommendation: "APPROVE"} Note over MCP: SSE stream closes ```