mstro-app 0.1.47
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/LICENSE +21 -0
- package/README.md +177 -0
- package/bin/commands/config.js +145 -0
- package/bin/commands/login.js +313 -0
- package/bin/commands/logout.js +75 -0
- package/bin/commands/status.js +197 -0
- package/bin/commands/whoami.js +161 -0
- package/bin/configure-claude.js +298 -0
- package/bin/mstro.js +581 -0
- package/bin/postinstall.js +45 -0
- package/bin/release.sh +110 -0
- package/dist/server/cli/headless/claude-invoker.d.ts +17 -0
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker.js +311 -0
- package/dist/server/cli/headless/claude-invoker.js.map +1 -0
- package/dist/server/cli/headless/index.d.ts +13 -0
- package/dist/server/cli/headless/index.d.ts.map +1 -0
- package/dist/server/cli/headless/index.js +10 -0
- package/dist/server/cli/headless/index.js.map +1 -0
- package/dist/server/cli/headless/mcp-config.d.ts +11 -0
- package/dist/server/cli/headless/mcp-config.d.ts.map +1 -0
- package/dist/server/cli/headless/mcp-config.js +76 -0
- package/dist/server/cli/headless/mcp-config.js.map +1 -0
- package/dist/server/cli/headless/output-utils.d.ts +33 -0
- package/dist/server/cli/headless/output-utils.d.ts.map +1 -0
- package/dist/server/cli/headless/output-utils.js +101 -0
- package/dist/server/cli/headless/output-utils.js.map +1 -0
- package/dist/server/cli/headless/prompt-utils.d.ts +21 -0
- package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -0
- package/dist/server/cli/headless/prompt-utils.js +84 -0
- package/dist/server/cli/headless/prompt-utils.js.map +1 -0
- package/dist/server/cli/headless/runner.d.ts +24 -0
- package/dist/server/cli/headless/runner.d.ts.map +1 -0
- package/dist/server/cli/headless/runner.js +99 -0
- package/dist/server/cli/headless/runner.js.map +1 -0
- package/dist/server/cli/headless/types.d.ts +106 -0
- package/dist/server/cli/headless/types.d.ts.map +1 -0
- package/dist/server/cli/headless/types.js +4 -0
- package/dist/server/cli/headless/types.js.map +1 -0
- package/dist/server/cli/improvisation-session-manager.d.ts +155 -0
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -0
- package/dist/server/cli/improvisation-session-manager.js +415 -0
- package/dist/server/cli/improvisation-session-manager.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +386 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mcp/bouncer-cli.d.ts +3 -0
- package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-cli.js +99 -0
- package/dist/server/mcp/bouncer-cli.js.map +1 -0
- package/dist/server/mcp/bouncer-integration.d.ts +36 -0
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-integration.js +301 -0
- package/dist/server/mcp/bouncer-integration.js.map +1 -0
- package/dist/server/mcp/security-audit.d.ts +52 -0
- package/dist/server/mcp/security-audit.d.ts.map +1 -0
- package/dist/server/mcp/security-audit.js +118 -0
- package/dist/server/mcp/security-audit.js.map +1 -0
- package/dist/server/mcp/security-patterns.d.ts +73 -0
- package/dist/server/mcp/security-patterns.d.ts.map +1 -0
- package/dist/server/mcp/security-patterns.js +247 -0
- package/dist/server/mcp/security-patterns.js.map +1 -0
- package/dist/server/mcp/server.d.ts +3 -0
- package/dist/server/mcp/server.d.ts.map +1 -0
- package/dist/server/mcp/server.js +146 -0
- package/dist/server/mcp/server.js.map +1 -0
- package/dist/server/routes/files.d.ts +9 -0
- package/dist/server/routes/files.d.ts.map +1 -0
- package/dist/server/routes/files.js +24 -0
- package/dist/server/routes/files.js.map +1 -0
- package/dist/server/routes/improvise.d.ts +3 -0
- package/dist/server/routes/improvise.d.ts.map +1 -0
- package/dist/server/routes/improvise.js +72 -0
- package/dist/server/routes/improvise.js.map +1 -0
- package/dist/server/routes/index.d.ts +10 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +12 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/instances.d.ts +10 -0
- package/dist/server/routes/instances.d.ts.map +1 -0
- package/dist/server/routes/instances.js +47 -0
- package/dist/server/routes/instances.js.map +1 -0
- package/dist/server/routes/notifications.d.ts +3 -0
- package/dist/server/routes/notifications.d.ts.map +1 -0
- package/dist/server/routes/notifications.js +136 -0
- package/dist/server/routes/notifications.js.map +1 -0
- package/dist/server/services/analytics.d.ts +56 -0
- package/dist/server/services/analytics.d.ts.map +1 -0
- package/dist/server/services/analytics.js +240 -0
- package/dist/server/services/analytics.js.map +1 -0
- package/dist/server/services/auth.d.ts +26 -0
- package/dist/server/services/auth.d.ts.map +1 -0
- package/dist/server/services/auth.js +71 -0
- package/dist/server/services/auth.js.map +1 -0
- package/dist/server/services/client-id.d.ts +10 -0
- package/dist/server/services/client-id.d.ts.map +1 -0
- package/dist/server/services/client-id.js +61 -0
- package/dist/server/services/client-id.js.map +1 -0
- package/dist/server/services/credentials.d.ts +39 -0
- package/dist/server/services/credentials.d.ts.map +1 -0
- package/dist/server/services/credentials.js +110 -0
- package/dist/server/services/credentials.js.map +1 -0
- package/dist/server/services/files.d.ts +119 -0
- package/dist/server/services/files.d.ts.map +1 -0
- package/dist/server/services/files.js +560 -0
- package/dist/server/services/files.js.map +1 -0
- package/dist/server/services/instances.d.ts +52 -0
- package/dist/server/services/instances.d.ts.map +1 -0
- package/dist/server/services/instances.js +241 -0
- package/dist/server/services/instances.js.map +1 -0
- package/dist/server/services/pathUtils.d.ts +47 -0
- package/dist/server/services/pathUtils.d.ts.map +1 -0
- package/dist/server/services/pathUtils.js +124 -0
- package/dist/server/services/pathUtils.js.map +1 -0
- package/dist/server/services/platform.d.ts +72 -0
- package/dist/server/services/platform.d.ts.map +1 -0
- package/dist/server/services/platform.js +368 -0
- package/dist/server/services/platform.js.map +1 -0
- package/dist/server/services/sentry.d.ts +5 -0
- package/dist/server/services/sentry.d.ts.map +1 -0
- package/dist/server/services/sentry.js +71 -0
- package/dist/server/services/sentry.js.map +1 -0
- package/dist/server/services/terminal/pty-manager.d.ts +149 -0
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -0
- package/dist/server/services/terminal/pty-manager.js +377 -0
- package/dist/server/services/terminal/pty-manager.js.map +1 -0
- package/dist/server/services/terminal/tmux-manager.d.ts +82 -0
- package/dist/server/services/terminal/tmux-manager.d.ts.map +1 -0
- package/dist/server/services/terminal/tmux-manager.js +352 -0
- package/dist/server/services/terminal/tmux-manager.js.map +1 -0
- package/dist/server/services/websocket/autocomplete.d.ts +50 -0
- package/dist/server/services/websocket/autocomplete.d.ts.map +1 -0
- package/dist/server/services/websocket/autocomplete.js +361 -0
- package/dist/server/services/websocket/autocomplete.js.map +1 -0
- package/dist/server/services/websocket/file-utils.d.ts +44 -0
- package/dist/server/services/websocket/file-utils.d.ts.map +1 -0
- package/dist/server/services/websocket/file-utils.js +272 -0
- package/dist/server/services/websocket/file-utils.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts +246 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -0
- package/dist/server/services/websocket/handler.js +1771 -0
- package/dist/server/services/websocket/handler.js.map +1 -0
- package/dist/server/services/websocket/index.d.ts +11 -0
- package/dist/server/services/websocket/index.d.ts.map +1 -0
- package/dist/server/services/websocket/index.js +14 -0
- package/dist/server/services/websocket/index.js.map +1 -0
- package/dist/server/services/websocket/types.d.ts +214 -0
- package/dist/server/services/websocket/types.d.ts.map +1 -0
- package/dist/server/services/websocket/types.js +4 -0
- package/dist/server/services/websocket/types.js.map +1 -0
- package/dist/server/utils/agent-manager.d.ts +69 -0
- package/dist/server/utils/agent-manager.d.ts.map +1 -0
- package/dist/server/utils/agent-manager.js +269 -0
- package/dist/server/utils/agent-manager.js.map +1 -0
- package/dist/server/utils/paths.d.ts +25 -0
- package/dist/server/utils/paths.d.ts.map +1 -0
- package/dist/server/utils/paths.js +38 -0
- package/dist/server/utils/paths.js.map +1 -0
- package/dist/server/utils/port-manager.d.ts +10 -0
- package/dist/server/utils/port-manager.d.ts.map +1 -0
- package/dist/server/utils/port-manager.js +60 -0
- package/dist/server/utils/port-manager.js.map +1 -0
- package/dist/server/utils/port.d.ts +26 -0
- package/dist/server/utils/port.d.ts.map +1 -0
- package/dist/server/utils/port.js +83 -0
- package/dist/server/utils/port.js.map +1 -0
- package/hooks/bouncer.sh +138 -0
- package/package.json +74 -0
- package/server/README.md +191 -0
- package/server/cli/headless/claude-invoker.ts +415 -0
- package/server/cli/headless/index.ts +39 -0
- package/server/cli/headless/mcp-config.ts +87 -0
- package/server/cli/headless/output-utils.ts +109 -0
- package/server/cli/headless/prompt-utils.ts +108 -0
- package/server/cli/headless/runner.ts +133 -0
- package/server/cli/headless/types.ts +118 -0
- package/server/cli/improvisation-session-manager.ts +531 -0
- package/server/index.ts +456 -0
- package/server/mcp/README.md +122 -0
- package/server/mcp/bouncer-cli.ts +127 -0
- package/server/mcp/bouncer-integration.ts +430 -0
- package/server/mcp/security-audit.ts +180 -0
- package/server/mcp/security-patterns.ts +290 -0
- package/server/mcp/server.ts +174 -0
- package/server/routes/files.ts +29 -0
- package/server/routes/improvise.ts +82 -0
- package/server/routes/index.ts +13 -0
- package/server/routes/instances.ts +54 -0
- package/server/routes/notifications.ts +158 -0
- package/server/services/analytics.ts +277 -0
- package/server/services/auth.ts +80 -0
- package/server/services/client-id.ts +68 -0
- package/server/services/credentials.ts +134 -0
- package/server/services/files.ts +710 -0
- package/server/services/instances.ts +275 -0
- package/server/services/pathUtils.ts +158 -0
- package/server/services/platform.test.ts +1314 -0
- package/server/services/platform.ts +435 -0
- package/server/services/sentry.ts +81 -0
- package/server/services/terminal/pty-manager.ts +464 -0
- package/server/services/terminal/tmux-manager.ts +426 -0
- package/server/services/websocket/autocomplete.ts +438 -0
- package/server/services/websocket/file-utils.ts +305 -0
- package/server/services/websocket/handler.test.ts +20 -0
- package/server/services/websocket/handler.ts +2047 -0
- package/server/services/websocket/index.ts +40 -0
- package/server/services/websocket/types.ts +339 -0
- package/server/tsconfig.json +19 -0
- package/server/utils/agent-manager.ts +323 -0
- package/server/utils/paths.ts +45 -0
- package/server/utils/port-manager.ts +70 -0
- package/server/utils/port.ts +102 -0
package/hooks/bouncer.sh
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License. See LICENSE file for details.
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# Mstro Bouncer Gate - Claude Code Hook
|
|
7
|
+
#
|
|
8
|
+
# This hook intercepts Claude Code tool calls and routes them through
|
|
9
|
+
# the Mstro bouncer for security analysis before execution.
|
|
10
|
+
#
|
|
11
|
+
# Installation:
|
|
12
|
+
# Run: npx mstro --configure-hooks
|
|
13
|
+
#
|
|
14
|
+
# Dependencies: Node.js (no jq or bun required)
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
# Configuration - MSTRO_BOUNCER_CLI is set by configure-claude.js
|
|
20
|
+
BOUNCER_CLI="${MSTRO_BOUNCER_CLI:-}"
|
|
21
|
+
BOUNCER_TIMEOUT="${BOUNCER_TIMEOUT:-10}"
|
|
22
|
+
BOUNCER_LOG="${BOUNCER_LOG:-$HOME/.claude/logs/bouncer.log}"
|
|
23
|
+
|
|
24
|
+
# Ensure log directory exists
|
|
25
|
+
mkdir -p "$(dirname "$BOUNCER_LOG")"
|
|
26
|
+
|
|
27
|
+
# Read hook input from stdin (JSON format from Claude Code)
|
|
28
|
+
INPUT=$(cat)
|
|
29
|
+
|
|
30
|
+
# Use Node.js inline to parse JSON and handle logic (eliminates jq dependency)
|
|
31
|
+
RESULT=$(node --input-type=module -e "
|
|
32
|
+
import { spawn } from 'child_process';
|
|
33
|
+
import { appendFileSync } from 'fs';
|
|
34
|
+
|
|
35
|
+
const input = JSON.parse(process.argv[1]);
|
|
36
|
+
const bouncerCli = process.argv[2];
|
|
37
|
+
const timeout = parseInt(process.argv[3], 10) * 1000;
|
|
38
|
+
const logFile = process.argv[4];
|
|
39
|
+
|
|
40
|
+
const toolName = input.tool_name || input.toolName || 'unknown';
|
|
41
|
+
const toolInput = input.input || input.toolInput || {};
|
|
42
|
+
|
|
43
|
+
function log(msg) {
|
|
44
|
+
const timestamp = new Date().toISOString();
|
|
45
|
+
appendFileSync(logFile, \`[\${timestamp}] \${msg}\n\`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function output(decision, reason) {
|
|
49
|
+
console.log(JSON.stringify({ decision, reason }));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Quick path for read-only operations
|
|
53
|
+
const readOnlyOps = ['Read', 'Glob', 'Grep', 'Search', 'List', 'WebFetch', 'WebSearch'];
|
|
54
|
+
if (readOnlyOps.includes(toolName)) {
|
|
55
|
+
output('allow', 'Read-only operation');
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Build operation string for logging
|
|
60
|
+
let operation = toolName + ': ';
|
|
61
|
+
if (toolName === 'Bash' && toolInput.command) {
|
|
62
|
+
operation += toolInput.command;
|
|
63
|
+
} else if (['Write', 'Edit'].includes(toolName)) {
|
|
64
|
+
operation += toolInput.file_path || toolInput.filePath || toolInput.path || JSON.stringify(toolInput);
|
|
65
|
+
} else {
|
|
66
|
+
operation += JSON.stringify(toolInput);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
log('Analyzing: ' + toolName);
|
|
70
|
+
|
|
71
|
+
// Check if bouncer CLI is available
|
|
72
|
+
if (bouncerCli) {
|
|
73
|
+
try {
|
|
74
|
+
const child = spawn('node', [bouncerCli], {
|
|
75
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
76
|
+
timeout: timeout
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
let stdout = '';
|
|
80
|
+
let stderr = '';
|
|
81
|
+
|
|
82
|
+
child.stdout.on('data', (data) => { stdout += data; });
|
|
83
|
+
child.stderr.on('data', (data) => { stderr += data; });
|
|
84
|
+
|
|
85
|
+
child.stdin.write(JSON.stringify(input));
|
|
86
|
+
child.stdin.end();
|
|
87
|
+
|
|
88
|
+
child.on('close', (code) => {
|
|
89
|
+
if (stderr) log('Bouncer stderr: ' + stderr);
|
|
90
|
+
|
|
91
|
+
if (code === 0 && stdout.trim()) {
|
|
92
|
+
try {
|
|
93
|
+
const result = JSON.parse(stdout.trim());
|
|
94
|
+
log(result.decision + ': ' + operation + ' - ' + (result.reason || ''));
|
|
95
|
+
console.log(stdout.trim());
|
|
96
|
+
} catch {
|
|
97
|
+
log('allow (parse error): ' + operation);
|
|
98
|
+
output('allow', 'Bouncer response parse error, allowing');
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
log('allow (bouncer error): ' + operation);
|
|
102
|
+
output('allow', 'Bouncer error, allowing');
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
child.on('error', (err) => {
|
|
107
|
+
log('allow (spawn error): ' + operation + ' - ' + err.message);
|
|
108
|
+
output('allow', 'Bouncer spawn error, allowing');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
} catch (err) {
|
|
112
|
+
log('allow (exception): ' + operation + ' - ' + err.message);
|
|
113
|
+
output('allow', 'Bouncer exception, allowing');
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
// Fallback: critical threat pattern matching only
|
|
117
|
+
const criticalPatterns = [
|
|
118
|
+
{ pattern: /rm\s+-rf\s+(\/|~)(\$|\s)/, reason: 'Critical threat: recursive delete of root or home' },
|
|
119
|
+
{ pattern: /:\(\)\{.*\}|:\(\)\{.*:\|:/, reason: 'Critical threat: fork bomb detected' },
|
|
120
|
+
{ pattern: /dd\s+if=\/dev\/zero\s+of=\/dev\/sd/, reason: 'Critical threat: disk overwrite' },
|
|
121
|
+
{ pattern: /mkfs\s+\/dev\/sd/, reason: 'Critical threat: filesystem format' },
|
|
122
|
+
{ pattern: />\s*\/dev\/sd/, reason: 'Critical threat: direct disk write' },
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
for (const { pattern, reason } of criticalPatterns) {
|
|
126
|
+
if (pattern.test(operation)) {
|
|
127
|
+
log('DENIED: ' + operation + ' - ' + reason);
|
|
128
|
+
output('deny', reason);
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
log('allow (fallback): ' + operation);
|
|
134
|
+
output('allow', 'Basic pattern check passed');
|
|
135
|
+
}
|
|
136
|
+
" "$INPUT" "$BOUNCER_CLI" "$BOUNCER_TIMEOUT" "$BOUNCER_LOG" 2>> "$BOUNCER_LOG")
|
|
137
|
+
|
|
138
|
+
echo "$RESULT"
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mstro-app",
|
|
3
|
+
"version": "0.1.47",
|
|
4
|
+
"description": "No-code AI assistant - run Claude Code workflows from your laptop, cloud VM, or any machine",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Mstro",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/mstro-app/mstro.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://mstro.app",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"cli",
|
|
15
|
+
"ai",
|
|
16
|
+
"claude",
|
|
17
|
+
"anthropic",
|
|
18
|
+
"orchestration",
|
|
19
|
+
"workflow",
|
|
20
|
+
"mcp",
|
|
21
|
+
"automation"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"mstro": "./bin/mstro.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin/",
|
|
31
|
+
"server/",
|
|
32
|
+
"hooks/",
|
|
33
|
+
"dist/",
|
|
34
|
+
"!**/*.backup",
|
|
35
|
+
"!**/*.bak",
|
|
36
|
+
"!**/.env",
|
|
37
|
+
"!**/.env.*"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"postinstall": "node bin/postinstall.js",
|
|
41
|
+
"build": "tsc -p tsconfig.build.json",
|
|
42
|
+
"dev": "tsx server/index.ts",
|
|
43
|
+
"dev:mcp": "tsx server/mcp/server.ts",
|
|
44
|
+
"start": "NODE_ENV=production tsx server/index.ts",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest",
|
|
47
|
+
"test:coverage": "vitest run --coverage",
|
|
48
|
+
"prepublishOnly": "npm run build && npm test",
|
|
49
|
+
"mstro": "node bin/mstro.js",
|
|
50
|
+
"mstro:dev": "node bin/mstro.js --dev",
|
|
51
|
+
"check": "tsc -p tsconfig.build.json && vitest run && biome check ."
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@hono/node-server": "^1.19.6",
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.21.1",
|
|
56
|
+
"@sentry/node": "^10.38.0",
|
|
57
|
+
"fuse.js": "^7.1.0",
|
|
58
|
+
"hono": "^4.10.6",
|
|
59
|
+
"posthog-node": "^5.21.2",
|
|
60
|
+
"tsx": "^4.21.0",
|
|
61
|
+
"update-notifier": "^7.3.1",
|
|
62
|
+
"ws": "^8.18.0"
|
|
63
|
+
},
|
|
64
|
+
"optionalDependencies": {
|
|
65
|
+
"node-pty": "^1.1.0"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@biomejs/biome": "^2.3.13",
|
|
69
|
+
"@types/node": "^24.10.7",
|
|
70
|
+
"@types/ws": "^8.18.1",
|
|
71
|
+
"typescript": "~5.9.3",
|
|
72
|
+
"vitest": "4.0.18"
|
|
73
|
+
}
|
|
74
|
+
}
|
package/server/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Mstro v2 Server - Modern Hono Implementation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This is a modernized server implementation for Mstro v2, built with **Hono** - a lightweight, fast, and type-safe web framework.
|
|
6
|
+
|
|
7
|
+
### Why Hono?
|
|
8
|
+
|
|
9
|
+
Migrating from Express (mstro-v1) to Hono provides:
|
|
10
|
+
|
|
11
|
+
- **Modern & Fast**: Built for edge computing with minimal overhead (~12KB vs Express's much larger footprint)
|
|
12
|
+
- **TypeScript-first**: Excellent type inference for routes and context
|
|
13
|
+
- **Web Standards**: Built on Web APIs (Request/Response objects)
|
|
14
|
+
- **Cleaner Code**: Less boilerplate, more declarative than Express
|
|
15
|
+
- **Future-proof**: Works with Node.js, Bun, Deno, and Cloudflare Workers
|
|
16
|
+
- **Better Performance**: Significantly faster routing and middleware execution
|
|
17
|
+
|
|
18
|
+
## Architecture
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
server/
|
|
22
|
+
├── index.ts # Main server entry point
|
|
23
|
+
├── types.ts # TypeScript type definitions
|
|
24
|
+
├── services/
|
|
25
|
+
│ └── scores.ts # Score management service
|
|
26
|
+
└── tsconfig.json # TypeScript configuration
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Running the Server
|
|
30
|
+
|
|
31
|
+
### Development Mode
|
|
32
|
+
```bash
|
|
33
|
+
npm run dev:server
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The server will start on port `3001` by default. You can change this by setting the `PORT` environment variable:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
PORT=8080 npm run dev:server
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API Endpoints
|
|
43
|
+
|
|
44
|
+
### Health & Configuration
|
|
45
|
+
|
|
46
|
+
- **GET** `/health` - Health check endpoint
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"status": "ok",
|
|
50
|
+
"timestamp": "2025-11-14T14:45:42.425Z",
|
|
51
|
+
"version": "2.0.0",
|
|
52
|
+
"framework": "Hono"
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- **GET** `/api/config` - Server configuration
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"lockWithPin": false,
|
|
60
|
+
"version": "2.0.0",
|
|
61
|
+
"framework": "Hono"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Scores Management
|
|
66
|
+
|
|
67
|
+
- **GET** `/api/scores` - List all scores (local, global, examples)
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"scores": {
|
|
71
|
+
"localScores": [...],
|
|
72
|
+
"globalScores": [...],
|
|
73
|
+
"exampleScores": [...]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- **GET** `/api/scores/:filename` - Get a specific local score
|
|
79
|
+
- **GET** `/api/scores/examples/:filename` - Get a specific example score
|
|
80
|
+
- **GET** `/api/scores/global/:filename` - Get a specific global score
|
|
81
|
+
|
|
82
|
+
- **POST** `/api/scores` - Save a new score
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"metadata": {
|
|
86
|
+
"name": "My Score",
|
|
87
|
+
"version": "1.0.0",
|
|
88
|
+
"description": "Score description"
|
|
89
|
+
},
|
|
90
|
+
"config": {
|
|
91
|
+
"defaultModel": "sonnet"
|
|
92
|
+
},
|
|
93
|
+
"movements": [...],
|
|
94
|
+
"entryPoint": "step1"
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Middleware Stack
|
|
99
|
+
|
|
100
|
+
1. **CORS** - Cross-origin resource sharing enabled for all routes
|
|
101
|
+
2. **Logger** - HTTP request logging for debugging
|
|
102
|
+
3. **Error Handling** - Centralized error handling with proper status codes
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
### Manual Testing
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Health check
|
|
110
|
+
curl http://localhost:3001/health
|
|
111
|
+
|
|
112
|
+
# List scores
|
|
113
|
+
curl http://localhost:3001/api/scores
|
|
114
|
+
|
|
115
|
+
# Get specific score
|
|
116
|
+
curl http://localhost:3001/api/scores/my-score.json
|
|
117
|
+
|
|
118
|
+
# Save a score
|
|
119
|
+
curl -X POST http://localhost:3001/api/scores \
|
|
120
|
+
-H "Content-Type: application/json" \
|
|
121
|
+
-d @score.json
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Migration Status
|
|
125
|
+
|
|
126
|
+
### ✅ Completed
|
|
127
|
+
- [x] Health check endpoint
|
|
128
|
+
- [x] Configuration endpoint
|
|
129
|
+
- [x] List all scores (local, global, examples)
|
|
130
|
+
- [x] Get specific score by filename and type
|
|
131
|
+
- [x] Save new scores
|
|
132
|
+
|
|
133
|
+
### 🔄 To Be Migrated
|
|
134
|
+
- [ ] Execute score endpoints
|
|
135
|
+
- [ ] WebSocket for improvise sessions
|
|
136
|
+
- [ ] Instances management
|
|
137
|
+
- [ ] Git integration endpoints
|
|
138
|
+
- [ ] Authentication/PIN management
|
|
139
|
+
- [ ] File autocomplete endpoint
|
|
140
|
+
- [ ] Score generation with AI (streaming)
|
|
141
|
+
|
|
142
|
+
## Type Safety
|
|
143
|
+
|
|
144
|
+
All routes are fully typed using TypeScript. The `OrchestraScore` type ensures consistency across the entire application:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
interface OrchestraScore {
|
|
148
|
+
metadata: {
|
|
149
|
+
name: string
|
|
150
|
+
version: string
|
|
151
|
+
description?: string
|
|
152
|
+
// ...
|
|
153
|
+
}
|
|
154
|
+
movements: Movement[]
|
|
155
|
+
entryPoint: string
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Performance Comparison
|
|
160
|
+
|
|
161
|
+
Hono vs Express benchmarks (approximate):
|
|
162
|
+
|
|
163
|
+
- **Routing**: ~3-4x faster
|
|
164
|
+
- **JSON parsing**: ~2x faster
|
|
165
|
+
- **Memory footprint**: ~60% smaller
|
|
166
|
+
- **Bundle size**: ~95% smaller
|
|
167
|
+
|
|
168
|
+
## Next Steps
|
|
169
|
+
|
|
170
|
+
1. **Add WebSocket support** for real-time improvise sessions
|
|
171
|
+
2. **Implement streaming endpoints** for score generation
|
|
172
|
+
3. **Add authentication middleware** for PIN-based security
|
|
173
|
+
4. **Set up rate limiting** for production use
|
|
174
|
+
5. **Consider Bun runtime** for even better performance
|
|
175
|
+
|
|
176
|
+
## Compatibility
|
|
177
|
+
|
|
178
|
+
- Node.js 18+ (ESM modules)
|
|
179
|
+
- TypeScript 5.9+
|
|
180
|
+
- Compatible with the existing mstro-v1 client (same API surface)
|
|
181
|
+
|
|
182
|
+
## MCP Server
|
|
183
|
+
|
|
184
|
+
The MCP bouncer server is now integrated into mstro-v2 at `server/mcp/`. Start it with:
|
|
185
|
+
```bash
|
|
186
|
+
npm run dev:mcp
|
|
187
|
+
# or
|
|
188
|
+
bun run server/mcp/server.ts
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The server provides security analysis for Claude Code tool use via the Model Context Protocol.
|