mcp-scraper 0.2.6 → 0.2.8

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.
Files changed (44) hide show
  1. package/README.md +13 -6
  2. package/dist/bin/api-server.cjs +582 -171
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +2 -2
  5. package/dist/bin/browser-agent-stdio-server.cjs +442 -9
  6. package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
  7. package/dist/bin/browser-agent-stdio-server.js +2 -2
  8. package/dist/bin/mcp-scraper-combined-stdio-server.cjs +519 -31
  9. package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
  10. package/dist/bin/mcp-scraper-combined-stdio-server.js +3 -3
  11. package/dist/bin/mcp-scraper-install.cjs +2 -1
  12. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  13. package/dist/bin/mcp-scraper-install.js +2 -1
  14. package/dist/bin/mcp-scraper-install.js.map +1 -1
  15. package/dist/bin/mcp-stdio-server.cjs +68 -13
  16. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  17. package/dist/bin/mcp-stdio-server.js +2 -2
  18. package/dist/bin/paa-harvest.cjs +42 -6
  19. package/dist/bin/paa-harvest.cjs.map +1 -1
  20. package/dist/bin/paa-harvest.js +1 -1
  21. package/dist/chunk-5HMOPP76.js +793 -0
  22. package/dist/chunk-5HMOPP76.js.map +1 -0
  23. package/dist/{chunk-7WB2W6FO.js → chunk-6NEXSNSA.js} +69 -14
  24. package/dist/chunk-6NEXSNSA.js.map +1 -0
  25. package/dist/{chunk-MY3S7EX7.js → chunk-CQTAKXBN.js} +43 -7
  26. package/dist/chunk-CQTAKXBN.js.map +1 -0
  27. package/dist/chunk-I26QN7WQ.js +7 -0
  28. package/dist/chunk-I26QN7WQ.js.map +1 -0
  29. package/dist/index.cjs +42 -6
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/{server-MKCU3M7Y.js → server-BTTDFPSQ.js} +456 -142
  33. package/dist/server-BTTDFPSQ.js.map +1 -0
  34. package/dist/{worker-NAKGTIF5.js → worker-5O44YBF4.js} +2 -2
  35. package/docs/mcp-tool-quality-spec.md +3 -1
  36. package/package.json +1 -1
  37. package/dist/chunk-7WB2W6FO.js.map +0 -1
  38. package/dist/chunk-MY3S7EX7.js.map +0 -1
  39. package/dist/chunk-T6SIPPOQ.js +0 -7
  40. package/dist/chunk-T6SIPPOQ.js.map +0 -1
  41. package/dist/chunk-XL4V7VKD.js +0 -360
  42. package/dist/chunk-XL4V7VKD.js.map +0 -1
  43. package/dist/server-MKCU3M7Y.js.map +0 -1
  44. /package/dist/{worker-NAKGTIF5.js.map → worker-5O44YBF4.js.map} +0 -0
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  HttpMcpToolExecutor,
4
4
  buildPaaExtractorMcpServer
5
- } from "../chunk-7WB2W6FO.js";
5
+ } from "../chunk-6NEXSNSA.js";
6
6
  import "../chunk-M2S27J6Z.js";
7
- import "../chunk-T6SIPPOQ.js";
7
+ import "../chunk-I26QN7WQ.js";
8
8
 
9
9
  // bin/mcp-stdio-server.ts
10
10
  import { readFileSync } from "fs";
@@ -262,6 +262,8 @@ var MOBILE_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X)
262
262
  var DEFAULT_KERNEL_BROWSER_TIMEOUT_SECONDS = 180;
263
263
  var KERNEL_BROWSER_CLOSE_TIMEOUT_MS = 3e3;
264
264
  var KERNEL_SESSION_DELETE_TIMEOUT_MS = 5e3;
