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.
Files changed (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/bin/commands/config.js +145 -0
  4. package/bin/commands/login.js +313 -0
  5. package/bin/commands/logout.js +75 -0
  6. package/bin/commands/status.js +197 -0
  7. package/bin/commands/whoami.js +161 -0
  8. package/bin/configure-claude.js +298 -0
  9. package/bin/mstro.js +581 -0
  10. package/bin/postinstall.js +45 -0
  11. package/bin/release.sh +110 -0
  12. package/dist/server/cli/headless/claude-invoker.d.ts +17 -0
  13. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -0
  14. package/dist/server/cli/headless/claude-invoker.js +311 -0
  15. package/dist/server/cli/headless/claude-invoker.js.map +1 -0
  16. package/dist/server/cli/headless/index.d.ts +13 -0
  17. package/dist/server/cli/headless/index.d.ts.map +1 -0
  18. package/dist/server/cli/headless/index.js +10 -0
  19. package/dist/server/cli/headless/index.js.map +1 -0
  20. package/dist/server/cli/headless/mcp-config.d.ts +11 -0
  21. package/dist/server/cli/headless/mcp-config.d.ts.map +1 -0
  22. package/dist/server/cli/headless/mcp-config.js +76 -0
  23. package/dist/server/cli/headless/mcp-config.js.map +1 -0
  24. package/dist/server/cli/headless/output-utils.d.ts +33 -0
  25. package/dist/server/cli/headless/output-utils.d.ts.map +1 -0
  26. package/dist/server/cli/headless/output-utils.js +101 -0
  27. package/dist/server/cli/headless/output-utils.js.map +1 -0
  28. package/dist/server/cli/headless/prompt-utils.d.ts +21 -0
  29. package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -0
  30. package/dist/server/cli/headless/prompt-utils.js +84 -0
  31. package/dist/server/cli/headless/prompt-utils.js.map +1 -0
  32. package/dist/server/cli/headless/runner.d.ts +24 -0
  33. package/dist/server/cli/headless/runner.d.ts.map +1 -0
  34. package/dist/server/cli/headless/runner.js +99 -0
  35. package/dist/server/cli/headless/runner.js.map +1 -0
  36. package/dist/server/cli/headless/types.d.ts +106 -0
  37. package/dist/server/cli/headless/types.d.ts.map +1 -0
  38. package/dist/server/cli/headless/types.js +4 -0
  39. package/dist/server/cli/headless/types.js.map +1 -0
  40. package/dist/server/cli/improvisation-session-manager.d.ts +155 -0
  41. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -0
  42. package/dist/server/cli/improvisation-session-manager.js +415 -0
  43. package/dist/server/cli/improvisation-session-manager.js.map +1 -0
  44. package/dist/server/index.d.ts +2 -0
  45. package/dist/server/index.d.ts.map +1 -0
  46. package/dist/server/index.js +386 -0
  47. package/dist/server/index.js.map +1 -0
  48. package/dist/server/mcp/bouncer-cli.d.ts +3 -0
  49. package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
  50. package/dist/server/mcp/bouncer-cli.js +99 -0
  51. package/dist/server/mcp/bouncer-cli.js.map +1 -0
  52. package/dist/server/mcp/bouncer-integration.d.ts +36 -0
  53. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -0
  54. package/dist/server/mcp/bouncer-integration.js +301 -0
  55. package/dist/server/mcp/bouncer-integration.js.map +1 -0
  56. package/dist/server/mcp/security-audit.d.ts +52 -0
  57. package/dist/server/mcp/security-audit.d.ts.map +1 -0
  58. package/dist/server/mcp/security-audit.js +118 -0
  59. package/dist/server/mcp/security-audit.js.map +1 -0
  60. package/dist/server/mcp/security-patterns.d.ts +73 -0
  61. package/dist/server/mcp/security-patterns.d.ts.map +1 -0
  62. package/dist/server/mcp/security-patterns.js +247 -0
  63. package/dist/server/mcp/security-patterns.js.map +1 -0
  64. package/dist/server/mcp/server.d.ts +3 -0
  65. package/dist/server/mcp/server.d.ts.map +1 -0
  66. package/dist/server/mcp/server.js +146 -0
  67. package/dist/server/mcp/server.js.map +1 -0
  68. package/dist/server/routes/files.d.ts +9 -0
  69. package/dist/server/routes/files.d.ts.map +1 -0
  70. package/dist/server/routes/files.js +24 -0
  71. package/dist/server/routes/files.js.map +1 -0
  72. package/dist/server/routes/improvise.d.ts +3 -0
  73. package/dist/server/routes/improvise.d.ts.map +1 -0
  74. package/dist/server/routes/improvise.js +72 -0
  75. package/dist/server/routes/improvise.js.map +1 -0
  76. package/dist/server/routes/index.d.ts +10 -0
  77. package/dist/server/routes/index.d.ts.map +1 -0
  78. package/dist/server/routes/index.js +12 -0
  79. package/dist/server/routes/index.js.map +1 -0
  80. package/dist/server/routes/instances.d.ts +10 -0
  81. package/dist/server/routes/instances.d.ts.map +1 -0
  82. package/dist/server/routes/instances.js +47 -0
  83. package/dist/server/routes/instances.js.map +1 -0
  84. package/dist/server/routes/notifications.d.ts +3 -0
  85. package/dist/server/routes/notifications.d.ts.map +1 -0
  86. package/dist/server/routes/notifications.js +136 -0
  87. package/dist/server/routes/notifications.js.map +1 -0
  88. package/dist/server/services/analytics.d.ts +56 -0
  89. package/dist/server/services/analytics.d.ts.map +1 -0
  90. package/dist/server/services/analytics.js +240 -0
  91. package/dist/server/services/analytics.js.map +1 -0
  92. package/dist/server/services/auth.d.ts +26 -0
  93. package/dist/server/services/auth.d.ts.map +1 -0
  94. package/dist/server/services/auth.js +71 -0
  95. package/dist/server/services/auth.js.map +1 -0
  96. package/dist/server/services/client-id.d.ts +10 -0
  97. package/dist/server/services/client-id.d.ts.map +1 -0
  98. package/dist/server/services/client-id.js +61 -0
  99. package/dist/server/services/client-id.js.map +1 -0
  100. package/dist/server/services/credentials.d.ts +39 -0
  101. package/dist/server/services/credentials.d.ts.map +1 -0
  102. package/dist/server/services/credentials.js +110 -0
  103. package/dist/server/services/credentials.js.map +1 -0
  104. package/dist/server/services/files.d.ts +119 -0
  105. package/dist/server/services/files.d.ts.map +1 -0
  106. package/dist/server/services/files.js +560 -0
  107. package/dist/server/services/files.js.map +1 -0
  108. package/dist/server/services/instances.d.ts +52 -0
  109. package/dist/server/services/instances.d.ts.map +1 -0
  110. package/dist/server/services/instances.js +241 -0
  111. package/dist/server/services/instances.js.map +1 -0
  112. package/dist/server/services/pathUtils.d.ts +47 -0
  113. package/dist/server/services/pathUtils.d.ts.map +1 -0
  114. package/dist/server/services/pathUtils.js +124 -0
  115. package/dist/server/services/pathUtils.js.map +1 -0
  116. package/dist/server/services/platform.d.ts +72 -0
  117. package/dist/server/services/platform.d.ts.map +1 -0
  118. package/dist/server/services/platform.js +368 -0
  119. package/dist/server/services/platform.js.map +1 -0
  120. package/dist/server/services/sentry.d.ts +5 -0
  121. package/dist/server/services/sentry.d.ts.map +1 -0
  122. package/dist/server/services/sentry.js +71 -0
  123. package/dist/server/services/sentry.js.map +1 -0
  124. package/dist/server/services/terminal/pty-manager.d.ts +149 -0
  125. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -0
  126. package/dist/server/services/terminal/pty-manager.js +377 -0
  127. package/dist/server/services/terminal/pty-manager.js.map +1 -0
  128. package/dist/server/services/terminal/tmux-manager.d.ts +82 -0
  129. package/dist/server/services/terminal/tmux-manager.d.ts.map +1 -0
  130. package/dist/server/services/terminal/tmux-manager.js +352 -0
  131. package/dist/server/services/terminal/tmux-manager.js.map +1 -0
  132. package/dist/server/services/websocket/autocomplete.d.ts +50 -0
  133. package/dist/server/services/websocket/autocomplete.d.ts.map +1 -0
  134. package/dist/server/services/websocket/autocomplete.js +361 -0
  135. package/dist/server/services/websocket/autocomplete.js.map +1 -0
  136. package/dist/server/services/websocket/file-utils.d.ts +44 -0
  137. package/dist/server/services/websocket/file-utils.d.ts.map +1 -0
  138. package/dist/server/services/websocket/file-utils.js +272 -0
  139. package/dist/server/services/websocket/file-utils.js.map +1 -0
  140. package/dist/server/services/websocket/handler.d.ts +246 -0
  141. package/dist/server/services/websocket/handler.d.ts.map +1 -0
  142. package/dist/server/services/websocket/handler.js +1771 -0
  143. package/dist/server/services/websocket/handler.js.map +1 -0
  144. package/dist/server/services/websocket/index.d.ts +11 -0
  145. package/dist/server/services/websocket/index.d.ts.map +1 -0
  146. package/dist/server/services/websocket/index.js +14 -0
  147. package/dist/server/services/websocket/index.js.map +1 -0
  148. package/dist/server/services/websocket/types.d.ts +214 -0
  149. package/dist/server/services/websocket/types.d.ts.map +1 -0
  150. package/dist/server/services/websocket/types.js +4 -0
  151. package/dist/server/services/websocket/types.js.map +1 -0
  152. package/dist/server/utils/agent-manager.d.ts +69 -0
  153. package/dist/server/utils/agent-manager.d.ts.map +1 -0
  154. package/dist/server/utils/agent-manager.js +269 -0
  155. package/dist/server/utils/agent-manager.js.map +1 -0
  156. package/dist/server/utils/paths.d.ts +25 -0
  157. package/dist/server/utils/paths.d.ts.map +1 -0
  158. package/dist/server/utils/paths.js +38 -0
  159. package/dist/server/utils/paths.js.map +1 -0
  160. package/dist/server/utils/port-manager.d.ts +10 -0
  161. package/dist/server/utils/port-manager.d.ts.map +1 -0
  162. package/dist/server/utils/port-manager.js +60 -0
  163. package/dist/server/utils/port-manager.js.map +1 -0
  164. package/dist/server/utils/port.d.ts +26 -0
  165. package/dist/server/utils/port.d.ts.map +1 -0
  166. package/dist/server/utils/port.js +83 -0
  167. package/dist/server/utils/port.js.map +1 -0
  168. package/hooks/bouncer.sh +138 -0
  169. package/package.json +74 -0
  170. package/server/README.md +191 -0
  171. package/server/cli/headless/claude-invoker.ts +415 -0
  172. package/server/cli/headless/index.ts +39 -0
  173. package/server/cli/headless/mcp-config.ts +87 -0
  174. package/server/cli/headless/output-utils.ts +109 -0
  175. package/server/cli/headless/prompt-utils.ts +108 -0
  176. package/server/cli/headless/runner.ts +133 -0
  177. package/server/cli/headless/types.ts +118 -0
  178. package/server/cli/improvisation-session-manager.ts +531 -0
  179. package/server/index.ts +456 -0
  180. package/server/mcp/README.md +122 -0
  181. package/server/mcp/bouncer-cli.ts +127 -0
  182. package/server/mcp/bouncer-integration.ts +430 -0
  183. package/server/mcp/security-audit.ts +180 -0
  184. package/server/mcp/security-patterns.ts +290 -0
  185. package/server/mcp/server.ts +174 -0
  186. package/server/routes/files.ts +29 -0
  187. package/server/routes/improvise.ts +82 -0
  188. package/server/routes/index.ts +13 -0
  189. package/server/routes/instances.ts +54 -0
  190. package/server/routes/notifications.ts +158 -0
  191. package/server/services/analytics.ts +277 -0
  192. package/server/services/auth.ts +80 -0
  193. package/server/services/client-id.ts +68 -0
  194. package/server/services/credentials.ts +134 -0
  195. package/server/services/files.ts +710 -0
  196. package/server/services/instances.ts +275 -0
  197. package/server/services/pathUtils.ts +158 -0
  198. package/server/services/platform.test.ts +1314 -0
  199. package/server/services/platform.ts +435 -0
  200. package/server/services/sentry.ts +81 -0
  201. package/server/services/terminal/pty-manager.ts +464 -0
  202. package/server/services/terminal/tmux-manager.ts +426 -0
  203. package/server/services/websocket/autocomplete.ts +438 -0
  204. package/server/services/websocket/file-utils.ts +305 -0
  205. package/server/services/websocket/handler.test.ts +20 -0
  206. package/server/services/websocket/handler.ts +2047 -0
  207. package/server/services/websocket/index.ts +40 -0
  208. package/server/services/websocket/types.ts +339 -0
  209. package/server/tsconfig.json +19 -0
  210. package/server/utils/agent-manager.ts +323 -0
  211. package/server/utils/paths.ts +45 -0
  212. package/server/utils/port-manager.ts +70 -0
  213. package/server/utils/port.ts +102 -0
@@ -0,0 +1,269 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * Agent Manager
5
+ *
6
+ * Handles agent discovery, installation, and availability checking.
7
+ * Implements pre-flight file copy approach for agent hot-loading.
8
+ */
9
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync } from 'node:fs';
10
+ import { homedir } from 'node:os';
11
+ import { basename, dirname, join } from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+ export class AgentManager {
14
+ bundledAgentsPath;
15
+ globalAgentsPath;
16
+ constructor() {
17
+ // Path to bundled agents in mstro installation
18
+ // In ES modules, we need to get __dirname equivalent using import.meta.url
19
+ const __filename = fileURLToPath(import.meta.url);
20
+ const __dirname = dirname(__filename);
21
+ this.bundledAgentsPath = join(dirname(dirname(__dirname)), '.claude', 'agents');
22
+ // Global user agents directory
23
+ this.globalAgentsPath = join(homedir(), '.claude', 'agents');
24
+ }
25
+ /**
26
+ * Get path to project agents directory
27
+ */
28
+ getProjectAgentsPath(workingDir) {
29
+ return join(workingDir, '.claude', 'agents');
30
+ }
31
+ /**
32
+ * List all available bundled agents
33
+ */
34
+ listBundledAgents() {
35
+ if (!existsSync(this.bundledAgentsPath)) {
36
+ return [];
37
+ }
38
+ const files = readdirSync(this.bundledAgentsPath)
39
+ .filter(f => f.endsWith('.md') && f !== 'README.md');
40
+ return files.map(file => ({
41
+ name: basename(file, '.md'),
42
+ path: join(this.bundledAgentsPath, file),
43
+ location: 'bundled',
44
+ description: this.extractDescription(join(this.bundledAgentsPath, file))
45
+ }));
46
+ }
47
+ /**
48
+ * List all globally installed agents
49
+ */
50
+ listGlobalAgents() {
51
+ if (!existsSync(this.globalAgentsPath)) {
52
+ return [];
53
+ }
54
+ const files = readdirSync(this.globalAgentsPath)
55
+ .filter(f => f.endsWith('.md'));
56
+ return files.map(file => ({
57
+ name: basename(file, '.md'),
58
+ path: join(this.globalAgentsPath, file),
59
+ location: 'global',
60
+ description: this.extractDescription(join(this.globalAgentsPath, file))
61
+ }));
62
+ }
63
+ /**
64
+ * List all project-level agents
65
+ */
66
+ listProjectAgents(workingDir) {
67
+ const projectPath = this.getProjectAgentsPath(workingDir);
68
+ if (!existsSync(projectPath)) {
69
+ return [];
70
+ }
71
+ const files = readdirSync(projectPath)
72
+ .filter(f => f.endsWith('.md'));
73
+ return files.map(file => ({
74
+ name: basename(file, '.md'),
75
+ path: join(projectPath, file),
76
+ location: 'project',
77
+ description: this.extractDescription(join(projectPath, file))
78
+ }));
79
+ }
80
+ /**
81
+ * Extract description from agent markdown file (first line after title)
82
+ */
83
+ extractDescription(filePath) {
84
+ try {
85
+ const content = readFileSync(filePath, 'utf-8');
86
+ const lines = content.split('\n').filter(l => l.trim());
87
+ // Find first non-header line
88
+ for (const line of lines) {
89
+ if (!line.startsWith('#')) {
90
+ return line.trim();
91
+ }
92
+ }
93
+ }
94
+ catch {
95
+ // Ignore errors
96
+ }
97
+ return undefined;
98
+ }
99
+ /**
100
+ * Check if an agent is available (exists in project, global, or bundled)
101
+ */
102
+ findAgent(agentName, workingDir) {
103
+ const agentFile = `${agentName}.md`;
104
+ // 1. Check project-level (if working dir provided)
105
+ if (workingDir) {
106
+ const projectPath = join(this.getProjectAgentsPath(workingDir), agentFile);
107
+ if (existsSync(projectPath)) {
108
+ return {
109
+ name: agentName,
110
+ path: projectPath,
111
+ location: 'project',
112
+ description: this.extractDescription(projectPath)
113
+ };
114
+ }
115
+ }
116
+ // 2. Check global
117
+ const globalPath = join(this.globalAgentsPath, agentFile);
118
+ if (existsSync(globalPath)) {
119
+ return {
120
+ name: agentName,
121
+ path: globalPath,
122
+ location: 'global',
123
+ description: this.extractDescription(globalPath)
124
+ };
125
+ }
126
+ // 3. Check bundled
127
+ const bundledPath = join(this.bundledAgentsPath, agentFile);
128
+ if (existsSync(bundledPath)) {
129
+ return {
130
+ name: agentName,
131
+ path: bundledPath,
132
+ location: 'bundled',
133
+ description: this.extractDescription(bundledPath)
134
+ };
135
+ }
136
+ return null;
137
+ }
138
+ /**
139
+ * Ensure an agent is available for use
140
+ * If not in project or global, copy from bundled to project
141
+ */
142
+ async ensureAgentAvailable(agentName, workingDir) {
143
+ const agentFile = `${agentName}.md`;
144
+ const projectPath = join(this.getProjectAgentsPath(workingDir), agentFile);
145
+ const globalPath = join(this.globalAgentsPath, agentFile);
146
+ const bundledPath = join(this.bundledAgentsPath, agentFile);
147
+ // If already in project or global, we're done
148
+ if (existsSync(projectPath)) {
149
+ return {
150
+ name: agentName,
151
+ path: projectPath,
152
+ location: 'project',
153
+ description: this.extractDescription(projectPath)
154
+ };
155
+ }
156
+ if (existsSync(globalPath)) {
157
+ return {
158
+ name: agentName,
159
+ path: globalPath,
160
+ location: 'global',
161
+ description: this.extractDescription(globalPath)
162
+ };
163
+ }
164
+ // Check if bundled agent exists
165
+ if (!existsSync(bundledPath)) {
166
+ throw new Error(`Agent not found: ${agentName}\nNot available in bundled, global, or project agents.`);
167
+ }
168
+ // Copy bundled agent to project
169
+ const targetDir = dirname(projectPath);
170
+ mkdirSync(targetDir, { recursive: true });
171
+ copyFileSync(bundledPath, projectPath);
172
+ return {
173
+ name: agentName,
174
+ path: projectPath,
175
+ location: 'project',
176
+ description: this.extractDescription(projectPath)
177
+ };
178
+ }
179
+ /**
180
+ * Install a specific bundled agent to global directory
181
+ */
182
+ installAgentGlobally(agentName) {
183
+ const agentFile = `${agentName}.md`;
184
+ const bundledPath = join(this.bundledAgentsPath, agentFile);
185
+ const globalPath = join(this.globalAgentsPath, agentFile);
186
+ if (!existsSync(bundledPath)) {
187
+ throw new Error(`Bundled agent not found: ${agentName}`);
188
+ }
189
+ // Create global agents directory if needed
190
+ mkdirSync(this.globalAgentsPath, { recursive: true });
191
+ // Copy to global
192
+ copyFileSync(bundledPath, globalPath);
193
+ }
194
+ /**
195
+ * Install all bundled agents to global directory
196
+ */
197
+ installAllAgentsGlobally() {
198
+ const bundled = this.listBundledAgents();
199
+ const installed = [];
200
+ mkdirSync(this.globalAgentsPath, { recursive: true });
201
+ for (const agent of bundled) {
202
+ const targetPath = join(this.globalAgentsPath, `${agent.name}.md`);
203
+ copyFileSync(agent.path, targetPath);
204
+ installed.push(agent.name);
205
+ }
206
+ return installed;
207
+ }
208
+ /**
209
+ * Install a specific bundled agent to project directory
210
+ */
211
+ installAgentToProject(agentName, workingDir) {
212
+ const agentFile = `${agentName}.md`;
213
+ const bundledPath = join(this.bundledAgentsPath, agentFile);
214
+ const projectPath = join(this.getProjectAgentsPath(workingDir), agentFile);
215
+ if (!existsSync(bundledPath)) {
216
+ throw new Error(`Bundled agent not found: ${agentName}`);
217
+ }
218
+ // Create project agents directory if needed
219
+ const targetDir = dirname(projectPath);
220
+ mkdirSync(targetDir, { recursive: true });
221
+ // Copy to project
222
+ copyFileSync(bundledPath, projectPath);
223
+ }
224
+ /**
225
+ * Install all bundled agents to project directory
226
+ */
227
+ installAllAgentsToProject(workingDir) {
228
+ const bundled = this.listBundledAgents();
229
+ const installed = [];
230
+ const projectAgentsPath = this.getProjectAgentsPath(workingDir);
231
+ mkdirSync(projectAgentsPath, { recursive: true });
232
+ for (const agent of bundled) {
233
+ const targetPath = join(projectAgentsPath, `${agent.name}.md`);
234
+ copyFileSync(agent.path, targetPath);
235
+ installed.push(agent.name);
236
+ }
237
+ return installed;
238
+ }
239
+ /**
240
+ * Extract agent names from a score object
241
+ */
242
+ extractAgentNamesFromScore(score) {
243
+ if (!Array.isArray(score.movements))
244
+ return [];
245
+ const names = score.movements
246
+ .flatMap(m => Array.isArray(m.musicians) ? m.musicians : [])
247
+ .filter((m) => m.type === 'custom')
248
+ .map((m) => m.config?.agent || m.role)
249
+ .filter(Boolean);
250
+ return [...new Set(names)];
251
+ }
252
+ /**
253
+ * Ensure all agents required by a score are available
254
+ */
255
+ async ensureScoreAgentsAvailable(score, workingDir) {
256
+ const agentNames = this.extractAgentNamesFromScore(score);
257
+ const results = new Map();
258
+ for (const agentName of agentNames) {
259
+ const info = await this.ensureAgentAvailable(agentName, workingDir);
260
+ results.set(agentName, info);
261
+ }
262
+ return results;
263
+ }
264
+ }
265
+ /**
266
+ * Singleton instance
267
+ */
268
+ export const agentManager = new AgentManager();
269
+ //# sourceMappingURL=agent-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-manager.js","sourceRoot":"","sources":["../../../server/utils/agent-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Root directory of the mstro package installation.
3
+ * This is the directory containing package.json.
4
+ *
5
+ * Structure: /path/to/mstro/server/utils/paths.ts
6
+ * So we go up 2 levels: utils -> server -> mstro root
7
+ */
8
+ export declare const MSTRO_ROOT: string;
9
+ /**
10
+ * Path to the MCP bouncer server script
11
+ */
12
+ export declare const MCP_SERVER_PATH: string;
13
+ /**
14
+ * Path to the MCP bouncer configuration template
15
+ */
16
+ export declare const MCP_CONFIG_TEMPLATE_PATH: string;
17
+ /**
18
+ * Path to the hooks directory
19
+ */
20
+ export declare const HOOKS_DIR: string;
21
+ /**
22
+ * Path to the bouncer hook script
23
+ */
24
+ export declare const BOUNCER_HOOK: string;
25
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../server/utils/paths.ts"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAA8B,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,eAAe,QAA8C,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,wBAAwB,QAAgD,CAAC;AAEtF;;GAEG;AACH,eAAO,MAAM,SAAS,QAA+B,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,YAAY,QAAmC,CAAC"}
@@ -0,0 +1,38 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * Path Utilities for Mstro Package
5
+ *
6
+ * Provides consistent path resolution for installed npm package.
7
+ * Works correctly whether running from source or installed globally.
8
+ */
9
+ import { dirname, resolve } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ // ES module equivalent of __dirname for this file
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+ /**
15
+ * Root directory of the mstro package installation.
16
+ * This is the directory containing package.json.
17
+ *
18
+ * Structure: /path/to/mstro/server/utils/paths.ts
19
+ * So we go up 2 levels: utils -> server -> mstro root
20
+ */
21
+ export const MSTRO_ROOT = resolve(__dirname, '../..');
22
+ /**
23
+ * Path to the MCP bouncer server script
24
+ */
25
+ export const MCP_SERVER_PATH = resolve(MSTRO_ROOT, 'server/mcp/server.ts');
26
+ /**
27
+ * Path to the MCP bouncer configuration template
28
+ */
29
+ export const MCP_CONFIG_TEMPLATE_PATH = resolve(MSTRO_ROOT, 'mstro-bouncer-mcp.json');
30
+ /**
31
+ * Path to the hooks directory
32
+ */
33
+ export const HOOKS_DIR = resolve(MSTRO_ROOT, 'hooks');
34
+ /**
35
+ * Path to the bouncer hook script
36
+ */
37
+ export const BOUNCER_HOOK = resolve(HOOKS_DIR, 'bouncer.sh');
38
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../server/utils/paths.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,kDAAkD;AAClD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;AAE3E;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC;AAEtF;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Find an available port starting from the default port
3
+ * Tries ports: 3001, 3002, 3003, ... up to 3010
4
+ */
5
+ export declare function findAvailablePort(startPort?: number): Promise<number>;
6
+ /**
7
+ * Get the default port from environment or use 3001
8
+ */
9
+ export declare function getDefaultPort(): number;
10
+ //# sourceMappingURL=port-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-manager.d.ts","sourceRoot":"","sources":["../../../server/utils/port-manager.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,GAAE,MAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAYzF;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CASvC"}
@@ -0,0 +1,60 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * Port Manager - Finds available ports for Mstro instances
5
+ *
6
+ * Handles port discovery when multiple Mstro instances run on the same machine.
7
+ * Tries a range of ports starting from the default until an available one is found.
8
+ */
9
+ import { createServer } from 'node:net';
10
+ const DEFAULT_PORT = 3001;
11
+ const MAX_PORT_ATTEMPTS = 10;
12
+ /**
13
+ * Check if a port is available
14
+ */
15
+ async function isPortAvailable(port) {
16
+ return new Promise((resolve) => {
17
+ const server = createServer();
18
+ server.once('error', (err) => {
19
+ if (err.code === 'EADDRINUSE') {
20
+ resolve(false);
21
+ }
22
+ else {
23
+ resolve(false);
24
+ }
25
+ });
26
+ server.once('listening', () => {
27
+ server.close();
28
+ resolve(true);
29
+ });
30
+ server.listen(port);
31
+ });
32
+ }
33
+ /**
34
+ * Find an available port starting from the default port
35
+ * Tries ports: 3001, 3002, 3003, ... up to 3010
36
+ */
37
+ export async function findAvailablePort(startPort = DEFAULT_PORT) {
38
+ for (let i = 0; i < MAX_PORT_ATTEMPTS; i++) {
39
+ const port = startPort + i;
40
+ const available = await isPortAvailable(port);
41
+ if (available) {
42
+ return port;
43
+ }
44
+ }
45
+ throw new Error(`Could not find available port after ${MAX_PORT_ATTEMPTS} attempts (tried ${startPort}-${startPort + MAX_PORT_ATTEMPTS - 1})`);
46
+ }
47
+ /**
48
+ * Get the default port from environment or use 3001
49
+ */
50
+ export function getDefaultPort() {
51
+ const envPort = process.env.PORT;
52
+ if (envPort) {
53
+ const parsed = parseInt(envPort, 10);
54
+ if (!Number.isNaN(parsed) && parsed > 0 && parsed < 65536) {
55
+ return parsed;
56
+ }
57
+ }
58
+ return DEFAULT_PORT;
59
+ }
60
+ //# sourceMappingURL=port-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-manager.js","sourceRoot":"","sources":["../../../server/utils/port-manager.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,MAAM,YAAY,GAAG,IAAI,CAAA;AACzB,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAE5B;;GAEG;AACH,KAAK,UAAU,eAAe,CAAC,IAAY;IACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;QAE7B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAQ,EAAE,EAAE;YAChC,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,CAAA;YAChB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,EAAE,CAAA;YACd,OAAO,CAAC,IAAI,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACrB,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,YAAoB,YAAY;IACtE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,SAAS,GAAG,CAAC,CAAA;QAC1B,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;QAE7C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,IAAI,CAAA;QACb,CAAC;IAEH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,uCAAuC,iBAAiB,oBAAoB,SAAS,IAAI,SAAS,GAAG,iBAAiB,GAAG,CAAC,GAAG,CAAC,CAAA;AAChJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA;IAChC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,KAAK,EAAE,CAAC;YAC1D,OAAO,MAAM,CAAA;QACf,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Check if a port is available by trying to bind to it
3
+ * Uses '::' (IPv6 any) which also binds IPv4 on most systems,
4
+ * ensuring we detect servers listening on any interface.
5
+ */
6
+ export declare function isPortAvailable(port: number): Promise<boolean>;
7
+ /**
8
+ * Check multiple ports in parallel and return the first available one
9
+ */
10
+ export declare function findFirstAvailablePort(ports: number[]): Promise<number | null>;
11
+ /**
12
+ * Find an available port starting from startPort
13
+ */
14
+ export declare function findAvailablePort(startPort: number, maxTries?: number): Promise<number>;
15
+ /**
16
+ * Find an available port pair for frontend and backend
17
+ * Frontend = EVEN port (3000, 3002, 3004...)
18
+ * Backend = ODD port (3001, 3003, 3005...)
19
+ *
20
+ * Checks all candidate ports in parallel for fast detection.
21
+ */
22
+ export declare function findAvailablePortPair(startPort?: number, maxPairs?: number): Promise<{
23
+ frontend: number;
24
+ backend: number;
25
+ }>;
26
+ //# sourceMappingURL=port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../server/utils/port.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB9D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMpF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAQjG;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,SAAS,GAAE,MAAa,EAAE,QAAQ,GAAE,MAAW,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC3I"}
@@ -0,0 +1,83 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ /**
4
+ * Port utilities for finding available ports
5
+ *
6
+ * Convention: Frontend uses EVEN ports (3000, 3002, 3004...)
7
+ * Backend uses ODD ports (3001, 3003, 3005...)
8
+ * This ensures they never compete for the same port.
9
+ */
10
+ import { createServer } from 'node:net';
11
+ /**
12
+ * Check if a port is available by trying to bind to it
13
+ * Uses '::' (IPv6 any) which also binds IPv4 on most systems,
14
+ * ensuring we detect servers listening on any interface.
15
+ */
16
+ export function isPortAvailable(port) {
17
+ return new Promise((resolve) => {
18
+ const server = createServer();
19
+ server.once('error', () => {
20
+ server.close();
21
+ resolve(false); // Port is in use
22
+ });
23
+ server.once('listening', () => {
24
+ server.close();
25
+ resolve(true); // Port is available
26
+ });
27
+ // Use '::' to bind on all interfaces (IPv4 + IPv6)
28
+ // This ensures we detect servers on any interface
29
+ server.listen(port, '::');
30
+ });
31
+ }
32
+ /**
33
+ * Check multiple ports in parallel and return the first available one
34
+ */
35
+ export async function findFirstAvailablePort(ports) {
36
+ const results = await Promise.all(ports.map(async (port) => ({ port, available: await isPortAvailable(port) })));
37
+ const available = results.find(r => r.available);
38
+ return available ? available.port : null;
39
+ }
40
+ /**
41
+ * Find an available port starting from startPort
42
+ */
43
+ export async function findAvailablePort(startPort, maxTries = 20) {
44
+ // Check all ports in parallel for speed
45
+ const ports = Array.from({ length: maxTries }, (_, i) => startPort + i);
46
+ const port = await findFirstAvailablePort(ports);
47
+ if (port !== null) {
48
+ return port;
49
+ }
50
+ throw new Error(`No available ports found between ${startPort} and ${startPort + maxTries}`);
51
+ }
52
+ /**
53
+ * Find an available port pair for frontend and backend
54
+ * Frontend = EVEN port (3000, 3002, 3004...)
55
+ * Backend = ODD port (3001, 3003, 3005...)
56
+ *
57
+ * Checks all candidate ports in parallel for fast detection.
58
+ */
59
+ export async function findAvailablePortPair(startPort = 3000, maxPairs = 20) {
60
+ // Ensure startPort is even
61
+ const basePort = startPort % 2 === 0 ? startPort : startPort + 1;
62
+ // Generate all candidate pairs
63
+ const pairs = [];
64
+ for (let i = 0; i < maxPairs; i++) {
65
+ pairs.push({
66
+ frontend: basePort + (i * 2), // 3000, 3002, 3004...
67
+ backend: basePort + (i * 2) + 1 // 3001, 3003, 3005...
68
+ });
69
+ }
70
+ // Check all ports in parallel (both frontend and backend ports)
71
+ const allPorts = pairs.flatMap(p => [p.frontend, p.backend]);
72
+ const results = await Promise.all(allPorts.map(async (port) => ({ port, available: await isPortAvailable(port) })));
73
+ // Build a set of available ports for O(1) lookup
74
+ const availablePorts = new Set(results.filter(r => r.available).map(r => r.port));
75
+ // Find first pair where both ports are available
76
+ for (const pair of pairs) {
77
+ if (availablePorts.has(pair.frontend) && availablePorts.has(pair.backend)) {
78
+ return pair;
79
+ }
80
+ }
81
+ throw new Error(`No available port pairs found starting from ${startPort}`);
82
+ }
83
+ //# sourceMappingURL=port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port.js","sourceRoot":"","sources":["../../../server/utils/port.ts"],"names":[],"mappings":"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"}