{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { parseCliOptions, printHelp } from './cli-utils.js';\nimport { LocalRelayMcpServer } from './mcpRelayServer.js';\n\nlet options: ReturnType<typeof parseCliOptions>;\ntry {\n  options = parseCliOptions(process.argv.slice(2));\n} catch (err) {\n  process.stderr.write(\n    `[webmcp-local-relay] error: ${err instanceof Error ? err.message : String(err)}\\n`\n  );\n  process.exit(1);\n}\n\nif (options.help) {\n  printHelp();\n  process.exit(0);\n}\n\nif (options.allowedOrigins.includes('*')) {\n  process.stderr.write(\n    '[webmcp-local-relay] WARNING: accepting connections from ALL host page origins. Use --widget-origin to restrict.\\n'\n  );\n}\n\nconst relay = new LocalRelayMcpServer({\n  bridgeOptions: options,\n});\n\ntry {\n  await relay.start();\n} catch (err) {\n  const message = err instanceof Error ? err.message : String(err);\n  if (message.includes('EACCES')) {\n    process.stderr.write(\n      `[webmcp-local-relay] error: insufficient permissions to bind to ${options.host}:${options.port}.\\n`\n    );\n  } else {\n    process.stderr.write(`[webmcp-local-relay] error: failed to start bridge server: ${message}\\n`);\n  }\n  process.exit(1);\n}\n\ntry {\n  await relay.startStdio();\n} catch (err) {\n  const message = err instanceof Error ? err.message : String(err);\n  process.stderr.write(`[webmcp-local-relay] error: failed to start stdio transport: ${message}\\n`);\n  process.exit(1);\n}\n\n// --- Auto-exit when the MCP client disconnects, preventing zombie processes ---\n\nlet parentCheckInterval: NodeJS.Timeout | undefined;\nlet shuttingDown = false;\n\n/**\n * Gracefully shuts down bridge and MCP server for process termination signals.\n * Force-exits after 5 seconds if graceful shutdown does not complete, preventing hangs.\n */\nconst shutdown = async (signal: string) => {\n  if (shuttingDown) {\n    return;\n  }\n  shuttingDown = true;\n  if (parentCheckInterval) {\n    clearInterval(parentCheckInterval);\n    parentCheckInterval = undefined;\n  }\n\n  // Safety net: force-exit if graceful shutdown hangs (e.g. SDK writing to a broken stdio pipe)\n  const forceExitTimer = setTimeout(() => {\n    process.stderr.write('[webmcp-local-relay] warn: graceful shutdown timed out, force exiting\\n');\n    process.exit(1);\n  }, 5_000);\n\n  process.stderr.write(`[webmcp-local-relay] received ${signal}, shutting down\\n`);\n\n  try {\n    await relay.stop();\n  } catch (err) {\n    process.stderr.write(\n      `[webmcp-local-relay] error during shutdown: ${err instanceof Error ? err.message : String(err)}\\n`\n    );\n    clearTimeout(forceExitTimer);\n    process.exit(1);\n  }\n  clearTimeout(forceExitTimer);\n  process.exit(0);\n};\n\nprocess.stdin.on('end', () => {\n  void shutdown('stdin-closed');\n});\nprocess.stdin.on('error', () => {\n  void shutdown('stdin-error');\n});\nprocess.stdout.on('error', () => {\n  void shutdown('stdout-error');\n});\n\nif (process.platform !== 'win32') {\n  parentCheckInterval = setInterval(() => {\n    if (process.ppid === 1) {\n      void shutdown('parent-exited');\n    }\n  }, 30_000);\n  parentCheckInterval.unref();\n}\n\nif (relay.bridge.mode === 'server') {\n  process.stderr.write(\n    `[webmcp-local-relay] server mode: listening on ws://${options.host}:${relay.bridge.port} (allowed origins: ${options.allowedOrigins.join(', ')})\\n`\n  );\n} else {\n  process.stderr.write(\n    `[webmcp-local-relay] client mode: proxying through existing relay at ws://${options.host}:${relay.bridge.port}\\n`\n  );\n}\n\nprocess.on('uncaughtException', (err) => {\n  process.stderr.write(\n    `[webmcp-local-relay] error: uncaught exception: ${err.stack ?? err.message}\\n`\n  );\n  void shutdown('uncaughtException');\n});\nprocess.on('unhandledRejection', (reason) => {\n  const message = reason instanceof Error ? (reason.stack ?? reason.message) : String(reason);\n  process.stderr.write(`[webmcp-local-relay] error: unhandled rejection: ${message}\\n`);\n  void shutdown('unhandledRejection');\n});\n\nprocess.on('SIGINT', () => {\n  void shutdown('SIGINT');\n});\nprocess.on('SIGTERM', () => {\n  void shutdown('SIGTERM');\n});\n"],"mappings":"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"}