@graphty/remote-logger 1.2.1 → 1.2.3
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/README.md +1 -1
- package/dist/client/RemoteLogClient.d.ts +2 -1
- package/dist/client/RemoteLogClient.d.ts.map +1 -1
- package/dist/client/RemoteLogClient.js +20 -10
- package/dist/client/RemoteLogClient.js.map +1 -1
- package/dist/client/types.d.ts +6 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +20 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-server.d.ts +5 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +6 -5
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/server/dual-server.d.ts +7 -4
- package/dist/server/dual-server.d.ts.map +1 -1
- package/dist/server/dual-server.js +123 -44
- package/dist/server/dual-server.js.map +1 -1
- package/dist/server/log-server.d.ts +2 -2
- package/dist/server/log-server.d.ts.map +1 -1
- package/dist/server/log-server.js +32 -55
- package/dist/server/log-server.js.map +1 -1
- package/dist/server/self-signed-cert.d.ts +9 -0
- package/dist/server/self-signed-cert.d.ts.map +1 -1
- package/dist/server/self-signed-cert.js +9 -0
- package/dist/server/self-signed-cert.js.map +1 -1
- package/dist/ui/ConsoleCaptureUI.d.ts.map +1 -1
- package/dist/ui/ConsoleCaptureUI.js +6 -1
- package/dist/ui/ConsoleCaptureUI.js.map +1 -1
- package/package.json +3 -1
- package/src/client/RemoteLogClient.ts +22 -11
- package/src/client/types.ts +6 -0
- package/src/mcp/index.ts +42 -0
- package/src/mcp/mcp-server.ts +6 -5
- package/src/server/dual-server.ts +165 -51
- package/src/server/log-server.ts +35 -60
- package/src/server/self-signed-cert.ts +9 -0
- package/src/ui/ConsoleCaptureUI.ts +6 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ Usage:
|
|
|
99
99
|
|
|
100
100
|
Options:
|
|
101
101
|
--port, -p <port> Port to listen on (default: 9080)
|
|
102
|
-
--host, -h <host> Hostname to bind to (default:
|
|
102
|
+
--host, -h <host> Hostname to bind to (default: 0.0.0.0)
|
|
103
103
|
--cert, -c <path> Path to SSL certificate file (enables HTTPS)
|
|
104
104
|
--key, -k <path> Path to SSL private key file (enables HTTPS)
|
|
105
105
|
--log-file, -l <path> Write logs to file (JSONL format)
|
|
@@ -38,6 +38,7 @@ export declare class RemoteLogClient {
|
|
|
38
38
|
private readonly throttlePatterns;
|
|
39
39
|
private readonly projectMarker;
|
|
40
40
|
private readonly worktreePath;
|
|
41
|
+
private readonly timeoutMs;
|
|
41
42
|
private pendingLogs;
|
|
42
43
|
private batchTimer;
|
|
43
44
|
private isClosed;
|
|
@@ -81,7 +82,7 @@ export declare class RemoteLogClient {
|
|
|
81
82
|
/**
|
|
82
83
|
* Makes the actual HTTP request to send logs.
|
|
83
84
|
* @param logs - The log entries to send
|
|
84
|
-
* @throws Error if the request fails
|
|
85
|
+
* @throws Error if the request fails or times out
|
|
85
86
|
*/
|
|
86
87
|
private sendRequest;
|
|
87
88
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteLogClient.d.ts","sourceRoot":"","sources":["../../src/client/RemoteLogClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAY,sBAAsB,EAAmB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"RemoteLogClient.d.ts","sourceRoot":"","sources":["../../src/client/RemoteLogClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAY,sBAAsB,EAAmB,MAAM,YAAY,CAAC;AAgDpF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,eAAe;IACxB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoB;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAA8B;IAElD,iEAAiE;IACjE,OAAO,CAAC,iBAAiB,CAA6B;IAEtD;;;OAGG;gBACS,OAAO,EAAE,sBAAsB;IAc3C;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAuBtB;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAqBzE;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;YACW,SAAS;IAYvB;;;OAGG;YACW,aAAa;IAuB3B;;;;OAIG;YACW,WAAW;IAwCzB;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAIb;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAU/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAEtF"}
|
|
@@ -28,6 +28,7 @@ const DEFAULT_BATCH_INTERVAL_MS = 1000;
|
|
|
28
28
|
const DEFAULT_MAX_RETRIES = 3;
|
|
29
29
|
const DEFAULT_RETRY_DELAY_MS = 1000;
|
|
30
30
|
const DEFAULT_SESSION_PREFIX = "session";
|
|
31
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
31
32
|
/**
|
|
32
33
|
* Generates a unique session ID with the given prefix.
|
|
33
34
|
* Format: {prefix}-{timestamp}-{random}
|
|
@@ -81,6 +82,7 @@ export class RemoteLogClient {
|
|
|
81
82
|
this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
82
83
|
this.retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
83
84
|
this.throttlePatterns = options.throttlePatterns ?? [];
|
|
85
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
84
86
|
// Priority: explicit option > global variable
|
|
85
87
|
this.projectMarker = options.projectMarker ?? getGlobalValue("__REMOTE_LOG_PROJECT_MARKER__");
|
|
86
88
|
this.worktreePath = options.worktreePath ?? getGlobalValue("__REMOTE_LOG_WORKTREE_PATH__");
|
|
@@ -185,7 +187,7 @@ export class RemoteLogClient {
|
|
|
185
187
|
/**
|
|
186
188
|
* Makes the actual HTTP request to send logs.
|
|
187
189
|
* @param logs - The log entries to send
|
|
188
|
-
* @throws Error if the request fails
|
|
190
|
+
* @throws Error if the request fails or times out
|
|
189
191
|
*/
|
|
190
192
|
async sendRequest(logs) {
|
|
191
193
|
const requestBody = {
|
|
@@ -199,15 +201,23 @@ export class RemoteLogClient {
|
|
|
199
201
|
if (this.worktreePath !== undefined) {
|
|
200
202
|
requestBody.worktreePath = this.worktreePath;
|
|
201
203
|
}
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
const controller = new AbortController();
|
|
205
|
+
const timeoutId = setTimeout(() => { controller.abort(); }, this.timeoutMs);
|
|
206
|
+
try {
|
|
207
|
+
const response = await fetch(`${this.serverUrl}/log`, {
|
|
208
|
+
method: "POST",
|
|
209
|
+
headers: {
|
|
210
|
+
"Content-Type": "application/json",
|
|
211
|
+
},
|
|
212
|
+
body: JSON.stringify(requestBody),
|
|
213
|
+
signal: controller.signal,
|
|
214
|
+
});
|
|
215
|
+
if (!response.ok) {
|
|
216
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
clearTimeout(timeoutId);
|
|
211
221
|
}
|
|
212
222
|
}
|
|
213
223
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteLogClient.js","sourceRoot":"","sources":["../../src/client/RemoteLogClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAsE;IAC1F,IAAI,CAAC;QACD,IAAI,IAAI,KAAK,+BAA+B,EAAE,CAAC;YAC3C,OAAO,OAAO,6BAA6B,KAAK,WAAW,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5G,CAAC;QACD,IAAI,IAAI,KAAK,8BAA8B,EAAE,CAAC;YAC1C,OAAO,OAAO,4BAA4B,KAAK,WAAW,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1G,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,qDAAqD;QACrD,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,mCAAmC;AACnC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AACvC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,sBAAsB,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"RemoteLogClient.js","sourceRoot":"","sources":["../../src/client/RemoteLogClient.ts"],"names":[],"mappings":"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"}
|
package/dist/client/types.d.ts
CHANGED
|
@@ -56,5 +56,11 @@ export interface RemoteLogClientOptions {
|
|
|
56
56
|
* __REMOTE_LOG_WORKTREE_PATH__ global variable (injected by Vite plugin).
|
|
57
57
|
*/
|
|
58
58
|
worktreePath?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Request timeout in milliseconds.
|
|
61
|
+
* Requests that take longer than this will be aborted and retried.
|
|
62
|
+
* @default 5000
|
|
63
|
+
*/
|
|
64
|
+
timeoutMs?: number;
|
|
59
65
|
}
|
|
60
66
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* @module mcp
|
|
6
6
|
*/
|
|
7
7
|
export { createMcpServer, getToolNames, startMcpServer } from "./mcp-server.js";
|
|
8
|
-
export { logsGetRecentHandler, type LogsGetRecentInput, logsGetRecentInputSchema, type LogsGetRecentOutput, logsGetRecentTool, logsListSessionsHandler, type LogsListSessionsInput, logsListSessionsInputSchema, type LogsListSessionsOutput, logsListSessionsTool, logsStatusHandler, type LogsStatusInput, logsStatusInputSchema, type LogsStatusOutput, logsStatusTool, } from "./tools/index.js";
|
|
8
|
+
export { getLogFilePath, logsClearHandler, type LogsClearInput, logsClearInputSchema, type LogsClearOutput, logsClearTool, logsGetAllHandler, type LogsGetAllInput, logsGetAllInputSchema, type LogsGetAllOutput, logsGetAllTool, logsGetErrorsHandler, type LogsGetErrorsInput, logsGetErrorsInputSchema, type LogsGetErrorsOutput, logsGetErrorsTool, logsGetFilePathHandler, type LogsGetFilePathInput, logsGetFilePathInputSchema, type LogsGetFilePathOutput, logsGetFilePathTool, logsGetRecentHandler, type LogsGetRecentInput, logsGetRecentInputSchema, type LogsGetRecentOutput, logsGetRecentTool, logsListSessionsHandler, type LogsListSessionsInput, logsListSessionsInputSchema, type LogsListSessionsOutput, logsListSessionsTool, logsReceiveHandler, type LogsReceiveInput, logsReceiveInputSchema, type LogsReceiveOutput, logsReceiveTool, logsSearchHandler, type LogsSearchInput, logsSearchInputSchema, type LogsSearchOutput, logsSearchTool, logsStatusHandler, type LogsStatusInput, logsStatusInputSchema, type LogsStatusOutput, logsStatusTool, } from "./tools/index.js";
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/mcp/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGhF,OAAO,EAEH,cAAc,EAEd,gBAAgB,EAChB,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,eAAe,EACpB,aAAa,EAEb,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,EAEd,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,mBAAmB,EAEnB,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,iBAAiB,EAEjB,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,2BAA2B,EAC3B,KAAK,sBAAsB,EAC3B,oBAAoB,EAEpB,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,eAAe,EAEf,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,EAEd,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,GACjB,MAAM,kBAAkB,CAAC"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -5,5 +5,24 @@
|
|
|
5
5
|
* @module mcp
|
|
6
6
|
*/
|
|
7
7
|
export { createMcpServer, getToolNames, startMcpServer } from "./mcp-server.js";
|
|
8
|
-
export
|
|
8
|
+
// Re-export all tool handlers, schemas, and definitions for programmatic use
|
|
9
|
+
export {
|
|
10
|
+
// logs_get_file_path
|
|
11
|
+
getLogFilePath,
|
|
12
|
+
// logs_clear
|
|
13
|
+
logsClearHandler, logsClearInputSchema, logsClearTool,
|
|
14
|
+
// logs_get_all
|
|
15
|
+
logsGetAllHandler, logsGetAllInputSchema, logsGetAllTool,
|
|
16
|
+
// logs_get_errors
|
|
17
|
+
logsGetErrorsHandler, logsGetErrorsInputSchema, logsGetErrorsTool, logsGetFilePathHandler, logsGetFilePathInputSchema, logsGetFilePathTool,
|
|
18
|
+
// logs_get_recent
|
|
19
|
+
logsGetRecentHandler, logsGetRecentInputSchema, logsGetRecentTool,
|
|
20
|
+
// logs_list_sessions
|
|
21
|
+
logsListSessionsHandler, logsListSessionsInputSchema, logsListSessionsTool,
|
|
22
|
+
// logs_receive
|
|
23
|
+
logsReceiveHandler, logsReceiveInputSchema, logsReceiveTool,
|
|
24
|
+
// logs_search
|
|
25
|
+
logsSearchHandler, logsSearchInputSchema, logsSearchTool,
|
|
26
|
+
// logs_status
|
|
27
|
+
logsStatusHandler, logsStatusInputSchema, logsStatusTool, } from "./tools/index.js";
|
|
9
28
|
//# sourceMappingURL=index.js.map
|
package/dist/mcp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEhF,6EAA6E;AAC7E,OAAO;AACH,qBAAqB;AACrB,cAAc;AACd,aAAa;AACb,gBAAgB,EAEhB,oBAAoB,EAEpB,aAAa;AACb,eAAe;AACf,iBAAiB,EAEjB,qBAAqB,EAErB,cAAc;AACd,kBAAkB;AAClB,oBAAoB,EAEpB,wBAAwB,EAExB,iBAAiB,EACjB,sBAAsB,EAEtB,0BAA0B,EAE1B,mBAAmB;AACnB,kBAAkB;AAClB,oBAAoB,EAEpB,wBAAwB,EAExB,iBAAiB;AACjB,qBAAqB;AACrB,uBAAuB,EAEvB,2BAA2B,EAE3B,oBAAoB;AACpB,eAAe;AACf,kBAAkB,EAElB,sBAAsB,EAEtB,eAAe;AACf,cAAc;AACd,iBAAiB,EAEjB,qBAAqB,EAErB,cAAc;AACd,cAAc;AACd,iBAAiB,EAEjB,qBAAqB,EAErB,cAAc,GACjB,MAAM,kBAAkB,CAAC"}
|
package/dist/mcp/mcp-server.d.ts
CHANGED
|
@@ -13,6 +13,11 @@ import type { LogStorage } from "../server/log-storage.js";
|
|
|
13
13
|
* @returns Array of registered tool names
|
|
14
14
|
*/
|
|
15
15
|
export declare function getToolNames(): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Server instructions for LLMs describing the overall purpose and usage.
|
|
18
|
+
* Exported for testing purposes.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SERVER_INSTRUCTIONS = "Remote Logger MCP Server - View console.log output from browser applications.\n\n## What is Remote Logging?\n\nBrowser applications run in a sandbox - their console.log() output appears in browser DevTools but is NOT visible to CLI tools or this assistant. Remote logging bridges this gap by sending browser logs to a server where they can be queried.\n\n## When to Use Remote Logging\n\nUse this when debugging applications where developer tools aren't easily accessible:\n- Storybook components (stories running in browser)\n- Web applications during development\n- Mobile web apps (phones, tablets) where DevTools requires USB debugging\n- VR/AR applications where you can't see a console while wearing a headset\n- Embedded devices, kiosks, or smart displays without keyboard access\n- Any JavaScript running in a browser context\n\nRemote logging is especially valuable for LLM assistants like this one - it enables reading, interpreting, and acting on application logs without requiring user interaction with browser DevTools.\n\n## Architecture\n\nBrowser App \u2192 HTTP POST to /log \u2192 Log Server (stores in memory + JSONL files) \u2192 MCP Tools (query logs)\n\n## Setting Up a Browser App to Send Logs\n\nFirst, get the server endpoint URL by calling logs_status - look for server.httpEndpoint in the response.\n\n### Option 1: Using the RemoteLogClient SDK (Recommended)\n\nInstall: npm install @graphty/remote-logger\n\n```typescript\nimport { RemoteLogClient } from \"@graphty/remote-logger\";\n\nconst logger = new RemoteLogClient({\n serverUrl: \"http://localhost:9080\", // Get this from logs_status (client appends /log)\n projectMarker: \"my-project\", // Optional: for filtering\n});\n\n// Intercept all console.log/warn/error calls\nlogger.interceptConsole();\n\n// Or log manually\nlogger.log(\"INFO\", \"Hello from browser!\");\n```\n\n### Option 2: Raw fetch() calls\n\n```typescript\nfetch(\"http://localhost:9080/log\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n sessionId: \"unique-session-id\",\n logs: [\n { time: new Date().toISOString(), level: \"INFO\", message: \"Hello!\" }\n ]\n })\n});\n```\n\n## Querying Logs (MCP Tools)\n\nOnce browser logs are flowing to the server:\n\n1. logs_status - Check server health, get endpoint URL, see retention settings\n2. logs_get_recent - View recent logs (primary tool, sorted chronologically)\n3. logs_get_errors - Quick filter for ERROR level only\n4. logs_search - Find specific text (supports regex)\n5. logs_list_sessions - See all browser sessions\n6. logs_get_all - Get all logs grouped by session\n7. logs_get_file_path - Get JSONL file path for Grep/Read tools\n8. logs_clear - Delete logs (requires confirmation)\n\n## Typical Debugging Workflow\n\n1. Call logs_status to verify server is running and get the endpoint URL\n2. Ensure the browser app is configured to send logs to that endpoint\n3. Trigger the action in the browser you want to debug\n4. Call logs_get_recent to see what happened\n5. Use logs_search if looking for specific errors or messages";
|
|
16
21
|
/**
|
|
17
22
|
* Create an MCP server with logging tools.
|
|
18
23
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAyC3D;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAyC3D;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAEvC;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,okGA+E8B,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAkM9D;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvE"}
|
package/dist/mcp/mcp-server.js
CHANGED
|
@@ -20,8 +20,9 @@ export function getToolNames() {
|
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Server instructions for LLMs describing the overall purpose and usage.
|
|
23
|
+
* Exported for testing purposes.
|
|
23
24
|
*/
|
|
24
|
-
const SERVER_INSTRUCTIONS = `Remote Logger MCP Server - View console.log output from browser applications.
|
|
25
|
+
export const SERVER_INSTRUCTIONS = `Remote Logger MCP Server - View console.log output from browser applications.
|
|
25
26
|
|
|
26
27
|
## What is Remote Logging?
|
|
27
28
|
|
|
@@ -41,7 +42,7 @@ Remote logging is especially valuable for LLM assistants like this one - it enab
|
|
|
41
42
|
|
|
42
43
|
## Architecture
|
|
43
44
|
|
|
44
|
-
Browser App → HTTP POST to /
|
|
45
|
+
Browser App → HTTP POST to /log → Log Server (stores in memory + JSONL files) → MCP Tools (query logs)
|
|
45
46
|
|
|
46
47
|
## Setting Up a Browser App to Send Logs
|
|
47
48
|
|
|
@@ -55,8 +56,8 @@ Install: npm install @graphty/remote-logger
|
|
|
55
56
|
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
56
57
|
|
|
57
58
|
const logger = new RemoteLogClient({
|
|
58
|
-
serverUrl: "http://localhost:9080
|
|
59
|
-
projectMarker: "my-project",
|
|
59
|
+
serverUrl: "http://localhost:9080", // Get this from logs_status (client appends /log)
|
|
60
|
+
projectMarker: "my-project", // Optional: for filtering
|
|
60
61
|
});
|
|
61
62
|
|
|
62
63
|
// Intercept all console.log/warn/error calls
|
|
@@ -69,7 +70,7 @@ logger.log("INFO", "Hello from browser!");
|
|
|
69
70
|
### Option 2: Raw fetch() calls
|
|
70
71
|
|
|
71
72
|
\`\`\`typescript
|
|
72
|
-
fetch("http://localhost:9080/
|
|
73
|
+
fetch("http://localhost:9080/log", {
|
|
73
74
|
method: "POST",
|
|
74
75
|
headers: { "Content-Type": "application/json" },
|
|
75
76
|
body: JSON.stringify({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/mcp/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAGjF,OAAO,EACH,gBAAgB,EAEhB,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EAEjB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EAEpB,wBAAwB,EACxB,iBAAiB,EACjB,sBAAsB,EAEtB,0BAA0B,EAC1B,mBAAmB,EACnB,oBAAoB,EAEpB,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EAEvB,2BAA2B,EAC3B,oBAAoB,EACpB,kBAAkB,EAElB,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EAEjB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,cAAc,GACjB,MAAM,kBAAkB,CAAC;AAE1B,0CAA0C;AAC1C,IAAI,eAAe,GAAa,EAAE,CAAC;AAEnC;;;;GAIG;AACH,MAAM,UAAU,YAAY;IACxB,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC;AAChC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/mcp/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* @module server/dual-server
|
|
7
7
|
*/
|
|
8
8
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
9
|
+
import * as http from "http";
|
|
10
|
+
import * as https from "https";
|
|
11
11
|
import { JsonlWriter } from "./jsonl-writer.js";
|
|
12
12
|
import { LogStorage } from "./log-storage.js";
|
|
13
13
|
/**
|
|
@@ -16,17 +16,18 @@ import { LogStorage } from "./log-storage.js";
|
|
|
16
16
|
* @param basePort - Starting port number
|
|
17
17
|
* @param host - Host to bind to
|
|
18
18
|
* @param quiet - Suppress output messages
|
|
19
|
+
* @param maxPort - Maximum port number to scan up to (default: 9099)
|
|
19
20
|
* @returns Promise resolving to available port number
|
|
20
21
|
* @throws Error if no available port found within MAX_PORT_SCAN_ATTEMPTS
|
|
21
22
|
*/
|
|
22
|
-
export declare function findAvailablePort(basePort: number, host: string, quiet?: boolean): Promise<number>;
|
|
23
|
+
export declare function findAvailablePort(basePort: number, host: string, quiet?: boolean, maxPort?: number): Promise<number>;
|
|
23
24
|
/**
|
|
24
25
|
* Options for creating a dual server.
|
|
25
26
|
*/
|
|
26
27
|
export interface DualServerOptions {
|
|
27
28
|
/** Port for HTTP server (default: 9080) */
|
|
28
29
|
httpPort?: number;
|
|
29
|
-
/** Host for HTTP server (default:
|
|
30
|
+
/** Host for HTTP server (default: 0.0.0.0) */
|
|
30
31
|
httpHost?: string;
|
|
31
32
|
/** Enable MCP server (default: true) */
|
|
32
33
|
mcpEnabled?: boolean;
|
|
@@ -46,6 +47,8 @@ export interface DualServerOptions {
|
|
|
46
47
|
jsonlWriter?: JsonlWriter;
|
|
47
48
|
/** Only serve /log POST and /health GET endpoints (default: false) */
|
|
48
49
|
logReceiveOnly?: boolean;
|
|
50
|
+
/** Maximum port number to scan up to (default: 9099) */
|
|
51
|
+
maxPortNumber?: number;
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* Result of creating a dual server.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dual-server.d.ts","sourceRoot":"","sources":["../../src/server/dual-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"dual-server.d.ts","sourceRoot":"","sources":["../../src/server/dual-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAqI/D;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,OAAe,EACtB,OAAO,GAAE,MAAwB,GAClC,OAAO,CAAC,MAAM,CAAC,CA0CjB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,iFAAiF;IACjF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,sEAAsE;IACtE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,qDAAqD;IACrD,UAAU,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IACxC,0CAA0C;IAC1C,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,kCAAkC;IAClC,OAAO,EAAE,UAAU,CAAC;IACpB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyJjG"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* @module server/dual-server
|
|
7
7
|
*/
|
|
8
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
import { internalIpV4Sync } from "internal-ip";
|
|
9
10
|
import * as net from "net";
|
|
10
11
|
import * as os from "os";
|
|
11
12
|
import * as path from "path";
|
|
@@ -26,6 +27,72 @@ const colors = {
|
|
|
26
27
|
const MAX_PORT_SCAN_ATTEMPTS = 100;
|
|
27
28
|
/** Maximum port number allowed (ports 9000-9099 per project guidelines) */
|
|
28
29
|
const MAX_PORT_NUMBER = 9099;
|
|
30
|
+
/** Maximum retries for binding after EADDRINUSE during listen */
|
|
31
|
+
const MAX_BIND_RETRIES = 10;
|
|
32
|
+
/**
|
|
33
|
+
* Attempt to bind an HTTP/HTTPS server to a port with retry on EADDRINUSE.
|
|
34
|
+
* This handles race conditions where a port becomes unavailable between
|
|
35
|
+
* port scanning and actual binding.
|
|
36
|
+
* @param serverFactory - Function to create a new server instance
|
|
37
|
+
* @param startPort - Starting port to try
|
|
38
|
+
* @param host - Host to bind to
|
|
39
|
+
* @param quiet - Suppress output messages
|
|
40
|
+
* @param maxPort - Maximum port number to scan up to (default: 9099)
|
|
41
|
+
* @returns Promise resolving to bound server and actual port
|
|
42
|
+
*/
|
|
43
|
+
async function tryBindWithRetry(serverFactory, startPort, host, quiet, maxPort = MAX_PORT_NUMBER) {
|
|
44
|
+
let port = startPort;
|
|
45
|
+
let attempts = 0;
|
|
46
|
+
while (attempts < MAX_BIND_RETRIES) {
|
|
47
|
+
if (port > maxPort) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
const server = serverFactory();
|
|
51
|
+
try {
|
|
52
|
+
await new Promise((resolve, reject) => {
|
|
53
|
+
const errorHandler = (err) => {
|
|
54
|
+
if (err.code === "EADDRINUSE") {
|
|
55
|
+
if (!quiet) {
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
console.log(`${colors.yellow}Port ${port} claimed during bind, trying ${port + 1}...${colors.reset}`);
|
|
58
|
+
}
|
|
59
|
+
reject(err);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
reject(err);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
server.once("error", errorHandler);
|
|
66
|
+
server.listen({ port, host, exclusive: false }, () => {
|
|
67
|
+
server.removeListener("error", errorHandler);
|
|
68
|
+
resolve();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
// Success - server is bound
|
|
72
|
+
if (!quiet) {
|
|
73
|
+
// eslint-disable-next-line no-console
|
|
74
|
+
console.log(`${colors.green}HTTP server listening on ${host}:${port}${colors.reset}`);
|
|
75
|
+
}
|
|
76
|
+
return { server, port };
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (err.code === "EADDRINUSE") {
|
|
80
|
+
port++;
|
|
81
|
+
attempts++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
// Re-throw non-EADDRINUSE errors
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Exhausted retries
|
|
89
|
+
const errorMsg = `Could not bind to any port after ${attempts} attempts. ` +
|
|
90
|
+
`Ports ${startPort}-${port - 1} are all in use or were claimed during bind.`;
|
|
91
|
+
if (!quiet) {
|
|
92
|
+
console.error(`${colors.red}${errorMsg}${colors.reset}`);
|
|
93
|
+
}
|
|
94
|
+
throw new Error(errorMsg);
|
|
95
|
+
}
|
|
29
96
|
/**
|
|
30
97
|
* Check if a port is available for binding.
|
|
31
98
|
* @param port - Port number to check
|
|
@@ -60,15 +127,16 @@ async function isPortAvailable(port, host) {
|
|
|
60
127
|
* @param basePort - Starting port number
|
|
61
128
|
* @param host - Host to bind to
|
|
62
129
|
* @param quiet - Suppress output messages
|
|
130
|
+
* @param maxPort - Maximum port number to scan up to (default: 9099)
|
|
63
131
|
* @returns Promise resolving to available port number
|
|
64
132
|
* @throws Error if no available port found within MAX_PORT_SCAN_ATTEMPTS
|
|
65
133
|
*/
|
|
66
|
-
export async function findAvailablePort(basePort, host, quiet = false) {
|
|
134
|
+
export async function findAvailablePort(basePort, host, quiet = false, maxPort = MAX_PORT_NUMBER) {
|
|
67
135
|
let port = basePort;
|
|
68
136
|
let attempts = 0;
|
|
69
137
|
while (attempts < MAX_PORT_SCAN_ATTEMPTS) {
|
|
70
|
-
if (port >
|
|
71
|
-
//
|
|
138
|
+
if (port > maxPort) {
|
|
139
|
+
// Stop if we exceed max port
|
|
72
140
|
break;
|
|
73
141
|
}
|
|
74
142
|
if (await isPortAvailable(port, host)) {
|
|
@@ -86,8 +154,8 @@ export async function findAvailablePort(basePort, host, quiet = false) {
|
|
|
86
154
|
attempts++;
|
|
87
155
|
}
|
|
88
156
|
// No available port found
|
|
89
|
-
const errorMsg = `Could not find available port after ${
|
|
90
|
-
`Ports ${basePort}-${port - 1} are all in use. ` +
|
|
157
|
+
const errorMsg = `Could not find available port after ${attempts} attempts starting from ${basePort}. ` +
|
|
158
|
+
`Ports ${basePort}-${Math.min(port - 1, maxPort)} are all in use. ` +
|
|
91
159
|
`Try killing existing processes: pkill -f "remote-log-server"`;
|
|
92
160
|
if (!quiet) {
|
|
93
161
|
console.error(`${colors.red}${errorMsg}${colors.reset}`);
|
|
@@ -103,7 +171,7 @@ export async function findAvailablePort(basePort, host, quiet = false) {
|
|
|
103
171
|
* @returns Promise resolving to the dual server result
|
|
104
172
|
*/
|
|
105
173
|
export async function createDualServer(options = {}) {
|
|
106
|
-
const { httpPort: requestedPort = 9080, httpHost = "
|
|
174
|
+
const { httpPort: requestedPort = 9080, httpHost = "0.0.0.0", mcpEnabled = true, httpEnabled = true, quiet = false, storage: externalStorage, jsonlWriter: externalJsonlWriter, logReceiveOnly = false, certPath, keyPath, maxPortNumber = MAX_PORT_NUMBER, } = options;
|
|
107
175
|
// Create or use provided JSONL writer
|
|
108
176
|
const jsonlBaseDir = path.join(os.tmpdir(), "remote-logger");
|
|
109
177
|
const jsonlWriter = externalJsonlWriter ?? new JsonlWriter(jsonlBaseDir);
|
|
@@ -112,48 +180,38 @@ export async function createDualServer(options = {}) {
|
|
|
112
180
|
let httpServer;
|
|
113
181
|
let mcpServer;
|
|
114
182
|
let actualHttpPort;
|
|
183
|
+
// Track active connections for graceful shutdown
|
|
184
|
+
const activeConnections = new Set();
|
|
115
185
|
// Start HTTP server if enabled
|
|
116
186
|
if (httpEnabled) {
|
|
117
187
|
// Find an available port starting from the requested port
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
await
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
console.error(`${colors.red}${errorMsg}${colors.reset}`);
|
|
141
|
-
}
|
|
142
|
-
reject(new Error(errorMsg));
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
reject(err);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
serverToStart.listen({ port: portToUse, host: httpHost, exclusive: false }, () => {
|
|
149
|
-
serverToStart.removeListener("error", reject);
|
|
150
|
-
if (!quiet) {
|
|
151
|
-
// eslint-disable-next-line no-console
|
|
152
|
-
console.log(`${colors.green}HTTP server listening on ${httpHost}:${portToUse}${colors.reset}`);
|
|
153
|
-
}
|
|
154
|
-
resolve();
|
|
188
|
+
const startPort = await findAvailablePort(requestedPort, httpHost, quiet, maxPortNumber);
|
|
189
|
+
// Factory function to create server instances (for retry on bind failure)
|
|
190
|
+
const createServerInstance = () => {
|
|
191
|
+
return createLogServer({
|
|
192
|
+
port: startPort, // Port is set but not used until bind
|
|
193
|
+
host: httpHost,
|
|
194
|
+
storage,
|
|
195
|
+
quiet: true, // Quiet during factory, messages handled by tryBindWithRetry
|
|
196
|
+
logReceiveOnly,
|
|
197
|
+
certPath,
|
|
198
|
+
keyPath,
|
|
199
|
+
}).server;
|
|
200
|
+
};
|
|
201
|
+
// Bind with retry logic to handle race conditions
|
|
202
|
+
const bindResult = await tryBindWithRetry(createServerInstance, startPort, httpHost, quiet, maxPortNumber);
|
|
203
|
+
httpServer = bindResult.server;
|
|
204
|
+
actualHttpPort = bindResult.port;
|
|
205
|
+
// Track connections for graceful shutdown
|
|
206
|
+
httpServer.on("connection", (socket) => {
|
|
207
|
+
activeConnections.add(socket);
|
|
208
|
+
socket.once("close", () => {
|
|
209
|
+
activeConnections.delete(socket);
|
|
155
210
|
});
|
|
156
211
|
});
|
|
212
|
+
// Set short keep-alive timeout for tests (connections close faster)
|
|
213
|
+
httpServer.keepAliveTimeout = 1000;
|
|
214
|
+
httpServer.headersTimeout = 2000;
|
|
157
215
|
// Set server config in storage so MCP tools can report it
|
|
158
216
|
// Determine protocol based on whether valid cert files were provided
|
|
159
217
|
const useHttps = certPath && keyPath && certFilesExist(certPath, keyPath);
|
|
@@ -169,11 +227,27 @@ export async function createDualServer(options = {}) {
|
|
|
169
227
|
else {
|
|
170
228
|
mode = "dual";
|
|
171
229
|
}
|
|
230
|
+
// When bound to all interfaces (0.0.0.0), detect the machine's IP address
|
|
231
|
+
// for the endpoint URL since 0.0.0.0 is not a routable address for clients
|
|
232
|
+
let endpointHost = httpHost;
|
|
233
|
+
if (httpHost === "0.0.0.0") {
|
|
234
|
+
const internalIp = internalIpV4Sync();
|
|
235
|
+
if (internalIp) {
|
|
236
|
+
endpointHost = internalIp;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
// Fallback for local-only use - don't use hostname as it may not resolve
|
|
240
|
+
endpointHost = "127.0.0.1";
|
|
241
|
+
if (!quiet) {
|
|
242
|
+
console.warn(`${colors.yellow}Could not detect LAN IP. Endpoint URL will only work locally.${colors.reset}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
172
246
|
storage.setServerConfig({
|
|
173
247
|
httpPort: actualHttpPort,
|
|
174
248
|
httpHost,
|
|
175
249
|
protocol,
|
|
176
|
-
httpEndpoint: `${protocol}://${
|
|
250
|
+
httpEndpoint: `${protocol}://${endpointHost}:${actualHttpPort}/log`,
|
|
177
251
|
mode,
|
|
178
252
|
});
|
|
179
253
|
}
|
|
@@ -189,6 +263,11 @@ export async function createDualServer(options = {}) {
|
|
|
189
263
|
const shutdown = async () => {
|
|
190
264
|
// Close HTTP server
|
|
191
265
|
if (httpServer?.listening) {
|
|
266
|
+
// Destroy all active connections to ensure clean shutdown
|
|
267
|
+
for (const socket of activeConnections) {
|
|
268
|
+
socket.destroy();
|
|
269
|
+
}
|
|
270
|
+
activeConnections.clear();
|
|
192
271
|
await new Promise((resolve) => {
|
|
193
272
|
httpServer.close(() => { resolve(); });
|
|
194
273
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dual-server.js","sourceRoot":"","sources":["../../src/server/dual-server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAGjF,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,uCAAuC;AACvC,MAAM,MAAM,GAAG;IACX,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,UAAU;IACf,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;CACnB,CAAC;AAEF,sEAAsE;AACtE,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC,2EAA2E;AAC3E,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B;;;;;GAKG;AACH,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY;IACrD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,uEAAuE;QACvE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC5B,OAAO,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;iBAAM,CAAC;gBACJ,uDAAuD;gBACvD,OAAO,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC1B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBACd,OAAO,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,kCAAkC;QAClC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACP,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"dual-server.js","sourceRoot":"","sources":["../../src/server/dual-server.ts"],"names":[],"mappings":"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"}
|