cbrowser 16.17.0 → 17.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/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ export { CBrowser } from "./browser.js";
27
27
  export { getDefaultConfig, getPaths, ensureDirectories, mergeConfig } from "./config.js";
28
28
  export type { CBrowserConfig, CBrowserPaths, BrowserType } from "./config.js";
29
29
  export * from "./types.js";
30
- export { BUILTIN_PERSONAS } from "./personas.js";
30
+ export { BUILTIN_PERSONAS, registerPersonas } from "./personas.js";
31
31
  export * from "./trait-reference.js";
32
32
  export { startMcpServer, createMcpServer, connectMcpServer } from "./mcp-server.js";
33
33
  export { startDaemon, stopDaemon, getDaemonStatus, isDaemonRunning, sendToDaemon, runDaemonServer } from "./daemon.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzF,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGjD,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAIvH,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1E,cAAc,oBAAoB,CAAC;AAInC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,4BAA4B,CAAC;AAI3C,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzF,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGnE,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAIvH,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,wBAAwB,CAAC;AAGvC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1E,cAAc,oBAAoB,CAAC;AAInC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,4BAA4B,CAAC;AAI3C,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@
26
26
  export { CBrowser } from "./browser.js";
27
27
  export { getDefaultConfig, getPaths, ensureDirectories, mergeConfig } from "./config.js";
28
28
  export * from "./types.js";
29
- export { BUILTIN_PERSONAS } from "./personas.js";
29
+ export { BUILTIN_PERSONAS, registerPersonas } from "./personas.js";
30
30
  // Trait Reference (v15.0.0) - Cognitive trait definitions and guidelines
31
31
  export * from "./trait-reference.js";
32
32
  export { startMcpServer, createMcpServer, connectMcpServer } from "./mcp-server.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzF,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,yEAAyE;AACzE,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvH,2BAA2B;AAC3B,wBAAwB;AACxB,cAAc,mBAAmB,CAAC;AAElC,iBAAiB;AACjB,cAAc,oBAAoB,CAAC;AAEnC,kBAAkB;AAClB,cAAc,qBAAqB,CAAC;AAEpC,qBAAqB;AACrB,cAAc,wBAAwB,CAAC;AAEvC,6BAA6B;AAC7B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E,2BAA2B;AAC3B,cAAc,oBAAoB,CAAC;AAEnC,6CAA6C;AAC7C,uDAAuD;AACvD,cAAc,oBAAoB,CAAC;AAEnC,sEAAsE;AACtE,cAAc,4BAA4B,CAAC;AAE3C,2EAA2E;AAC3E,oEAAoE;AACpE,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzF,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,yEAAyE;AACzE,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvH,2BAA2B;AAC3B,wBAAwB;AACxB,cAAc,mBAAmB,CAAC;AAElC,iBAAiB;AACjB,cAAc,oBAAoB,CAAC;AAEnC,kBAAkB;AAClB,cAAc,qBAAqB,CAAC;AAEpC,qBAAqB;AACrB,cAAc,wBAAwB,CAAC;AAEvC,6BAA6B;AAC7B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E,2BAA2B;AAC3B,cAAc,oBAAoB,CAAC;AAEnC,6CAA6C;AAC7C,uDAAuD;AACvD,cAAc,oBAAoB,CAAC;AAEnC,sEAAsE;AACtE,cAAc,4BAA4B,CAAC;AAE3C,2EAA2E;AAC3E,oEAAoE;AACpE,cAAc,mBAAmB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server-remote.d.ts","sourceRoot":"","sources":["../src/mcp-server-remote.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AA6BH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAopGpE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoM1F"}
