brave-real-browser-mcp-server 2.9.21 → 2.10.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/dist/handlers/advanced-extraction-handlers.js +483 -0
- package/dist/handlers/advanced-video-media-handlers.js +100 -41
- package/dist/handlers/api-integration-handlers.js +2 -1
- package/dist/handlers/captcha-handlers.js +2 -1
- package/dist/handlers/dynamic-session-handlers.js +41 -9
- package/dist/handlers/pagination-handlers.js +5 -5
- package/dist/handlers/smart-data-extractors.js +4 -4
- package/dist/handlers/visual-tools-handlers.js +2 -1
- package/dist/index.js +231 -106
- package/dist/mcp-response-validator.js +145 -0
- package/dist/tool-definitions.js +50 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import { getPageInstance } from '../browser-manager.js';
|
|
3
3
|
import axios from 'axios';
|
|
4
|
+
import { sleep } from '../system-utils.js';
|
|
4
5
|
/**
|
|
5
6
|
* REST API Endpoint Finder - Discover REST API endpoints
|
|
6
7
|
*/
|
|
@@ -46,7 +47,7 @@ export async function handleRESTAPIEndpointFinder(args) {
|
|
|
46
47
|
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
|
|
47
48
|
}
|
|
48
49
|
// Wait for additional requests
|
|
49
|
-
await
|
|
50
|
+
await sleep(scanDuration);
|
|
50
51
|
page.off('request', requestHandler);
|
|
51
52
|
}
|
|
52
53
|
// Also scan page content for API endpoints
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import { getPageInstance } from '../browser-manager.js';
|
|
3
3
|
import Tesseract from 'tesseract.js';
|
|
4
|
+
import { sleep } from '../system-utils.js';
|
|
4
5
|
/**
|
|
5
6
|
* OCR Engine - Extract text from captcha images using OCR
|
|
6
7
|
*/
|
|
@@ -207,7 +208,7 @@ export async function handlePuzzleCaptchaHandler(args) {
|
|
|
207
208
|
const stepSize = targetDistance / steps;
|
|
208
209
|
for (let i = 0; i < steps; i++) {
|
|
209
210
|
await page.mouse.move(box.x + box.width / 2 + (stepSize * i), box.y + box.height / 2, { steps: 5 });
|
|
210
|
-
await
|
|
211
|
+
await sleep(50 + Math.random() * 50); // Random delay for human-like behavior
|
|
211
212
|
}
|
|
212
213
|
await page.mouse.up();
|
|
213
214
|
result.attemptedSolve = true;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// @ts-nocheck
|
|
4
4
|
import { getCurrentPage } from '../browser-manager.js';
|
|
5
5
|
import { validateWorkflow } from '../workflow-validation.js';
|
|
6
|
-
import { withErrorHandling } from '../system-utils.js';
|
|
6
|
+
import { withErrorHandling, sleep } from '../system-utils.js';
|
|
7
7
|
/**
|
|
8
8
|
* Shadow DOM Extractor - Extract content from Shadow DOM
|
|
9
9
|
*/
|
|
@@ -291,11 +291,20 @@ export async function handleFormAutoFill(args) {
|
|
|
291
291
|
* AJAX Content Waiter - Wait for dynamic content to load
|
|
292
292
|
*/
|
|
293
293
|
export async function handleAjaxContentWaiter(args) {
|
|
294
|
-
|
|
295
|
-
validateWorkflow('ajax_content_waiter', {
|
|
294
|
+
try {
|
|
295
|
+
const validation = validateWorkflow('ajax_content_waiter', {
|
|
296
296
|
requireBrowser: true,
|
|
297
297
|
requirePage: true,
|
|
298
298
|
});
|
|
299
|
+
if (!validation.isValid) {
|
|
300
|
+
return {
|
|
301
|
+
content: [{
|
|
302
|
+
type: 'text',
|
|
303
|
+
text: `⚠️ ${validation.errorMessage || 'Workflow validation failed'}`,
|
|
304
|
+
}],
|
|
305
|
+
isError: true,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
299
308
|
const page = getCurrentPage();
|
|
300
309
|
const waitFor = args.waitFor || 'selector'; // selector, xhr, timeout
|
|
301
310
|
const value = args.value;
|
|
@@ -320,7 +329,7 @@ export async function handleAjaxContentWaiter(args) {
|
|
|
320
329
|
}
|
|
321
330
|
}
|
|
322
331
|
if (waitFor === 'xhr') {
|
|
323
|
-
const duration = value || 5000;
|
|
332
|
+
const duration = parseInt(value) || 5000;
|
|
324
333
|
let xhrCount = 0;
|
|
325
334
|
const requestHandler = (request) => {
|
|
326
335
|
if (request.resourceType() === 'xhr' || request.resourceType() === 'fetch') {
|
|
@@ -328,8 +337,16 @@ export async function handleAjaxContentWaiter(args) {
|
|
|
328
337
|
}
|
|
329
338
|
};
|
|
330
339
|
page.on('request', requestHandler);
|
|
331
|
-
await
|
|
340
|
+
await sleep(duration);
|
|
332
341
|
page.off('request', requestHandler);
|
|
342
|
+
if (xhrCount === 0) {
|
|
343
|
+
return {
|
|
344
|
+
content: [{
|
|
345
|
+
type: 'text',
|
|
346
|
+
text: `ℹ️ Waited ${duration}ms - No XHR/Fetch requests detected.\n\n💡 Note: Monitoring captures NEW requests made during wait period. Page already loaded before monitoring started.`,
|
|
347
|
+
}],
|
|
348
|
+
};
|
|
349
|
+
}
|
|
333
350
|
return {
|
|
334
351
|
content: [{
|
|
335
352
|
type: 'text',
|
|
@@ -338,8 +355,8 @@ export async function handleAjaxContentWaiter(args) {
|
|
|
338
355
|
};
|
|
339
356
|
}
|
|
340
357
|
if (waitFor === 'timeout') {
|
|
341
|
-
const duration = value || 3000;
|
|
342
|
-
await
|
|
358
|
+
const duration = parseInt(value) || 3000;
|
|
359
|
+
await sleep(duration);
|
|
343
360
|
return {
|
|
344
361
|
content: [{
|
|
345
362
|
type: 'text',
|
|
@@ -347,8 +364,23 @@ export async function handleAjaxContentWaiter(args) {
|
|
|
347
364
|
}],
|
|
348
365
|
};
|
|
349
366
|
}
|
|
350
|
-
|
|
351
|
-
|
|
367
|
+
return {
|
|
368
|
+
content: [{
|
|
369
|
+
type: 'text',
|
|
370
|
+
text: `❌ Unknown waitFor type: ${waitFor}. Valid types: 'selector', 'xhr', 'timeout'`,
|
|
371
|
+
}],
|
|
372
|
+
isError: true,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
return {
|
|
377
|
+
content: [{
|
|
378
|
+
type: 'text',
|
|
379
|
+
text: `❌ AJAX content waiter failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
380
|
+
}],
|
|
381
|
+
isError: true,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
352
384
|
}
|
|
353
385
|
/**
|
|
354
386
|
* Modal Popup Handler - Handle modal popups
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// @ts-nocheck
|
|
4
4
|
import { getCurrentPage } from '../browser-manager.js';
|
|
5
5
|
import { validateWorkflow } from '../workflow-validation.js';
|
|
6
|
-
import { withErrorHandling } from '../system-utils.js';
|
|
6
|
+
import { withErrorHandling, sleep } from '../system-utils.js';
|
|
7
7
|
import * as xml2js from 'xml2js';
|
|
8
8
|
/**
|
|
9
9
|
* "Next" button automatically detect और click करके सभी pages से data collect करता है
|
|
@@ -51,14 +51,14 @@ export async function handleAutoPagination(args) {
|
|
|
51
51
|
}
|
|
52
52
|
// Click next button
|
|
53
53
|
await nextButton.click();
|
|
54
|
-
await
|
|
54
|
+
await sleep(waitBetweenPages);
|
|
55
55
|
// Wait for navigation or content load
|
|
56
56
|
try {
|
|
57
57
|
await page.waitForNavigation({ timeout: 5000, waitUntil: 'domcontentloaded' });
|
|
58
58
|
}
|
|
59
59
|
catch (e) {
|
|
60
60
|
// No navigation occurred, content loaded dynamically
|
|
61
|
-
await
|
|
61
|
+
await sleep(1000);
|
|
62
62
|
}
|
|
63
63
|
currentPage++;
|
|
64
64
|
}
|
|
@@ -114,7 +114,7 @@ export async function handleInfiniteScroll(args) {
|
|
|
114
114
|
window.scrollTo(0, document.body.scrollHeight);
|
|
115
115
|
});
|
|
116
116
|
// Wait for new content to load
|
|
117
|
-
await
|
|
117
|
+
await sleep(scrollDelay);
|
|
118
118
|
scrollCount++;
|
|
119
119
|
}
|
|
120
120
|
return {
|
|
@@ -145,7 +145,7 @@ export async function handleMultiPageScraper(args) {
|
|
|
145
145
|
const url = urls[i];
|
|
146
146
|
try {
|
|
147
147
|
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
|
148
|
-
await
|
|
148
|
+
await sleep(waitBetweenPages);
|
|
149
149
|
const pageData = await page.evaluate((selector) => {
|
|
150
150
|
const elements = document.querySelectorAll(selector);
|
|
151
151
|
return Array.from(elements).map((el) => ({
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// @ts-nocheck
|
|
4
4
|
import { getCurrentPage } from '../browser-manager.js';
|
|
5
5
|
import { validateWorkflow } from '../workflow-validation.js';
|
|
6
|
-
import { withErrorHandling } from '../system-utils.js';
|
|
6
|
+
import { withErrorHandling, sleep } from '../system-utils.js';
|
|
7
7
|
/**
|
|
8
8
|
* HTML Elements Extractor - Extract all HTML elements with complete details
|
|
9
9
|
*/
|
|
@@ -203,7 +203,7 @@ export async function handleAjaxExtractor(args) {
|
|
|
203
203
|
if (url && page.url() !== url) {
|
|
204
204
|
await page.goto(url, { waitUntil: 'networkidle2' });
|
|
205
205
|
}
|
|
206
|
-
await
|
|
206
|
+
await sleep(duration);
|
|
207
207
|
page.off('request', requestHandler);
|
|
208
208
|
return {
|
|
209
209
|
content: [{
|
|
@@ -247,7 +247,7 @@ export async function handleFetchXHR(args) {
|
|
|
247
247
|
}
|
|
248
248
|
};
|
|
249
249
|
page.on('response', responseHandler);
|
|
250
|
-
await
|
|
250
|
+
await sleep(duration);
|
|
251
251
|
page.off('response', responseHandler);
|
|
252
252
|
return {
|
|
253
253
|
content: [{
|
|
@@ -296,7 +296,7 @@ export async function handleNetworkRecorder(args) {
|
|
|
296
296
|
};
|
|
297
297
|
page.on('request', requestHandler);
|
|
298
298
|
page.on('response', responseHandler);
|
|
299
|
-
await
|
|
299
|
+
await sleep(duration);
|
|
300
300
|
page.off('request', requestHandler);
|
|
301
301
|
page.off('response', responseHandler);
|
|
302
302
|
return {
|
|
@@ -4,6 +4,7 @@ import * as fs from 'fs/promises';
|
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import pixelmatch from 'pixelmatch';
|
|
6
6
|
import { PNG } from 'pngjs';
|
|
7
|
+
import { sleep } from '../system-utils.js';
|
|
7
8
|
/**
|
|
8
9
|
* Full Page Screenshot - Capture entire page
|
|
9
10
|
*/
|
|
@@ -236,7 +237,7 @@ export async function handleVideoRecording(args) {
|
|
|
236
237
|
const framePath = path.join(framesDir, `frame_${i.toString().padStart(4, '0')}.png`);
|
|
237
238
|
await page.screenshot({ path: framePath });
|
|
238
239
|
frames.push(framePath);
|
|
239
|
-
await
|
|
240
|
+
await sleep(frameDelay);
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
243
|
return {
|