mcp-scraper 0.32.3 → 0.33.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.
Files changed (36) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/api-server.cjs +13 -15
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +2 -2
  5. package/dist/bin/mcp-scraper-cli.cjs +5 -5
  6. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  7. package/dist/bin/mcp-scraper-cli.js +2 -2
  8. package/dist/bin/mcp-scraper-install.cjs +1 -1
  9. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  10. package/dist/bin/mcp-scraper-install.js +1 -1
  11. package/dist/bin/mcp-stdio-server.cjs +6 -6
  12. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  13. package/dist/bin/mcp-stdio-server.js +2 -2
  14. package/dist/bin/paa-harvest.js +1 -1
  15. package/dist/{chunk-MKZIL4EA.js → chunk-AT2PFWHW.js} +5 -5
  16. package/dist/chunk-AT2PFWHW.js.map +1 -0
  17. package/dist/{chunk-AEMABLEL.js → chunk-ERORC7AP.js} +1 -3
  18. package/dist/chunk-IASKABFL.js +7 -0
  19. package/dist/chunk-IASKABFL.js.map +1 -0
  20. package/dist/{chunk-GNRHBIYZ.js → chunk-JURXY3DP.js} +7 -7
  21. package/dist/chunk-JURXY3DP.js.map +1 -0
  22. package/dist/index.js +1 -1
  23. package/dist/{server-NHLEIKDZ.js → server-RKAKXRAR.js} +9 -12
  24. package/dist/server-RKAKXRAR.js.map +1 -0
  25. package/dist/{worker-ZZCZNY3R.js → worker-JU5FX3NE.js} +2 -2
  26. package/docs/adr/0003-waive-unrecoverable-scheduled-model-cost.md +22 -0
  27. package/docs/adr/README.md +1 -0
  28. package/docs/mcp-tool-manifest.generated.json +7 -12
  29. package/package.json +1 -1
  30. package/dist/chunk-GNRHBIYZ.js.map +0 -1
  31. package/dist/chunk-MKZIL4EA.js.map +0 -1
  32. package/dist/chunk-XF46AB5C.js +0 -7
  33. package/dist/chunk-XF46AB5C.js.map +0 -1
  34. package/dist/server-NHLEIKDZ.js.map +0 -1
  35. /package/dist/{chunk-AEMABLEL.js.map → chunk-ERORC7AP.js.map} +0 -0
  36. /package/dist/{worker-ZZCZNY3R.js.map → worker-JU5FX3NE.js.map} +0 -0
package/README.md CHANGED
@@ -88,7 +88,7 @@ Build the branded one-click bundle:
88
88
  npm run build:mcpb
89
89
  ```
90
90
 
91
- The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.32.3`, SHA-256 `1e44cc581a788e799b5e0eb7e909178714a50030d86bbdc6c2b119d84b04fb97`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
91
+ The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.33.0`, SHA-256 `e1426b852fdcb832bfa615e3d1a56828f5c0ed411ba2920241112174ac6d10d6`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
92
92
 
93
93
  The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
94
94
 
@@ -15945,7 +15945,7 @@ var init_server_schemas = __esm({
15945
15945
  gl: import_zod15.z.string().optional(),
15946
15946
  hl: import_zod15.z.string().optional(),
15947
15947
  device: import_zod15.z.enum(["desktop", "mobile"]).optional(),
15948
- proxyMode: import_zod15.z.enum(["location", "configured", "none"]).optional(),
15948
+ proxyMode: import_zod15.z.enum(["configured", "none"]).optional(),
15949
15949
  proxyZip: import_zod15.z.string().regex(/^\d{5}$/).optional(),
15950
15950
  debug: import_zod15.z.boolean().optional(),
15951
15951
  serpOnly: import_zod15.z.boolean().optional(),
@@ -19253,13 +19253,11 @@ var init_video_routes = __esm({
19253
19253
  function buildGoogleLocalResultsUrl(input) {
19254
19254
  const query = [input.query, input.location].filter(Boolean).join(" ");
19255
19255
  const params = new URLSearchParams({ q: query, udm: "1", gl: input.gl, hl: input.hl, pws: "0" });
19256
- if (input.location) params.set("uule", encodeUule(normalizeLocation(input.location)));
19257
19256
  return `https://www.google.com/search?${params.toString()}`;