1
+ {"version":3,"file":"mcp-server-remote.d.ts","sourceRoot":"","sources":["../src/mcp-server-remote.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AA6BH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgwFpE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoM1F"}
@@ -60,13 +60,11 @@ import { capturePerformanceBaseline, detectPerformanceRegression, listPerformanc
60
60
  import { getPersonaValues, PERSONA_VALUE_PROFILES, rankInfluencePatternsForProfile, INFLUENCE_PATTERNS, } from "./values/index.js";
61
61
  // Version from package.json - single source of truth
62
62
  import { VERSION } from "./version.js";
63
- // Stealth/Enterprise loader (v16.2.0)
64
- import { getEnforcer, isEnterpriseAvailable, getEnterpriseVersion, } from "./stealth/index.js";
65
63
  // Shared browser instance
66
64
  let browser = null;
67
65
  // Stealth state (enterprise integration)
68
- let stealthEnforcer = null;
69
- let stealthConfig = null;
66
+ const stealthEnforcer = null;
67
+ const stealthConfig = null;
70
68
  async function getBrowser() {
71
69
  if (!browser) {
72
70
  // Pass proxy configuration from stealth config if available
@@ -307,47 +305,7 @@ function configureMcpTools(server) {
307
305
  ],
308
306
  };
309
307
  });
310
- server.tool("cloudflare_detect", "Detect if the current page is a Cloudflare challenge page. Returns the type of challenge (turnstile, managed, interstitial, js-challenge) and evidence.", {}, async () => {
311
- const b = await getBrowser();
312
- const result = await b.detectCloudflareChallenge();
313
- return {
314
- content: [
315
- {
316
- type: "text",
317
- text: JSON.stringify({
318
- detected: result.detected,
319
- challenge_type: result.type,
320
- evidence: result.evidence,
321
- message: result.detected
322
- ? `Cloudflare ${result.type} challenge detected. Use cloudflare_wait to wait for resolution.`
323
- : "No Cloudflare challenge detected on current page.",
324
- }, null, 2),
325
- },
326
- ],
327
- };
328
- });
329
- server.tool("cloudflare_wait", "Wait for a Cloudflare challenge to resolve. Use this after navigating to a page that shows a Cloudflare protection page. The tool will poll until the challenge completes or times out.", {
330
- timeout: z.number().optional().describe("Maximum time to wait in milliseconds (default: 30000)"),
331
- }, async ({ timeout }) => {
332
- const b = await getBrowser();
333
- const result = await b.waitForCloudflareResolution(timeout ?? 30000);
334
- const screenshot = await b.screenshot();
335
- return {
336
- content: [
337
- {
338
- type: "text",
339
- text: JSON.stringify({
340
- resolved: result.resolved,
341
- original_url: result.originalUrl,
342
- final_url: result.finalUrl,
343
- wait_time_ms: result.waitTime,
344
- message: result.message,
345
- screenshot,
346
- }, null, 2),
347
- },
348
- ],
349
- };
350
- });
308
+ // NOTE: cloudflare_detect and cloudflare_wait moved to Enterprise (v16.18.0)
351
309
  // =========================================================================
352
310
  // Interaction Tools
353
311
  // =========================================================================
@@ -2320,298 +2278,12 @@ Begin the simulation now. Narrate your thoughts as this persona.
2320
2278
  };
2321
2279
  });
2322
2280
  // ============================================================================
