scrapeunblocker-mcp 0.12.7 → 0.12.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.
package/README.md CHANGED
@@ -16,7 +16,7 @@ You bring your **own** API key. Nothing is shared or proxied through us.
16
16
  | `browse_page` | Run interactive browser `steps` on a page (click, type, select, scroll, wait), then return the resulting HTML. Not read-only: it acts on the website. |
17
17
  | `list_elements` | List a page's notable elements with a ready-to-use selector for each (selector discovery). |
18
18
  | `fetch_parsed` | Fetch a page and return AI-parsed structured JSON. |
19
- | `google_search` | Run a Google search and return the results page as JSON: organic results with real URLs, favicons, sitelinks and ratings, ads, AI Overview, People also ask, related searches with links, knowledge panel, news, videos, local and shopping results. |
19
+ | `google_search` | Run a Google search and return the results page as JSON: organic results with real URLs, favicons, sitelinks and ratings, ads, AI Overview, People also ask, related searches with links, knowledge panel, news, videos, local and shopping results. Set `full_urls: true` to get every result's exact page URL: Google gives out the last links up to about 40 seconds after the search, so the call takes that much longer (billed the same). Without it, a result whose link has not come yet has the site's home page as its `url`. |
20
20
  | `fetch_markdown` | Fetch a page and return it as clean Markdown: the main content with absolute links, without scripts, styles, navigation or footer. Usually 2-25% the size of the HTML, so it is the cheap way for a model to read a page. |
21
21
  | `search_and_read` | Search Google and read the top results in one call: Google's AI Overview (when there is one), the first 1-5 result pages as Markdown, and the other results as title, URL and snippet. Billed as one search plus one request per page read. |
22
22
  | `list_plugins` | List the ready-made site plugins (100+: Amazon, Walmart, Zillow, Booking.com, Indeed, Google Trends, YouTube, App Store, Ahrefs, ...) with their parameters. Free - it calls nothing. |
package/dist/index.js CHANGED
@@ -8955,7 +8955,7 @@ ${body}`);
8955
8955
  }
8956
8956
 
8957
8957
  // src/index.ts
8958
- var VERSION = "0.12.7";
8958
+ var VERSION = "0.12.9";
8959
8959
  var DEFAULT_BASE_URL = "https://api.scrapeunblocker.com";
8960
8960
  var API_KEY_HEADER = "x-scrapeunblocker-key";
8961
8961
  function resolveApiKey() {
@@ -8968,11 +8968,16 @@ function resolveBaseUrl() {
8968
8968
  ""
8969
8969
  );
8970
8970
  }
8971
+ function userAgent() {
8972
+ const name = server.server.getClientVersion()?.name ?? "";
8973
+ const app = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 32).replace(/^-+|-+$/g, "");
8974
+ return app ? `scrapeunblocker-mcp/${VERSION} mcp-host/${app}` : `scrapeunblocker-mcp/${VERSION}`;
8975
+ }
8971
8976
  function client() {
8972
8977
  const apiKey = resolveApiKey();
8973
8978
  if (!apiKey) throw new Error(MISSING_KEY_MESSAGE);
8974
8979
  const baseUrl = process.env.SCRAPEUNBLOCKER_BASE_URL || void 0;
8975
- return new ScrapeUnblockerClient({ apiKey, baseUrl, userAgent: `scrapeunblocker-mcp/${VERSION}` });
8980
+ return new ScrapeUnblockerClient({ apiKey, baseUrl, userAgent: userAgent() });
8976
8981
  }
8977
8982
  function errorText(err) {
8978
8983
  if (err instanceof Error) return err.message;
@@ -9027,7 +9032,7 @@ function pageSourceUrl(params) {
9027
9032
  function requestHeaders(apiKey) {
9028
9033
  return {
9029
9034
  [API_KEY_HEADER]: apiKey,
9030
- "User-Agent": `scrapeunblocker-mcp/${VERSION}`,
9035
+ "User-Agent": userAgent(),
9031
9036
  Accept: "*/*"
9032
9037
  };
9033
9038
  }
@@ -9346,18 +9351,23 @@ server.registerTool(
9346
9351
  {
9347
9352
  title: "Google search results",
9348
9353
  annotations: { title: "Google search results", readOnlyHint: true, openWorldHint: true, destructiveHint: false },
9349
- description: "Run a Google search through ScrapeUnblocker and return the results page as structured JSON: organic results with their real URLs, favicons, sitelinks and star ratings, ads, the AI Overview, People also ask, related searches with their links, the knowledge panel, top stories, videos, local and shopping results. Use this to discover URLs before fetching them.",
9354
+ description: "Run a Google search through ScrapeUnblocker and return the results page as structured JSON: organic results with their real URLs, favicons, sitelinks and star ratings, ads, the AI Overview, People also ask, related searches with their links, the knowledge panel, top stories, videos, local and shopping results. Use this to discover URLs before fetching them. Set `full_urls` when you need the exact page URL of every result.",
9350
9355
  inputSchema: {
9351
9356
  keyword: z3.string().min(1).describe("The search query."),
9352
9357
  proxy_country: z3.string().length(2).optional().describe("Optional ISO country code to search from, e.g. 'US'."),
9353
- pages_to_check: z3.number().int().positive().max(10).optional().describe("How many result pages to collect (default 1).")
9358
+ pages_to_check: z3.number().int().positive().max(10).optional().describe("How many result pages to collect (default 1)."),
9359
+ full_urls: z3.boolean().optional().describe(
9360
+ "Wait until Google gives out every result's real URL. Set it when you need the exact page URL of all results (e.g. to cite or open them); leave it off for quick answers. Google releases a results page's links a few at a time, the last ones up to about 40 seconds after the search: without it a result whose link has not come yet has the site's home page as its `url` (or a Google redirect link), with it the call takes up to about 40 seconds longer. Billed the same."
9361
+ )
9354
9362
  }
9355
9363
  },
9356
9364
  async (args) => {
9357
9365
  try {
9358
- const results = await client().serp(args.keyword, {
9359
- proxyCountry: args.proxy_country,
9360
- pagesToCheck: args.pages_to_check
9366
+ const results = await client().plugin("/serpApi", {
9367
+ keyword: args.keyword,
9368
+ proxy_country: args.proxy_country,
9369
+ pages_to_check: args.pages_to_check ?? 1,
9370
+ full_urls: args.full_urls ? true : void 0
9361
9371
  });
9362
9372
  return {
9363
9373
  content: [{ type: "text", text: JSON.stringify(results, null, 2) }]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrapeunblocker-mcp",
3
- "version": "0.12.7",
3
+ "version": "0.12.9",
4
4
  "mcpName": "com.scrapeunblocker/scrapeunblocker-mcp",
5
5
  "description": "Model Context Protocol (MCP) server for ScrapeUnblocker - lets Claude fetch any web page's HTML (or AI-parsed JSON) and run 100+ site plugins that return structured JSON, through the ScrapeUnblocker anti-bot API, using your own API key.",
6
6
  "keywords": [