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 +26 -2
- package/dist/.assetsignore +2 -0
- package/dist/index.js +35 -8
- package/dist/mcp-app.html +13 -13
- package/dist/server.d.ts +14 -1
- package/dist/server.js +1270 -55
- package/dist/src/abc-guide.d.ts +4 -0
- package/dist/src/browser-fallback.d.ts +1 -1
- package/dist/src/strudel-browser-fallback.d.ts +8 -0
- package/dist/src/strudel-guide.d.ts +3 -0
- package/dist/strudel-app.html +109 -0
- package/dist/wrangler.json +1 -0
- package/package.json +13 -5
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
|
-
- **
|
|
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
|
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, (
|
|
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(
|
|
30674
|
+
await startStdioServer(factory);
|
|
30648
30675
|
} else {
|
|
30649
|
-
await startStreamableHTTPServer(
|
|
30676
|
+
await startStreamableHTTPServer(factory);
|
|
30650
30677
|
}
|
|
30651
30678
|
}
|
|
30652
30679
|
main().catch((e) => {
|