@dynamicu/chromedebug-mcp 2.6.6 → 2.7.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/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/chrome-extension/activation-manager.js +18 -4
- package/chrome-extension/background.js +1044 -552
- package/chrome-extension/browser-recording-manager.js +256 -0
- package/chrome-extension/chrome-debug-logger.js +168 -0
- package/chrome-extension/console-interception-library.js +430 -0
- package/chrome-extension/content.css +16 -16
- package/chrome-extension/content.js +617 -215
- package/chrome-extension/data-buffer.js +206 -17
- package/chrome-extension/extension-config.js +1 -1
- package/chrome-extension/frame-capture.js +52 -15
- package/chrome-extension/license-helper.js +26 -0
- package/chrome-extension/manifest.free.json +3 -6
- package/chrome-extension/options.js +1 -1
- package/chrome-extension/popup.html +315 -181
- package/chrome-extension/popup.js +673 -526
- package/chrome-extension/pro/enhanced-capture.js +406 -0
- package/chrome-extension/pro/frame-editor.html +410 -0
- package/chrome-extension/pro/frame-editor.js +1496 -0
- package/chrome-extension/pro/function-tracker.js +843 -0
- package/chrome-extension/pro/jszip.min.js +13 -0
- package/config/chromedebug-config.json +101 -0
- package/dist/chromedebug-extension-free.zip +0 -0
- package/package.json +3 -1
- package/scripts/package-pro-extension.js +1 -1
- package/scripts/webpack.config.free.cjs +11 -8
- package/scripts/webpack.config.pro.cjs +5 -0
- package/src/chrome-controller.js +7 -7
- package/src/cli.js +2 -2
- package/src/database.js +61 -9
- package/src/http-server.js +3 -2
- package/src/index.js +9 -6
- package/src/mcp/server.js +2 -2
- package/src/services/process-manager.js +10 -6
- package/src/services/process-tracker.js +10 -5
- package/src/services/profile-manager.js +17 -2
- package/src/validation/schemas.js +36 -6
- package/src/index-direct.js +0 -157
- package/src/index-modular.js +0 -219
- package/src/index-monolithic-backup.js +0 -2230
- package/src/legacy/chrome-controller-old.js +0 -1406
- package/src/legacy/index-express.js +0 -625
- package/src/legacy/index-old.js +0 -977
- package/src/legacy/routes.js +0 -260
- package/src/legacy/shared-storage.js +0 -101
|
@@ -1,625 +0,0 @@
|
|
|
1
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import {
|
|
4
|
-
ListToolsRequestSchema,
|
|
5
|
-
CallToolRequestSchema
|
|
6
|
-
} from '@modelcontextprotocol/sdk/types.js';
|
|
7
|
-
import { ChromeController } from './chrome-controller.js';
|
|
8
|
-
import express from 'express';
|
|
9
|
-
import { findAvailablePort } from './utils.js';
|
|
10
|
-
|
|
11
|
-
// Create a single Chrome controller instance for this MCP server
|
|
12
|
-
const chromeController = new ChromeController();
|
|
13
|
-
|
|
14
|
-
const server = new Server(
|
|
15
|
-
{
|
|
16
|
-
name: 'chrome-pilot',
|
|
17
|
-
version: '1.0.0',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
capabilities: {
|
|
21
|
-
tools: {},
|
|
22
|
-
},
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const tools = [
|
|
27
|
-
{
|
|
28
|
-
name: 'launch_chrome',
|
|
29
|
-
description: 'Launch a Chrome browser instance for this MCP server',
|
|
30
|
-
inputSchema: {
|
|
31
|
-
type: 'object',
|
|
32
|
-
properties: {},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
name: 'connect_to_existing_chrome',
|
|
37
|
-
description: 'Connect to an existing Chrome instance with debugging enabled',
|
|
38
|
-
inputSchema: {
|
|
39
|
-
type: 'object',
|
|
40
|
-
properties: {
|
|
41
|
-
port: {
|
|
42
|
-
type: 'number',
|
|
43
|
-
description: 'Debugging port Chrome is running on (default: 9222)',
|
|
44
|
-
default: 9222,
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'navigate_to',
|
|
51
|
-
description: 'Navigate to a URL',
|
|
52
|
-
inputSchema: {
|
|
53
|
-
type: 'object',
|
|
54
|
-
properties: {
|
|
55
|
-
url: {
|
|
56
|
-
type: 'string',
|
|
57
|
-
description: 'URL to navigate to',
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
required: ['url'],
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
name: 'pause_execution',
|
|
65
|
-
description: 'Pause Chrome execution',
|
|
66
|
-
inputSchema: {
|
|
67
|
-
type: 'object',
|
|
68
|
-
properties: {},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: 'resume_execution',
|
|
73
|
-
description: 'Resume Chrome execution',
|
|
74
|
-
inputSchema: {
|
|
75
|
-
type: 'object',
|
|
76
|
-
properties: {},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
name: 'step_over',
|
|
81
|
-
description: 'Step over in Chrome debugger',
|
|
82
|
-
inputSchema: {
|
|
83
|
-
type: 'object',
|
|
84
|
-
properties: {},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
name: 'evaluate_expression',
|
|
89
|
-
description: 'Evaluate a JavaScript expression in Chrome',
|
|
90
|
-
inputSchema: {
|
|
91
|
-
type: 'object',
|
|
92
|
-
properties: {
|
|
93
|
-
expression: {
|
|
94
|
-
type: 'string',
|
|
95
|
-
description: 'JavaScript expression to evaluate',
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
required: ['expression'],
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: 'get_scopes',
|
|
103
|
-
description: 'Get scope variables from the top call frame',
|
|
104
|
-
inputSchema: {
|
|
105
|
-
type: 'object',
|
|
106
|
-
properties: {},
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
name: 'set_breakpoint',
|
|
111
|
-
description: 'Set a breakpoint at a specific URL and line',
|
|
112
|
-
inputSchema: {
|
|
113
|
-
type: 'object',
|
|
114
|
-
properties: {
|
|
115
|
-
url: {
|
|
116
|
-
type: 'string',
|
|
117
|
-
description: 'URL of the script',
|
|
118
|
-
},
|
|
119
|
-
lineNumber: {
|
|
120
|
-
type: 'number',
|
|
121
|
-
description: 'Line number for the breakpoint',
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
required: ['url', 'lineNumber'],
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
name: 'get_logs',
|
|
129
|
-
description: 'Get recent console logs',
|
|
130
|
-
inputSchema: {
|
|
131
|
-
type: 'object',
|
|
132
|
-
properties: {},
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
name: 'check_connection',
|
|
137
|
-
description: 'Check if Chrome is connected',
|
|
138
|
-
inputSchema: {
|
|
139
|
-
type: 'object',
|
|
140
|
-
properties: {},
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
name: 'force_reset',
|
|
145
|
-
description: 'Force reset Chrome by killing all processes and clearing state',
|
|
146
|
-
inputSchema: {
|
|
147
|
-
type: 'object',
|
|
148
|
-
properties: {},
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
name: 'take_screenshot',
|
|
153
|
-
description: 'Take a screenshot optimized for AI processing',
|
|
154
|
-
inputSchema: {
|
|
155
|
-
type: 'object',
|
|
156
|
-
properties: {
|
|
157
|
-
type: {
|
|
158
|
-
type: 'string',
|
|
159
|
-
description: 'Image type (default: jpeg)',
|
|
160
|
-
enum: ['png', 'jpeg'],
|
|
161
|
-
},
|
|
162
|
-
fullPage: {
|
|
163
|
-
type: 'boolean',
|
|
164
|
-
description: 'Capture full page (default: true, but limited to 600px height for AI)',
|
|
165
|
-
},
|
|
166
|
-
lowRes: {
|
|
167
|
-
type: 'boolean',
|
|
168
|
-
description: 'Low-resolution mode for AI (default: true)',
|
|
169
|
-
},
|
|
170
|
-
quality: {
|
|
171
|
-
type: 'number',
|
|
172
|
-
description: 'JPEG quality (1-100, default: 30)',
|
|
173
|
-
minimum: 1,
|
|
174
|
-
maximum: 100,
|
|
175
|
-
},
|
|
176
|
-
path: {
|
|
177
|
-
type: 'string',
|
|
178
|
-
description: 'Save screenshot to file path',
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
name: 'get_selected_element',
|
|
185
|
-
description: 'Get information about the currently selected element',
|
|
186
|
-
inputSchema: {
|
|
187
|
-
type: 'object',
|
|
188
|
-
properties: {},
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
name: 'apply_css_to_selected',
|
|
193
|
-
description: 'Apply CSS styles to the currently selected element',
|
|
194
|
-
inputSchema: {
|
|
195
|
-
type: 'object',
|
|
196
|
-
properties: {
|
|
197
|
-
css: {
|
|
198
|
-
type: 'string',
|
|
199
|
-
description: 'CSS rules to apply',
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
required: ['css'],
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
name: 'execute_js_on_selected',
|
|
207
|
-
description: 'Execute JavaScript code on the currently selected element',
|
|
208
|
-
inputSchema: {
|
|
209
|
-
type: 'object',
|
|
210
|
-
properties: {
|
|
211
|
-
code: {
|
|
212
|
-
type: 'string',
|
|
213
|
-
description: 'JavaScript code to execute. The element is available as the "element" variable.',
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
required: ['code'],
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
name: 'clear_selected_element',
|
|
221
|
-
description: 'Clear the currently selected element',
|
|
222
|
-
inputSchema: {
|
|
223
|
-
type: 'object',
|
|
224
|
-
properties: {},
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
name: 'select_element',
|
|
229
|
-
description: 'Select an element on the page for manipulation',
|
|
230
|
-
inputSchema: {
|
|
231
|
-
type: 'object',
|
|
232
|
-
properties: {
|
|
233
|
-
selector: {
|
|
234
|
-
type: 'string',
|
|
235
|
-
description: 'CSS selector for the element',
|
|
236
|
-
},
|
|
237
|
-
instruction: {
|
|
238
|
-
type: 'string',
|
|
239
|
-
description: 'Optional instruction for what to do with the element',
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
required: ['selector'],
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
];
|
|
246
|
-
|
|
247
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
248
|
-
return { tools };
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
252
|
-
const { name, arguments: args } = request.params;
|
|
253
|
-
|
|
254
|
-
try {
|
|
255
|
-
switch (name) {
|
|
256
|
-
case 'launch_chrome': {
|
|
257
|
-
const result = await chromeController.launch();
|
|
258
|
-
return {
|
|
259
|
-
content: [
|
|
260
|
-
{
|
|
261
|
-
type: 'text',
|
|
262
|
-
text: JSON.stringify(result, null, 2),
|
|
263
|
-
},
|
|
264
|
-
],
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
case 'connect_to_existing_chrome': {
|
|
269
|
-
const port = args.port || 9222;
|
|
270
|
-
const result = await chromeController.connectToExisting(port);
|
|
271
|
-
return {
|
|
272
|
-
content: [
|
|
273
|
-
{
|
|
274
|
-
type: 'text',
|
|
275
|
-
text: JSON.stringify(result, null, 2),
|
|
276
|
-
},
|
|
277
|
-
],
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
case 'navigate_to': {
|
|
282
|
-
const result = await chromeController.navigateTo(args.url);
|
|
283
|
-
return {
|
|
284
|
-
content: [
|
|
285
|
-
{
|
|
286
|
-
type: 'text',
|
|
287
|
-
text: JSON.stringify(result, null, 2),
|
|
288
|
-
},
|
|
289
|
-
],
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
case 'pause_execution': {
|
|
294
|
-
const result = await chromeController.pause();
|
|
295
|
-
return {
|
|
296
|
-
content: [
|
|
297
|
-
{
|
|
298
|
-
type: 'text',
|
|
299
|
-
text: JSON.stringify(result, null, 2),
|
|
300
|
-
},
|
|
301
|
-
],
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
case 'resume_execution': {
|
|
306
|
-
const result = await chromeController.resume();
|
|
307
|
-
return {
|
|
308
|
-
content: [
|
|
309
|
-
{
|
|
310
|
-
type: 'text',
|
|
311
|
-
text: JSON.stringify(result, null, 2),
|
|
312
|
-
},
|
|
313
|
-
],
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
case 'step_over': {
|
|
318
|
-
const result = await chromeController.stepOver();
|
|
319
|
-
return {
|
|
320
|
-
content: [
|
|
321
|
-
{
|
|
322
|
-
type: 'text',
|
|
323
|
-
text: JSON.stringify(result, null, 2),
|
|
324
|
-
},
|
|
325
|
-
],
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
case 'evaluate_expression': {
|
|
330
|
-
const result = await chromeController.evaluate(args.expression);
|
|
331
|
-
return {
|
|
332
|
-
content: [
|
|
333
|
-
{
|
|
334
|
-
type: 'text',
|
|
335
|
-
text: JSON.stringify(result, null, 2),
|
|
336
|
-
},
|
|
337
|
-
],
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
case 'get_scopes': {
|
|
342
|
-
const result = await chromeController.getScopes();
|
|
343
|
-
return {
|
|
344
|
-
content: [
|
|
345
|
-
{
|
|
346
|
-
type: 'text',
|
|
347
|
-
text: JSON.stringify(result, null, 2),
|
|
348
|
-
},
|
|
349
|
-
],
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
case 'set_breakpoint': {
|
|
354
|
-
const result = await chromeController.setBreakpoint(args.url, args.lineNumber);
|
|
355
|
-
return {
|
|
356
|
-
content: [
|
|
357
|
-
{
|
|
358
|
-
type: 'text',
|
|
359
|
-
text: JSON.stringify(result, null, 2),
|
|
360
|
-
},
|
|
361
|
-
],
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
case 'get_logs': {
|
|
366
|
-
const result = chromeController.getLogs();
|
|
367
|
-
return {
|
|
368
|
-
content: [
|
|
369
|
-
{
|
|
370
|
-
type: 'text',
|
|
371
|
-
text: JSON.stringify(result, null, 2),
|
|
372
|
-
},
|
|
373
|
-
],
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
case 'check_connection': {
|
|
378
|
-
const isConnected = await chromeController.isConnected();
|
|
379
|
-
return {
|
|
380
|
-
content: [
|
|
381
|
-
{
|
|
382
|
-
type: 'text',
|
|
383
|
-
text: JSON.stringify({ connected: isConnected }, null, 2),
|
|
384
|
-
},
|
|
385
|
-
],
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
case 'force_reset': {
|
|
390
|
-
const result = await chromeController.forceReset();
|
|
391
|
-
return {
|
|
392
|
-
content: [
|
|
393
|
-
{
|
|
394
|
-
type: 'text',
|
|
395
|
-
text: JSON.stringify(result, null, 2),
|
|
396
|
-
},
|
|
397
|
-
],
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
case 'take_screenshot': {
|
|
402
|
-
const result = await chromeController.takeScreenshot(args);
|
|
403
|
-
|
|
404
|
-
if (result.saved) {
|
|
405
|
-
return {
|
|
406
|
-
content: [
|
|
407
|
-
{
|
|
408
|
-
type: 'text',
|
|
409
|
-
text: `Screenshot saved successfully!\n\nPath: ${result.path}\nType: ${result.type}\nFull page: ${result.fullPage}`,
|
|
410
|
-
},
|
|
411
|
-
],
|
|
412
|
-
};
|
|
413
|
-
} else if (result.truncated) {
|
|
414
|
-
return {
|
|
415
|
-
content: [
|
|
416
|
-
{
|
|
417
|
-
type: 'text',
|
|
418
|
-
text: `Screenshot preview (truncated):\n\nSize: ${result.size}\nType: ${result.type}\nFull page: ${result.fullPage}\n\n${result.message}`,
|
|
419
|
-
},
|
|
420
|
-
],
|
|
421
|
-
};
|
|
422
|
-
} else if (result.error) {
|
|
423
|
-
return {
|
|
424
|
-
content: [
|
|
425
|
-
{
|
|
426
|
-
type: 'text',
|
|
427
|
-
text: `Error taking screenshot: ${result.message}`,
|
|
428
|
-
},
|
|
429
|
-
],
|
|
430
|
-
isError: true,
|
|
431
|
-
};
|
|
432
|
-
} else if (result.lowRes) {
|
|
433
|
-
return {
|
|
434
|
-
content: [
|
|
435
|
-
{
|
|
436
|
-
type: 'text',
|
|
437
|
-
text: `Low-resolution screenshot captured for AI parsing\n\nSize: ${result.size}\nType: ${result.type}\nFull page: ${result.fullPage}\nQuality: ${result.quality || 'N/A'}\n\ndata:image/${result.type};base64,${result.screenshot}`,
|
|
438
|
-
},
|
|
439
|
-
],
|
|
440
|
-
};
|
|
441
|
-
} else {
|
|
442
|
-
return {
|
|
443
|
-
content: [
|
|
444
|
-
{
|
|
445
|
-
type: 'text',
|
|
446
|
-
text: `Screenshot captured!\n\nSize: ${result.size}\nType: ${result.type}\nFull page: ${result.fullPage}\n\nBase64 data: ${result.screenshot.substring(0, 100)}...\n\nNote: Full screenshot is too large to display. Use 'lowRes: true' for AI-parseable screenshots or 'path' to save to file.`,
|
|
447
|
-
},
|
|
448
|
-
],
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
case 'get_selected_element': {
|
|
454
|
-
const result = await chromeController.getSelectedElement();
|
|
455
|
-
return {
|
|
456
|
-
content: [
|
|
457
|
-
{
|
|
458
|
-
type: 'text',
|
|
459
|
-
text: JSON.stringify(result, null, 2),
|
|
460
|
-
},
|
|
461
|
-
],
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
case 'apply_css_to_selected': {
|
|
466
|
-
const result = await chromeController.applyToSelectedElement(args.css);
|
|
467
|
-
return {
|
|
468
|
-
content: [
|
|
469
|
-
{
|
|
470
|
-
type: 'text',
|
|
471
|
-
text: JSON.stringify(result, null, 2),
|
|
472
|
-
},
|
|
473
|
-
],
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
case 'execute_js_on_selected': {
|
|
478
|
-
const result = await chromeController.executeOnSelectedElement(args.code);
|
|
479
|
-
return {
|
|
480
|
-
content: [
|
|
481
|
-
{
|
|
482
|
-
type: 'text',
|
|
483
|
-
text: JSON.stringify(result, null, 2),
|
|
484
|
-
},
|
|
485
|
-
],
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
case 'clear_selected_element': {
|
|
490
|
-
const result = await chromeController.clearSelectedElement();
|
|
491
|
-
return {
|
|
492
|
-
content: [
|
|
493
|
-
{
|
|
494
|
-
type: 'text',
|
|
495
|
-
text: JSON.stringify(result, null, 2),
|
|
496
|
-
},
|
|
497
|
-
],
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
case 'select_element': {
|
|
502
|
-
const result = await chromeController.selectElement(args.selector, args.instruction);
|
|
503
|
-
return {
|
|
504
|
-
content: [
|
|
505
|
-
{
|
|
506
|
-
type: 'text',
|
|
507
|
-
text: JSON.stringify(result, null, 2),
|
|
508
|
-
},
|
|
509
|
-
],
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
default:
|
|
514
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
515
|
-
}
|
|
516
|
-
} catch (error) {
|
|
517
|
-
return {
|
|
518
|
-
content: [
|
|
519
|
-
{
|
|
520
|
-
type: 'text',
|
|
521
|
-
text: `Error: ${error.message}`,
|
|
522
|
-
},
|
|
523
|
-
],
|
|
524
|
-
isError: true,
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
// Minimal Express server for Chrome extension support
|
|
530
|
-
const app = express();
|
|
531
|
-
|
|
532
|
-
app.use((req, res, next) => {
|
|
533
|
-
res.header('Access-Control-Allow-Origin', '*');
|
|
534
|
-
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
535
|
-
res.header('Access-Control-Allow-Headers', 'Content-Type');
|
|
536
|
-
if (req.method === 'OPTIONS') {
|
|
537
|
-
res.sendStatus(200);
|
|
538
|
-
} else {
|
|
539
|
-
next();
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
app.use(express.json({ limit: '10mb' }));
|
|
544
|
-
|
|
545
|
-
// Essential endpoints for Chrome extension
|
|
546
|
-
app.post('/chrome-pilot/dom-intent', async (req, res) => {
|
|
547
|
-
try {
|
|
548
|
-
const { selector, instruction, elementInfo } = req.body;
|
|
549
|
-
if (!selector) {
|
|
550
|
-
return res.status(400).json({ error: 'Selector is required' });
|
|
551
|
-
}
|
|
552
|
-
const result = await chromeController.selectElement(selector, instruction, elementInfo);
|
|
553
|
-
res.json(result);
|
|
554
|
-
} catch (error) {
|
|
555
|
-
res.status(500).json({ error: error.message });
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
// Navigation endpoint for extension
|
|
560
|
-
app.post('/chrome-pilot/navigate', async (req, res) => {
|
|
561
|
-
try {
|
|
562
|
-
const { url } = req.body;
|
|
563
|
-
if (!url) {
|
|
564
|
-
return res.status(400).json({ error: 'URL is required' });
|
|
565
|
-
}
|
|
566
|
-
const result = await chromeController.navigateTo(url);
|
|
567
|
-
res.json(result);
|
|
568
|
-
} catch (error) {
|
|
569
|
-
res.status(500).json({ error: error.message });
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
app.get('/chrome-pilot/status', async (req, res) => {
|
|
574
|
-
try {
|
|
575
|
-
const status = await chromeController.getConnectionStatus();
|
|
576
|
-
res.json({
|
|
577
|
-
connected: status.connected,
|
|
578
|
-
status: 'ok',
|
|
579
|
-
debugPort: status.debugPort,
|
|
580
|
-
browserWSEndpoint: status.browserWSEndpoint
|
|
581
|
-
});
|
|
582
|
-
} catch (error) {
|
|
583
|
-
res.json({ connected: false, status: 'error', error: error.message });
|
|
584
|
-
}
|
|
585
|
-
});
|
|
586
|
-
|
|
587
|
-
app.get('/chrome-pilot/port', (req, res) => {
|
|
588
|
-
res.json({
|
|
589
|
-
port: process.env.SERVER_PORT || 3000,
|
|
590
|
-
message: 'Chrome Debug server port',
|
|
591
|
-
timestamp: new Date().toISOString()
|
|
592
|
-
});
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
async function main() {
|
|
596
|
-
// Start minimal Express server for Chrome extension
|
|
597
|
-
const startPort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
|
598
|
-
const port = await findAvailablePort(startPort);
|
|
599
|
-
process.env.SERVER_PORT = port.toString();
|
|
600
|
-
|
|
601
|
-
app.listen(port, () => {
|
|
602
|
-
console.error(`Chrome Debug extension API on port ${port}`);
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
// Start MCP server
|
|
606
|
-
const transport = new StdioServerTransport();
|
|
607
|
-
await server.connect(transport);
|
|
608
|
-
console.error('Chrome Debug MCP server running');
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Clean shutdown
|
|
612
|
-
process.on('SIGINT', async () => {
|
|
613
|
-
await chromeController.close();
|
|
614
|
-
process.exit(0);
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
process.on('SIGTERM', async () => {
|
|
618
|
-
await chromeController.close();
|
|
619
|
-
process.exit(0);
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
main().catch((error) => {
|
|
623
|
-
console.error('Fatal error:', error);
|
|
624
|
-
process.exit(1);
|
|
625
|
-
});
|