mcp-scraper 0.26.1 → 0.26.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.
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.26.1`, SHA-256 `905485382791a260e76c51753f927e2c3505784d693292a79748e9e0faaf5ee3`). 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.26.3`, SHA-256 `3d2725b44772eb50c0514f9b89a00fa69d3bbcd57644d29cefc355feeefbd595`). 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
 
@@ -229,6 +229,8 @@ All MCP tools expose output schemas and return `structuredContent` with the IDs,
229
229
 
230
230
  The canonical tool inventory is generated at `docs/mcp-tool-manifest.generated.json`. Both the `mcp-scraper` stdio server and the hosted endpoint at `https://mcpscraper.dev/mcp` expose the same 163 tools: 76 scraper, browser, workflow, billing, and connected-service tools plus 87 durable-memory tools. Release verification compares the exact local and remote tool-name sets, not only the count.
231
231
 
232
+ For contract parity, stdio and MCPB memory calls invoke the matching public tool on the hosted MCP Scraper `/mcp` endpoint. The hosted aggregate runtime owns MCP Scraper-specific billing, scheduling, credential, and in-process cutover policy; its internal `/memory/mcp-call` bridge is a fallback to the standalone memory service, not the public stdio execution path. Direct `mcp-memory` OAuth and stdio clients continue to use `memory.mcpscraper.dev` and must be verified as a separate dependent release surface.
233
+
232
234
  ## Resources
233
235
 
234
236
  The `mcp-scraper` NPX stdio server also exposes saved reports as MCP resources: `resources/list` returns the most recent Markdown reports from your output directory as `report://` URIs, and `resources/read` returns their content — so an MCP client can pull prior research into context without re-scraping or spending credits. The hosted endpoint does not expose resources (it saves no files).
@@ -29688,7 +29688,7 @@ var PACKAGE_VERSION;
29688
29688
  var init_version = __esm({
29689
29689
  "src/version.ts"() {
29690
29690
  "use strict";
29691
- PACKAGE_VERSION = "0.26.1";
29691
+ PACKAGE_VERSION = "0.26.3";
29692
29692
  }
29693
29693
  });
29694
29694
 
@@ -43055,6 +43055,42 @@ var init_service_connections = __esm({
43055
43055
  });
43056
43056
 
43057
43057
  // src/api/main-nango-transport.ts
43058
+ function nangoClientErrorText(error) {
43059
+ if (error instanceof Error) return error.message;
43060
+ if (typeof error === "string") return error;
43061
+ try {
43062
+ return JSON.stringify(error);
43063
+ } catch {
43064
+ return "";
43065
+ }
43066
+ }
43067
+ function normalizeNangoClientError(error) {
43068
+ if (error instanceof MainNangoTransportError) return error;
43069
+ const detail = nangoClientErrorText(error);
43070
+ if (/SERVICE_DISABLED|accessNotConfigured/i.test(detail)) {
43071
+ return new MainNangoTransportError(
43072
+ "The provider API required by this connection is disabled. Enable it in the provider project, wait for propagation, then retry.",
43073
+ 409,
43074
+ "provider_api_disabled",
43075
+ false
43076
+ );
43077
+ }
43078
+ if (/PERMISSION_DENIED|insufficientPermissions|insufficient permission/i.test(detail)) {
43079
+ return new MainNangoTransportError(
43080
+ "The connected account does not have permission to run this provider operation.",
43081
+ 403,
43082
+ "missing_provider_permission",
43083
+ false
43084
+ );
43085
+ }
43086
+ if (/RESOURCE_EXHAUSTED|rate.?limit|status["']?\s*:\s*429/i.test(detail)) {
43087
+ return new MainNangoTransportError("The connected provider is temporarily rate limited.", 429, "upstream_rate_limited", true);
43088
+ }
43089
+ if (/UNAUTHENTICATED|invalid_grant|status["']?\s*:\s*401/i.test(detail)) {
43090
+ return new MainNangoTransportError("The service connection requires reconnection.", 409, "connection_inactive", false);
43091
+ }
43092
+ return new MainNangoTransportError("The service connection is temporarily unavailable.", 503, "connection_transport_unavailable");
43093
+ }
43058
43094
  function asRecord2(value) {
43059
43095
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
43060
43096
  }
@@ -43286,19 +43322,31 @@ async function withNangoClient(connection, run) {
43286
43322
  });
43287
43323
  return value;
43288
43324
  } catch (error) {
43325
+ const normalized = normalizeNangoClientError(error);
43289
43326
  await recordServiceConnectionHealth({
43290
43327
  connectionId: connection.id,
43291
- operationalStatus: "unavailable",
43292
- failureCode: "connection_transport_unavailable",
43293
- retryable: true,
43328
+ operationalStatus: normalized.code === "connection_transport_unavailable" ? "unavailable" : "degraded",
43329
+ failureCode: normalized.code,
43330
+ retryable: normalized.retryable,
43294
43331
  evidenceSource: "nango_mcp"
43295
43332
  }).catch(() => void 0);
43296
- if (error instanceof MainNangoTransportError) throw error;
43297
- throw new MainNangoTransportError("The service connection is temporarily unavailable.", 503, "connection_transport_unavailable");
43333
+ throw normalized;
43298
43334
  } finally {
43299
43335
  await client2.close().catch(() => void 0);
43300
43336
  }
43301
43337
  }
43338
+ async function probeNangoConnectionDirect(identity, connectionId) {
43339
+ const connection = await requireOwnedActiveConnection(identity, connectionId);
43340
+ const providerKey = connection.provider ?? connection.providerConfigKey;
43341
+ if (providerKey !== "google-search-console") return;
43342
+ await withNangoClient(connection, async (client2) => {
43343
+ const listed = await client2.listTools();
43344
+ if (!listed.tools.some((tool) => tool.name === "list-sites")) {
43345
+ throw new MainNangoTransportError("The Search Console health-check tool is unavailable.", 404, "live_tool_missing", false);
43346
+ }
43347
+ await client2.callTool({ name: "list-sites", arguments: {} });
43348
+ });
43349
+ }
43302
43350
  async function listNangoToolsDirect(identity, connectionId) {
43303
43351
  const connection = await requireOwnedActiveConnection(identity, connectionId);
43304
43352
  const listed = await withNangoClient(connection, (client2) => client2.listTools());
@@ -44111,6 +44159,7 @@ async function testNangoConnection(identity, connectionId) {
44111
44159
  }
44112
44160
  try {
44113
44161
  const { tools } = await listNangoToolsDirect(identity, connectionId);
44162
+ await probeNangoConnectionDirect(identity, connectionId);
44114
44163
  return { operationalStatus: "available", checkedAt: (/* @__PURE__ */ new Date()).toISOString(), toolCount: tools.length };
44115
44164
  } catch (error) {
44116
44165
  throw asNangoControlError(error);
@@ -44532,6 +44581,7 @@ var init_nango_control = __esm({
44532
44581
  "connection_transport_unavailable",
44533
44582
  "connection_control_failed",
44534
44583
  "missing_provider_permission",
44584
+ "provider_api_disabled",
44535
44585
  "permission_verification_unavailable",
44536
44586
  "meta_app_feature_not_enabled",
44537
44587
  "insufficient_credits",