@graphty/remote-logger 1.2.2 → 1.3.0
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 +53 -2
- package/dist/bundle/browser-entry.d.ts +34 -0
- package/dist/bundle/browser-entry.d.ts.map +1 -0
- package/dist/bundle/browser-entry.js +129 -0
- package/dist/bundle/browser-entry.js.map +1 -0
- 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 +54 -8
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/tools/index.d.ts +6 -6
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +1 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/logs-clear.d.ts +1 -2
- package/dist/mcp/tools/logs-clear.d.ts.map +1 -1
- package/dist/mcp/tools/logs-get-all.d.ts +1 -2
- package/dist/mcp/tools/logs-get-all.d.ts.map +1 -1
- package/dist/mcp/tools/logs-get-errors.d.ts +1 -2
- package/dist/mcp/tools/logs-get-errors.d.ts.map +1 -1
- package/dist/mcp/tools/logs-get-file-path.d.ts +8 -2
- package/dist/mcp/tools/logs-get-file-path.d.ts.map +1 -1
- package/dist/mcp/tools/logs-get-file-path.js +1 -1
- package/dist/mcp/tools/logs-get-file-path.js.map +1 -1
- package/dist/mcp/tools/logs-receive.d.ts +9 -10
- package/dist/mcp/tools/logs-receive.d.ts.map +1 -1
- package/dist/mcp/tools/logs-search.d.ts +1 -2
- package/dist/mcp/tools/logs-search.d.ts.map +1 -1
- package/dist/mcp/tools/logs-status.d.ts.map +1 -1
- package/dist/mcp/tools/logs-status.js +4 -1
- package/dist/mcp/tools/logs-status.js.map +1 -1
- package/dist/remote-logger.browser.js +166 -0
- package/dist/remote-logger.browser.js.map +1 -0
- 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 +124 -50
- package/dist/server/dual-server.js.map +1 -1
- package/dist/server/log-server.d.ts +12 -2
- package/dist/server/log-server.d.ts.map +1 -1
- package/dist/server/log-server.js +109 -63
- package/dist/server/log-server.js.map +1 -1
- package/dist/server/log-storage.d.ts +4 -0
- package/dist/server/log-storage.d.ts.map +1 -1
- package/dist/server/log-storage.js.map +1 -1
- package/dist/server/proxy.d.ts +39 -0
- package/dist/server/proxy.d.ts.map +1 -0
- package/dist/server/proxy.js +290 -0
- package/dist/server/proxy.js.map +1 -0
- 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 +7 -2
- package/src/bundle/browser-entry.ts +157 -0
- 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 +54 -8
- package/src/mcp/tools/index.ts +7 -0
- package/src/mcp/tools/logs-clear.ts +1 -1
- package/src/mcp/tools/logs-get-all.ts +1 -1
- package/src/mcp/tools/logs-get-errors.ts +1 -1
- package/src/mcp/tools/logs-get-file-path.ts +2 -2
- package/src/mcp/tools/logs-receive.ts +1 -1
- package/src/mcp/tools/logs-search.ts +1 -1
- package/src/mcp/tools/logs-status.ts +4 -1
- package/src/server/dual-server.ts +165 -57
- package/src/server/log-server.ts +126 -68
- package/src/server/log-storage.ts +4 -0
- package/src/server/proxy.ts +357 -0
- package/src/server/self-signed-cert.ts +9 -0
- package/src/ui/ConsoleCaptureUI.ts +6 -1
package/README.md
CHANGED
|
@@ -48,7 +48,32 @@ npx remote-log-server --port 9080
|
|
|
48
48
|
remote-log-server --port 9080
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
### 2. Add
|
|
51
|
+
### 2. Add Logging to Your Application
|
|
52
|
+
|
|
53
|
+
#### Option A: Script Tag (Zero Install)
|
|
54
|
+
|
|
55
|
+
The server serves a browser-ready script at `/remote-logger.js` that auto-configures itself:
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<script src="http://localhost:9080/remote-logger.js"></script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or paste in the browser console for quick debugging:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
var s=document.createElement('script');s.src='http://localhost:9080/remote-logger.js';document.head.appendChild(s);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The script automatically intercepts all `console.log/warn/error/info/debug` calls and forwards them to the server. It exposes `window.__remoteLogger__` for manual control:
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
// Stop intercepting console
|
|
71
|
+
window.__remoteLogger__.destroy();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Add `?ui=true` to the script URL to show a floating console capture widget.
|
|
75
|
+
|
|
76
|
+
#### Option B: NPM Package
|
|
52
77
|
|
|
53
78
|
```typescript
|
|
54
79
|
import { RemoteLogClient } from "@graphty/remote-logger";
|
|
@@ -91,6 +116,30 @@ Log levels are displayed with the following colors:
|
|
|
91
116
|
| TRACE | Dim/gray |
|
|
92
117
|
| LOG (default) | Green |
|
|
93
118
|
|
|
119
|
+
## Debugging Third-Party Sites
|
|
120
|
+
|
|
121
|
+
The server includes a reverse proxy that injects the remote logger into any website -- no install required on the target site.
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
http://localhost:9080/proxy/https://example.com
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Point your browser (including iOS Safari) at the proxy URL. The proxy:
|
|
128
|
+
- Fetches the target page and injects the remote-logger script into HTML responses (using parse5 for safe HTML manipulation)
|
|
129
|
+
- Injects a `<base>` tag so relative URLs resolve through the proxy
|
|
130
|
+
- Strips Content-Security-Policy headers that would block the injected script
|
|
131
|
+
- Strips integrity attributes (SRI) from script/link tags
|
|
132
|
+
- Rewrites Set-Cookie Domain/Secure attributes for HTTP proxy compatibility
|
|
133
|
+
- Uses a custom TLS fingerprint to avoid CDN bot detection (Fastly, Akamai)
|
|
134
|
+
- Passes non-HTML resources (CSS, JS, images) through unmodified
|
|
135
|
+
|
|
136
|
+
**Limitations:**
|
|
137
|
+
- Resources using absolute paths (e.g., `/fonts/...`, `/media/...`) bypass the `<base>` tag and return 404
|
|
138
|
+
- JavaScript `fetch()` calls using absolute paths may bypass the proxy
|
|
139
|
+
- OAuth redirect flows that check the origin domain will not work
|
|
140
|
+
- WebSocket connections are not proxied
|
|
141
|
+
- Sites with very aggressive bot detection may still block the proxy
|
|
142
|
+
|
|
94
143
|
## CLI Reference
|
|
95
144
|
|
|
96
145
|
```
|
|
@@ -99,7 +148,7 @@ Usage:
|
|
|
99
148
|
|
|
100
149
|
Options:
|
|
101
150
|
--port, -p <port> Port to listen on (default: 9080)
|
|
102
|
-
--host, -h <host> Hostname to bind to (default:
|
|
151
|
+
--host, -h <host> Hostname to bind to (default: 0.0.0.0)
|
|
103
152
|
--cert, -c <path> Path to SSL certificate file (enables HTTPS)
|
|
104
153
|
--key, -k <path> Path to SSL private key file (enables HTTPS)
|
|
105
154
|
--log-file, -l <path> Write logs to file (JSONL format)
|
|
@@ -216,6 +265,8 @@ const server = startLogServer({
|
|
|
216
265
|
| Endpoint | Method | Description |
|
|
217
266
|
|----------|--------|-------------|
|
|
218
267
|
| `/log` | POST | Receive logs from client |
|
|
268
|
+
| `/remote-logger.js` | GET | Browser-ready auto-config script |
|
|
269
|
+
| `/proxy/<url>` | * | Reverse proxy with script injection |
|
|
219
270
|
| `/logs` | GET | Get all logs by session |
|
|
220
271
|
| `/logs/recent` | GET | Get recent logs (`?n=50&errors=true`) |
|
|
221
272
|
| `/logs/errors` | GET | Get error-level logs only |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser bundle entry point for the remote logger.
|
|
3
|
+
*
|
|
4
|
+
* When loaded as a script tag, this auto-initializes a RemoteLogClient
|
|
5
|
+
* that intercepts console methods and forwards them to the server.
|
|
6
|
+
*
|
|
7
|
+
* Server URL detection priority:
|
|
8
|
+
* 1. window.__REMOTE_LOG_SERVER_URL__ (injected by server when serving this file)
|
|
9
|
+
* 2. document.currentScript.src (parse origin from script tag URL)
|
|
10
|
+
* 3. window.location.origin (fallback)
|
|
11
|
+
*
|
|
12
|
+
* Exposes window.__remoteLogger__ for manual control.
|
|
13
|
+
* @module bundle/browser-entry
|
|
14
|
+
*/
|
|
15
|
+
import { RemoteLogClient } from "../client/RemoteLogClient.js";
|
|
16
|
+
import { ConsoleCaptureUI } from "../ui/ConsoleCaptureUI.js";
|
|
17
|
+
declare global {
|
|
18
|
+
interface Window {
|
|
19
|
+
__REMOTE_LOG_SERVER_URL__?: string;
|
|
20
|
+
__remoteLogger__?: RemoteLoggerGlobal;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export interface RemoteLoggerGlobal {
|
|
24
|
+
client: RemoteLogClient;
|
|
25
|
+
ui?: ConsoleCaptureUI;
|
|
26
|
+
destroy: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Initialize the remote logger, intercepting console methods.
|
|
30
|
+
* @returns The remote logger global object, or undefined if no server URL detected
|
|
31
|
+
*/
|
|
32
|
+
export declare function initRemoteLogger(): RemoteLoggerGlobal | undefined;
|
|
33
|
+
export { ConsoleCaptureUI, RemoteLogClient };
|
|
34
|
+
//# sourceMappingURL=browser-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-entry.d.ts","sourceRoot":"","sources":["../../src/bundle/browser-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,yBAAyB,CAAC,EAAE,MAAM,CAAC;QACnC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;KACzC;CACJ;AAcD,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,EAAE,CAAC,EAAE,gBAAgB,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB;AAoDD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,kBAAkB,GAAG,SAAS,CAqDjE;AAMD,OAAO,EAAE,gBAAgB,EAAC,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser bundle entry point for the remote logger.
|
|
3
|
+
*
|
|
4
|
+
* When loaded as a script tag, this auto-initializes a RemoteLogClient
|
|
5
|
+
* that intercepts console methods and forwards them to the server.
|
|
6
|
+
*
|
|
7
|
+
* Server URL detection priority:
|
|
8
|
+
* 1. window.__REMOTE_LOG_SERVER_URL__ (injected by server when serving this file)
|
|
9
|
+
* 2. document.currentScript.src (parse origin from script tag URL)
|
|
10
|
+
* 3. window.location.origin (fallback)
|
|
11
|
+
*
|
|
12
|
+
* Exposes window.__remoteLogger__ for manual control.
|
|
13
|
+
* @module bundle/browser-entry
|
|
14
|
+
*/
|
|
15
|
+
import { RemoteLogClient } from "../client/RemoteLogClient.js";
|
|
16
|
+
import { ConsoleCaptureUI } from "../ui/ConsoleCaptureUI.js";
|
|
17
|
+
const CONSOLE_LEVEL_MAP = {
|
|
18
|
+
log: "LOG",
|
|
19
|
+
warn: "WARN",
|
|
20
|
+
error: "ERROR",
|
|
21
|
+
info: "INFO",
|
|
22
|
+
debug: "DEBUG",
|
|
23
|
+
};
|
|
24
|
+
const INTERCEPTED_METHODS = ["log", "warn", "error", "info", "debug"];
|
|
25
|
+
function detectServerUrl() {
|
|
26
|
+
if (typeof window !== "undefined" && window.__REMOTE_LOG_SERVER_URL__) {
|
|
27
|
+
return window.__REMOTE_LOG_SERVER_URL__;
|
|
28
|
+
}
|
|
29
|
+
if (typeof document !== "undefined" && document.currentScript) {
|
|
30
|
+
try {
|
|
31
|
+
const scriptUrl = new URL(document.currentScript.src);
|
|
32
|
+
return scriptUrl.origin;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Invalid URL, fall through
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (typeof window !== "undefined" && window.location) {
|
|
39
|
+
return window.location.origin;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
function shouldShowUI() {
|
|
44
|
+
if (typeof document === "undefined" || !document.currentScript) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const { src } = document.currentScript;
|
|
49
|
+
if (!src) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const params = new URL(src).searchParams;
|
|
53
|
+
return params.get("ui") === "true";
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function formatArg(arg) {
|
|
60
|
+
if (typeof arg === "string") {
|
|
61
|
+
return arg;
|
|
62
|
+
}
|
|
63
|
+
if (arg instanceof Error) {
|
|
64
|
+
return `${arg.name}: ${arg.message}`;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
return JSON.stringify(arg);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return String(arg);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function formatArgs(args) {
|
|
74
|
+
return args.map(formatArg).join(" ");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Initialize the remote logger, intercepting console methods.
|
|
78
|
+
* @returns The remote logger global object, or undefined if no server URL detected
|
|
79
|
+
*/
|
|
80
|
+
export function initRemoteLogger() {
|
|
81
|
+
const serverUrl = detectServerUrl();
|
|
82
|
+
if (!serverUrl) {
|
|
83
|
+
console.warn("[RemoteLogger] Could not detect server URL. Set window.__REMOTE_LOG_SERVER_URL__ before loading.");
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const client = new RemoteLogClient({
|
|
87
|
+
serverUrl,
|
|
88
|
+
sessionPrefix: "remote",
|
|
89
|
+
batchIntervalMs: 500,
|
|
90
|
+
});
|
|
91
|
+
const originalMethods = {};
|
|
92
|
+
for (const method of INTERCEPTED_METHODS) {
|
|
93
|
+
// eslint-disable-next-line no-console
|
|
94
|
+
originalMethods[method] = console[method];
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
console[method] = (...args) => {
|
|
97
|
+
originalMethods[method].apply(console, args);
|
|
98
|
+
const message = formatArgs(args);
|
|
99
|
+
client.log(CONSOLE_LEVEL_MAP[method], message);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
let ui;
|
|
103
|
+
if (shouldShowUI()) {
|
|
104
|
+
ui = new ConsoleCaptureUI();
|
|
105
|
+
}
|
|
106
|
+
const destroy = () => {
|
|
107
|
+
for (const method of INTERCEPTED_METHODS) {
|
|
108
|
+
// eslint-disable-next-line no-console
|
|
109
|
+
console[method] = originalMethods[method];
|
|
110
|
+
}
|
|
111
|
+
void client.close();
|
|
112
|
+
if (ui) {
|
|
113
|
+
ui.destroy();
|
|
114
|
+
}
|
|
115
|
+
if (typeof window !== "undefined") {
|
|
116
|
+
delete window.__remoteLogger__;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const global = { client, ui, destroy };
|
|
120
|
+
if (typeof window !== "undefined") {
|
|
121
|
+
window.__remoteLogger__ = global;
|
|
122
|
+
}
|
|
123
|
+
return global;
|
|
124
|
+
}
|
|
125
|
+
// Auto-initialize on load
|
|
126
|
+
initRemoteLogger();
|
|
127
|
+
// Re-export for manual use via the IIFE global
|
|
128
|
+
export { ConsoleCaptureUI, RemoteLogClient };
|
|
129
|
+
//# sourceMappingURL=browser-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-entry.js","sourceRoot":"","sources":["../../src/bundle/browser-entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -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: Script tag (zero install)\n\nThe server serves a browser-ready script that auto-configures itself.\nGet the script URL from logs_status - look for server.scriptUrl in the response.\n\nAdd to HTML:\n```html\n<script src=\"http://localhost:9080/remote-logger.js\"></script>\n```\n\nOr paste in browser console:\n```javascript\nvar s=document.createElement('script');s.src='http://localhost:9080/remote-logger.js';document.head.appendChild(s);\n```\n\nThe script automatically:\n- Intercepts all console.log/warn/error/info/debug calls\n- Sends them to the server it was loaded from (zero config)\n- Exposes window.__remoteLogger__ for manual control (e.g., window.__remoteLogger__.destroy())\n\nAdd ?ui=true to the script URL to show a floating console capture widget.\n\n### Option 3: 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## Debugging Third-Party Websites\n\nThe server includes a reverse proxy that injects the remote logger into any website.\nGet the proxy base URL from logs_status - look for server.proxyBaseUrl.\n\nTo debug a third-party site, prepend the proxy base URL to the target URL:\n {proxyBaseUrl}https://example.com/page\n\nExample: http://192.168.1.x:9080/proxy/https://example.com\n\nThe proxy automatically:\n- Injects the remote-logger script into HTML responses\n- Strips Content-Security-Policy headers that would block the script\n- Forwards cookies, auth headers, and other request data\n- Passes non-HTML resources (CSS, JS, images) through unmodified\n\nLimitations:\n- Resources using absolute paths (e.g., /fonts/..., /media/...) bypass the base tag and return 404\n- JavaScript fetch() calls using absolute paths may bypass the proxy\n- OAuth redirect flows that check the origin domain will not work\n- WebSocket connections are not proxied (future enhancement)\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, script URL, and proxy URL\n2. Add logging to the browser app using one of the options above (script tag is simplest)\n - For third-party sites, use the proxy: navigate to {proxyBaseUrl}https://target-site.com\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,86JA4H8B,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
|
|
@@ -66,10 +67,32 @@ logger.interceptConsole();
|
|
|
66
67
|
logger.log("INFO", "Hello from browser!");
|
|
67
68
|
\`\`\`
|
|
68
69
|
|
|
69
|
-
### Option 2:
|
|
70
|
+
### Option 2: Script tag (zero install)
|
|
71
|
+
|
|
72
|
+
The server serves a browser-ready script that auto-configures itself.
|
|
73
|
+
Get the script URL from logs_status - look for server.scriptUrl in the response.
|
|
74
|
+
|
|
75
|
+
Add to HTML:
|
|
76
|
+
\`\`\`html
|
|
77
|
+
<script src="http://localhost:9080/remote-logger.js"></script>
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
Or paste in browser console:
|
|
81
|
+
\`\`\`javascript
|
|
82
|
+
var s=document.createElement('script');s.src='http://localhost:9080/remote-logger.js';document.head.appendChild(s);
|
|
83
|
+
\`\`\`
|
|
84
|
+
|
|
85
|
+
The script automatically:
|
|
86
|
+
- Intercepts all console.log/warn/error/info/debug calls
|
|
87
|
+
- Sends them to the server it was loaded from (zero config)
|
|
88
|
+
- Exposes window.__remoteLogger__ for manual control (e.g., window.__remoteLogger__.destroy())
|
|
89
|
+
|
|
90
|
+
Add ?ui=true to the script URL to show a floating console capture widget.
|
|
91
|
+
|
|
92
|
+
### Option 3: Raw fetch() calls
|
|
70
93
|
|
|
71
94
|
\`\`\`typescript
|
|
72
|
-
fetch("http://localhost:9080/
|
|
95
|
+
fetch("http://localhost:9080/log", {
|
|
73
96
|
method: "POST",
|
|
74
97
|
headers: { "Content-Type": "application/json" },
|
|
75
98
|
body: JSON.stringify({
|
|
@@ -81,6 +104,28 @@ fetch("http://localhost:9080/logs", {
|
|
|
81
104
|
});
|
|
82
105
|
\`\`\`
|
|
83
106
|
|
|
107
|
+
## Debugging Third-Party Websites
|
|
108
|
+
|
|
109
|
+
The server includes a reverse proxy that injects the remote logger into any website.
|
|
110
|
+
Get the proxy base URL from logs_status - look for server.proxyBaseUrl.
|
|
111
|
+
|
|
112
|
+
To debug a third-party site, prepend the proxy base URL to the target URL:
|
|
113
|
+
{proxyBaseUrl}https://example.com/page
|
|
114
|
+
|
|
115
|
+
Example: http://192.168.1.x:9080/proxy/https://example.com
|
|
116
|
+
|
|
117
|
+
The proxy automatically:
|
|
118
|
+
- Injects the remote-logger script into HTML responses
|
|
119
|
+
- Strips Content-Security-Policy headers that would block the script
|
|
120
|
+
- Forwards cookies, auth headers, and other request data
|
|
121
|
+
- Passes non-HTML resources (CSS, JS, images) through unmodified
|
|
122
|
+
|
|
123
|
+
Limitations:
|
|
124
|
+
- Resources using absolute paths (e.g., /fonts/..., /media/...) bypass the base tag and return 404
|
|
125
|
+
- JavaScript fetch() calls using absolute paths may bypass the proxy
|
|
126
|
+
- OAuth redirect flows that check the origin domain will not work
|
|
127
|
+
- WebSocket connections are not proxied (future enhancement)
|
|
128
|
+
|
|
84
129
|
## Querying Logs (MCP Tools)
|
|
85
130
|
|
|
86
131
|
Once browser logs are flowing to the server:
|
|
@@ -96,8 +141,9 @@ Once browser logs are flowing to the server:
|
|
|
96
141
|
|
|
97
142
|
## Typical Debugging Workflow
|
|
98
143
|
|
|
99
|
-
1. Call logs_status to verify server is running and get the endpoint URL
|
|
100
|
-
2.
|
|
144
|
+
1. Call logs_status to verify server is running and get the endpoint URL, script URL, and proxy URL
|
|
145
|
+
2. Add logging to the browser app using one of the options above (script tag is simplest)
|
|
146
|
+
- For third-party sites, use the proxy: navigate to {proxyBaseUrl}https://target-site.com
|
|
101
147
|
3. Trigger the action in the browser you want to debug
|
|
102
148
|
4. Call logs_get_recent to see what happened
|
|
103
149
|
5. Use logs_search if looking for specific errors or messages`;
|
|
@@ -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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"}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* MCP tool exports and registration.
|
|
3
3
|
* @module mcp/tools
|
|
4
4
|
*/
|
|
5
|
-
export { logsClearHandler, type LogsClearInput, logsClearInputSchema, logsClearTool, } from "./logs-clear.js";
|
|
6
|
-
export { logsGetAllHandler, type LogsGetAllInput, logsGetAllInputSchema, logsGetAllTool, } from "./logs-get-all.js";
|
|
7
|
-
export { logsGetErrorsHandler, type LogsGetErrorsInput, logsGetErrorsInputSchema, logsGetErrorsTool, } from "./logs-get-errors.js";
|
|
8
|
-
export { logsGetFilePathHandler, type LogsGetFilePathInput, logsGetFilePathInputSchema, logsGetFilePathTool, } from "./logs-get-file-path.js";
|
|
5
|
+
export { logsClearHandler, type LogsClearInput, logsClearInputSchema, type LogsClearOutput, logsClearTool, } from "./logs-clear.js";
|
|
6
|
+
export { logsGetAllHandler, type LogsGetAllInput, logsGetAllInputSchema, type LogsGetAllOutput, logsGetAllTool, } from "./logs-get-all.js";
|
|
7
|
+
export { logsGetErrorsHandler, type LogsGetErrorsInput, logsGetErrorsInputSchema, type LogsGetErrorsOutput, logsGetErrorsTool, } from "./logs-get-errors.js";
|
|
8
|
+
export { getLogFilePath, logsGetFilePathHandler, type LogsGetFilePathInput, logsGetFilePathInputSchema, type LogsGetFilePathOutput, logsGetFilePathTool, } from "./logs-get-file-path.js";
|
|
9
9
|
export { logsGetRecentHandler, type LogsGetRecentInput, logsGetRecentInputSchema, type LogsGetRecentOutput, logsGetRecentTool, } from "./logs-get-recent.js";
|
|
10
10
|
export { logsListSessionsHandler, type LogsListSessionsInput, logsListSessionsInputSchema, type LogsListSessionsOutput, logsListSessionsTool, } from "./logs-list-sessions.js";
|
|
11
|
-
export { logsReceiveHandler, type LogsReceiveInput, logsReceiveInputSchema, logsReceiveTool, } from "./logs-receive.js";
|
|
12
|
-
export { logsSearchHandler, type LogsSearchInput, logsSearchInputSchema, logsSearchTool, } from "./logs-search.js";
|
|
11
|
+
export { logsReceiveHandler, type LogsReceiveInput, logsReceiveInputSchema, type LogsReceiveOutput, logsReceiveTool, } from "./logs-receive.js";
|
|
12
|
+
export { logsSearchHandler, type LogsSearchInput, logsSearchInputSchema, type LogsSearchOutput, logsSearchTool, } from "./logs-search.js";
|
|
13
13
|
export { logsStatusHandler, type LogsStatusInput, logsStatusInputSchema, type LogsStatusOutput, logsStatusTool, } from "./logs-status.js";
|
|
14
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,gBAAgB,EAChB,KAAK,cAAc,EACnB,oBAAoB,EACpB,aAAa,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,cAAc,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,iBAAiB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,mBAAmB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACH,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,iBAAiB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,2BAA2B,EAC3B,KAAK,sBAAsB,EAC3B,oBAAoB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACH,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,cAAc,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACH,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,GACjB,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,gBAAgB,EAChB,KAAK,cAAc,EACnB,oBAAoB,EACpB,KAAK,eAAe,EACpB,aAAa,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,iBAAiB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,cAAc,EACd,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,mBAAmB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACH,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,iBAAiB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACH,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,2BAA2B,EAC3B,KAAK,sBAAsB,EAC3B,oBAAoB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACH,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACH,iBAAiB,EACjB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,GACjB,MAAM,kBAAkB,CAAC"}
|