19258
19257
  }
19259
19258
  function buildGoogleOrganicSearchUrl(input) {
19260
19259
  const query = [input.query, input.location].filter(Boolean).join(" ");
19261
19260
  const params = new URLSearchParams({ q: query, gl: input.gl, hl: input.hl, pws: "0" });
19262
- if (input.location) params.set("uule", encodeUule(normalizeLocation(input.location)));
19263
19261
  return `https://www.google.com/search?${params.toString()}`;
19264
19262
  }
19265
19263
  function mapsIdentifiersFromUrl(url) {
@@ -19284,7 +19282,6 @@ var init_MapsSearchExtractor = __esm({
19284
19282
  "use strict";
19285
19283
  init_errors();
19286
19284
  init_BrowserDriver();
19287
- init_uule();
19288
19285
  LOCAL_RESULTS_PAGE_LIMIT = 8;
19289
19286
  LOCAL_RESULTS_WAIT_MS = 1e3;
19290
19287
  MAPS_REDIRECT_BASE = "https://serp-redirector.vercel.app";
@@ -20163,6 +20160,7 @@ async function cleanupDisposableProxy(kernelApiKey, proxyId, eventName) {
20163
20160
  }
20164
20161
  }
20165
20162
  async function runMapsSearchWithRotation(options) {
20163
+ if (options.proxyMode === "location") options = { ...options, proxyMode: "none" };
20166
20164
  const attempts = [];
20167
20165
  const maxAttempts = mapsSearchMaxAttemptsForProxyMode(options.proxyMode) + 1;
20168
20166
  const started = Date.now();
@@ -24138,7 +24136,7 @@ var init_directory_workflow = __esm({
24138
24136
  saveCsv: import_zod26.z.boolean().default(true),
24139
24137
  gl: import_zod26.z.string().length(2).default("us"),
24140
24138
  hl: import_zod26.z.string().length(2).default("en"),
24141
- proxyMode: import_zod26.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE),
24139
+ proxyMode: import_zod26.z.enum(["configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE),
24142
24140
  proxyZip: import_zod26.z.string().regex(/^\d{5}$/).optional(),
24143
24141
  debug: import_zod26.z.boolean().default(false),
24144
24142
  headless: import_zod26.z.boolean().default(true),
@@ -24794,7 +24792,7 @@ var init_directory = __esm({
24794
24792
  maxCities: import_zod28.z.number().int().min(1).max(100).default(25),
24795
24793
  maxResultsPerCity: import_zod28.z.number().int().min(1).max(50).default(20),
24796
24794
  concurrency: import_zod28.z.number().int().min(1).max(5).default(5),
24797
- proxyMode: import_zod28.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE),
24795
+ proxyMode: import_zod28.z.enum(["configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE),
24798
24796
  saveCsv: import_zod28.z.boolean().default(true)
24799
24797
  });
24800
24798
  DIRECTORY_CSV_HEADERS = [
@@ -24949,7 +24947,7 @@ var init_get_leads = __esm({
24949
24947
  enrichWebsites: import_zod29.z.boolean().default(true).describe("Visit each business website (home + contact pages) to harvest email and social links. Uses the proxy/browser-backed extractor so blocked sites still resolve."),
24950
24948
  hydrateReviewCounts: import_zod29.z.boolean().default(true).describe("Deep-dive each profile to confirm the review count and booking URL that the Maps search list omits."),
24951
24949
  concurrency: import_zod29.z.number().int().min(1).max(4).default(3).describe("How many businesses to enrich in parallel. Keep low to respect per-account concurrency limits."),
24952
- proxyMode: import_zod29.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy targeting for the Maps search. location targets the market; none is for local debugging.")
24950
+ proxyMode: import_zod29.z.enum(["configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy behavior for the Maps search. Leave unset for clean egress; country/region localization comes from gl/hl plus the city or region in the query.")
24953
24951
  });
24954
24952
  LEADS_CSV_HEADERS = [
24955
24953
  "position",
@@ -25168,7 +25166,7 @@ var init_local_competitive_audit = __esm({
25168
25166
  hydrateTop: import_zod30.z.number().int().min(0).max(10).default(5),
25169
25167
  maxReviews: import_zod30.z.number().int().min(0).max(500).default(50),
25170
25168
  concurrency: import_zod30.z.number().int().min(1).max(5).default(5),
25171
- proxyMode: import_zod30.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE),
25169
+ proxyMode: import_zod30.z.enum(["configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE),
25172
25170
  returnPartial: import_zod30.z.boolean().default(true)
25173
25171
  });
25174
25172
  localCompetitiveAuditWorkflowDefinition = {
@@ -25621,7 +25619,7 @@ var init_comparison_briefs = __esm({
25621
25619
  init_directory();
25622
25620
  init_seo_workflow_utils();
25623
25621
  init_schemas3();
25624
- ProxyModeSchema = import_zod31.z.enum(["location", "configured", "none"]);
25622
+ ProxyModeSchema = import_zod31.z.enum(["configured", "none"]);
25625
25623
  MapComparisonInputSchema = import_zod31.z.object({
25626
25624
  query: import_zod31.z.string().min(1),
25627
25625
  location: import_zod31.z.string().optional(),
@@ -29814,7 +29812,7 @@ var PACKAGE_VERSION;
29814
29812
  var init_version = __esm({
29815
29813
  "src/version.ts"() {
29816
29814
  "use strict";
29817
- PACKAGE_VERSION = "0.32.3";
29815
+ PACKAGE_VERSION = "0.33.0";
29818
29816
  }
29819
29817
  });
29820
29818
 
@@ -30278,7 +30276,7 @@ var init_mcp_tool_schemas = __esm({
30278
30276
  gl: import_zod35.z.string().length(2).default("us").describe("Google country code inferred from location or user language."),
30279
30277
  hl: import_zod35.z.string().default("en").describe("Google interface/content language inferred from the user request."),
30280
30278
  device: import_zod35.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only for mobile rankings."),
30281
- proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress). Do NOT set "location" just because a city was named \u2014 that comes from city-in-query wording. "location" forces residential geo-IP for rank-tracking fidelity, is frequently CAPTCHA-blocked, and accepts failures.'),
30279
+ proxyMode: import_zod35.z.enum(["configured", "none"]).default(DEFAULT_PROXY_MODE).describe("Leave unset for clean egress (the default). Country/region localization comes from gl/hl plus the city or region in the query \u2014 not from a proxy."),
30282
30280
  proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location".'),
30283
30281
  debug: import_zod35.z.boolean().default(false).describe("Include sanitized diagnostics for debugging localization, CAPTCHA, or proxy behavior.")
30284
30282
  };
@@ -30447,7 +30445,7 @@ var init_mcp_tool_schemas = __esm({
30447
30445
  hl: import_zod35.z.string().length(2).default("en").describe("Language inferred from user request."),
30448
30446
  maxResults: import_zod35.z.number().int().min(1).max(50).default(10).describe("Number of candidates to return. Default 10, maximum 50."),
30449
30447
  includeServices: import_zod35.z.boolean().default(false).describe("Open each returned business profile to include its configured services and areas served when available. Adds a page visit per business; does not collect review cards."),
30450
- proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Leave unset for the default route (stealth browser on the managed ISP proxy, retried on a fresh session when Google blocks). Localization comes from the city in the query plus gl/hl. location forces an explicit residential proxy \u2014 not recommended for Google."),
30448
+ proxyMode: import_zod35.z.enum(["configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Leave unset for the default route (stealth browser on the managed ISP proxy, retried on a fresh session when Google blocks). Country/region localization comes from the city or region in the query plus gl/hl \u2014 not from a proxy."),
30451
30449
  proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe("Optional US ZIP override, only used when proxyMode is location."),
30452
30450
  debug: import_zod35.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
30453
30451
  };
@@ -30462,7 +30460,7 @@ var init_mcp_tool_schemas = __esm({
30462
30460
  includeZipGroups: import_zod35.z.boolean().default(true).describe("Attach ZIP groups from a configured US ZIPS CSV when available (MCP_SCRAPER_USZIPS_CSV_PATH or usZipsCsvPath)."),
30463
30461
  usZipsCsvPath: import_zod35.z.string().optional().describe("Local/test-only path to a US ZIPS CSV (state_abbr, zipcode, county, city columns). Deployed APIs should use MCP_SCRAPER_USZIPS_CSV_PATH instead. For ZIP enrichment, set MCP_SCRAPER_USZIPS_CSV_PATH on the server, or pass this in local/test mode."),
30464
30462
  saveCsv: import_zod35.z.boolean().default(true).describe("Save a directory-ready CSV of results to the MCP Scraper output directory and return its path."),
30465
- proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy behavior per city search. Leave unset for the default route (stealth browser on the managed ISP proxy, retried fresh on a Google block). location forces an explicit residential proxy \u2014 not recommended for Google."),
30463
+ proxyMode: import_zod35.z.enum(["configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy behavior per city search. Leave unset for the default route (stealth browser on the managed ISP proxy, retried fresh on a Google block). Country/region localization comes from the city or region in the query plus gl/hl \u2014 not from a proxy."),
30466
30464
  proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe("Optional ZIP override for proxy targeting; normally omitted."),
30467
30465
  debug: import_zod35.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
30468
30466
  };
@@ -31302,7 +31300,7 @@ var init_mcp_tool_schemas = __esm({
31302
31300
  gl: import_zod35.z.string().length(2).default("us").describe("Google country code inferred from location or user language."),
31303
31301
  hl: import_zod35.z.string().default("en").describe("Google interface/content language inferred from user request."),
31304
31302
  device: import_zod35.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only for mobile rankings."),
31305
- proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress). Do NOT set "location" just because a city was named \u2014 that comes from city-in-query wording. "location" forces residential geo-IP for rank-tracking fidelity, is frequently CAPTCHA-blocked, and accepts failures.'),
31303
+ proxyMode: import_zod35.z.enum(["configured", "none"]).default(DEFAULT_PROXY_MODE).describe("Leave unset for clean egress (the default). Country/region localization comes from gl/hl plus the city or region in the query \u2014 not from a proxy."),
31306
31304
  proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location".'),
31307
31305
  debug: import_zod35.z.boolean().default(false).describe("Include sanitized diagnostics for debugging localization, CAPTCHA, or proxy behavior."),
31308
31306
  pages: import_zod35.z.number().int().min(1).max(2).default(1).describe("Number of result pages to fetch (1\u20132).")
@@ -31313,7 +31311,7 @@ var init_mcp_tool_schemas = __esm({
31313
31311
  gl: import_zod35.z.string().length(2).default("us").describe("Google country code inferred from the requested market."),
31314
31312
  hl: import_zod35.z.string().default("en").describe("Google interface/content language inferred from the user request."),
31315
31313
  device: import_zod35.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only for mobile rankings/evidence."),
31316
- proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress). Do NOT set "location" just because a city was named \u2014 that comes from city-in-query wording. "location" forces residential geo-IP, is frequently CAPTCHA-blocked, and accepts failures.'),
31314
+ proxyMode: import_zod35.z.enum(["configured", "none"]).default(DEFAULT_PROXY_MODE).describe("Leave unset for clean egress (the default). Country/region localization comes from gl/hl plus the city or region in the query \u2014 not from a proxy."),
31317
31315
  proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location".'),
31318
31316
  pages: import_zod35.z.number().int().min(1).max(2).default(1).describe("Google result pages to capture. Use 2 only for deeper ranking evidence."),
31319
31317
  debug: import_zod35.z.boolean().default(false).describe("Include sanitized browser/proxy/location diagnostics."),