real-browser-mcp-server 1.0.8 → 1.0.10
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/lib/cjs/index.js +6 -15
- package/lib/esm/index.mjs +6 -15
- package/package.json +1 -1
- package/src/ai/core.js +3 -7
- package/src/mcp/handlers.js +17 -37
- package/test/cjs/test.js +1 -3
- package/test/esm/test.mjs +1 -3
- package/typings.d.ts +0 -2
package/lib/cjs/index.js
CHANGED
|
@@ -70,13 +70,10 @@ function getDefaultHeadless() {
|
|
|
70
70
|
return envHeadless === 'true';
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
function setupRealPage(browser, page
|
|
73
|
+
function setupRealPage(browser, page) {
|
|
74
74
|
if (page._setupApplied) return page;
|
|
75
75
|
page._setupApplied = true;
|
|
76
76
|
|
|
77
|
-
const headless = options.headless !== undefined ? options.headless : getDefaultHeadless();
|
|
78
|
-
const showCursor = options.showCursor !== undefined ? options.showCursor : false;
|
|
79
|
-
|
|
80
77
|
// Enable ad blocker
|
|
81
78
|
if (adBlockerInstance) {
|
|
82
79
|
adBlockerInstance.enableBlockingInPage(page).catch(() => {});
|
|
@@ -90,13 +87,11 @@ function setupRealPage(browser, page, options = {}) {
|
|
|
90
87
|
|
|
91
88
|
// Ghost Cursor integration - Bézier curve human-like mouse movement
|
|
92
89
|
try {
|
|
93
|
-
|
|
94
|
-
const cursorPromise = createCursor(page, undefined, false, {}, showCursor);
|
|
90
|
+
const cursor = createCursor(page);
|
|
95
91
|
page.realCursor = {
|
|
96
92
|
move: async (selector, options = {}) => {
|
|
97
93
|
try {
|
|
98
|
-
|
|
99
|
-
await cursor.move(selector, options);
|
|
94
|
+
await cursor.actions.move(selector, options);
|
|
100
95
|
} catch (e) {
|
|
101
96
|
// Fallback to native hover if ghost-cursor fails
|
|
102
97
|
try { await page.hover(selector); } catch (_) {}
|
|
@@ -105,8 +100,7 @@ function setupRealPage(browser, page, options = {}) {
|
|
|
105
100
|
};
|
|
106
101
|
page.realClick = async (selector, options = {}) => {
|
|
107
102
|
try {
|
|
108
|
-
|
|
109
|
-
await cursor.click(selector, options);
|
|
103
|
+
await cursor.actions.click({ target: selector, ...options });
|
|
110
104
|
} catch (e) {
|
|
111
105
|
// Fallback to native click if ghost-cursor fails
|
|
112
106
|
await page.click(selector, options);
|
|
@@ -234,7 +228,6 @@ async function connect({
|
|
|
234
228
|
proxy = {},
|
|
235
229
|
turnstile = false,
|
|
236
230
|
executablePath = undefined,
|
|
237
|
-
visualCursor = undefined,
|
|
238
231
|
} = {}) {
|
|
239
232
|
let playwrightProxy = undefined;
|
|
240
233
|
if (proxy && proxy.host && proxy.port) {
|
|
@@ -335,9 +328,7 @@ async function connect({
|
|
|
335
328
|
|
|
336
329
|
await applyUserAgentOverride(page, modifiedUa, userAgentMetadata);
|
|
337
330
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
setupRealPage(browser, page, { headless, showCursor });
|
|
331
|
+
setupRealPage(browser, page);
|
|
341
332
|
|
|
342
333
|
page = await pageController({
|
|
343
334
|
browser,
|
|
@@ -348,7 +339,7 @@ async function connect({
|
|
|
348
339
|
|
|
349
340
|
context.on('page', async (newPage) => {
|
|
350
341
|
await applyUserAgentOverride(newPage, modifiedUa, userAgentMetadata);
|
|
351
|
-
setupRealPage(browser, newPage
|
|
342
|
+
setupRealPage(browser, newPage);
|
|
352
343
|
await pageController({
|
|
353
344
|
browser,
|
|
354
345
|
page: newPage,
|
package/lib/esm/index.mjs
CHANGED
|
@@ -75,13 +75,10 @@ function getDefaultHeadless() {
|
|
|
75
75
|
return envHeadless === 'true';
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
function setupRealPage(browser, page
|
|
78
|
+
function setupRealPage(browser, page) {
|
|
79
79
|
if (page._setupApplied) return page;
|
|
80
80
|
page._setupApplied = true;
|
|
81
81
|
|
|
82
|
-
const headless = options.headless !== undefined ? options.headless : getDefaultHeadless();
|
|
83
|
-
const showCursor = options.showCursor !== undefined ? options.showCursor : false;
|
|
84
|
-
|
|
85
82
|
// Enable ad blocker
|
|
86
83
|
if (adBlockerInstance) {
|
|
87
84
|
adBlockerInstance.enableBlockingInPage(page).catch(() => {});
|
|
@@ -95,13 +92,11 @@ function setupRealPage(browser, page, options = {}) {
|
|
|
95
92
|
|
|
96
93
|
// Ghost Cursor integration - Bézier curve human-like mouse movement
|
|
97
94
|
try {
|
|
98
|
-
|
|
99
|
-
const cursorPromise = createCursor(page, undefined, false, {}, showCursor);
|
|
95
|
+
const cursor = createCursor(page);
|
|
100
96
|
page.realCursor = {
|
|
101
97
|
move: async (selector, options = {}) => {
|
|
102
98
|
try {
|
|
103
|
-
|
|
104
|
-
await cursor.move(selector, options);
|
|
99
|
+
await cursor.actions.move(selector, options);
|
|
105
100
|
} catch (e) {
|
|
106
101
|
// Fallback to native hover if ghost-cursor fails
|
|
107
102
|
try { await page.hover(selector); } catch (_) {}
|
|
@@ -110,8 +105,7 @@ function setupRealPage(browser, page, options = {}) {
|
|
|
110
105
|
};
|
|
111
106
|
page.realClick = async (selector, options = {}) => {
|
|
112
107
|
try {
|
|
113
|
-
|
|
114
|
-
await cursor.click(selector, options);
|
|
108
|
+
await cursor.actions.click({ target: selector, ...options });
|
|
115
109
|
} catch (e) {
|
|
116
110
|
// Fallback to native click if ghost-cursor fails
|
|
117
111
|
await page.click(selector, options);
|
|
@@ -238,7 +232,6 @@ export async function connect({
|
|
|
238
232
|
proxy = {},
|
|
239
233
|
turnstile = false,
|
|
240
234
|
executablePath = undefined,
|
|
241
|
-
visualCursor = undefined,
|
|
242
235
|
} = {}) {
|
|
243
236
|
let playwrightProxy = undefined;
|
|
244
237
|
if (proxy && proxy.host && proxy.port) {
|
|
@@ -339,9 +332,7 @@ export async function connect({
|
|
|
339
332
|
|
|
340
333
|
await applyUserAgentOverride(page, modifiedUa, userAgentMetadata);
|
|
341
334
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
setupRealPage(browser, page, { headless, showCursor });
|
|
335
|
+
setupRealPage(browser, page);
|
|
345
336
|
|
|
346
337
|
page = await pageController({
|
|
347
338
|
browser,
|
|
@@ -352,7 +343,7 @@ export async function connect({
|
|
|
352
343
|
|
|
353
344
|
context.on('page', async (newPage) => {
|
|
354
345
|
await applyUserAgentOverride(newPage, modifiedUa, userAgentMetadata);
|
|
355
|
-
setupRealPage(browser, newPage
|
|
346
|
+
setupRealPage(browser, newPage);
|
|
356
347
|
await pageController({
|
|
357
348
|
browser,
|
|
358
349
|
page: newPage,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "real-browser-mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "MCP Server for Real Browser - Patchright (undetected Playwright fork) with Stealth Mode, Ad Blocker, and Turnstile Auto-Solver for undetectable web automation.",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/esm/index.mjs",
|
package/src/ai/core.js
CHANGED
|
@@ -90,13 +90,9 @@ class AICore {
|
|
|
90
90
|
if (element) {
|
|
91
91
|
if (humanLike) {
|
|
92
92
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const { createCursor } = require('ghost-cursor-patchright');
|
|
97
|
-
const cursor = await createCursor(page);
|
|
98
|
-
await cursor.click(selector);
|
|
99
|
-
}
|
|
93
|
+
const { createCursor } = require('ghost-cursor-patchright');
|
|
94
|
+
const cursor = createCursor(page);
|
|
95
|
+
await cursor.click(selector);
|
|
100
96
|
} catch {
|
|
101
97
|
await element.click();
|
|
102
98
|
}
|
package/src/mcp/handlers.js
CHANGED
|
@@ -1239,23 +1239,20 @@ const handlers = {
|
|
|
1239
1239
|
notifyProgress('click', 'progress', 'Used force click (JS)');
|
|
1240
1240
|
} else if (humanLike) {
|
|
1241
1241
|
try {
|
|
1242
|
+
const { createCursor } = require('ghost-cursor-patchright');
|
|
1243
|
+
const cursor = createCursor(page);
|
|
1244
|
+
|
|
1242
1245
|
if (context !== page) {
|
|
1243
1246
|
const element = await context.$(selector);
|
|
1244
1247
|
if (element) {
|
|
1245
1248
|
const box = await element.boundingBox();
|
|
1246
1249
|
if (box) {
|
|
1247
|
-
|
|
1248
|
-
await page.realCursor.move({ x: box.x + box.width / 2, y: box.y + box.height / 2 });
|
|
1249
|
-
}
|
|
1250
|
+
await cursor.moveTo({ x: box.x + box.width / 2, y: box.y + box.height / 2 });
|
|
1250
1251
|
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2, { clickCount, delay });
|
|
1251
1252
|
}
|
|
1252
1253
|
}
|
|
1253
1254
|
} else {
|
|
1254
|
-
|
|
1255
|
-
await page.realClick(selector);
|
|
1256
|
-
} else {
|
|
1257
|
-
await context.click(selector, { clickCount, delay });
|
|
1258
|
-
}
|
|
1255
|
+
await cursor.click(selector);
|
|
1259
1256
|
}
|
|
1260
1257
|
notifyProgress('click', 'progress', 'Used human-like cursor movement');
|
|
1261
1258
|
} catch (e) {
|
|
@@ -2005,13 +2002,9 @@ const handlers = {
|
|
|
2005
2002
|
|
|
2006
2003
|
// Click submit button with human-like behavior
|
|
2007
2004
|
try {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
const { createCursor } = require('ghost-cursor-patchright');
|
|
2012
|
-
const cursor = await createCursor(page);
|
|
2013
|
-
await cursor.click(submitSelector);
|
|
2014
|
-
}
|
|
2005
|
+
const { createCursor } = require('ghost-cursor-patchright');
|
|
2006
|
+
const cursor = createCursor(page);
|
|
2007
|
+
await cursor.click(submitSelector);
|
|
2015
2008
|
} catch (e) {
|
|
2016
2009
|
await page.click(submitSelector);
|
|
2017
2010
|
}
|
|
@@ -4773,18 +4766,13 @@ const handlers = {
|
|
|
4773
4766
|
}
|
|
4774
4767
|
}
|
|
4775
4768
|
}, identity, String(value));
|
|
4769
|
+
} else {
|
|
4776
4770
|
// Smart Type
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
const cursor = await createCursor(page);
|
|
4783
|
-
await cursor.click(identity);
|
|
4784
|
-
} catch (e) {
|
|
4785
|
-
await page.click(identity);
|
|
4786
|
-
}
|
|
4787
|
-
}
|
|
4771
|
+
const { createCursor } = require('ghost-cursor-patchright');
|
|
4772
|
+
const cursor = createCursor(page);
|
|
4773
|
+
|
|
4774
|
+
// Click center of element
|
|
4775
|
+
await cursor.click(identity);
|
|
4788
4776
|
|
|
4789
4777
|
// Clear existing
|
|
4790
4778
|
await page.evaluate(s => document.querySelector(s).value = '', identity);
|
|
@@ -4847,17 +4835,9 @@ const handlers = {
|
|
|
4847
4835
|
});
|
|
4848
4836
|
|
|
4849
4837
|
if (submitSelector) {
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
try {
|
|
4854
|
-
const { createCursor } = require('ghost-cursor-patchright');
|
|
4855
|
-
const cursor = await createCursor(page);
|
|
4856
|
-
await cursor.click(submitSelector);
|
|
4857
|
-
} catch (e) {
|
|
4858
|
-
await page.click(submitSelector);
|
|
4859
|
-
}
|
|
4860
|
-
}
|
|
4838
|
+
const { createCursor } = require('ghost-cursor-patchright');
|
|
4839
|
+
const cursor = createCursor(page);
|
|
4840
|
+
await cursor.click(submitSelector);
|
|
4861
4841
|
|
|
4862
4842
|
try {
|
|
4863
4843
|
await page.waitForNavigation({ timeout: 5000, waitUntil: 'domcontentloaded' });
|
package/test/cjs/test.js
CHANGED
|
@@ -4,7 +4,7 @@ const { connect } = require('../../lib/cjs/index.js');
|
|
|
4
4
|
|
|
5
5
|
const realBrowserOption = {
|
|
6
6
|
turnstile: true,
|
|
7
|
-
headless:
|
|
7
|
+
headless: true,
|
|
8
8
|
customConfig: {}
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -32,9 +32,7 @@ test.after(async () => {
|
|
|
32
32
|
|
|
33
33
|
test('DrissionPage Detector', async () => {
|
|
34
34
|
await page.goto("https://web.archive.org/web/20240913054632/https://drissionpage.pages.dev/", { timeout: 60000 });
|
|
35
|
-
await page.waitForSelector("#detector", { timeout: 20000 });
|
|
36
35
|
await page.realClick("#detector")
|
|
37
|
-
await page.waitForSelector("#isBot span", { timeout: 20000 });
|
|
38
36
|
let result = await page.evaluate(() => { return document.querySelector('#isBot span').textContent.includes("not") ? true : false })
|
|
39
37
|
assert.strictEqual(result, true, "DrissionPage Detector test failed!")
|
|
40
38
|
})
|
package/test/esm/test.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { connect } from '../../lib/esm/index.mjs';
|
|
|
4
4
|
|
|
5
5
|
const realBrowserOption = {
|
|
6
6
|
turnstile: true,
|
|
7
|
-
headless:
|
|
7
|
+
headless: true,
|
|
8
8
|
customConfig: {}
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -32,9 +32,7 @@ test.after(async () => {
|
|
|
32
32
|
|
|
33
33
|
test('DrissionPage Detector', async () => {
|
|
34
34
|
await page.goto("https://web.archive.org/web/20240913054632/https://drissionpage.pages.dev/", { timeout: 70000 });
|
|
35
|
-
await page.waitForSelector("#detector", { timeout: 20000 });
|
|
36
35
|
await page.realClick("#detector")
|
|
37
|
-
await page.waitForSelector("#isBot span", { timeout: 20000 });
|
|
38
36
|
let result = await page.evaluate(() => { return document.querySelector('#isBot span').textContent.includes("not") ? true : false })
|
|
39
37
|
assert.strictEqual(result, true, "DrissionPage Detector test failed!")
|
|
40
38
|
})
|
package/typings.d.ts
CHANGED
|
@@ -31,8 +31,6 @@ declare module "real-browser-mcp-server" {
|
|
|
31
31
|
enableBlocker?: boolean;
|
|
32
32
|
/** Blocker configuration options */
|
|
33
33
|
blockerOptions?: BlockerOptions;
|
|
34
|
-
/** Enable visual cursor arrow overlay (defaults to true in headed/visible mode, false in headless mode) */
|
|
35
|
-
visualCursor?: boolean;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
interface ProxyOptions {
|