2323
- // STEALTH/ENTERPRISE TOOLS (v16.2.0)
2324
- // These tools interface with cbrowser-enterprise when installed
2325
- // ============================================================================
2326
- server.tool("stealth_status", "Check if CBrowser Enterprise is installed and show stealth capabilities. Enterprise provides constitutional stealth mode for authorized testing.", {}, async () => {
2327
- const available = await isEnterpriseAvailable();
2328
- const version = getEnterpriseVersion();
2329
- const enabled = stealthConfig?.enabled ?? false;
2330
- const proxyConfigured = !!stealthConfig?.proxy?.server;
2331
- return {
2332
- content: [
2333
- {
2334
- type: "text",
2335
- text: JSON.stringify({
2336
- enterprise_available: available,
2337
- enterprise_version: version,
2338
- stealth_enabled: enabled,
2339
- stealth_config: enabled ? {
2340
- authorized_domains: stealthConfig?.authorization?.authorizedDomains ?? [],
2341
- blocked_domains: stealthConfig?.authorization?.blockedDomains ?? [],
2342
- } : null,
2343
- proxy_configured: proxyConfigured,
2344
- proxy_server: proxyConfigured
2345
- ? stealthConfig?.proxy?.server?.replace(/:[^:@]*@/, ":****@") // Mask password
2346
- : null,
2347
- message: available
2348
- ? `Enterprise v${version} available. Stealth ${enabled ? "enabled" : "disabled"}.${proxyConfigured ? " Proxy active." : ""}`
2349
- : "Enterprise not installed. Install cbrowser-enterprise for stealth capabilities.",
2350
- }, null, 2),
2351
- },
2352
- ],
2353
- };
2354
- });
2355
- server.tool("stealth_enable", "Enable constitutional stealth mode for authorized domains. Requires cbrowser-enterprise. You must have authorization to test on the specified domains. Optionally configure a residential/datacenter proxy to bypass IP-based detection.", {
2356
- authorized_domains: z.array(z.string()).describe("Domains you are authorized to test (e.g., ['*.mycompany.com', 'staging.example.com'])"),
2357
- signed_by: z.string().describe("Your email or identifier confirming authorization"),
2358
- proxy_server: z.string().optional().describe("Proxy server URL (e.g., 'http://proxy.example.com:8080' or 'socks5://proxy.example.com:1080'). Use residential proxies for best detection bypass."),
2359
- proxy_username: z.string().optional().describe("Proxy authentication username (optional)"),
2360
- proxy_password: z.string().optional().describe("Proxy authentication password (optional)"),
2361
- }, async ({ authorized_domains, signed_by, proxy_server, proxy_username, proxy_password }) => {
2362
- const available = await isEnterpriseAvailable();
2363
- if (!available) {
2364
- return {
2365
- content: [
2366
- {
2367
- type: "text",
2368
- text: JSON.stringify({
2369
- success: false,
2370
- error: "Enterprise not installed",
2371
- message: "Stealth mode requires cbrowser-enterprise. Contact alexandria.shai.eden@gmail.com for access.",
2372
- }, null, 2),
2373
- },
2374
- ],
2375
- };
2376
- }
2377
- // Create stealth config with acknowledgment
2378
- stealthConfig = {
2379
- enabled: true,
2380
- authorization: {
2381
- authorizedDomains: authorized_domains,
2382
- blockedDomains: [],
2383
- requireExplicitAuth: true,
2384
- },
2385
- acknowledgment: {
2386
- ownershipConfirmed: true,
2387
- authorizedTestingOnly: true,
2388
- acceptsResponsibility: true,
2389
- signedBy: signed_by,
2390
- signedAt: new Date().toISOString(),
2391
- },
2392
- rateLimits: {
2393
- requestsPerMinute: 30,
2394
- formsPerMinute: 5,
2395
- authAttemptsPerMinute: 3,
2396
- },
2397
- // Add proxy config if provided
2398
- proxy: proxy_server ? {
2399
- server: proxy_server,
2400
- username: proxy_username,
2401
- password: proxy_password,
2402
- } : undefined,
2403
- };
2404
- // Get enforcer with config
2405
- stealthEnforcer = await getEnforcer(stealthConfig);
2406
- // Reset browser to apply stealth and proxy to new pages
2407
- if (browser) {
2408
- await browser.close();
2409
- browser = null;
2410
- }
2411
- return {
2412
- content: [
2413
- {
2414
- type: "text",
2415
- text: JSON.stringify({
2416
- success: true,
2417
- message: "Stealth mode enabled",
2418
- authorized_domains,
2419
- signed_by,
2420
- signed_at: stealthConfig.acknowledgment?.signedAt,
2421
- rate_limits: stealthConfig.rateLimits,
2422
- proxy_configured: !!proxy_server,
2423
- proxy_server: proxy_server ? proxy_server.replace(/:[^:@]*@/, ":****@") : null, // Mask password in logs
2424
- note: proxy_server
2425
- ? "Stealth measures and proxy will be applied to all new pages on authorized domains."
2426
- : "Stealth measures will be applied to all new pages on authorized domains.",
2427
- }, null, 2),
2428
- },
2429
- ],
2430
- };
2431
- });
2432
- server.tool("stealth_check", "Check if a stealth action is allowed on a specific URL. Returns whether the action can proceed and any restrictions.", {
2433
- action: z.string().describe("Action to check (e.g., 'navigate', 'click', 'fill', 'submit')"),
2434
- url: z.string().url().describe("URL where the action would occur"),
2435
- }, async ({ action, url }) => {
2436
- if (!stealthEnforcer) {
2437
- return {
2438
- content: [
2439
- {
2440
- type: "text",
2441
- text: JSON.stringify({
2442
- allowed: false,
2443
- reason: "Stealth not enabled",
2444
- suggestion: "Use stealth_enable to configure authorized domains first.",
2445
- }, null, 2),
2446
- },
2447
- ],
2448
- };
2449
- }
2450
- const check = await stealthEnforcer.canExecuteWithStealth(action, url);
2451
- return {
2452
- content: [
2453
- {
2454
- type: "text",
2455
- text: JSON.stringify({
2456
- allowed: check.allowed,
2457
- zone: check.zone,
2458
- reason: check.reason,
2459
- suggestion: check.suggestion,
2460
- requires_confirmation: check.requiresConfirmation ?? false,
2461
- }, null, 2),
2462
- },
2463
- ],
2464
- };
2465
- });
2466
- server.tool("stealth_disable", "Disable stealth mode and clear the enforcer. Browser state is preserved - no recovery needed.", {}, async () => {
2467
- const wasEnabled = stealthConfig?.enabled ?? false;
2468
- stealthEnforcer = null;
2469
- stealthConfig = null;
2470
- // Preserve browser state - don't close
2471
- // User can call reset_browser explicitly if needed
2472
- return {
2473
- content: [
2474
- {
2475
- type: "text",
2476
- text: JSON.stringify({
2477
- success: true,
2478
- was_enabled: wasEnabled,
2479
- browser_preserved: true,
2480
- message: wasEnabled
2481
- ? "Stealth mode disabled. Browser state preserved - continue using normally."
2482
- : "Stealth was not enabled.",
2483
- }, null, 2),
2484
- },
2485
- ],
2486
- };
2487
- });
2488
- // ============================================================================
2489
- // STEALTH DIAGNOSTIC TOOL (v16.3.0)
2281
+ // NOTE: Stealth tools moved to Enterprise (v16.18.0)
2282
+ // The following tools are now Enterprise-only:
2283
+ // - stealth_status, stealth_enable, stealth_disable, stealth_check, stealth_diagnose
2284
+ // - cloudflare_detect, cloudflare_wait
2285
+ // Contact alexandria.shai.eden@gmail.com for Enterprise access.
2490
2286
  // ============================================================================
