mcp-music-studio 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Forked from [`@modelcontextprotocol/server-sheet-music`](https://github.com/mode
8
8
 
9
9
  - **8 style presets** — rock, jazz, bossa, waltz, march, reggae, folk, classical. One parameter adds drums + bass + chord accompaniment.
10
10
  - **30 instruments** — selectable from UI or via tool parameter, with fuzzy matching
11
- - **Browser fallback** — `openInBrowser: true` launches a standalone player for CLI environments (Claude Code, Codex, Gemini CLI) that don't support ext-apps UI
11
+ - **Three rendering modes** — ext-apps inline UI for Claude Desktop/VS Code, browser fallback for CLI environments, configurable via `--render-mode`
12
12
  - **`get-music-guide` tool** — on-demand reference for AI systems (instruments, drums, ABC syntax, arrangements, genre templates, MIDI directives)
13
13
  - **7 `music://guide/*` resources** — same content for resource-capable clients
14
14
  - **Note highlighting** — currently playing notes light up during playback
@@ -148,7 +148,6 @@ Creates and plays music with visual sheet music and multi-instrument audio.
148
148
  | `tempo` | number? | BPM (40-240) |
149
149
  | `swing` | number? | Swing feel (0-100) |
150
150
  | `transpose` | number? | Semitones (-12 to 12) |
151
- | `openInBrowser` | boolean? | Open standalone browser player (for CLI environments without UI) |
152
151
 
153
152
  **Example — jazz arrangement:**
154
153
  ```json
@@ -174,6 +173,31 @@ Returns reference material for composition. Topics:
174
173
  | `styles` | What each style preset does and when to use it |
175
174
  | `midi-directives` | Full `%%MIDI` reference for ABCJS |
176
175
 
176
+ ## Render Modes
177
+
178
+ The server auto-detects whether the client supports ext-apps UI. For clients that don't, use `--render-mode` to control how music is delivered:
179
+
180
+ | Mode | Flag | Behavior |
181
+ |------|------|----------|
182
+ | `auto` | (default) | Inline ext-apps UI for Claude Desktop, VS Code |
183
+ | `browser` | `--render-mode browser` | Saves HTML player and opens in system browser |
184
+ | `html` | `--render-mode html` | Returns HTML as embedded resource in response |
185
+
186
+ Use `--output-dir` to control where HTML player files are saved (default: `~/Desktop/mcp-music-studio`).
187
+
188
+ **Example — Cherry Studio, CLI environments, or other non-ext-apps clients:**
189
+
190
+ ```json
191
+ {
192
+ "mcpServers": {
193
+ "music-studio": {
194
+ "command": "npx",
195
+ "args": ["-y", "mcp-music-studio", "--stdio", "--render-mode", "browser", "--output-dir", "/path/to/output"]
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
177
201
  ## Development
178
202
 
179
203
  ```bash
@@ -0,0 +1,2 @@
1
+ wrangler.json
2
+ .dev.vars
package/dist/index.js CHANGED
@@ -19630,7 +19630,7 @@ var require_is_promise = __commonJS((exports, module) => {
19630
19630
  }
19631
19631
  });
19632
19632
 
19633
- // node_modules/path-to-regexp/dist/index.js
19633
+ // node_modules/router/node_modules/path-to-regexp/dist/index.js
19634
19634
  var require_dist = __commonJS((exports) => {
19635
19635
  Object.defineProperty(exports, "__esModule", { value: true });
19636
19636
  exports.PathError = exports.TokenData = undefined;
@@ -30624,13 +30624,13 @@ async function startStreamableHTTPServer(createServer2) {
30624
30624
  }
30625
30625
  }
30626
30626
  });
30627
- const httpServer = app.listen(port, (err) => {
30628
- if (err) {
30629
- console.error("Failed to start server:", err);
30630
- process.exit(1);
30631
- }
30627
+ const httpServer = app.listen(port, () => {
30632
30628
  console.log(`MCP server listening on http://localhost:${port}/mcp`);
30633
30629
  });
30630
+ httpServer.on("error", (err) => {
30631
+ console.error("Failed to start server:", err);
30632
+ process.exit(1);
30633
+ });
30634
30634
  const shutdown = () => {
30635
30635
  console.log(`
30636
30636
  Shutting down...`);
@@ -30642,11 +30642,38 @@ Shutting down...`);
30642
30642
  async function startStdioServer(createServer2) {
30643
30643
  await createServer2().connect(new StdioServerTransport);
30644
30644
  }
30645
+ function parseArg(name) {
30646
+ for (let i = 0;i < process.argv.length; i++) {
30647
+ const arg = process.argv[i].trim();
30648
+ if (arg === name && i + 1 < process.argv.length)
30649
+ return process.argv[i + 1].trim();
30650
+ if (arg.startsWith(name + "="))
30651
+ return arg.slice(name.length + 1).trim();
30652
+ if (arg.startsWith(name + " "))
30653
+ return arg.slice(name.length).trim();
30654
+ }
30655
+ return;
30656
+ }
30657
+ function parseRenderMode() {
30658
+ const val = parseArg("--render-mode");
30659
+ if (!val)
30660
+ return "auto";
30661
+ if (val === "html" || val === "browser" || val === "auto")
30662
+ return val;
30663
+ console.error(`Unknown render mode "${val}", using "auto"`);
30664
+ return "auto";
30665
+ }
30666
+ function parseOutputDir() {
30667
+ return parseArg("--output-dir");
30668
+ }
30645
30669
  async function main() {
30670
+ const defaultRenderMode = parseRenderMode();
30671
+ const outputDir = parseOutputDir();
30672
+ const factory = () => createServer({ defaultRenderMode, outputDir });
30646
30673
  if (process.argv.includes("--stdio")) {
30647
- await startStdioServer(createServer);
30674
+ await startStdioServer(factory);
30648
30675
  } else {
30649
- await startStreamableHTTPServer(createServer);
30676
+ await startStreamableHTTPServer(factory);
30650
30677
  }
30651
30678
  }
30652
30679
  main().catch((e) => {