scrapeunblocker-mcp 0.2.1 → 0.2.3

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 (2) hide show
  1. package/dist/index.js +23 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
  import { z } from "zod";
7
7
  import { APIError, ScrapeUnblockerClient } from "scrapeunblocker";
8
- var VERSION = "0.2.1";
8
+ var VERSION = "0.2.3";
9
9
  var DEFAULT_BASE_URL = "https://api.scrapeunblocker.com";
10
10
  var API_KEY_HEADER = "x-scrapeunblocker-key";
11
11
  function resolveApiKey() {
@@ -45,11 +45,24 @@ ${page}` : `${head}
45
45
 
46
46
  The target sent no page body.`;
47
47
  }
48
+ function noDataExtractedHtml(raw) {
49
+ if (!raw || raw.data_extracted !== false) return null;
50
+ return typeof raw.html === "string" ? raw.html : "";
51
+ }
52
+ function noDataExtractedText(url, html) {
53
+ const head = `No structured data could be extracted from ${url}: the page loaded, but nothing on it matched a structured shape. The call was billed like fetch_html, so the rendered page is returned instead.`;
54
+ return html.trim() ? `${head}
55
+
56
+ The rendered HTML follows:
57
+
58
+ ${html}` : head;
59
+ }
48
60
  function errorResult(url, err) {
49
- const gone = err instanceof APIError ? targetGoneStatus(err.statusCode) : null;
50
- if (gone !== null) {
51
- const body = err instanceof APIError ? err.body ?? "" : "";
52
- return { content: [{ type: "text", text: targetGoneText(url, gone, body) }] };
61
+ if (err instanceof APIError) {
62
+ const gone = targetGoneStatus(err.statusCode);
63
+ if (gone !== null) {
64
+ return { content: [{ type: "text", text: targetGoneText(url, gone, err.body ?? "") }] };
65
+ }
53
66
  }
54
67
  return { content: [{ type: "text", text: errorText(err) }], isError: true };
55
68
  }
@@ -277,7 +290,7 @@ server.registerTool(
277
290
  "fetch_parsed",
278
291
  {
279
292
  title: "Fetch AI-parsed page data",
280
- description: "Fetch a web page through ScrapeUnblocker and return AI-parsed structured JSON instead of raw HTML (e.g. product details, article content). Best for extracting fields from product, listing or article pages without writing your own HTML parsing.",
293
+ description: "Fetch a web page through ScrapeUnblocker and return AI-parsed structured JSON instead of raw HTML (e.g. product details, article content). Best for extracting fields from product, listing or article pages without writing your own HTML parsing. If the page holds no structured data, the result says so and returns the rendered HTML instead (billed like fetch_html).",
281
294
  inputSchema: {
282
295
  url: z.string().url().describe("The absolute URL to fetch and parse."),
283
296
  proxy_country: z.string().length(2).optional().describe("Optional ISO country code to route through, e.g. 'US'."),
@@ -292,6 +305,10 @@ server.registerTool(
292
305
  proxyCountry: args.proxy_country,
293
306
  rulesHint: args.rules_hint
294
307
  });
308
+ const noDataHtml = noDataExtractedHtml(parsed.raw);
309
+ if (noDataHtml !== null) {
310
+ return { content: [{ type: "text", text: noDataExtractedText(args.url, noDataHtml) }] };
311
+ }
295
312
  return {
296
313
  content: [{ type: "text", text: JSON.stringify(parsed, null, 2) }]
297
314
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrapeunblocker-mcp",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
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) through the ScrapeUnblocker anti-bot API, using your own API key.",
6
6
  "keywords": [