@lujoai/lujo-mcp 0.7.5 → 0.7.7

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/bin/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  // lujo-mcp-server launcher — locates the platform-specific binary in the companion
3
- // lujo-mcp-<platform>-<arch> package and spawns it as the MCP stdio server.
3
+ // lujo-mcp-<platform>-<arch> package and starts the local unified server.
4
4
  //
5
5
  // Mirrors the pattern used by esbuild/@biomejs/@nuphus: the root package is a thin
6
6
  // meta package whose optionalDependencies install only the binary for the current
@@ -87,7 +87,11 @@ or reinstall the meta package:
87
87
  npm install -g @lujoai/lujo-mcp`);
88
88
  process.exit(1);
89
89
  }
90
- const child = spawn(bin, process.argv.slice(2), {
90
+ // npm users get the useful local mode out of the box: one process serves both
91
+ // MCP stdio and localhost HTTP, so Browser SDK /ingest events are immediately
92
+ // visible to the MCP client. Keep an explicit --no-http escape hatch for
93
+ // clients that require a pure stdio process (and for release smoke tests).
94
+ const child = spawn(bin, translateArgs(process.argv.slice(2)), {
91
95
  stdio: 'inherit',
92
96
  windowsHide: true,
93
97
  });
@@ -95,10 +99,53 @@ or reinstall the meta package:
95
99
  console.error(`[lujo-mcp-server] failed to spawn ${bin}: ${err.message}`);
96
100
  process.exit(1);
97
101
  });
102
+
103
+ // FIX(R8): 终止信号必须转发。宿主(Claude / Codex / Trae 等)停止 MCP 服务
104
+ // 时只处理它直接启动的那个进程——也就是本启动器——被 spawn 出来的二进制不会
105
+ // 被自动带走(Windows 没有 POSIX 的进程组/信号语义,实测杀掉启动器后二进制
106
+ // 存活并继续监听统一模式的 HTTP 端口)。孤儿会接收浏览器 SDK 发往该端口的
107
+ // 全部上报,新起的实例抢不到端口,当前会话因此表现为「报过错但
108
+ // diagnose_issue 查不到任何现场」。
109
+ // 子进程自身退出时由下面的 exit 处理器决定本进程退出码,这里只负责带离。
110
+ let forwarding = false;
111
+ function forward(signal) {
112
+ if (forwarding) return;
113
+ forwarding = true;
114
+ try {
115
+ child.kill(signal);
116
+ } catch {
117
+ // 子进程可能已经退出:无需要做的,交给 exit 兜底
118
+ }
119
+ }
120
+ // Windows 收不到 SIGTERM/SIGHUP(注册无害且永不触发),但能收到 SIGBREAK。
121
+ for (const sig of ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGBREAK']) {
122
+ process.on(sig, () => forward('SIGTERM'));
123
+ }
124
+ process.on('uncaughtException', (err) => {
125
+ console.error(`[lujo-mcp-server] launcher error: ${err && err.message}`);
126
+ forward('SIGTERM');
127
+ process.exit(1);
128
+ });
129
+ // 任何原因导致的本进程退出(含上面的 process.exit 路径)都不能把子进程留下。
130
+ process.on('exit', () => forward('SIGTERM'));
131
+
98
132
  child.on('exit', (code, signal) => {
99
133
  if (signal) process.kill(process.pid, signal);
100
134
  else process.exit(code == null ? 0 : code);
101
135
  });
102
136
  }
103
137
 
104
- run();
138
+ // 参数拼装与 npm 默认模式:抽出以便在无平台二进制的环境下直接单测。
139
+ function translateArgs(requestedArgs) {
140
+ const args = Array.isArray(requestedArgs) ? requestedArgs.slice() : [];
141
+ const disableHttp = args.includes('--no-http');
142
+ const childArgs = args.filter((arg) => arg !== '--no-http');
143
+ if (!disableHttp && !childArgs.includes('--http')) childArgs.push('--http');
144
+ return childArgs;
145
+ }
146
+
147
+ if (require.main === module) {
148
+ run();
149
+ }
150
+
151
+ module.exports = { platformPackageName, translateArgs, binaryNameFor };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * lujo-mcp Browser SDK v0.7.5
2
+ * lujo-mcp Browser SDK v0.7.7
3
3
  *
4
4
  * 版本以 browser-sdk/package.json 的 version 为准(本注释仅为可读性,
5
5
  * 升级时随版本 bump 一并更新,避免再次漂移)。
@@ -861,6 +861,8 @@
861
861
  message: String(msg),
862
862
  frames: frames,
863
863
  trace_id: _traceId,
864
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
865
+ session_id: _sessionId,
864
866
  source: "browser-sdk",
865
867
  extra: {
866
868
  session_id: _sessionId,
@@ -906,6 +908,8 @@
906
908
  message: message,
907
909
  frames: frames,
908
910
  trace_id: _traceId,
911
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
912
+ session_id: _sessionId,
909
913
  source: "browser-sdk",
910
914
  extra: {
911
915
  session_id: _sessionId,
@@ -1042,6 +1046,8 @@
1042
1046
  _send("/ingest/network", {
1043
1047
  record: record,
1044
1048
  trace_id: _traceId,
1049
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
1050
+ session_id: _sessionId,
1045
1051
  source: "browser-sdk",
1046
1052
  extra: { session_id: _sessionId },
1047
1053
  }, force);
@@ -1478,6 +1484,8 @@
1478
1484
  _send("/ingest/ui-event", {
1479
1485
  event: uiEvent,
1480
1486
  trace_id: _traceId,
1487
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
1488
+ session_id: _sessionId,
1481
1489
  source: "browser-sdk",
1482
1490
  extra: { session_id: _sessionId },
1483
1491
  });
@@ -1543,6 +1551,8 @@
1543
1551
  level: level,
1544
1552
  message: messages.join(" "),
1545
1553
  trace_id: _traceId,
1554
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
1555
+ session_id: _sessionId,
1546
1556
  source: "browser-sdk",
1547
1557
  extra: {
1548
1558
  session_id: _sessionId,
@@ -1765,6 +1775,8 @@
1765
1775
  observed: silentPayload.observed,
1766
1776
  observed_events: silentPayload.observed_events,
1767
1777
  trace_id: silentPayload.trace_id,
1778
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
1779
+ session_id: _sessionId,
1768
1780
  source: silentPayload.source,
1769
1781
  extra: silentPayload.extra,
1770
1782
  }, true);
@@ -1792,6 +1804,8 @@
1792
1804
  message: error ? error.message || String(error) : "",
1793
1805
  frames: error && error.stack ? _parseStack(error.stack) : [],
1794
1806
  trace_id: _traceId,
1807
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
1808
+ session_id: _sessionId,
1795
1809
  source: "browser-sdk",
1796
1810
  extra: Object.assign({
1797
1811
  session_id: _sessionId,
@@ -1815,6 +1829,8 @@
1815
1829
  route_path: event.route_path || (global.location ? global.location.pathname : ""),
1816
1830
  },
1817
1831
  trace_id: _traceId,
1832
+ // FIX: R2 —— session_id 上移到顶层规范位置(extra 内保留兼容旧服务端)
1833
+ session_id: _sessionId,
1818
1834
  source: "browser-sdk",
1819
1835
  extra: { session_id: _sessionId },
1820
1836
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lujoai/lujo-mcp",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "description": "Lujo-MCP — MCP Runtime Debugging Context Server for AI coding agents. Gives Claude, Cursor, Trae and any MCP-compatible client real runtime debugging context: browser errors, console logs, network failures, UI interaction traces and session context. Zero-config, install via npm.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -43,8 +43,8 @@
43
43
  "prepublishOnly": "node ./scripts/check-clean-bin.js"
44
44
  },
45
45
  "optionalDependencies": {
46
- "@lujoai/lujo-mcp-win32-x64": "0.7.5",
47
- "@lujoai/lujo-mcp-linux-x64": "0.7.5",
48
- "@lujoai/lujo-mcp-osx-arm64": "0.7.5"
46
+ "@lujoai/lujo-mcp-win32-x64": "0.7.7",
47
+ "@lujoai/lujo-mcp-linux-x64": "0.7.7",
48
+ "@lujoai/lujo-mcp-osx-arm64": "0.7.7"
49
49
  }
50
50
  }