mcp-scraper 0.2.7 → 0.2.9

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 (64) hide show
  1. package/README.md +44 -5
  2. package/dist/bin/api-server.cjs +2417 -648
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +3 -3
  5. package/dist/bin/browser-agent-stdio-server.cjs +1 -1
  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-cli.cjs +1276 -0
  9. package/dist/bin/mcp-scraper-cli.cjs.map +1 -0
  10. package/dist/bin/mcp-scraper-cli.d.cts +1 -0
  11. package/dist/bin/mcp-scraper-cli.d.ts +1 -0
  12. package/dist/bin/mcp-scraper-cli.js +476 -0
  13. package/dist/bin/mcp-scraper-cli.js.map +1 -0
  14. package/dist/bin/mcp-scraper-combined-stdio-server.cjs +69 -14
  15. package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
  16. package/dist/bin/mcp-scraper-combined-stdio-server.js +3 -3
  17. package/dist/bin/mcp-scraper-install.cjs +5 -1
  18. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  19. package/dist/bin/mcp-scraper-install.js +5 -1
  20. package/dist/bin/mcp-scraper-install.js.map +1 -1
  21. package/dist/bin/mcp-stdio-server.cjs +69 -14
  22. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  23. package/dist/bin/mcp-stdio-server.js +2 -2
  24. package/dist/bin/paa-harvest.cjs +42 -6
  25. package/dist/bin/paa-harvest.cjs.map +1 -1
  26. package/dist/bin/paa-harvest.js +1 -1
  27. package/dist/{chunk-3TF6UT2P.js → chunk-5E6KJC26.js} +2 -2
  28. package/dist/{chunk-D4CJBZBY.js → chunk-7GCCOT3M.js} +372 -1
  29. package/dist/chunk-7GCCOT3M.js.map +1 -0
  30. package/dist/chunk-BJDCPCIE.js +7 -0
  31. package/dist/chunk-BJDCPCIE.js.map +1 -0
  32. package/dist/{chunk-MY3S7EX7.js → chunk-CQTAKXBN.js} +43 -7
  33. package/dist/chunk-CQTAKXBN.js.map +1 -0
  34. package/dist/chunk-L6IS63WS.js +869 -0
  35. package/dist/chunk-L6IS63WS.js.map +1 -0
  36. package/dist/{chunk-IQOCZGJJ.js → chunk-ROS67BNV.js} +5 -5
  37. package/dist/{chunk-7SI6XIR3.js → chunk-XAY5U67D.js} +70 -15
  38. package/dist/chunk-XAY5U67D.js.map +1 -0
  39. package/dist/{db-YWCNHBLH.js → db-BVHYI57K.js} +38 -2
  40. package/dist/index.cjs +42 -6
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.js +1 -1
  43. package/dist/{server-RIKRBDOI.js → server-BKJ7LULQ.js} +818 -394
  44. package/dist/server-BKJ7LULQ.js.map +1 -0
  45. package/dist/{worker-NAKGTIF5.js → worker-TDJQ6TH3.js} +8 -8
  46. package/docs/mcp-tool-quality-spec.md +3 -1
  47. package/docs/specs/agent-ready-seo-packet-spec.md +237 -0
  48. package/docs/specs/cli-agent-wiring-spec.md +203 -0
  49. package/docs/specs/deferred-work-spec.md +12 -0
  50. package/docs/specs/local-competitive-audit-spec.md +312 -0
  51. package/docs/specs/scheduled-workflows-api-spec.md +304 -0
  52. package/docs/specs/seo-cli-growth-roadmap-spec.md +179 -0
  53. package/docs/specs/seo-workflow-runner-and-reports-spec.md +241 -0
  54. package/package.json +3 -2
  55. package/dist/chunk-7SI6XIR3.js.map +0 -1
  56. package/dist/chunk-D4CJBZBY.js.map +0 -1
  57. package/dist/chunk-IZE5UW7Y.js +0 -7
  58. package/dist/chunk-IZE5UW7Y.js.map +0 -1
  59. package/dist/chunk-MY3S7EX7.js.map +0 -1
  60. package/dist/server-RIKRBDOI.js.map +0 -1
  61. /package/dist/{chunk-3TF6UT2P.js.map → chunk-5E6KJC26.js.map} +0 -0
  62. /package/dist/{chunk-IQOCZGJJ.js.map → chunk-ROS67BNV.js.map} +0 -0
  63. /package/dist/{db-YWCNHBLH.js.map → db-BVHYI57K.js.map} +0 -0
  64. /package/dist/{worker-NAKGTIF5.js.map → worker-TDJQ6TH3.js.map} +0 -0
@@ -225,6 +225,8 @@ var MOBILE_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X)
225
225
  var DEFAULT_KERNEL_BROWSER_TIMEOUT_SECONDS = 180;
226
226
  var KERNEL_BROWSER_CLOSE_TIMEOUT_MS = 3e3;
227
227
  var KERNEL_SESSION_DELETE_TIMEOUT_MS = 5e3;