2491
- server.tool("stealth_diagnose", "Navigate to a URL and diagnose what bot detection methods the site uses. Returns analysis of fingerprint, IP, behavioral, and WAF/Cloudflare detection.", {
2492
- url: z.string().url().describe("URL to diagnose for bot detection methods"),
2493
- }, async ({ url }) => {
2494
- const b = await getBrowser();
2495
- const diagnosis = {
2496
- url,
2497
- detection_methods: {
2498
- fingerprint: { detected: false, evidence: [] },
2499
- ip_reputation: { likely: false, evidence: [] },
2500
- behavioral: { detected: false, evidence: [] },
2501
- waf_cloudflare: { detected: false, type: null, evidence: [] },
2502
- },
2503
- page_loaded: false,
2504
- recommendations: [],
2505
- };
2506
- try {
2507
- // Navigate with short timeout to detect blocks
2508
- const navResult = await b.navigate(url);
2509
- if (!navResult.success) {
2510
- diagnosis.detection_methods.ip_reputation.likely = true;
2511
- diagnosis.detection_methods.ip_reputation.evidence.push("Navigation failed: " + (navResult.errors?.join(", ") || "unknown error"));
2512
- diagnosis.recommendations.push("Site may block datacenter IPs. Consider residential proxy.");
2513
- return {
2514
- content: [{ type: "text", text: JSON.stringify(diagnosis, null, 2) }],
2515
- };
2516
- }
2517
- diagnosis.page_loaded = true;
2518
- // Check page content for detection indicators
2519
- const page = await b.getPage();
2520
- if (page) {
2521
- const content = await page.content();
2522
- const pageUrl = page.url();
2523
- // Cloudflare detection
2524
- if (content.includes("cf-browser-verification") || content.includes("cf_chl_opt")) {
2525
- diagnosis.detection_methods.waf_cloudflare.detected = true;
2526
- diagnosis.detection_methods.waf_cloudflare.type = "Cloudflare Challenge";
2527
- diagnosis.detection_methods.waf_cloudflare.evidence.push("Found cf-browser-verification in page");
2528
- diagnosis.recommendations.push("Cloudflare challenge detected. Stealth may help with browser checks.");
2529
- }
2530
- if (content.includes("turnstile") || content.includes("challenges.cloudflare.com")) {
2531
- diagnosis.detection_methods.waf_cloudflare.detected = true;
2532
- diagnosis.detection_methods.waf_cloudflare.type = "Cloudflare Turnstile";
2533
- diagnosis.detection_methods.waf_cloudflare.evidence.push("Found Turnstile widget");
2534
- diagnosis.recommendations.push("Turnstile CAPTCHA present. May pass with stealth, but IP reputation affects success.");
2535
- }
2536
- // Reddit-style IP blocking - v16.7.2: More specific patterns to reduce false positives
2537
- const blockPatterns = [
2538
- /you.{0,20}(have been|are|'ve been) blocked/i,
2539
- /your.{0,20}(ip|access).{0,20}(blocked|denied)/i,
2540
- /access.{0,10}(to this|has been).{0,10}denied/i,
2541
- /request.{0,15}blocked/i,
2542
- /temporarily blocked/i,
2543
- /ip.{0,10}(address|range).{0,15}blocked/i,
2544
- ];
2545
- const isBlocked = blockPatterns.some(p => p.test(content)) ||
2546
- pageUrl.includes("/blocked") ||
2547
- pageUrl.includes("access-denied");
2548
- if (isBlocked) {
2549
- diagnosis.detection_methods.ip_reputation.likely = true;
2550
- diagnosis.detection_methods.ip_reputation.evidence.push("Page indicates access/IP blocking");
2551
- diagnosis.recommendations.push("IP-based blocking detected. Requires residential proxy.");
2552
- }
2553
- // Check for common bot detection scripts
2554
- const botDetectors = [
2555
- { name: "PerimeterX", pattern: /px-captcha|human-challenge/ },
2556
- { name: "DataDome", pattern: /datadome|dd\.js/ },
2557
- { name: "Akamai Bot Manager", pattern: /akamai.*bot|_abck/ },
2558
- { name: "Shape Security", pattern: /shape.*security/ },
2559
- { name: "Imperva/Incapsula", pattern: /incap_ses|visid_incap/ },
2560
- { name: "Distil Networks", pattern: /distil|d\.js/ },
2561
- ];
2562
- for (const detector of botDetectors) {
2563
- if (detector.pattern.test(content)) {
2564
- diagnosis.detection_methods.fingerprint.detected = true;
2565
- diagnosis.detection_methods.fingerprint.evidence.push(`Found ${detector.name} signatures`);
2566
- }
2567
- }
2568
- // Check for navigator.webdriver detection - v16.7.2: Only in JS context
2569
- // Patterns that indicate actual detection code, not just documentation
2570
- const webdriverPatterns = [
2571
- /navigator\s*\.\s*webdriver/,
2572
- /window\s*\.\s*navigator\s*\.\s*webdriver/,
2573
- /\.webdriver\s*[=!]/, // Assignment or comparison
2574
- /webdriver.*true|true.*webdriver/i, // Boolean check context
2575
- ];
2576
- if (webdriverPatterns.some(p => p.test(content))) {
2577
- diagnosis.detection_methods.fingerprint.detected = true;
2578
- diagnosis.detection_methods.fingerprint.evidence.push("Page checks navigator.webdriver");
2579
- diagnosis.recommendations.push("Enable stealth to patch navigator.webdriver.");
2580
- }
2581
- // Check for automation tool detection - v16.7.2: Only in detection context
2582
- const automationDetectionPatterns = [
2583
- /window\s*\.\s*(?:__)?(?:puppeteer|playwright|selenium)/i,
2584
- /navigator\s*\.\s*(?:__)?(?:puppeteer|playwright|selenium)/i,
2585
- /typeof\s+(?:puppeteer|playwright|selenium)/i,
2586
- /["'](?:puppeteer|playwright|selenium)["']\s*in\s*window/i,
2587
- ];
2588
- if (automationDetectionPatterns.some(p => p.test(content))) {
2589
- diagnosis.detection_methods.fingerprint.detected = true;
2590
- diagnosis.detection_methods.fingerprint.evidence.push("Page checks for automation tools");
2591
- }
2592
- // Summary recommendations
2593
- if (diagnosis.detection_methods.fingerprint.detected && !diagnosis.detection_methods.ip_reputation.likely) {
2594
- diagnosis.recommendations.push("Browser fingerprint detection found. Stealth mode should help.");
2595
- }
2596
- if (diagnosis.detection_methods.ip_reputation.likely) {
2597
- diagnosis.recommendations.push("IP reputation is the primary block. Stealth alone won't solve this.");
2598
- }
2599
- if (!diagnosis.detection_methods.fingerprint.detected &&
2600
- !diagnosis.detection_methods.ip_reputation.likely &&
2601
- !diagnosis.detection_methods.waf_cloudflare.detected) {
2602
- diagnosis.recommendations.push("No obvious bot detection found. Site should work without stealth.");
2603
- }
2604
- }
2605
- }
2606
- catch (error) {
2607
- diagnosis.detection_methods.ip_reputation.likely = true;
2608
- diagnosis.detection_methods.ip_reputation.evidence.push("Error: " + String(error));
2609
- diagnosis.recommendations.push("Navigation error - likely IP-based blocking.");
2610
- }
2611
- return {
2612
- content: [{ type: "text", text: JSON.stringify(diagnosis, null, 2) }],
2613
- };
2614
- });
2615
2287
  }
2616
2288
  /**
2617
2289
  * Create a configured MCP server instance