brms-host 1.0.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/build/bin/install.d.ts +13 -0
- package/build/bin/install.js +124 -0
- package/build/bin/install.js.map +1 -0
- package/build/bridge/native-messaging.d.ts +27 -0
- package/build/bridge/native-messaging.js +118 -0
- package/build/bridge/native-messaging.js.map +1 -0
- package/build/browser/connection.d.ts +12 -0
- package/build/browser/connection.js +57 -0
- package/build/browser/connection.js.map +1 -0
- package/build/browser/console.d.ts +16 -0
- package/build/browser/console.js +44 -0
- package/build/browser/console.js.map +1 -0
- package/build/browser/dom.d.ts +9 -0
- package/build/browser/dom.js +16 -0
- package/build/browser/dom.js.map +1 -0
- package/build/browser/network.d.ts +14 -0
- package/build/browser/network.js +47 -0
- package/build/browser/network.js.map +1 -0
- package/build/index.d.ts +8 -0
- package/build/index.js +111 -0
- package/build/index.js.map +1 -0
- package/build/server.d.ts +2 -0
- package/build/server.js +30 -0
- package/build/server.js.map +1 -0
- package/build/tools/connection.tools.d.ts +2 -0
- package/build/tools/connection.tools.js +28 -0
- package/build/tools/connection.tools.js.map +1 -0
- package/build/tools/console.tools.d.ts +2 -0
- package/build/tools/console.tools.js +25 -0
- package/build/tools/console.tools.js.map +1 -0
- package/build/tools/debug.tools.d.ts +2 -0
- package/build/tools/debug.tools.js +226 -0
- package/build/tools/debug.tools.js.map +1 -0
- package/build/tools/dom.tools.d.ts +2 -0
- package/build/tools/dom.tools.js +26 -0
- package/build/tools/dom.tools.js.map +1 -0
- package/build/tools/events.tools.d.ts +2 -0
- package/build/tools/events.tools.js +18 -0
- package/build/tools/events.tools.js.map +1 -0
- package/build/tools/layout.tools.d.ts +2 -0
- package/build/tools/layout.tools.js +20 -0
- package/build/tools/layout.tools.js.map +1 -0
- package/build/tools/network.tools.d.ts +2 -0
- package/build/tools/network.tools.js +29 -0
- package/build/tools/network.tools.js.map +1 -0
- package/build/tools/screenshot.tools.d.ts +2 -0
- package/build/tools/screenshot.tools.js +40 -0
- package/build/tools/screenshot.tools.js.map +1 -0
- package/build/tools/styles.tools.d.ts +2 -0
- package/build/tools/styles.tools.js +22 -0
- package/build/tools/styles.tools.js.map +1 -0
- package/build/types/index.d.ts +130 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -0
- package/build/utils/errors.d.ts +16 -0
- package/build/utils/errors.js +29 -0
- package/build/utils/errors.js.map +1 -0
- package/build/utils/logger.d.ts +11 -0
- package/build/utils/logger.js +15 -0
- package/build/utils/logger.js.map +1 -0
- package/package.json +35 -0
package/build/index.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* BRMS Host entry point.
|
|
4
|
+
*
|
|
5
|
+
* - Starts an HTTP server on port 3100 exposing MCP via Streamable HTTP
|
|
6
|
+
* - Starts the native messaging bridge to communicate with the Chrome extension
|
|
7
|
+
*/
|
|
8
|
+
import { createServer as createHttpServer } from 'node:http';
|
|
9
|
+
import { writeFileSync, appendFileSync } from 'node:fs';
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
12
|
+
import { createServer } from './server.js';
|
|
13
|
+
import { bridge } from './bridge/native-messaging.js';
|
|
14
|
+
import { log } from './utils/logger.js';
|
|
15
|
+
const PORT = parseInt(process.env.BRMS_PORT ?? '3100', 10);
|
|
16
|
+
const DEBUG_LOG = '/tmp/brms-host-debug.log';
|
|
17
|
+
function debugLog(msg) {
|
|
18
|
+
const line = `[${new Date().toISOString()}] ${msg}\n`;
|
|
19
|
+
try {
|
|
20
|
+
appendFileSync(DEBUG_LOG, line);
|
|
21
|
+
}
|
|
22
|
+
catch { }
|
|
23
|
+
log.info(msg);
|
|
24
|
+
}
|
|
25
|
+
// Catch everything that might kill the process
|
|
26
|
+
process.on('exit', (code) => {
|
|
27
|
+
debugLog(`Process exiting with code ${code}`);
|
|
28
|
+
});
|
|
29
|
+
process.on('uncaughtException', (err) => {
|
|
30
|
+
debugLog(`UNCAUGHT EXCEPTION: ${err.stack ?? err.message}`);
|
|
31
|
+
});
|
|
32
|
+
process.on('unhandledRejection', (reason) => {
|
|
33
|
+
debugLog(`UNHANDLED REJECTION: ${reason}`);
|
|
34
|
+
});
|
|
35
|
+
process.on('SIGTERM', () => debugLog('Received SIGTERM'));
|
|
36
|
+
process.on('SIGINT', () => debugLog('Received SIGINT'));
|
|
37
|
+
// Keep process alive even if stdin closes
|
|
38
|
+
process.stdin.on('end', () => {
|
|
39
|
+
debugLog('stdin ended — keeping process alive');
|
|
40
|
+
});
|
|
41
|
+
process.stdin.resume();
|
|
42
|
+
async function main() {
|
|
43
|
+
writeFileSync(DEBUG_LOG, `=== BRMS Host starting at ${new Date().toISOString()} ===\n`);
|
|
44
|
+
debugLog(`PID: ${process.pid}, Node: ${process.version}`);
|
|
45
|
+
debugLog(`stdin isTTY: ${process.stdin.isTTY}, stdout isTTY: ${process.stdout.isTTY}`);
|
|
46
|
+
bridge.start();
|
|
47
|
+
debugLog('Bridge started');
|
|
48
|
+
const mcpServer = createServer();
|
|
49
|
+
debugLog('MCP server created');
|
|
50
|
+
const transport = new StreamableHTTPServerTransport({
|
|
51
|
+
sessionIdGenerator: () => randomUUID(),
|
|
52
|
+
});
|
|
53
|
+
const httpServer = createHttpServer(async (req, res) => {
|
|
54
|
+
const url = new URL(req.url ?? '/', `http://localhost:${PORT}`);
|
|
55
|
+
if (url.pathname === '/mcp') {
|
|
56
|
+
try {
|
|
57
|
+
// Parse body for POST requests before passing to transport
|
|
58
|
+
if (req.method === 'POST') {
|
|
59
|
+
const body = await new Promise((resolve, reject) => {
|
|
60
|
+
let data = '';
|
|
61
|
+
req.on('data', (chunk) => { data += chunk.toString(); });
|
|
62
|
+
req.on('end', () => resolve(data));
|
|
63
|
+
req.on('error', reject);
|
|
64
|
+
});
|
|
65
|
+
const parsedBody = JSON.parse(body);
|
|
66
|
+
await transport.handleRequest(req, res, parsedBody);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
await transport.handleRequest(req, res);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
debugLog(`MCP request error: ${err instanceof Error ? err.stack : err}`);
|
|
74
|
+
if (!res.headersSent) {
|
|
75
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
76
|
+
res.end(JSON.stringify({ error: String(err) }));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (url.pathname === '/health') {
|
|
82
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
83
|
+
res.end(JSON.stringify({ status: 'ok', extensionConnected: bridge.isConnected() }));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
res.writeHead(404);
|
|
87
|
+
res.end('Not found');
|
|
88
|
+
});
|
|
89
|
+
await mcpServer.connect(transport);
|
|
90
|
+
debugLog('MCP connected to transport');
|
|
91
|
+
httpServer.on('error', (err) => {
|
|
92
|
+
if (err.code === 'EADDRINUSE') {
|
|
93
|
+
debugLog(`Port ${PORT} in use, retrying in 1s...`);
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
httpServer.close();
|
|
96
|
+
httpServer.listen(PORT);
|
|
97
|
+
}, 1000);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
debugLog(`HTTP server error: ${err.message}`);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
httpServer.listen(PORT, () => {
|
|
104
|
+
debugLog(`HTTP server listening on :${PORT}`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
main().catch((err) => {
|
|
108
|
+
debugLog(`Fatal error in main: ${err.stack ?? err.message}`);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AACtD,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAC3D,MAAM,SAAS,GAAG,0BAA0B,CAAC;AAE7C,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,CAAC;IACtD,IAAI,CAAC;QAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACjD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChB,CAAC;AAED,+CAA+C;AAC/C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;IAC1B,QAAQ,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;IACtC,QAAQ,CAAC,uBAAuB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,EAAE;IAC1C,QAAQ,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC1D,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;AAExD,0CAA0C;AAC1C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;IAC3B,QAAQ,CAAC,qCAAqC,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;AAEvB,KAAK,UAAU,IAAI;IACjB,aAAa,CAAC,SAAS,EAAE,6BAA6B,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACxF,QAAQ,CAAC,QAAQ,OAAO,CAAC,GAAG,WAAW,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,OAAO,CAAC,KAAK,CAAC,KAAK,mBAAmB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAEvF,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAE3B,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IAE/B,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;QAClD,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;KACvC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAC;QAEhE,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,2DAA2D;gBAC3D,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAC1B,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;wBACzD,IAAI,IAAI,GAAG,EAAE,CAAC;wBACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;wBACjE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;wBACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBAC1B,CAAC,CAAC,CAAC;oBACH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACpC,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,QAAQ,CAAC,sBAAsB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;gBACzE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;YACpF,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;IAEvC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QACpD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC9B,QAAQ,CAAC,QAAQ,IAAI,4BAA4B,CAAC,CAAC;YACnD,UAAU,CAAC,GAAG,EAAE;gBACd,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC,EAAE,IAAI,CAAC,CAAC;QACX,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,sBAAsB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QAC3B,QAAQ,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,QAAQ,CAAC,wBAAwB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/build/server.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { registerConnectionTools } from './tools/connection.tools.js';
|
|
3
|
+
import { registerNetworkTools } from './tools/network.tools.js';
|
|
4
|
+
import { registerDOMTools } from './tools/dom.tools.js';
|
|
5
|
+
import { registerConsoleTools } from './tools/console.tools.js';
|
|
6
|
+
import { registerStyleTools } from './tools/styles.tools.js';
|
|
7
|
+
import { registerLayoutTools } from './tools/layout.tools.js';
|
|
8
|
+
import { registerScreenshotTools } from './tools/screenshot.tools.js';
|
|
9
|
+
import { registerEventTools } from './tools/events.tools.js';
|
|
10
|
+
import { registerDebugTools } from './tools/debug.tools.js';
|
|
11
|
+
export function createServer() {
|
|
12
|
+
const server = new McpServer({
|
|
13
|
+
name: 'brms',
|
|
14
|
+
version: '1.0.0',
|
|
15
|
+
});
|
|
16
|
+
// Phase 1 — core browser inspection
|
|
17
|
+
registerConnectionTools(server);
|
|
18
|
+
registerNetworkTools(server);
|
|
19
|
+
registerDOMTools(server);
|
|
20
|
+
registerConsoleTools(server);
|
|
21
|
+
// Phase 2 — styles, layout, screenshots, event listeners
|
|
22
|
+
registerStyleTools(server);
|
|
23
|
+
registerLayoutTools(server);
|
|
24
|
+
registerScreenshotTools(server);
|
|
25
|
+
registerEventTools(server);
|
|
26
|
+
// Phase 3 — AI debugging layer
|
|
27
|
+
registerDebugTools(server);
|
|
28
|
+
return server;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,oCAAoC;IACpC,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,yDAAyD;IACzD,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,+BAA+B;IAC/B,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { browserManager } from '../browser/connection.js';
|
|
3
|
+
import { networkMonitor } from '../browser/network.js';
|
|
4
|
+
import { consoleCapture } from '../browser/console.js';
|
|
5
|
+
import { safeResult } from '../utils/errors.js';
|
|
6
|
+
export function registerConnectionTools(server) {
|
|
7
|
+
server.tool('connect_browser', 'Connect to the browser via the BRMS Chrome Extension. The extension must be installed and active.', {}, async () => {
|
|
8
|
+
return safeResult(async () => {
|
|
9
|
+
const pages = await browserManager.connect();
|
|
10
|
+
networkMonitor.attach();
|
|
11
|
+
consoleCapture.attach();
|
|
12
|
+
return JSON.stringify({ connected: true, pages }, null, 2);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
server.tool('list_pages', 'List all open tabs/pages in the connected browser.', {}, async () => {
|
|
16
|
+
return safeResult(async () => {
|
|
17
|
+
const pages = await browserManager.getPages();
|
|
18
|
+
return JSON.stringify(pages, null, 2);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
server.tool('select_page', 'Select an open browser tab by index for subsequent inspection.', { index: z.number().int().min(0).describe('Zero-based index of the page to select') }, async ({ index }) => {
|
|
22
|
+
return safeResult(async () => {
|
|
23
|
+
const info = await browserManager.selectPage(index);
|
|
24
|
+
return JSON.stringify(info, null, 2);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=connection.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.tools.js","sourceRoot":"","sources":["../../src/tools/connection.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,mGAAmG,EACnG,EAAE,EACF,KAAK,IAAI,EAAE;QACT,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC;YAE7C,cAAc,CAAC,MAAM,EAAE,CAAC;YACxB,cAAc,CAAC,MAAM,EAAE,CAAC;YAExB,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,oDAAoD,EACpD,EAAE,EACF,KAAK,IAAI,EAAE;QACT,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,gEAAgE,EAChE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC,EAAE,EACrF,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QAClB,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACpD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { consoleCapture } from '../browser/console.js';
|
|
3
|
+
import { safeResult } from '../utils/errors.js';
|
|
4
|
+
export function registerConsoleTools(server) {
|
|
5
|
+
server.tool('get_console_errors', 'Return console errors (and optionally warnings) captured from the active page.', {
|
|
6
|
+
limit: z.number().int().min(1).max(200).optional().describe('Max number of entries to return'),
|
|
7
|
+
includeWarnings: z.boolean().optional().describe('Also include console warnings (default: false)'),
|
|
8
|
+
}, async ({ limit, includeWarnings }) => {
|
|
9
|
+
return safeResult(async () => {
|
|
10
|
+
const errors = consoleCapture.getErrors(limit);
|
|
11
|
+
let results = [...errors];
|
|
12
|
+
if (includeWarnings) {
|
|
13
|
+
const warnings = consoleCapture.getEntries('warn', limit);
|
|
14
|
+
results = [...results, ...warnings].sort((a, b) => a.timestamp - b.timestamp);
|
|
15
|
+
if (limit)
|
|
16
|
+
results = results.slice(-limit);
|
|
17
|
+
}
|
|
18
|
+
if (results.length === 0) {
|
|
19
|
+
return 'No console errors captured.';
|
|
20
|
+
}
|
|
21
|
+
return JSON.stringify(results, null, 2);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=console.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.tools.js","sourceRoot":"","sources":["../../src/tools/console.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,gFAAgF,EAChF;QACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QAC9F,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;KACnG,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE;QACnC,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC/C,IAAI,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;YAE1B,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBAC1D,OAAO,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC9E,IAAI,KAAK;oBAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;YAC7C,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,6BAA6B,CAAC;YACvC,CAAC;YAED,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { bridge } from '../bridge/native-messaging.js';
|
|
3
|
+
import { networkMonitor } from '../browser/network.js';
|
|
4
|
+
import { consoleCapture } from '../browser/console.js';
|
|
5
|
+
import { safeResult } from '../utils/errors.js';
|
|
6
|
+
export function registerDebugTools(server) {
|
|
7
|
+
// ───────────────────────────────────────────────
|
|
8
|
+
// debug_element
|
|
9
|
+
// ───────────────────────────────────────────────
|
|
10
|
+
server.tool('debug_element', 'Comprehensive diagnosis of why an element may not be clickable, visible, or behaving as expected. Checks the element and its entire ancestor chain for CSS issues, overlaps, disabled state, stacking context, and clickability.', {
|
|
11
|
+
selector: z.string().describe('CSS selector of the element to debug'),
|
|
12
|
+
}, async ({ selector }) => {
|
|
13
|
+
return safeResult(async () => {
|
|
14
|
+
const analysis = await bridge.sendRequest('debug_element', { selector });
|
|
15
|
+
if (!analysis.found) {
|
|
16
|
+
const result = { issue: 'Element not found', reasons: [`No element matches selector: ${selector}`], confidence: 1.0 };
|
|
17
|
+
return JSON.stringify(result);
|
|
18
|
+
}
|
|
19
|
+
const failedChecks = analysis.checks.filter((c) => !c.passed);
|
|
20
|
+
const diagnosis = {
|
|
21
|
+
issue: failedChecks.length > 0 ? failedChecks[0].detail : 'No obvious issues detected',
|
|
22
|
+
reasons: failedChecks.map((c) => c.detail),
|
|
23
|
+
confidence: failedChecks.length > 0 ? Math.min(0.95, 0.7 + failedChecks.length * 0.05) : 0.4,
|
|
24
|
+
};
|
|
25
|
+
return JSON.stringify({ ...analysis, diagnosis }, null, 2);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
// ───────────────────────────────────────────────
|
|
29
|
+
// diagnose_network
|
|
30
|
+
// ───────────────────────────────────────────────
|
|
31
|
+
server.tool('diagnose_network', 'Diagnose network issues: failed requests, slow responses, CORS problems, rate limiting, and error body parsing. Groups failures by domain.', {
|
|
32
|
+
urlPattern: z.string().optional().describe('Regex pattern to filter by URL'),
|
|
33
|
+
}, async ({ urlPattern }) => {
|
|
34
|
+
return safeResult(async () => {
|
|
35
|
+
const entries = networkMonitor.getEntries({ urlPattern });
|
|
36
|
+
const consoleErrors = consoleCapture.getErrors();
|
|
37
|
+
const durations = entries.map((e) => e.timing.duration).filter((d) => d > 0).sort((a, b) => a - b);
|
|
38
|
+
const p95Index = Math.floor(durations.length * 0.95);
|
|
39
|
+
const p95 = durations[p95Index] ?? 0;
|
|
40
|
+
const timingBuckets = { fast: 0, normal: 0, slow: 0, verySlow: 0 };
|
|
41
|
+
for (const d of durations) {
|
|
42
|
+
if (d < 200)
|
|
43
|
+
timingBuckets.fast++;
|
|
44
|
+
else if (d < 1000)
|
|
45
|
+
timingBuckets.normal++;
|
|
46
|
+
else if (d < 3000)
|
|
47
|
+
timingBuckets.slow++;
|
|
48
|
+
else
|
|
49
|
+
timingBuckets.verySlow++;
|
|
50
|
+
}
|
|
51
|
+
const failedRequests = entries
|
|
52
|
+
.filter((e) => e.status !== null && e.status >= 400)
|
|
53
|
+
.map((e) => {
|
|
54
|
+
let errorBody = null;
|
|
55
|
+
if (e.responseBody) {
|
|
56
|
+
try {
|
|
57
|
+
const parsed = JSON.parse(e.responseBody);
|
|
58
|
+
errorBody = parsed.message || parsed.error || parsed.detail || e.responseBody.slice(0, 500);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
errorBody = e.responseBody.slice(0, 500);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { url: e.url, status: e.status, method: e.method, errorBody };
|
|
65
|
+
});
|
|
66
|
+
const corsIssues = entries
|
|
67
|
+
.filter((e) => e.status === null && !e.resourceType.match(/^(image|stylesheet|font|media)$/i))
|
|
68
|
+
.map((e) => ({ url: e.url, method: e.method }));
|
|
69
|
+
const rateLimited = entries
|
|
70
|
+
.filter((e) => e.status === 429)
|
|
71
|
+
.map((e) => {
|
|
72
|
+
let domain = '';
|
|
73
|
+
try {
|
|
74
|
+
domain = new URL(e.url).hostname;
|
|
75
|
+
}
|
|
76
|
+
catch { }
|
|
77
|
+
return { url: e.url, domain };
|
|
78
|
+
});
|
|
79
|
+
const failuresByDomain = {};
|
|
80
|
+
for (const f of failedRequests) {
|
|
81
|
+
try {
|
|
82
|
+
const domain = new URL(f.url).hostname;
|
|
83
|
+
failuresByDomain[domain] = (failuresByDomain[domain] || 0) + 1;
|
|
84
|
+
}
|
|
85
|
+
catch { }
|
|
86
|
+
}
|
|
87
|
+
const parts = [];
|
|
88
|
+
parts.push(`${entries.length} total requests captured`);
|
|
89
|
+
if (failedRequests.length > 0)
|
|
90
|
+
parts.push(`${failedRequests.length} failed (4xx/5xx)`);
|
|
91
|
+
if (corsIssues.length > 0)
|
|
92
|
+
parts.push(`${corsIssues.length} possible CORS issues`);
|
|
93
|
+
if (rateLimited.length > 0)
|
|
94
|
+
parts.push(`${rateLimited.length} rate-limited (429)`);
|
|
95
|
+
if (timingBuckets.verySlow > 0)
|
|
96
|
+
parts.push(`${timingBuckets.verySlow} very slow requests (>3s)`);
|
|
97
|
+
if (p95 > 1000)
|
|
98
|
+
parts.push(`P95 response time: ${Math.round(p95)}ms`);
|
|
99
|
+
if (failedRequests.length === 0 && corsIssues.length === 0)
|
|
100
|
+
parts.push('No issues detected');
|
|
101
|
+
const diagnosis = {
|
|
102
|
+
totalRequests: entries.length,
|
|
103
|
+
timingBuckets,
|
|
104
|
+
p95ResponseTime: Math.round(p95),
|
|
105
|
+
failedRequests: failedRequests.slice(-30),
|
|
106
|
+
corsIssues: corsIssues.slice(-10),
|
|
107
|
+
rateLimited: rateLimited.slice(-10),
|
|
108
|
+
failuresByDomain,
|
|
109
|
+
relatedConsoleErrors: consoleErrors.slice(-10).map((e) => e.text),
|
|
110
|
+
summary: parts.join('. ') + '.',
|
|
111
|
+
};
|
|
112
|
+
return JSON.stringify(diagnosis, null, 2);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// ───────────────────────────────────────────────
|
|
116
|
+
// correlate_issues
|
|
117
|
+
// ───────────────────────────────────────────────
|
|
118
|
+
server.tool('correlate_issues', 'Cross-reference network errors, console errors, and DOM state. Detects broken resources, auth failure chains, repeated errors, and ranks by severity.', {}, async () => {
|
|
119
|
+
return safeResult(async () => {
|
|
120
|
+
const allNetworkEntries = networkMonitor.getEntries();
|
|
121
|
+
const networkErrors = allNetworkEntries.filter((e) => e.status !== null && e.status >= 400);
|
|
122
|
+
const consoleErrors = consoleCapture.getErrors(100);
|
|
123
|
+
const allConsole = consoleCapture.getEntries(undefined, 200);
|
|
124
|
+
const correlations = [];
|
|
125
|
+
// 1. Network <-> Console: URL pathname matching
|
|
126
|
+
for (const netErr of networkErrors.slice(-30)) {
|
|
127
|
+
let pathname = '';
|
|
128
|
+
try {
|
|
129
|
+
pathname = new URL(netErr.url).pathname;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const related = consoleErrors.filter((ce) => ce.text.includes(pathname));
|
|
135
|
+
if (related.length > 0) {
|
|
136
|
+
correlations.push({
|
|
137
|
+
domain: 'network <-> console',
|
|
138
|
+
severity: netErr.status >= 500 ? 'critical' : 'warning',
|
|
139
|
+
details: `Failed ${netErr.method} ${netErr.url} (${netErr.status}) has ${related.length} related console error(s)`,
|
|
140
|
+
evidence: related.slice(0, 3).map((r) => r.text.slice(0, 200)),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 2. Network -> DOM: broken images, failed scripts/stylesheets
|
|
145
|
+
const brokenResources = allNetworkEntries.filter((e) => (e.status !== null && e.status >= 400) &&
|
|
146
|
+
['script', 'stylesheet', 'image'].includes(e.resourceType));
|
|
147
|
+
for (const res of brokenResources.slice(-10)) {
|
|
148
|
+
let severity = 'warning';
|
|
149
|
+
if (res.resourceType === 'script')
|
|
150
|
+
severity = 'critical';
|
|
151
|
+
correlations.push({
|
|
152
|
+
domain: 'network -> DOM',
|
|
153
|
+
severity,
|
|
154
|
+
details: `Broken ${res.resourceType}: ${res.url} (${res.status})`,
|
|
155
|
+
evidence: [`Resource type: ${res.resourceType}`, `Status: ${res.status}`],
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// 3. Console -> DOM: check if element IDs from console errors exist
|
|
159
|
+
const errorTexts = consoleErrors.slice(-20).map((e) => e.text);
|
|
160
|
+
const domCorrelations = await bridge.sendRequest('correlate_dom_check', { errors: errorTexts });
|
|
161
|
+
const domResults = (domCorrelations.results ?? []);
|
|
162
|
+
for (const dc of domResults) {
|
|
163
|
+
correlations.push({
|
|
164
|
+
domain: 'console -> DOM',
|
|
165
|
+
severity: dc.exists ? 'info' : 'warning',
|
|
166
|
+
details: `Console error references ${dc.selector} (${dc.exists ? 'element exists' : 'element NOT found'})`,
|
|
167
|
+
evidence: [dc.error],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// 4. Auth failure chains (401 -> redirect pattern)
|
|
171
|
+
const authFailures = networkErrors.filter((e) => e.status === 401 || e.status === 403);
|
|
172
|
+
if (authFailures.length > 0) {
|
|
173
|
+
const redirectsAfter = allNetworkEntries.filter((e) => (e.status === 302 || e.status === 301) &&
|
|
174
|
+
e.timestamp > authFailures[0].timestamp);
|
|
175
|
+
correlations.push({
|
|
176
|
+
domain: 'auth chain',
|
|
177
|
+
severity: 'critical',
|
|
178
|
+
details: `${authFailures.length} auth failure(s) (401/403)${redirectsAfter.length > 0 ? ` followed by ${redirectsAfter.length} redirect(s)` : ''}`,
|
|
179
|
+
evidence: authFailures.slice(0, 5).map((a) => `${a.method} ${a.url} -> ${a.status}`),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// 5. Repeated errors
|
|
183
|
+
const errorCounts = {};
|
|
184
|
+
for (const ce of consoleErrors) {
|
|
185
|
+
const key = ce.text.slice(0, 100);
|
|
186
|
+
errorCounts[key] = (errorCounts[key] || 0) + 1;
|
|
187
|
+
}
|
|
188
|
+
const repeated = Object.entries(errorCounts).filter(([, count]) => count >= 3);
|
|
189
|
+
for (const [text, count] of repeated) {
|
|
190
|
+
correlations.push({
|
|
191
|
+
domain: 'repeated errors',
|
|
192
|
+
severity: 'warning',
|
|
193
|
+
details: `Console error repeated ${count} times`,
|
|
194
|
+
evidence: [text],
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// 6. Timeline (last 30 events chronologically)
|
|
198
|
+
const timeline = [
|
|
199
|
+
...allNetworkEntries.slice(-15).map((e) => ({
|
|
200
|
+
type: 'network',
|
|
201
|
+
time: e.timestamp,
|
|
202
|
+
summary: `${e.method} ${e.url.slice(0, 80)} -> ${e.status ?? 'aborted'}`,
|
|
203
|
+
})),
|
|
204
|
+
...allConsole.slice(-15).map((e) => ({
|
|
205
|
+
type: 'console',
|
|
206
|
+
time: e.timestamp,
|
|
207
|
+
summary: `[${e.level}] ${e.text.slice(0, 100)}`,
|
|
208
|
+
})),
|
|
209
|
+
].sort((a, b) => a.time - b.time);
|
|
210
|
+
const severityOrder = { critical: 0, warning: 1, info: 2 };
|
|
211
|
+
correlations.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
212
|
+
const critical = correlations.filter((c) => c.severity === 'critical').length;
|
|
213
|
+
const warning = correlations.filter((c) => c.severity === 'warning').length;
|
|
214
|
+
return JSON.stringify({
|
|
215
|
+
networkErrors: networkErrors.length,
|
|
216
|
+
consoleErrors: consoleErrors.length,
|
|
217
|
+
correlations,
|
|
218
|
+
timeline: timeline.slice(-30),
|
|
219
|
+
summary: correlations.length > 0
|
|
220
|
+
? `Found ${correlations.length} correlation(s): ${critical} critical, ${warning} warning, ${correlations.length - critical - warning} info`
|
|
221
|
+
: 'No cross-domain correlations found',
|
|
222
|
+
}, null, 2);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=debug.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.tools.js","sourceRoot":"","sources":["../../src/tools/debug.tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getSnapshot, queryDOM } from '../browser/dom.js';
|
|
3
|
+
import { safeResult } from '../utils/errors.js';
|
|
4
|
+
export function registerDOMTools(server) {
|
|
5
|
+
server.tool('get_dom_tree', 'Return the DOM tree structure of the active page. Optionally scope to a CSS selector and limit tree depth.', {
|
|
6
|
+
selector: z.string().optional().describe('CSS selector to scope the tree (default: entire document)'),
|
|
7
|
+
depth: z.number().int().min(1).max(20).optional().describe('Max tree depth (default: 10)'),
|
|
8
|
+
}, async ({ selector, depth }) => {
|
|
9
|
+
return safeResult(async () => {
|
|
10
|
+
const tree = await getSnapshot(selector, depth);
|
|
11
|
+
return JSON.stringify(tree, null, 2);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
server.tool('query_dom', 'Query the active page DOM using a CSS selector. Returns matching elements with tag, id, classes, text content, and attributes.', {
|
|
15
|
+
selector: z.string().describe('CSS selector to query'),
|
|
16
|
+
}, async ({ selector }) => {
|
|
17
|
+
return safeResult(async () => {
|
|
18
|
+
const elements = await queryDOM(selector);
|
|
19
|
+
if (elements.length === 0) {
|
|
20
|
+
return `No elements found matching selector: ${selector}`;
|
|
21
|
+
}
|
|
22
|
+
return JSON.stringify(elements, null, 2);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=dom.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.tools.js","sourceRoot":"","sources":["../../src/tools/dom.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,cAAc,EACd,4GAA4G,EAC5G;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC;QACrG,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;KAC3F,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;QAC5B,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,WAAW,EACX,gIAAgI,EAChI;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KACvD,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE1C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,wCAAwC,QAAQ,EAAE,CAAC;YAC5D,CAAC;YAED,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { bridge } from '../bridge/native-messaging.js';
|
|
3
|
+
import { safeResult } from '../utils/errors.js';
|
|
4
|
+
export function registerEventTools(server) {
|
|
5
|
+
server.tool('get_event_listeners', 'Get event listeners attached to elements matching a selector via Chrome DevTools Protocol. Returns event type, handler source preview, and listener options.', {
|
|
6
|
+
selector: z.string().describe('CSS selector to query'),
|
|
7
|
+
}, async ({ selector }) => {
|
|
8
|
+
return safeResult(async () => {
|
|
9
|
+
const result = await bridge.sendRequest('get_event_listeners', { selector });
|
|
10
|
+
const results = result.results;
|
|
11
|
+
if (!results || results.length === 0) {
|
|
12
|
+
return `No elements found for selector: ${selector}`;
|
|
13
|
+
}
|
|
14
|
+
return JSON.stringify(results, null, 2);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=events.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.tools.js","sourceRoot":"","sources":["../../src/tools/events.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,8JAA8J,EAC9J;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KACvD,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC7E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAyC,CAAC;YAEjE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrC,OAAO,mCAAmC,QAAQ,EAAE,CAAC;YACvD,CAAC;YAED,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { bridge } from '../bridge/native-messaging.js';
|
|
3
|
+
import { safeResult } from '../utils/errors.js';
|
|
4
|
+
export function registerLayoutTools(server) {
|
|
5
|
+
server.tool('get_layout_info', 'Get bounding box, visibility, viewport status, overlap detection, parent clipping, and scroll context for elements matching a selector.', {
|
|
6
|
+
selector: z.string().describe('CSS selector to query'),
|
|
7
|
+
}, async ({ selector }) => {
|
|
8
|
+
return safeResult(async () => {
|
|
9
|
+
const result = await bridge.sendRequest('get_layout', { selector });
|
|
10
|
+
return JSON.stringify(result.results ?? result, null, 2);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
server.tool('get_visible_elements', 'Return all interactive elements currently visible in the viewport with accessibility info (role, aria-label, disabled state).', {}, async () => {
|
|
14
|
+
return safeResult(async () => {
|
|
15
|
+
const result = await bridge.sendRequest('get_visible', {});
|
|
16
|
+
return JSON.stringify(result.elements ?? result, null, 2);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=layout.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.tools.js","sourceRoot":"","sources":["../../src/tools/layout.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,yIAAyI,EACzI;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KACvD,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,+HAA+H,EAC/H,EAAE,EACF,KAAK,IAAI,EAAE;QACT,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { networkMonitor } from '../browser/network.js';
|
|
3
|
+
import { safeResult } from '../utils/errors.js';
|
|
4
|
+
export function registerNetworkTools(server) {
|
|
5
|
+
server.tool('get_network_calls', 'Return captured network requests from the active page. Supports filtering by URL pattern, status code, and resource type.', {
|
|
6
|
+
urlPattern: z.string().optional().describe('Regex pattern to filter by URL'),
|
|
7
|
+
statusCode: z.number().int().optional().describe('Filter by exact HTTP status code'),
|
|
8
|
+
resourceType: z.string().optional().describe('Filter by resource type (xhr, fetch, document, stylesheet, image, script, etc.)'),
|
|
9
|
+
limit: z.number().int().min(1).max(100).optional().describe('Max number of entries to return (default: all, max 100)'),
|
|
10
|
+
}, async ({ urlPattern, statusCode, resourceType, limit }) => {
|
|
11
|
+
return safeResult(async () => {
|
|
12
|
+
const entries = networkMonitor.getEntries({ urlPattern, statusCode, resourceType, limit });
|
|
13
|
+
if (entries.length === 0) {
|
|
14
|
+
return 'No network calls captured yet. Browse some pages first, then try again.';
|
|
15
|
+
}
|
|
16
|
+
const summary = entries.map((e) => ({
|
|
17
|
+
url: e.url,
|
|
18
|
+
method: e.method,
|
|
19
|
+
status: e.status,
|
|
20
|
+
resourceType: e.resourceType,
|
|
21
|
+
timing: e.timing,
|
|
22
|
+
requestBody: e.requestBody,
|
|
23
|
+
responseBody: e.responseBody?.slice(0, 2000) ?? null,
|
|
24
|
+
}));
|
|
25
|
+
return JSON.stringify(summary, null, 2);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=network.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.tools.js","sourceRoot":"","sources":["../../src/tools/network.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,2HAA2H,EAC3H;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QAC5E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACpF,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iFAAiF,CAAC;QAC/H,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yDAAyD,CAAC;KACvH,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;QACxD,OAAO,UAAU,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;YAE3F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,yEAAyE,CAAC;YACnF,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClC,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,YAAY,EAAE,CAAC,CAAC,YAAY;gBAC5B,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI;aACrD,CAAC,CAAC,CAAC;YAEJ,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|