228
+ var DEFAULT_SERP_CHALLENGE_SOLVE_WAIT_MS = 2500;
229
+ var SERP_CHALLENGE_SOLVE_POLL_MS = 500;
228
230
  function positiveIntFromEnv(name, fallback) {
229
231
  const raw = process.env[name];
230
232
  if (!raw) return fallback;
@@ -536,20 +538,20 @@ var BrowserDriver = class {
536
538
  const diag = await this.captureDiagnostics(url);
537
539
  throw new ExtractionError(`page.goto failed: ${err.message} | ${diag}`);
538
540
  }
539
- const captchaCount = await this.page.locator(PAASelectors.captchaMarker).count();
540
- if (captchaCount > 0) {
541
+ if (await this.isSerpChallengeVisible()) {
541
542
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: true });
542
- throw new CaptchaError(this.captchaMessage());
543
+ const solved = await this.waitForSerpChallengeToClear(navDebug, url);
544
+ if (!solved) throw new CaptchaError(this.captchaMessage());
543
545
  }
544
546
  const fastFound = await this.page.waitForSelector(PAASelectors.item, { timeout: 4e3 }).catch(() => null);
545
547
  if (fastFound) {
546
548
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: true, captchaDetected: false });
547
549
  return { hasPaa: true };
548
550
  }
549
- const captchaAfter = await this.page.locator(PAASelectors.captchaMarker).count();
550
- if (captchaAfter > 0) {
551
+ if (await this.isSerpChallengeVisible()) {
551
552
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: true });
552
- throw new CaptchaError(this.captchaMessage());
553
+ const solved = await this.waitForSerpChallengeToClear(navDebug, url);
554
+ if (!solved) throw new CaptchaError(this.captchaMessage());
553
555
  }
554
556
  for (let i = 1; i <= 6; i++) {
555
557
  await this.page.evaluate((f) => {
@@ -565,6 +567,35 @@ var BrowserDriver = class {
565
567
  await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: false, captchaDetected: false });
566
568
  return { hasPaa: false };
567
569
  }
570
+ async isSerpChallengeVisible() {
571
+ if (!this.page) return false;
572
+ const captchaCount = await this.page.locator(PAASelectors.captchaMarker).count().catch(() => 0);
573
+ if (captchaCount > 0) return true;
574
+ const finalUrl = this.page.url();
575
+ if (/google\.[^/]+\/sorry\//i.test(finalUrl)) return true;
576
+ const bodySnippet = await this.page.evaluate(() => {
577
+ const text = (document.body?.innerText ?? "").replace(/\s+/g, " ").trim();
578
+ return text.slice(0, 1e3);
579
+ }).catch(() => "");
580
+ return /recaptcha|unusual traffic|are you a robot|about this page|detected unusual traffic/i.test(bodySnippet);
581
+ }
582
+ async waitForSerpChallengeToClear(navDebug, requestedUrl) {
583
+ if (!this.kernelClient || !this.page) return false;
584
+ const waitMs = positiveIntFromEnv("SERP_CHALLENGE_SOLVE_WAIT_MS", DEFAULT_SERP_CHALLENGE_SOLVE_WAIT_MS);
585
+ const deadline = Date.now() + waitMs;
586
+ while (Date.now() < deadline) {
587
+ await this.page.waitForTimeout(Math.min(SERP_CHALLENGE_SOLVE_POLL_MS, Math.max(250, deadline - Date.now())));
588
+ if (!await this.isSerpChallengeVisible()) {
589
+ await this.page.waitForTimeout(1e3);
590
+ if (!await this.isSerpChallengeVisible()) {
591
+ await this.updateSerpNavigationDebug(navDebug, requestedUrl, { hasPaa: null, captchaDetected: false });
592
+ return true;
593
+ }
594
+ }
595
+ }
596
+ await this.updateSerpNavigationDebug(navDebug, requestedUrl, { hasPaa: false, captchaDetected: true });
597
+ return false;
598
+ }
568
599
  async updateSerpNavigationDebug(navDebug, requestedUrl, state) {
569
600
  if (!navDebug || !this.page) return;
570
601
  try {
@@ -612,7 +643,12 @@ var BrowserDriver = class {
612
643
  async navigateTo(url) {
613
644
  try {
614
645
  await this.page.goto(url, { waitUntil: "domcontentloaded", timeout: 45e3 });
646
+ if (/google\.[^/]+\/search\?/i.test(url) && await this.isSerpChallengeVisible()) {
647
+ const solved = await this.waitForSerpChallengeToClear(null, url);
648
+ if (!solved) throw new CaptchaError(this.captchaMessage());
649
+ }
615
650
  } catch (err) {
651
+ if (err instanceof CaptchaError) throw err;
616
652
  const diag = await this.captureDiagnostics(url);
617
653
  throw new ExtractionError(`page.goto failed: ${err.message} | ${diag}`);
618
654
  }
@@ -2936,4 +2972,4 @@ export {
2936
2972
  resolveKernelProxyId,
2937
2973
  harvest
2938
2974
  };
2939
- //# sourceMappingURL=chunk-MY3S7EX7.js.map
2975
+ //# sourceMappingURL=chunk-CQTAKXBN.js.map