265
+ var DEFAULT_SERP_CHALLENGE_SOLVE_WAIT_MS = 2500;
266
+ var SERP_CHALLENGE_SOLVE_POLL_MS = 500;
265
267
  function positiveIntFromEnv(name, fallback) {
266
268
  const raw = process.env[name];
267
269
  if (!raw) return fallback;
@@ -573,20 +575,20 @@ var BrowserDriver = class {
573
575
  const diag = await this.captureDiagnostics(url);
574
576
  throw new ExtractionError(`page.goto failed: ${err.message} | ${diag}`);
575
577
  }
576
- const captchaCount = await this.page.locator(PAASelectors.captchaMarker).count();
577
- if (captchaCount > 0) {
578
+ if (await this.isSerpChallengeVisible()) {
578
579
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: true });
579
- throw new CaptchaError(this.captchaMessage());
580
+ const solved = await this.waitForSerpChallengeToClear(navDebug, url);
581
+ if (!solved) throw new CaptchaError(this.captchaMessage());
580
582
  }
581
583
  const fastFound = await this.page.waitForSelector(PAASelectors.item, { timeout: 4e3 }).catch(() => null);
582
584
  if (fastFound) {
583
585
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: true, captchaDetected: false });
584
586
  return { hasPaa: true };
585
587
  }
586
- const captchaAfter = await this.page.locator(PAASelectors.captchaMarker).count();
587
- if (captchaAfter > 0) {
588
+ if (await this.isSerpChallengeVisible()) {
588
589
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: true });
589
- throw new CaptchaError(this.captchaMessage());
590
+ const solved = await this.waitForSerpChallengeToClear(navDebug, url);
591
+ if (!solved) throw new CaptchaError(this.captchaMessage());
590
592
  }
591
593
  for (let i = 1; i <= 6; i++) {
592
594
  await this.page.evaluate((f) => {
@@ -602,6 +604,35 @@ var BrowserDriver = class {
602
604
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: false });
603
605
  return { hasPaa: false };
604
606
  }
607
+ async isSerpChallengeVisible() {
608
+ if (!this.page) return false;
609
+ const captchaCount = await this.page.locator(PAASelectors.captchaMarker).count().catch(() => 0);
610
+ if (captchaCount > 0) return true;
611
+ const finalUrl = this.page.url();
612
+ if (/google\.[^/]+\/sorry\//i.test(finalUrl)) return true;
613
+ const bodySnippet = await this.page.evaluate(() => {
614
+ const text = (document.body?.innerText ?? "").replace(/\s+/g, " ").trim();
615
+ return text.slice(0, 1e3);
616
+ }).catch(() => "");
617
+ return /recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(bodySnippet);
618
+ }
619
+ async waitForSerpChallengeToClear(navDebug, requestedUrl) {
620
+ if (!this.kernelClient || !this.page) return false;
621
+ const waitMs = positiveIntFromEnv("SERP_CHALLENGE_SOLVE_WAIT_MS", DEFAULT_SERP_CHALLENGE_SOLVE_WAIT_MS);
622
+ const deadline = Date.now() + waitMs;
623
+ while (Date.now() < deadline) {
624
+ await this.page.waitForTimeout(Math.min(SERP_CHALLENGE_SOLVE_POLL_MS, Math.max(250, deadline - Date.now())));
625
+ if (!await this.isSerpChallengeVisible()) {
626
+ await this.page.waitForTimeout(1e3);
627
+ if (!await this.isSerpChallengeVisible()) {
628
+ await this.updateSerpNavigationDebug(navDebug, requestedUrl, { hasPaa: null, captchaDetected: false });
629
+ return true;
630
+ }
631
+ }
632
+ }
633
+ await this.updateSerpNavigationDebug(navDebug, requestedUrl, { hasPaa: false, captchaDetected: true });
634
+ return false;
635
+ }
605
636
  async updateSerpNavigationDebug(navDebug, requestedUrl, state) {
606
637
  if (!navDebug || !this.page) return;
607
638
  try {
@@ -649,7 +680,12 @@ var BrowserDriver = class {
649
680
  async navigateTo(url) {
650
681
  try {
651
682
  await this.page.goto(url, { waitUntil: "domcontentloaded", timeout: 45e3 });
683
+ if (/google\.[^/]+\/search\?/i.test(url) && await this.isSerpChallengeVisible()) {
684
+ const solved = await this.waitForSerpChallengeToClear(null, url);
685
+ if (!solved) throw new CaptchaError(this.captchaMessage());
686
+ }
652
687
  } catch (err) {
688
+ if (err instanceof CaptchaError) throw err;
653
689
  const diag = await this.captureDiagnostics(url);
654
690
  throw new ExtractionError(`page.goto failed: ${err.message} | ${diag}`);
655
691
  }