staff-mcp 1.0.28 → 1.0.29

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.
@@ -0,0 +1,32 @@
1
+ interface SignalSource {
2
+ on(event: NodeJS.Signals, listener: () => void): unknown;
3
+ removeListener(event: NodeJS.Signals, listener: () => void): unknown;
4
+ }
5
+ export interface DockerProxyOptions {
6
+ command?: string;
7
+ commandPrefixArgs?: readonly string[];
8
+ input?: NodeJS.ReadableStream;
9
+ signalSource?: SignalSource;
10
+ gracefulShutdownTimeoutMs?: number;
11
+ containerIdWaitTimeoutMs?: number;
12
+ containerCleanupTimeoutMs?: number;
13
+ forceKillTimeoutMs?: number;
14
+ }
15
+ /**
16
+ * Reject Docker options that would detach the CLI or disable the lifecycle
17
+ * guarantees managed by staff-mcp. This validator is intentionally applied to
18
+ * user-supplied Docker options only, because the command executed inside the
19
+ * container can legitimately contain similarly named flags.
20
+ */
21
+ export declare function validateAdditionalDockerArgs(args: readonly string[]): void;
22
+ /**
23
+ * Run the Docker-compatible CLI and keep its lifecycle tied to this process.
24
+ *
25
+ * For stdio transport, the caller's stdin remains the MCP data channel. For
26
+ * HTTP/reverse transports, child.stdin is intentionally kept open as a private
27
+ * lifecycle pipe instead of being connected to process.stdin. This allows the
28
+ * service to run under PM2/systemd/Supervisor even when fd 0 is /dev/null, while
29
+ * still making the container exit if the host proxy disappears unexpectedly.
30
+ */
31
+ export declare function runDockerProxy(dockerArgs: readonly string[], transport: string, options?: DockerProxyOptions): Promise<number>;
32
+ export {};
@@ -0,0 +1,492 @@
1
+ import { spawn } from "node:child_process";
2
+ import { randomUUID } from "node:crypto";
3
+ import * as fs from "node:fs";
4
+ import * as os from "node:os";
5
+ import * as path from "node:path";
6
+ const HANDLED_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
7
+ const DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT_MS = 20_000;
8
+ const DEFAULT_CONTAINER_ID_WAIT_TIMEOUT_MS = 1_000;
9
+ const DEFAULT_CONTAINER_CLEANUP_TIMEOUT_MS = 20_000;
10
+ const DEFAULT_FORCE_KILL_TIMEOUT_MS = 5_000;
11
+ const CONTAINER_ID_POLL_INTERVAL_MS = 50;
12
+ function exitCodeFromSignal(signal) {
13
+ switch (signal) {
14
+ case "SIGHUP":
15
+ return 129;
16
+ case "SIGINT":
17
+ return 130;
18
+ case "SIGKILL":
19
+ return 137;
20
+ case "SIGTERM":
21
+ return 143;
22
+ default:
23
+ return 1;
24
+ }
25
+ }
26
+ function hasManagedIdentityArg(args) {
27
+ return args.some((arg) => arg === "--cidfile" ||
28
+ arg.startsWith("--cidfile=") ||
29
+ arg === "--name" ||
30
+ arg.startsWith("--name="));
31
+ }
32
+ function prepareContainerIdentity(dockerArgs) {
33
+ const args = [...dockerArgs];
34
+ if (hasManagedIdentityArg(args)) {
35
+ throw new Error("--cidfile and --name are managed internally by staff-mcp.");
36
+ }
37
+ const runIndex = args.indexOf("run");
38
+ if (runIndex < 0) {
39
+ throw new Error("Docker proxy arguments must contain the 'run' subcommand.");
40
+ }
41
+ const ownedDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "staff-mcp-container-"));
42
+ const cidFilePath = path.join(ownedDirectory, "container.cid");
43
+ const containerName = `staff-mcp-${process.pid}-${randomUUID()}`;
44
+ args.splice(runIndex + 1, 0, "--cidfile", cidFilePath, "--name", containerName);
45
+ return { args, cidFilePath, containerName, ownedDirectory };
46
+ }
47
+ function readContainerId(cidFilePath) {
48
+ try {
49
+ const containerId = fs.readFileSync(cidFilePath, "utf8").trim();
50
+ return /^[a-f0-9]{64}$/i.test(containerId) ? containerId : undefined;
51
+ }
52
+ catch (error) {
53
+ const code = error.code;
54
+ if (code === "ENOENT") {
55
+ return undefined;
56
+ }
57
+ console.error(`[staff-mcp] Failed to read Docker cidfile '${cidFilePath}':`, error);
58
+ return undefined;
59
+ }
60
+ }
61
+ function delay(milliseconds) {
62
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
63
+ }
64
+ function isMissingContainerError(stderr) {
65
+ return /no such container|no container with (?:name or id|id|name).*found|container .* does not exist/i.test(stderr);
66
+ }
67
+ /**
68
+ * Reject Docker options that would detach the CLI or disable the lifecycle
69
+ * guarantees managed by staff-mcp. This validator is intentionally applied to
70
+ * user-supplied Docker options only, because the command executed inside the
71
+ * container can legitimately contain similarly named flags.
72
+ */
73
+ export function validateAdditionalDockerArgs(args) {
74
+ for (const arg of args) {
75
+ const normalized = arg.toLowerCase();
76
+ const isShortDetachOption = (/^-[^-][a-z]*$/i.test(arg) && arg.slice(1).includes("d")) || normalized.startsWith("-d=");
77
+ if (isShortDetachOption ||
78
+ normalized === "--detach" ||
79
+ (normalized.startsWith("--detach=") && normalized !== "--detach=false")) {
80
+ throw new Error("detached containers are not supported by the staff-mcp Docker proxy");
81
+ }
82
+ if (normalized.startsWith("--rm=") && !["--rm=true", "--rm=t", "--rm=1"].includes(normalized)) {
83
+ throw new Error("--rm cannot be disabled by the staff-mcp Docker proxy");
84
+ }
85
+ if (normalized.startsWith("--interactive=") &&
86
+ !["--interactive=true", "--interactive=t", "--interactive=1"].includes(normalized)) {
87
+ throw new Error("interactive stdin cannot be disabled by the staff-mcp Docker proxy");
88
+ }
89
+ if (/^-[^-]*i[^=]*=/.test(arg)) {
90
+ throw new Error("assigned -i values are not supported; use -i or --interactive=true");
91
+ }
92
+ if (normalized === "--cidfile" ||
93
+ normalized.startsWith("--cidfile=") ||
94
+ normalized === "--name" ||
95
+ normalized.startsWith("--name=")) {
96
+ throw new Error("--cidfile and --name are managed internally by staff-mcp");
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Run the Docker-compatible CLI and keep its lifecycle tied to this process.
102
+ *
103
+ * For stdio transport, the caller's stdin remains the MCP data channel. For
104
+ * HTTP/reverse transports, child.stdin is intentionally kept open as a private
105
+ * lifecycle pipe instead of being connected to process.stdin. This allows the
106
+ * service to run under PM2/systemd/Supervisor even when fd 0 is /dev/null, while
107
+ * still making the container exit if the host proxy disappears unexpectedly.
108
+ */
109
+ export async function runDockerProxy(dockerArgs, transport, options = {}) {
110
+ const command = options.command ?? "docker";
111
+ const commandPrefixArgs = [...(options.commandPrefixArgs ?? [])];
112
+ const input = options.input ?? process.stdin;
113
+ const signalSource = options.signalSource ?? process;
114
+ const gracefulShutdownTimeoutMs = options.gracefulShutdownTimeoutMs ?? DEFAULT_GRACEFUL_SHUTDOWN_TIMEOUT_MS;
115
+ const containerIdWaitTimeoutMs = options.containerIdWaitTimeoutMs ?? DEFAULT_CONTAINER_ID_WAIT_TIMEOUT_MS;
116
+ const containerCleanupTimeoutMs = options.containerCleanupTimeoutMs ?? DEFAULT_CONTAINER_CLEANUP_TIMEOUT_MS;
117
+ const forceKillTimeoutMs = options.forceKillTimeoutMs ?? DEFAULT_FORCE_KILL_TIMEOUT_MS;
118
+ let containerIdentity;
119
+ try {
120
+ containerIdentity = prepareContainerIdentity(dockerArgs);
121
+ }
122
+ catch (error) {
123
+ const message = error instanceof Error ? error.message : String(error);
124
+ console.error(`[staff-mcp] Failed to prepare Docker proxy: ${message}`);
125
+ return 1;
126
+ }
127
+ return new Promise((resolve) => {
128
+ let child;
129
+ let cleanupChild;
130
+ let runExit;
131
+ let trackedContainerId;
132
+ let settled = false;
133
+ let shutdownStarted = false;
134
+ let shutdownActivated = false;
135
+ let cleanupInProgress = false;
136
+ let cleanupAttempted = false;
137
+ let containerCleanupConfirmed = false;
138
+ let cleanupFailed = false;
139
+ let escalationPromise;
140
+ let gracefulTimer;
141
+ let postCleanupTimer;
142
+ let postCleanupFinalTimer;
143
+ let cidPollTimer;
144
+ const signalHandlers = new Map();
145
+ const captureContainerId = () => {
146
+ if (!trackedContainerId) {
147
+ trackedContainerId = readContainerId(containerIdentity.cidFilePath);
148
+ }
149
+ return trackedContainerId;
150
+ };
151
+ const isChildRunning = () => child !== undefined && child.exitCode === null && child.signalCode === null;
152
+ const removeListeners = () => {
153
+ for (const [signal, handler] of signalHandlers) {
154
+ signalSource.removeListener(signal, handler);
155
+ }
156
+ signalHandlers.clear();
157
+ if (transport === "stdio" && child?.stdin) {
158
+ input.unpipe(child.stdin);
159
+ input.removeListener("end", handleInputEnd);
160
+ input.removeListener("error", handleInputError);
161
+ }
162
+ };
163
+ const finish = (exitCode) => {
164
+ if (settled) {
165
+ return;
166
+ }
167
+ settled = true;
168
+ if (gracefulTimer) {
169
+ clearTimeout(gracefulTimer);
170
+ }
171
+ if (postCleanupTimer) {
172
+ clearTimeout(postCleanupTimer);
173
+ }
174
+ if (postCleanupFinalTimer) {
175
+ clearTimeout(postCleanupFinalTimer);
176
+ }
177
+ if (cidPollTimer) {
178
+ clearInterval(cidPollTimer);
179
+ }
180
+ removeListeners();
181
+ try {
182
+ fs.rmSync(containerIdentity.ownedDirectory, { recursive: true, force: true });
183
+ }
184
+ catch (error) {
185
+ console.error(`[staff-mcp] Failed to remove temporary cidfile directory '${containerIdentity.ownedDirectory}':`, error);
186
+ }
187
+ resolve(exitCode);
188
+ };
189
+ const maybeFinish = () => {
190
+ if (!runExit || cleanupInProgress) {
191
+ return;
192
+ }
193
+ finish(cleanupFailed ? 1 : (runExit.code ?? exitCodeFromSignal(runExit.signal)));
194
+ };
195
+ const closeLifecyclePipe = () => {
196
+ if (!child?.stdin) {
197
+ return;
198
+ }
199
+ if (transport === "stdio") {
200
+ input.unpipe(child.stdin);
201
+ }
202
+ if (!child.stdin.destroyed && !child.stdin.writableEnded) {
203
+ child.stdin.end();
204
+ }
205
+ };
206
+ const waitForContainerId = async () => {
207
+ const deadline = Date.now() + containerIdWaitTimeoutMs;
208
+ let containerId = captureContainerId();
209
+ while (!containerId && isChildRunning() && Date.now() < deadline) {
210
+ await delay(Math.min(CONTAINER_ID_POLL_INTERVAL_MS, Math.max(1, deadline - Date.now())));
211
+ containerId = captureContainerId();
212
+ }
213
+ return containerId;
214
+ };
215
+ const forceRemoveContainer = (containerId) => new Promise((resolveCleanup) => {
216
+ let completed = false;
217
+ let cleanupSpawned = false;
218
+ let cleanupTimer;
219
+ let cleanupForceTimer;
220
+ let cleanupFinalTimer;
221
+ let stderr = "";
222
+ const complete = (success) => {
223
+ if (completed) {
224
+ return;
225
+ }
226
+ completed = true;
227
+ if (cleanupTimer) {
228
+ clearTimeout(cleanupTimer);
229
+ }
230
+ if (cleanupForceTimer) {
231
+ clearTimeout(cleanupForceTimer);
232
+ }
233
+ if (cleanupFinalTimer) {
234
+ clearTimeout(cleanupFinalTimer);
235
+ }
236
+ cleanupChild = undefined;
237
+ resolveCleanup(success);
238
+ };
239
+ try {
240
+ cleanupChild = spawn(command, [...commandPrefixArgs, "rm", "-f", containerId], {
241
+ stdio: ["ignore", "ignore", "pipe"],
242
+ });
243
+ }
244
+ catch (error) {
245
+ console.error(`[staff-mcp] Failed to start fallback container cleanup for ${containerId}:`, error);
246
+ complete(false);
247
+ return;
248
+ }
249
+ cleanupChild.once("spawn", () => {
250
+ cleanupSpawned = true;
251
+ });
252
+ cleanupChild.stderr?.on("data", (chunk) => {
253
+ if (stderr.length < 8_192) {
254
+ stderr += chunk.toString();
255
+ }
256
+ });
257
+ cleanupChild.once("error", (error) => {
258
+ console.error(`[staff-mcp] Failed to run fallback container cleanup for ${containerId}: ${error.message}`);
259
+ if (!cleanupSpawned && cleanupChild?.pid === undefined) {
260
+ complete(false);
261
+ }
262
+ });
263
+ cleanupChild.once("close", (code, signal) => {
264
+ if (completed) {
265
+ return;
266
+ }
267
+ const detail = stderr.trim();
268
+ if (code === 0 || isMissingContainerError(detail)) {
269
+ console.error(`[staff-mcp] Fallback container cleanup completed for ${containerId}.`);
270
+ complete(true);
271
+ return;
272
+ }
273
+ console.error(`[staff-mcp] Fallback container cleanup failed for ${containerId}: code ${code ?? "null"}` +
274
+ `${signal ? `, signal ${signal}` : ""}${detail ? `, ${detail}` : ""}`);
275
+ complete(false);
276
+ });
277
+ cleanupTimer = setTimeout(() => {
278
+ console.error(`[staff-mcp] Fallback container cleanup for ${containerId} exceeded ${containerCleanupTimeoutMs}ms; sending SIGTERM.`);
279
+ cleanupChild?.kill("SIGTERM");
280
+ cleanupForceTimer = setTimeout(() => {
281
+ if (!completed) {
282
+ console.error(`[staff-mcp] Fallback container cleanup for ${containerId} did not stop within an additional ${forceKillTimeoutMs}ms; sending SIGKILL.`);
283
+ cleanupChild?.kill("SIGKILL");
284
+ cleanupFinalTimer = setTimeout(() => {
285
+ if (!completed) {
286
+ console.error(`[staff-mcp] Fallback container cleanup for ${containerId} did not report completion after SIGKILL.`);
287
+ complete(false);
288
+ }
289
+ }, forceKillTimeoutMs);
290
+ }
291
+ }, forceKillTimeoutMs);
292
+ }, containerCleanupTimeoutMs);
293
+ });
294
+ const scheduleRunCliTermination = () => {
295
+ if (!isChildRunning() || postCleanupTimer) {
296
+ return;
297
+ }
298
+ child.kill("SIGTERM");
299
+ postCleanupTimer = setTimeout(() => {
300
+ if (!isChildRunning()) {
301
+ return;
302
+ }
303
+ console.error(`[staff-mcp] Docker CLI did not exit within ${forceKillTimeoutMs}ms; sending SIGKILL.`);
304
+ child.kill("SIGKILL");
305
+ postCleanupFinalTimer = setTimeout(() => {
306
+ if (!runExit && isChildRunning()) {
307
+ console.error("[staff-mcp] Docker CLI did not report completion after SIGKILL.");
308
+ cleanupFailed = true;
309
+ runExit = { code: 1, signal: null };
310
+ maybeFinish();
311
+ }
312
+ }, forceKillTimeoutMs);
313
+ }, forceKillTimeoutMs);
314
+ };
315
+ const escalateShutdown = () => {
316
+ if (escalationPromise) {
317
+ return escalationPromise;
318
+ }
319
+ escalationPromise = (async () => {
320
+ if (gracefulTimer) {
321
+ clearTimeout(gracefulTimer);
322
+ gracefulTimer = undefined;
323
+ }
324
+ if (!isChildRunning()) {
325
+ return;
326
+ }
327
+ if (containerCleanupConfirmed || cleanupAttempted) {
328
+ scheduleRunCliTermination();
329
+ return;
330
+ }
331
+ const containerId = await waitForContainerId();
332
+ if (!isChildRunning()) {
333
+ return;
334
+ }
335
+ if (!containerId) {
336
+ // Do not treat "no such container" as successful cleanup while the
337
+ // Docker CLI may still be pulling an image or creating the container.
338
+ // Stop the CLI first; its close handler will then remove the unique
339
+ // generated name after no further create request can be issued.
340
+ console.error(`[staff-mcp] Docker cidfile was unavailable; terminating the CLI before cleaning up '${containerIdentity.containerName}'.`);
341
+ scheduleRunCliTermination();
342
+ return;
343
+ }
344
+ cleanupInProgress = true;
345
+ cleanupAttempted = true;
346
+ const removed = await forceRemoveContainer(containerId);
347
+ cleanupInProgress = false;
348
+ if (removed) {
349
+ containerCleanupConfirmed = true;
350
+ cleanupFailed = false;
351
+ // Once the exact tracked container has been removed, it is safe to
352
+ // terminate a stuck CLI.
353
+ }
354
+ else {
355
+ cleanupFailed = true;
356
+ console.error(`[staff-mcp] Container ${containerId} could not be confirmed removed; terminating the stuck Docker CLI with an error status.`);
357
+ }
358
+ scheduleRunCliTermination();
359
+ maybeFinish();
360
+ })().finally(() => {
361
+ escalationPromise = undefined;
362
+ });
363
+ return escalationPromise;
364
+ };
365
+ const activateShutdown = () => {
366
+ if (!shutdownStarted || shutdownActivated || !child) {
367
+ return;
368
+ }
369
+ shutdownActivated = true;
370
+ closeLifecyclePipe();
371
+ gracefulTimer = setTimeout(() => {
372
+ if (!isChildRunning()) {
373
+ return;
374
+ }
375
+ console.error(`[staff-mcp] Docker proxy did not exit within ${gracefulShutdownTimeoutMs}ms; removing its tracked container.`);
376
+ void escalateShutdown();
377
+ }, gracefulShutdownTimeoutMs);
378
+ };
379
+ const requestShutdown = (reason, repeatedSignal = false) => {
380
+ if (settled) {
381
+ return;
382
+ }
383
+ if (!shutdownStarted) {
384
+ shutdownStarted = true;
385
+ console.error(`[staff-mcp] Docker proxy shutdown requested: ${reason}`);
386
+ activateShutdown();
387
+ return;
388
+ }
389
+ if (repeatedSignal) {
390
+ console.error(`[staff-mcp] Repeated shutdown signal received: ${reason}`);
391
+ void escalateShutdown();
392
+ }
393
+ };
394
+ function handleInputEnd() {
395
+ requestShutdown("stdio input closed");
396
+ }
397
+ function handleInputError(error) {
398
+ console.error(`[staff-mcp] Docker proxy input error: ${error.message}`);
399
+ requestShutdown("stdio input error");
400
+ }
401
+ for (const signal of HANDLED_SIGNALS) {
402
+ const handler = () => requestShutdown(`received ${signal}`, true);
403
+ signalHandlers.set(signal, handler);
404
+ signalSource.on(signal, handler);
405
+ }
406
+ try {
407
+ child = spawn(command, [...commandPrefixArgs, ...containerIdentity.args], {
408
+ stdio: ["pipe", "inherit", "inherit"],
409
+ });
410
+ }
411
+ catch (error) {
412
+ const message = error instanceof Error ? error.message : String(error);
413
+ console.error(`[staff-mcp] Failed to start docker proxy: ${message}`);
414
+ finish(1);
415
+ return;
416
+ }
417
+ if (!child.stdin) {
418
+ console.error("[staff-mcp] Failed to start docker proxy: child stdin is unavailable.");
419
+ child.kill("SIGKILL");
420
+ finish(1);
421
+ return;
422
+ }
423
+ child.stdin.on("error", (error) => {
424
+ if (!settled && error.code !== "EPIPE") {
425
+ console.error(`[staff-mcp] Docker proxy stdin error: ${error.message}`);
426
+ }
427
+ });
428
+ child.once("error", (error) => {
429
+ if (settled) {
430
+ return;
431
+ }
432
+ if (child?.pid === undefined) {
433
+ console.error(`[staff-mcp] Failed to start docker proxy: ${error.message}`);
434
+ finish(1);
435
+ return;
436
+ }
437
+ console.error(`[staff-mcp] Docker proxy process error: ${error.message}`);
438
+ cleanupFailed = true;
439
+ requestShutdown("Docker proxy process error", true);
440
+ });
441
+ child.once("close", (code, signal) => {
442
+ if (settled) {
443
+ return;
444
+ }
445
+ captureContainerId();
446
+ runExit = { code, signal };
447
+ if (gracefulTimer) {
448
+ clearTimeout(gracefulTimer);
449
+ }
450
+ if (postCleanupTimer) {
451
+ clearTimeout(postCleanupTimer);
452
+ }
453
+ if (postCleanupFinalTimer) {
454
+ clearTimeout(postCleanupFinalTimer);
455
+ }
456
+ console.error(`[staff-mcp] Docker proxy exited with code ${code ?? "null"}${signal ? ` (signal ${signal})` : ""}.`);
457
+ // If a supervisor killed the Docker CLI directly, --rm may not have
458
+ // completed. Clean up by exact ID when available, otherwise use the
459
+ // unique generated name that was part of the container-create request.
460
+ if (!cleanupInProgress &&
461
+ !cleanupAttempted &&
462
+ !containerCleanupConfirmed &&
463
+ (signal !== null || code !== 0)) {
464
+ const cleanupReference = trackedContainerId ?? containerIdentity.containerName;
465
+ cleanupInProgress = true;
466
+ cleanupAttempted = true;
467
+ void forceRemoveContainer(cleanupReference)
468
+ .then((removed) => {
469
+ containerCleanupConfirmed = removed;
470
+ cleanupFailed = !removed;
471
+ })
472
+ .finally(() => {
473
+ cleanupInProgress = false;
474
+ maybeFinish();
475
+ });
476
+ return;
477
+ }
478
+ maybeFinish();
479
+ });
480
+ cidPollTimer = setInterval(captureContainerId, CONTAINER_ID_POLL_INTERVAL_MS);
481
+ cidPollTimer.unref();
482
+ if (transport === "stdio") {
483
+ input.once("end", handleInputEnd);
484
+ input.once("error", handleInputError);
485
+ input.pipe(child.stdin);
486
+ }
487
+ // A signal source can synchronously request shutdown while handlers are
488
+ // being installed (and a real OS signal can arrive during startup).
489
+ activateShutdown();
490
+ });
491
+ }
492
+ //# sourceMappingURL=docker-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-proxy.js","sourceRoot":"","sources":["../../src/docker-proxy.ts"],"names":[],"mappings":"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"}
package/dist/src/index.js CHANGED
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
3
  import * as path from "path";
4
- import * as fs from "fs";
5
4
  import * as os from "os";
6
- import { spawn } from "child_process";
7
- import { fileURLToPath } from "url";
8
5
  import { createServerFactory } from "./server.js";
6
+ import { runDockerProxy, validateAdditionalDockerArgs } from "./docker-proxy.js";
7
+ import { STAFF_MCP_PACKAGE_ROOT, STAFF_MCP_VERSION } from "./package-info.js";
9
8
  import { startStdioServer } from "./transports/stdio.js";
10
9
  import { startHttpServer } from "./transports/http.js";
11
10
  import { startReverseServer } from "./transports/reverse.js";
@@ -23,13 +22,11 @@ process.on("uncaughtException", (err) => {
23
22
  process.on("unhandledRejection", (reason, promise) => {
24
23
  console.error("[staff-mcp] Unhandled Rejection at:", promise, "reason:", reason);
25
24
  });
26
- const __filename = fileURLToPath(import.meta.url);
27
- const __dirname = path.dirname(__filename);
28
25
  const program = new Command();
29
26
  program
30
27
  .name("staff-mcp")
31
28
  .description("MCP Server with file, shell, and LSP capabilities.")
32
- .version("1.0.0")
29
+ .version(STAFF_MCP_VERSION)
33
30
  .option("-t, --transport <type>", "Transport type (stdio, http, reverse)", "stdio")
34
31
  .option("-p, --port <number>", "Port for HTTP server", "3000")
35
32
  .option("-h, --host <address>", "Host for HTTP server", "127.0.0.1")
@@ -50,10 +47,7 @@ program
50
47
  // -------------------------------------------------------------
51
48
  if (options.docker) {
52
49
  // 1. Locate the package root (where package.json is)
53
- let pkgRoot = path.resolve(__dirname, "..");
54
- while (!fs.existsSync(path.join(pkgRoot, "package.json")) && pkgRoot !== "/") {
55
- pkgRoot = path.dirname(pkgRoot);
56
- }
50
+ const pkgRoot = STAFF_MCP_PACKAGE_ROOT;
57
51
  // 2. Cross-platform path normalizer for Volume Mounts
58
52
  const toDockerVolumePath = (p) => {
59
53
  if (os.platform() === "win32") {
@@ -98,13 +92,23 @@ program
98
92
  }
99
93
  // 6. Inject advanced custom args (e.g., ADB pass-through, network configs)
100
94
  if (options.dockerArgs && options.dockerArgs.length > 0) {
95
+ const additionalDockerArgs = [];
101
96
  // commander parses varargs as an array of strings
102
97
  options.dockerArgs.forEach((arg) => {
103
98
  // simple split by space if the user quoted them (e.g., "-e FOO=1")
104
99
  // If the user uses standard bash expansion, commander already handles it.
105
100
  const parts = arg.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || [arg];
106
- parts.forEach(p => dockerArgs.push(p.replace(/^['"]|['"]$/g, '')));
101
+ parts.forEach((part) => additionalDockerArgs.push(part.replace(/^['"]|['"]$/g, "")));
107
102
  });
103
+ try {
104
+ validateAdditionalDockerArgs(additionalDockerArgs);
105
+ }
106
+ catch (error) {
107
+ const message = error instanceof Error ? error.message : String(error);
108
+ console.error(`[staff-mcp] Invalid Docker arguments: ${message}`);
109
+ process.exit(1);
110
+ }
111
+ dockerArgs.push(...additionalDockerArgs);
108
112
  }
109
113
  // 7. Inject environment variable to detect docker proxy mode
110
114
  dockerArgs.push("-e", "STAFF_MCP_IS_DOCKER=1");
@@ -142,15 +146,14 @@ program
142
146
  if (options.enableLsp) {
143
147
  dockerArgs.push("--enable-lsp");
144
148
  }
145
- // 10. Spawn Docker and pipe I/O natively
146
- const child = spawn("docker", dockerArgs, { stdio: ["pipe", "inherit", "inherit"] });
147
- process.stdin.pipe(child.stdin);
148
- child.on("exit", (code) => process.exit(code ?? 0));
149
- child.on("error", (err) => {
150
- console.error("[staff-mcp] Failed to start docker proxy:", err.message);
151
- process.exit(1);
152
- });
153
- return; // Terminate host process execution
149
+ // 10. Run Docker with transport-aware stdin and a controlled shutdown lifecycle.
150
+ // Reverse/HTTP keep a private lifecycle pipe open instead of depending on
151
+ // the supervisor's stdin, which may be /dev/null or already closed.
152
+ const exitCode = await runDockerProxy(dockerArgs, options.transport);
153
+ // Supervisors such as PM2 keep an IPC channel open, so setting exitCode is
154
+ // not sufficient to terminate after the Docker child has been reaped.
155
+ // At this point cleanup has completed, making an explicit exit safe.
156
+ process.exit(exitCode);
154
157
  }
155
158
  // -------------------------------------------------------------
156
159
  // Standard Host Mode
@@ -179,7 +182,7 @@ program
179
182
  const profile = options.profile;
180
183
  const maxMcpSessions = parseInt(options.maxMcpSessions, 10) || 5;
181
184
  const enableLsp = !!options.enableLsp;
182
- const serverFactory = createServerFactory("staff-mcp", "1.0.0", workingDir, allowedDirs, profile, maxMcpSessions, enableLsp);
185
+ const serverFactory = createServerFactory("staff-mcp", STAFF_MCP_VERSION, workingDir, allowedDirs, profile, maxMcpSessions, enableLsp);
183
186
  if (options.transport === "http") {
184
187
  await startHttpServer(serverFactory, parseInt(options.port, 10), options.host);
185
188
  }
@@ -194,5 +197,5 @@ program
194
197
  await startStdioServer(serverFactory());
195
198
  }
196
199
  });
197
- program.parse(process.argv);
200
+ await program.parseAsync(process.argv);
198
201
  //# sourceMappingURL=index.js.map