mcp-scraper 0.66.4 → 0.66.6

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/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to MCP Scraper are documented here. The format is based on [
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.66.6] - 2026-08-26
8
+
9
+ ### Fixed
10
+
11
+ - Google Search Console bulk URL Inspection now uses one bounded provider batch request, preserves successful URL results beside localized failures, and no longer inherits the former one-minute connected-tool cutoff.
12
+
13
+ ## [0.66.5] - 2026-08-25
14
+
15
+ ### Fixed
16
+
17
+ - Local Sourcebook submissions now distinguish accepted processing from publication, tell MCP clients to keep checking until the run is terminal, and return a plain-language completion message with the exact live listing URL.
18
+
7
19
  ## [0.66.4] - 2026-08-25
8
20
 
9
21
  ### Added
@@ -1109,7 +1121,9 @@ All notable changes to MCP Scraper are documented here. The format is based on [
1109
1121
  - Write actions remain unavailable until the account owner explicitly enables them.
1110
1122
  - Provider-specific connection data is normalized into one agent-facing contract.
1111
1123
 
1112
- [Unreleased]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.4...HEAD
1124
+ [Unreleased]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.6...HEAD
1125
+ [0.66.6]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.5...v0.66.6
1126
+ [0.66.5]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.4...v0.66.5
1113
1127
  [0.66.4]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.3...v0.66.4
1114
1128
  [0.66.3]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.2...v0.66.3
1115
1129
  [0.66.2]: https://github.com/VilovietaSEO/mcp-scraper/compare/v0.66.1...v0.66.2
package/README.md CHANGED
@@ -159,7 +159,7 @@ Build the branded one-click bundle:
159
159
  npm run build:mcpb
160
160
  ```
161
161
 
162
- 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.66.4`, SHA-256 `53fa34844c0a030c9777cb0e62d547c446ebf6f553f0a850d33bd0aa4185f73c`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, API-key configuration field, and manually curated current-release message from the bundle manifest.
162
+ 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.66.6`, SHA-256 `828f1685c159314275c2ffd1ac437cc466801e1b0d4f43f09a65073581cb7db1`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, API-key configuration field, and manually curated current-release message from the bundle manifest.
163
163
 
164
164
  The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
165
165
 
@@ -33148,12 +33148,39 @@ function localSourcebookPublicUrls(category, state, slug4) {
33148
33148
  };
33149
33149
  }
33150
33150
  function localSourcebookPublicationLinks(submission) {
33151
+ const isLive = submission.publishedRevision !== null && submission.status !== "rejected" && submission.status !== "unpublished";
33151
33152
  return {
33152
33153
  ...localSourcebookPublicUrls(submission.category, submission.state, submission.slug),
33153
33154
  publicationStatus: submission.status,
33154
- isLive: submission.status === "published" && submission.publishedRevision !== null
33155
+ isLive
33155
33156
  };
33156
33157
  }
33158
+ function localSourcebookPublicationMessage(submission) {
33159
+ const { profileUrl } = localSourcebookPublicUrls(submission.category, submission.state, submission.slug);
33160
+ if (submission.status === "published" && submission.publishedRevision !== null) {
33161
+ return `Your Local Sourcebook listing is live: ${profileUrl}`;
33162
+ }
33163
+ if (submission.status === "failed") {
33164
+ if (submission.publishedRevision !== null) {
33165
+ return `We couldn't refresh this Local Sourcebook listing, but the previous version is still live: ${profileUrl}`;
33166
+ }
33167
+ return "We couldn't publish this Local Sourcebook listing because evidence collection failed. Review the reported issue before trying again.";
33168
+ }
33169
+ if (submission.status === "rejected") {
33170
+ return "This Local Sourcebook listing was rejected and is not live.";
33171
+ }
33172
+ if (submission.status === "unpublished") {
33173
+ return "This Local Sourcebook listing has been unpublished and is not live.";
33174
+ }
33175
+ if (submission.publishedRevision !== null) {
33176
+ return `We are collecting and compiling refreshed evidence. The current Local Sourcebook listing remains live: ${profileUrl}`;
33177
+ }
33178
+ return "Submission received. We are collecting and compiling evidence, so this Local Sourcebook listing is not live yet. Check the submission status again in about 10 seconds.";
33179
+ }
33180
+ function localSourcebookStatusCheck(submission) {
33181
+ const required = submission.status === "queued" || submission.status === "enriching" || submission.status === "needs_review";
33182
+ return required ? { required: true, submissionId: submission.id, pollAfterSeconds: 10 } : { required: false, submissionId: submission.id };
33183
+ }
33157
33184
  var DEFAULT_ROOT_DOMAIN, CATEGORY_PUBLIC_SLUGS;
33158
33185
  var init_local_sourcebook_public_urls = __esm({
33159
33186
  "src/api/local-sourcebook-public-urls.ts"() {
@@ -45265,7 +45292,7 @@ var init_local_sourcebook_routes = __esm({
45265
45292
  persisted = true;
45266
45293
  await persistLocalSourcebookTags(submission.id, Number(user.id), validation.normalizedTags, parsed.data.tagDecisions);
45267
45294
  const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
45268
- return c.json({ ok: true, valid: true, submission, publicUrls: localSourcebookPublicationLinks(submission), normalizedTags: validation.normalizedTags, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(identity.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
45295
+ return c.json({ ok: true, valid: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), normalizedTags: validation.normalizedTags, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(identity.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
45269
45296
  } catch (error) {
45270
45297
  if (billing && !persisted) await refundListingWrite(billing, "Local Sourcebook creation failed before persistence.").catch(() => null);
45271
45298
  const message = error instanceof Error ? error.message : String(error);
@@ -45314,7 +45341,7 @@ var init_local_sourcebook_routes = __esm({
45314
45341
  });
45315
45342
  persisted = true;
45316
45343
  const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
45317
- return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(input.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
45344
+ return c.json({ ok: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(input.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
45318
45345
  } catch (error) {
45319
45346
  if (billing && !persisted) await refundListingWrite(billing, "Local Sourcebook creation failed before persistence.").catch(() => null);
45320
45347
  return c.json({ error: "submission_conflict", message: error instanceof Error ? error.message : String(error) }, 409);
@@ -45324,7 +45351,7 @@ var init_local_sourcebook_routes = __esm({
45324
45351
  const userId = Number(c.get("user").id);
45325
45352
  const submission = await getLocalSourcebookSubmission(c.req.param("id"), userId);
45326
45353
  if (!submission) return c.json({ error: "not_found" }, 404);
45327
- return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), draft: await getLocalSourcebookDraft(submission.id, userId) });
45354
+ return c.json({ ok: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), draft: await getLocalSourcebookDraft(submission.id, userId) });
45328
45355
  });
45329
45356
  localSourcebookApp.on(["PATCH", "POST"], "/submissions/:id/draft", createApiKeyAuth(), (c) => c.json({
45330
45357
  error: "evidence_refresh_required",
@@ -45359,7 +45386,7 @@ var init_local_sourcebook_routes = __esm({
45359
45386
  return c.json({ error: "not_found" }, 404);
45360
45387
  }
45361
45388
  const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
45362
- return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(submission.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
45389
+ return c.json({ ok: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(submission.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
45363
45390
  } catch (error) {
45364
45391
  if (billing) await refundListingWrite(billing, "Local Sourcebook refresh failed before persistence.").catch(() => null);
45365
45392
  return c.json({ error: "moderated_listing", message: error instanceof Error ? error.message : String(error) }, 409);
@@ -49679,7 +49706,7 @@ var PACKAGE_VERSION;
49679
49706
  var init_version = __esm({
49680
49707
  "src/version.ts"() {
49681
49708
  "use strict";
49682
- PACKAGE_VERSION = "0.66.4";
49709
+ PACKAGE_VERSION = "0.66.6";
49683
49710
  }
49684
49711
  });
49685
49712
 
@@ -49910,11 +49937,16 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
49910
49937
  - A new capture costs 10 Credits total and includes broad website, exact Maps place, maximum-accessible review,
49911
49938
  service-area, staff, and genuine-media acquisition. When compilation succeeds, that exact system-authored evidence revision
49912
49939
  publishes automatically. Never supply owner-authored services, reviews, images, or other public claims.
49940
+ - An accepted capture is still processing, not complete. While its returned \`statusCheck.required\` is true,
49941
+ wait the suggested interval and call **local_sourcebook_submission_status** again before giving the user a
49942
+ final completion answer. When it publishes, say that the listing is live and include the exact clickable
49943
+ \`publicUrls.profileUrl\`; when it fails, report the returned failure message and cause.
49913
49944
  - Read progress and the compiled record with **local_sourcebook_submission_status**. Use
49914
49945
  **local_sourcebook_refresh** only when the owner intentionally wants to pay 2 Credits for a new acquisition pass.
49915
49946
  Contract, tag, preparation, validation, and status tools are free; idempotent retries are not charged twice.
49916
- - Capture and status responses return \`publicUrls.profileUrl\` and \`publicUrls.reviewsUrl\`. Always give those
49917
- exact links to the user; do not report a listing as live without including its clickable profile URL.
49947
+ - Capture and status responses return a plain-language \`message\`, a \`statusCheck\`, and exact public URLs. Do not
49948
+ describe a queued or enriching listing as complete, and do not report a listing as live without including its
49949
+ clickable \`publicUrls.profileUrl\`.
49918
49950
  - The last published revision remains public during refresh. Administrators can reject or unpublish an
49919
49951
  exceptional record, but routine subscriber publication does not require administrator review.
49920
49952
 
@@ -56210,14 +56242,14 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
56210
56242
  }, async (input) => executor.validateLocalSourcebookWrite(input));
56211
56243
  server.registerTool("local-sourcebook-capture", {
56212
56244
  title: "Capture Governed Local Sourcebook Listing",
56213
- description: "Strict owner-scoped LocalBusiness write path after list, contract, prepare, and validate. Creating a listing costs 10 Credits total, including website, exact-place, review, service-area, staff, genuine-media, and structured-data compilation; preparation and validation are free, and idempotent retries are not charged twice. Capture registers canonical tags and the accepted Schema.org LocalBusiness subtype, returns the exact LocalSourcebook.com profile and reviews URLs, and queues acquisition. MCP Scraper generates the final JSON-LD from source-backed evidence. A successful system-compiled evidence revision publishes automatically; owner-authored public claims and arbitrary JSON-LD are not accepted.",
56245
+ description: "Strict owner-scoped LocalBusiness write path after list, contract, prepare, and validate. Creating a listing costs 10 Credits total, including website, exact-place, review, service-area, staff, genuine-media, and structured-data compilation; preparation and validation are free, and idempotent retries are not charged twice. Capture registers canonical tags and the accepted Schema.org LocalBusiness subtype, then queues acquisition; an accepted capture is not yet live. Poll local_sourcebook_submission_status using statusCheck until it is terminal. When published, tell the user the returned message and exact publicUrls.profileUrl. MCP Scraper generates the final JSON-LD from source-backed evidence and publishes a successful system-compiled revision automatically; owner-authored public claims and arbitrary JSON-LD are not accepted.",
56214
56246
  inputSchema: LocalSourcebookCaptureInputSchema,
56215
56247
  outputSchema: recordOutputSchema("local-sourcebook-capture", LocalSourcebookOutputSchema),
56216
56248
  annotations: liveWebToolAnnotations("Capture Governed Local Sourcebook Listing")
56217
56249
  }, async (input) => executor.localSourcebookCapture(input));
56218
56250
  server.registerTool("local_sourcebook_submission_status", {
56219
56251
  title: "Local Sourcebook Submission Status",
56220
- description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and live LocalSourcebook.com profile and reviews URLs. When status is failed, acquisitionError says why \u2014 read it before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
56252
+ description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and LocalSourcebook.com profile and reviews URLs. While statusCheck.required is true, wait the returned interval and check again before giving the user a final completion answer. When published, present the returned message and exact clickable publicUrls.profileUrl. When failed, present the failure message and read acquisitionError before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
56221
56253
  inputSchema: LocalSourcebookSubmissionStatusInputSchema,
56222
56254
  outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
56223
56255
  annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
@@ -56586,7 +56618,8 @@ function httpErrorPayload(path6, res, data) {
56586
56618
  const safeCode = privateUpstreamState ? "service_unavailable" : recognized ? candidateCode : normalizePublicErrorCode(candidateCode);
56587
56619
  const bodyMessage = objectData ? objectData.message ?? objectData.error ?? rawCode : data;
56588
56620
  return {
56589
- ...recognized && objectData ? objectData : {},
56621
+ ...recognized && objectData && safeCode !== "mcp_request_timeout" ? objectData : {},
56622
+ ...recognized ? { code: safeCode } : {},
56590
56623
  error: safeCode,
56591
56624
  error_code: safeCode,
56592
56625
  error_type: recognized && typeof objectData?.error_type === "string" ? objectData.error_type : "http",
@@ -56594,7 +56627,7 @@ function httpErrorPayload(path6, res, data) {
56594
56627
  status: res.status,
56595
56628
  statusText: res.statusText,
56596
56629
  path: path6,
56597
- message: recognized && typeof bodyMessage === "string" && bodyMessage.trim() ? sanitizeVendorName(bodyMessage) : publicErrorMessage(safeCode)
56630
+ message: safeCode === "mcp_request_timeout" ? "The connected service operation timed out before returning a result. Retry failed items or use a smaller batch." : recognized && typeof bodyMessage === "string" && bodyMessage.trim() ? sanitizeVendorName(bodyMessage) : publicErrorMessage(safeCode)
56598
56631
  };
56599
56632
  }
56600
56633
  function withDefaultHostedProfile(input) {
@@ -84412,6 +84445,15 @@ function retryAfterMsFromText(value) {
84412
84445
  function normalizeNangoClientError(error) {
84413
84446
  if (error instanceof MainNangoTransportError) return error;
84414
84447
  const detail = nangoClientErrorText(error);
84448
+ const structured = error && typeof error === "object" ? error : null;
84449
+ if (structured?.code === -32001 || structured?.name === "RequestTimeout" || /Request timed out|RequestTimeout|Maximum total timeout exceeded/i.test(detail)) {
84450
+ return new MainNangoTransportError(
84451
+ "The connected service operation timed out before returning a result. Retry failed items or use a smaller batch.",
84452
+ 503,
84453
+ "mcp_request_timeout",
84454
+ true
84455
+ );
84456
+ }
84415
84457
  if (/SERVICE_DISABLED|accessNotConfigured/i.test(detail)) {
84416
84458
  return new MainNangoTransportError(
84417
84459
  "The provider API required by this connection is disabled. Enable it in the provider project, wait for propagation, then retry.",
@@ -84442,6 +84484,12 @@ function normalizeNangoClientError(error) {
84442
84484
  }
84443
84485
  return new MainNangoTransportError("The service connection is temporarily unavailable.", 503, "connection_transport_unavailable");
84444
84486
  }
84487
+ async function callNangoToolWithBudget(client2, tool, input) {
84488
+ return client2.callTool(
84489
+ { name: tool, arguments: input },
84490
+ { timeout: NANGO_TOOL_CALL_TIMEOUT_MS }
84491
+ );
84492
+ }
84445
84493
  function asRecord2(value) {
84446
84494
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
84447
84495
  }
@@ -84885,7 +84933,7 @@ async function callNangoToolDirect(args) {
84885
84933
  let result;
84886
84934
  let providerError;
84887
84935
  try {
84888
- result = await withNangoClient(connection, (client2) => client2.callTool({ name: args.tool, arguments: args.input }));
84936
+ result = await withNangoClient(connection, (client2) => callNangoToolWithBudget(client2, args.tool, args.input));
84889
84937
  } catch (error) {
84890
84938
  providerError = error;
84891
84939
  }
@@ -84950,7 +84998,7 @@ async function describeNangoToolDirect(identity, connectionId, toolName) {
84950
84998
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
84951
84999
  };
84952
85000
  }
84953
- var import_node_crypto68, import_client13, DEFAULT_NANGO_MCP_URL, NANGO_TIMEOUT_MS, NANGO_CONNECTION_PAGE_SIZE, NANGO_CONNECTION_MAX_PAGES, PROVIDER_IDENTITY_RETRY_MS, MAIN_INTEGRATION_CONTRACT_VERSION, MAIN_INTEGRATION_CONTRACT_HASH, MainNangoTransportError, IDENTITY_SUPPORTED_PROVIDERS;
85001
+ var import_node_crypto68, import_client13, DEFAULT_NANGO_MCP_URL, NANGO_TIMEOUT_MS, NANGO_TOOL_CALL_TIMEOUT_MS, NANGO_CONNECTION_PAGE_SIZE, NANGO_CONNECTION_MAX_PAGES, PROVIDER_IDENTITY_RETRY_MS, MAIN_INTEGRATION_CONTRACT_VERSION, MAIN_INTEGRATION_CONTRACT_HASH, MainNangoTransportError, IDENTITY_SUPPORTED_PROVIDERS;
84954
85002
  var init_main_nango_transport = __esm({
84955
85003
  "src/api/main-nango-transport.ts"() {
84956
85004
  "use strict";
@@ -84962,6 +85010,7 @@ var init_main_nango_transport = __esm({
84962
85010
  init_connected_tool_policy();
84963
85011
  DEFAULT_NANGO_MCP_URL = "https://api.nango.dev/mcp";
84964
85012
  NANGO_TIMEOUT_MS = 2e4;
85013
+ NANGO_TOOL_CALL_TIMEOUT_MS = 24e4;
84965
85014
  NANGO_CONNECTION_PAGE_SIZE = 100;
84966
85015
  NANGO_CONNECTION_MAX_PAGES = 20;
84967
85016
  PROVIDER_IDENTITY_RETRY_MS = 6 * 60 * 60 * 1e3;
@@ -17,7 +17,7 @@ loadDotEnv();
17
17
  async function main() {
18
18
  const [{ serve }, { app }, { startWorker }, { migrate }] = await Promise.all([
19
19
  import("@hono/node-server"),
20
- import("../server-YATQ3WHT.js"),
20
+ import("../server-5WPS3LZD.js"),
21
21
  import("../worker-UTBUWEXQ.js"),
22
22
  import("../db-4RVZ3NYZ.js")
23
23
  ]);
@@ -30,7 +30,7 @@ var import_promises5 = require("fs/promises");
30
30
  var import_node_path3 = require("path");
31
31
 
32
32
  // src/version.ts
33
- var PACKAGE_VERSION = "0.66.4";
33
+ var PACKAGE_VERSION = "0.66.6";
34
34
 
35
35
  // src/cli/agent-config.ts
36
36
  function apiKeyValue(options) {
@@ -13,7 +13,7 @@ import "../chunk-VXLU74YZ.js";
13
13
  import "../chunk-GGZEC22A.js";
14
14
  import {
15
15
  PACKAGE_VERSION
16
- } from "../chunk-EGNT3AY2.js";
16
+ } from "../chunk-NLEAYKOC.js";
17
17
 
18
18
  // src/cli/human-cli.ts
19
19
  import { Command } from "commander";
@@ -3,7 +3,7 @@
3
3
 
4
4
  // release-message.json
5
5
  var release_message_default = {
6
- message: "Strict MCP clients now discover all 259 tools through a compact runtime catalog, while generated SDKs retain complete output types."
6
+ message: "Search Console bulk URL Inspection now returns one ordered partial-result receipt without the former one-minute cutoff."
7
7
  };
8
8
 
9
9
  // src/install-terminal.ts
@@ -112,7 +112,7 @@ function renderInstallTerminal(options) {
112
112
  }
113
113
 
114
114
  // src/version.ts
115
- var PACKAGE_VERSION = "0.66.4";
115
+ var PACKAGE_VERSION = "0.66.6";
116
116
 
117
117
  // bin/mcp-scraper-install.ts
118
118
  var noColor = process.argv.includes("--no-color") || process.env.NO_COLOR !== void 0 || process.env.FORCE_COLOR === "0" || !process.stdout.isTTY;
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  renderInstallTerminal
4
- } from "../chunk-2XVDLF6H.js";
4
+ } from "../chunk-KPE52NPT.js";
5
5
  import {
6
6
  PACKAGE_VERSION
7
- } from "../chunk-EGNT3AY2.js";
7
+ } from "../chunk-NLEAYKOC.js";
8
8
 
9
9
  // bin/mcp-scraper-install.ts
10
10
  var noColor = process.argv.includes("--no-color") || process.env.NO_COLOR !== void 0 || process.env.FORCE_COLOR === "0" || !process.stdout.isTTY;
@@ -431,7 +431,8 @@ function httpErrorPayload(path, res, data) {
431
431
  const safeCode = privateUpstreamState ? "service_unavailable" : recognized ? candidateCode : normalizePublicErrorCode(candidateCode);
432
432
  const bodyMessage = objectData ? objectData.message ?? objectData.error ?? rawCode : data;
433
433
  return {
434
- ...recognized && objectData ? objectData : {},
434
+ ...recognized && objectData && safeCode !== "mcp_request_timeout" ? objectData : {},
435
+ ...recognized ? { code: safeCode } : {},
435
436
  error: safeCode,
436
437
  error_code: safeCode,
437
438
  error_type: recognized && typeof objectData?.error_type === "string" ? objectData.error_type : "http",
@@ -439,7 +440,7 @@ function httpErrorPayload(path, res, data) {
439
440
  status: res.status,
440
441
  statusText: res.statusText,
441
442
  path,
442
- message: recognized && typeof bodyMessage === "string" && bodyMessage.trim() ? sanitizeVendorName(bodyMessage) : publicErrorMessage(safeCode)
443
+ message: safeCode === "mcp_request_timeout" ? "The connected service operation timed out before returning a result. Retry failed items or use a smaller batch." : recognized && typeof bodyMessage === "string" && bodyMessage.trim() ? sanitizeVendorName(bodyMessage) : publicErrorMessage(safeCode)
443
444
  };
444
445
  }
445
446
  function withDefaultHostedProfile(input) {
@@ -1232,7 +1233,7 @@ render();
1232
1233
  }
1233
1234
 
1234
1235
  // src/version.ts
1235
- var PACKAGE_VERSION = "0.66.4";
1236
+ var PACKAGE_VERSION = "0.66.6";
1236
1237
 
1237
1238
  // src/mcp/input-field-descriptions.ts
1238
1239
  var import_zod = require("zod");
@@ -8378,11 +8379,16 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
8378
8379
  - A new capture costs 10 Credits total and includes broad website, exact Maps place, maximum-accessible review,
8379
8380
  service-area, staff, and genuine-media acquisition. When compilation succeeds, that exact system-authored evidence revision
8380
8381
  publishes automatically. Never supply owner-authored services, reviews, images, or other public claims.
8382
+ - An accepted capture is still processing, not complete. While its returned \`statusCheck.required\` is true,
8383
+ wait the suggested interval and call **local_sourcebook_submission_status** again before giving the user a
8384
+ final completion answer. When it publishes, say that the listing is live and include the exact clickable
8385
+ \`publicUrls.profileUrl\`; when it fails, report the returned failure message and cause.
8381
8386
  - Read progress and the compiled record with **local_sourcebook_submission_status**. Use
8382
8387
  **local_sourcebook_refresh** only when the owner intentionally wants to pay 2 Credits for a new acquisition pass.
8383
8388
  Contract, tag, preparation, validation, and status tools are free; idempotent retries are not charged twice.
8384
- - Capture and status responses return \`publicUrls.profileUrl\` and \`publicUrls.reviewsUrl\`. Always give those
8385
- exact links to the user; do not report a listing as live without including its clickable profile URL.
8389
+ - Capture and status responses return a plain-language \`message\`, a \`statusCheck\`, and exact public URLs. Do not
8390
+ describe a queued or enriching listing as complete, and do not report a listing as live without including its
8391
+ clickable \`publicUrls.profileUrl\`.
8386
8392
  - The last published revision remains public during refresh. Administrators can reject or unpublish an
8387
8393
  exceptional record, but routine subscriber publication does not require administrator review.
8388
8394
 
@@ -14231,14 +14237,14 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
14231
14237
  }, async (input) => executor.validateLocalSourcebookWrite(input));
14232
14238
  server.registerTool("local-sourcebook-capture", {
14233
14239
  title: "Capture Governed Local Sourcebook Listing",
14234
- description: "Strict owner-scoped LocalBusiness write path after list, contract, prepare, and validate. Creating a listing costs 10 Credits total, including website, exact-place, review, service-area, staff, genuine-media, and structured-data compilation; preparation and validation are free, and idempotent retries are not charged twice. Capture registers canonical tags and the accepted Schema.org LocalBusiness subtype, returns the exact LocalSourcebook.com profile and reviews URLs, and queues acquisition. MCP Scraper generates the final JSON-LD from source-backed evidence. A successful system-compiled evidence revision publishes automatically; owner-authored public claims and arbitrary JSON-LD are not accepted.",
14240
+ description: "Strict owner-scoped LocalBusiness write path after list, contract, prepare, and validate. Creating a listing costs 10 Credits total, including website, exact-place, review, service-area, staff, genuine-media, and structured-data compilation; preparation and validation are free, and idempotent retries are not charged twice. Capture registers canonical tags and the accepted Schema.org LocalBusiness subtype, then queues acquisition; an accepted capture is not yet live. Poll local_sourcebook_submission_status using statusCheck until it is terminal. When published, tell the user the returned message and exact publicUrls.profileUrl. MCP Scraper generates the final JSON-LD from source-backed evidence and publishes a successful system-compiled revision automatically; owner-authored public claims and arbitrary JSON-LD are not accepted.",
14235
14241
  inputSchema: LocalSourcebookCaptureInputSchema,
14236
14242
  outputSchema: recordOutputSchema("local-sourcebook-capture", LocalSourcebookOutputSchema),
14237
14243
  annotations: liveWebToolAnnotations("Capture Governed Local Sourcebook Listing")
14238
14244
  }, async (input) => executor.localSourcebookCapture(input));
14239
14245
  server.registerTool("local_sourcebook_submission_status", {
14240
14246
  title: "Local Sourcebook Submission Status",
14241
- description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and live LocalSourcebook.com profile and reviews URLs. When status is failed, acquisitionError says why \u2014 read it before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
14247
+ description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and LocalSourcebook.com profile and reviews URLs. While statusCheck.required is true, wait the returned interval and check again before giving the user a final completion answer. When published, present the returned message and exact clickable publicUrls.profileUrl. When failed, present the failure message and read acquisitionError before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
14242
14248
  inputSchema: LocalSourcebookSubmissionStatusInputSchema,
14243
14249
  outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
14244
14250
  annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
@@ -18660,7 +18666,7 @@ var HostedMemoryMcpToolExecutor = class {
18660
18666
 
18661
18667
  // release-message.json
18662
18668
  var release_message_default = {
18663
- message: "Strict MCP clients now discover all 259 tools through a compact runtime catalog, while generated SDKs retain complete output types."
18669
+ message: "Search Console bulk URL Inspection now returns one ordered partial-result receipt without the former one-minute cutoff."
18664
18670
  };
18665
18671
 
18666
18672
  // src/install-terminal.ts
@@ -13,18 +13,18 @@ import {
13
13
  registerScheduledResultsMcpTools,
14
14
  registerSerpIntelligenceCaptureTools,
15
15
  resolveDeploymentProfile
16
- } from "../chunk-UPN4W4SV.js";
16
+ } from "../chunk-VMWVEKZT.js";
17
17
  import "../chunk-PGJQDMC2.js";
18
18
  import "../chunk-3EYALCYK.js";
19
19
  import "../chunk-3TKKJQB4.js";
20
20
  import {
21
21
  renderInstallTerminal
22
- } from "../chunk-2XVDLF6H.js";
22
+ } from "../chunk-KPE52NPT.js";
23
23
  import "../chunk-VXLU74YZ.js";
24
24
  import "../chunk-GGZEC22A.js";
25
25
  import {
26
26
  PACKAGE_VERSION
27
- } from "../chunk-EGNT3AY2.js";
27
+ } from "../chunk-NLEAYKOC.js";
28
28
  import "../chunk-DNM65UCK.js";
29
29
  import "../chunk-AYJHI2FK.js";
30
30
  import "../chunk-55B3T5L2.js";
@@ -1,6 +1,6 @@
1
1
  // release-message.json
2
2
  var release_message_default = {
3
- message: "Strict MCP clients now discover all 259 tools through a compact runtime catalog, while generated SDKs retain complete output types."
3
+ message: "Search Console bulk URL Inspection now returns one ordered partial-result receipt without the former one-minute cutoff."
4
4
  };
5
5
 
6
6
  // src/install-terminal.ts
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var PACKAGE_VERSION = "0.66.4";
2
+ var PACKAGE_VERSION = "0.66.6";
3
3
 
4
4
  export {
5
5
  PACKAGE_VERSION
@@ -25,7 +25,7 @@ import {
25
25
  } from "./chunk-VXLU74YZ.js";
26
26
  import {
27
27
  PACKAGE_VERSION
28
- } from "./chunk-EGNT3AY2.js";
28
+ } from "./chunk-NLEAYKOC.js";
29
29
  import {
30
30
  createPrivateArtifact,
31
31
  privateArtifactOwnerId,
@@ -550,11 +550,16 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
550
550
  - A new capture costs 10 Credits total and includes broad website, exact Maps place, maximum-accessible review,
551
551
  service-area, staff, and genuine-media acquisition. When compilation succeeds, that exact system-authored evidence revision
552
552
  publishes automatically. Never supply owner-authored services, reviews, images, or other public claims.
553
+ - An accepted capture is still processing, not complete. While its returned \`statusCheck.required\` is true,
554
+ wait the suggested interval and call **local_sourcebook_submission_status** again before giving the user a
555
+ final completion answer. When it publishes, say that the listing is live and include the exact clickable
556
+ \`publicUrls.profileUrl\`; when it fails, report the returned failure message and cause.
553
557
  - Read progress and the compiled record with **local_sourcebook_submission_status**. Use
554
558
  **local_sourcebook_refresh** only when the owner intentionally wants to pay 2 Credits for a new acquisition pass.
555
559
  Contract, tag, preparation, validation, and status tools are free; idempotent retries are not charged twice.
556
- - Capture and status responses return \`publicUrls.profileUrl\` and \`publicUrls.reviewsUrl\`. Always give those
557
- exact links to the user; do not report a listing as live without including its clickable profile URL.
560
+ - Capture and status responses return a plain-language \`message\`, a \`statusCheck\`, and exact public URLs. Do not
561
+ describe a queued or enriching listing as complete, and do not report a listing as live without including its
562
+ clickable \`publicUrls.profileUrl\`.
558
563
  - The last published revision remains public during refresh. Administrators can reject or unpublish an
559
564
  exceptional record, but routine subscriber publication does not require administrator review.
560
565
 
@@ -11740,14 +11745,14 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
11740
11745
  }, async (input) => executor.validateLocalSourcebookWrite(input));
11741
11746
  server.registerTool("local-sourcebook-capture", {
11742
11747
  title: "Capture Governed Local Sourcebook Listing",
11743
- description: "Strict owner-scoped LocalBusiness write path after list, contract, prepare, and validate. Creating a listing costs 10 Credits total, including website, exact-place, review, service-area, staff, genuine-media, and structured-data compilation; preparation and validation are free, and idempotent retries are not charged twice. Capture registers canonical tags and the accepted Schema.org LocalBusiness subtype, returns the exact LocalSourcebook.com profile and reviews URLs, and queues acquisition. MCP Scraper generates the final JSON-LD from source-backed evidence. A successful system-compiled evidence revision publishes automatically; owner-authored public claims and arbitrary JSON-LD are not accepted.",
11748
+ description: "Strict owner-scoped LocalBusiness write path after list, contract, prepare, and validate. Creating a listing costs 10 Credits total, including website, exact-place, review, service-area, staff, genuine-media, and structured-data compilation; preparation and validation are free, and idempotent retries are not charged twice. Capture registers canonical tags and the accepted Schema.org LocalBusiness subtype, then queues acquisition; an accepted capture is not yet live. Poll local_sourcebook_submission_status using statusCheck until it is terminal. When published, tell the user the returned message and exact publicUrls.profileUrl. MCP Scraper generates the final JSON-LD from source-backed evidence and publishes a successful system-compiled revision automatically; owner-authored public claims and arbitrary JSON-LD are not accepted.",
11744
11749
  inputSchema: LocalSourcebookCaptureInputSchema,
11745
11750
  outputSchema: recordOutputSchema("local-sourcebook-capture", LocalSourcebookOutputSchema),
11746
11751
  annotations: liveWebToolAnnotations("Capture Governed Local Sourcebook Listing")
11747
11752
  }, async (input) => executor.localSourcebookCapture(input));
11748
11753
  server.registerTool("local_sourcebook_submission_status", {
11749
11754
  title: "Local Sourcebook Submission Status",
11750
- description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and live LocalSourcebook.com profile and reviews URLs. When status is failed, acquisitionError says why \u2014 read it before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
11755
+ description: "Read the caller\u2019s listing draft, enrichment coverage, revision number, publication state, and LocalSourcebook.com profile and reviews URLs. While statusCheck.required is true, wait the returned interval and check again before giving the user a final completion answer. When published, present the returned message and exact clickable publicUrls.profileUrl. When failed, present the failure message and read acquisitionError before retrying, since a refresh repeats the same acquisition. Coverage counters are written only on success, so zeroed counters on a failed listing do not mean the crawl never ran.",
11751
11756
  inputSchema: LocalSourcebookSubmissionStatusInputSchema,
11752
11757
  outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
11753
11758
  annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
@@ -12089,7 +12094,8 @@ function httpErrorPayload(path, res, data) {
12089
12094
  const safeCode = privateUpstreamState ? "service_unavailable" : recognized ? candidateCode : normalizePublicErrorCode(candidateCode);
12090
12095
  const bodyMessage = objectData ? objectData.message ?? objectData.error ?? rawCode : data;
12091
12096
  return {
12092
- ...recognized && objectData ? objectData : {},
12097
+ ...recognized && objectData && safeCode !== "mcp_request_timeout" ? objectData : {},
12098
+ ...recognized ? { code: safeCode } : {},
12093
12099
  error: safeCode,
12094
12100
  error_code: safeCode,
12095
12101
  error_type: recognized && typeof objectData?.error_type === "string" ? objectData.error_type : "http",
@@ -12097,7 +12103,7 @@ function httpErrorPayload(path, res, data) {
12097
12103
  status: res.status,
12098
12104
  statusText: res.statusText,
12099
12105
  path,
12100
- message: recognized && typeof bodyMessage === "string" && bodyMessage.trim() ? sanitizeVendorName(bodyMessage) : publicErrorMessage(safeCode)
12106
+ message: safeCode === "mcp_request_timeout" ? "The connected service operation timed out before returning a result. Retry failed items or use a smaller batch." : recognized && typeof bodyMessage === "string" && bodyMessage.trim() ? sanitizeVendorName(bodyMessage) : publicErrorMessage(safeCode)
12101
12107
  };
12102
12108
  }
12103
12109
  function withDefaultHostedProfile(input) {
@@ -199,7 +199,7 @@ import {
199
199
  resolveDeploymentProfile,
200
200
  resolveLocalSourcebookSchemaType,
201
201
  transcribeMediaUrl
202
- } from "./chunk-UPN4W4SV.js";
202
+ } from "./chunk-VMWVEKZT.js";
203
203
  import {
204
204
  auditImageUrls,
205
205
  auditImages,
@@ -256,7 +256,7 @@ import {
256
256
  } from "./chunk-GGZEC22A.js";
257
257
  import {
258
258
  PACKAGE_VERSION
259
- } from "./chunk-EGNT3AY2.js";
259
+ } from "./chunk-NLEAYKOC.js";
260
260
  import {
261
261
  SITE_EXTRACT_ARTIFACT_PREFIX,
262
262
  abandonExtractSettlement,
@@ -13665,12 +13665,39 @@ function localSourcebookPublicUrls(category, state, slug4) {
13665
13665
  };
13666
13666
  }
13667
13667
  function localSourcebookPublicationLinks(submission) {
13668
+ const isLive = submission.publishedRevision !== null && submission.status !== "rejected" && submission.status !== "unpublished";
13668
13669
  return {
13669
13670
  ...localSourcebookPublicUrls(submission.category, submission.state, submission.slug),
13670
13671
  publicationStatus: submission.status,
13671
- isLive: submission.status === "published" && submission.publishedRevision !== null
13672
+ isLive
13672
13673
  };
13673
13674
  }
13675
+ function localSourcebookPublicationMessage(submission) {
13676
+ const { profileUrl } = localSourcebookPublicUrls(submission.category, submission.state, submission.slug);
13677
+ if (submission.status === "published" && submission.publishedRevision !== null) {
13678
+ return `Your Local Sourcebook listing is live: ${profileUrl}`;
13679
+ }
13680
+ if (submission.status === "failed") {
13681
+ if (submission.publishedRevision !== null) {
13682
+ return `We couldn't refresh this Local Sourcebook listing, but the previous version is still live: ${profileUrl}`;
13683
+ }
13684
+ return "We couldn't publish this Local Sourcebook listing because evidence collection failed. Review the reported issue before trying again.";
13685
+ }
13686
+ if (submission.status === "rejected") {
13687
+ return "This Local Sourcebook listing was rejected and is not live.";
13688
+ }
13689
+ if (submission.status === "unpublished") {
13690
+ return "This Local Sourcebook listing has been unpublished and is not live.";
13691
+ }
13692
+ if (submission.publishedRevision !== null) {
13693
+ return `We are collecting and compiling refreshed evidence. The current Local Sourcebook listing remains live: ${profileUrl}`;
13694
+ }
13695
+ return "Submission received. We are collecting and compiling evidence, so this Local Sourcebook listing is not live yet. Check the submission status again in about 10 seconds.";
13696
+ }
13697
+ function localSourcebookStatusCheck(submission) {
13698
+ const required = submission.status === "queued" || submission.status === "enriching" || submission.status === "needs_review";
13699
+ return required ? { required: true, submissionId: submission.id, pollAfterSeconds: 10 } : { required: false, submissionId: submission.id };
13700
+ }
13674
13701
 
13675
13702
  // src/api/local-sourcebook-compiler.ts
13676
13703
  var CATEGORY_LABELS = {
@@ -24864,7 +24891,7 @@ localSourcebookApp.post("/capture", createApiKeyAuth(), async (c) => {
24864
24891
  persisted = true;
24865
24892
  await persistLocalSourcebookTags(submission.id, Number(user.id), validation.normalizedTags, parsed.data.tagDecisions);
24866
24893
  const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
24867
- return c.json({ ok: true, valid: true, submission, publicUrls: localSourcebookPublicationLinks(submission), normalizedTags: validation.normalizedTags, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(identity.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
24894
+ return c.json({ ok: true, valid: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), normalizedTags: validation.normalizedTags, acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(identity.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
24868
24895
  } catch (error) {
24869
24896
  if (billing && !persisted) await refundListingWrite(billing, "Local Sourcebook creation failed before persistence.").catch(() => null);
24870
24897
  const message = error instanceof Error ? error.message : String(error);
@@ -24913,7 +24940,7 @@ localSourcebookApp.post("/submissions", createApiKeyAuth(), async (c) => {
24913
24940
  });
24914
24941
  persisted = true;
24915
24942
  const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
24916
- return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(input.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
24943
+ return c.json({ ok: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(input.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
24917
24944
  } catch (error) {
24918
24945
  if (billing && !persisted) await refundListingWrite(billing, "Local Sourcebook creation failed before persistence.").catch(() => null);
24919
24946
  return c.json({ error: "submission_conflict", message: error instanceof Error ? error.message : String(error) }, 409);
@@ -24923,7 +24950,7 @@ localSourcebookApp.get("/submissions/:id", createApiKeyAuth(), async (c) => {
24923
24950
  const userId = Number(c.get("user").id);
24924
24951
  const submission = await getLocalSourcebookSubmission(c.req.param("id"), userId);
24925
24952
  if (!submission) return c.json({ error: "not_found" }, 404);
24926
- return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), draft: await getLocalSourcebookDraft(submission.id, userId) });
24953
+ return c.json({ ok: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), draft: await getLocalSourcebookDraft(submission.id, userId) });
24927
24954
  });
24928
24955
  localSourcebookApp.on(["PATCH", "POST"], "/submissions/:id/draft", createApiKeyAuth(), (c) => c.json({
24929
24956
  error: "evidence_refresh_required",
@@ -24958,7 +24985,7 @@ localSourcebookApp.post("/submissions/:id/refresh", createApiKeyAuth(), async (c
24958
24985
  return c.json({ error: "not_found" }, 404);
24959
24986
  }
24960
24987
  const dispatched = await dispatchLocalSourcebookAcquisition(submission.id).catch(() => false);
24961
- return c.json({ ok: true, submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(submission.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
24988
+ return c.json({ ok: true, message: localSourcebookPublicationMessage(submission), statusCheck: localSourcebookStatusCheck(submission), submission, publicUrls: localSourcebookPublicationLinks(submission), acquisition: { queued: true, dispatched }, acquisitionPlan: acquisitionPlan(submission.websiteUrl), billing: publicListingWriteBilling(billing) }, 202);
24962
24989
  } catch (error) {
24963
24990
  if (billing) await refundListingWrite(billing, "Local Sourcebook refresh failed before persistence.").catch(() => null);
24964
24991
  return c.json({ error: "moderated_listing", message: error instanceof Error ? error.message : String(error) }, 409);
@@ -44176,6 +44203,7 @@ function connectedToolPolicyOrThrow(registry, toolName) {
44176
44203
  // src/api/main-nango-transport.ts
44177
44204
  var DEFAULT_NANGO_MCP_URL = "https://api.nango.dev/mcp";
44178
44205
  var NANGO_TIMEOUT_MS = 2e4;
44206
+ var NANGO_TOOL_CALL_TIMEOUT_MS = 24e4;
44179
44207
  var NANGO_CONNECTION_PAGE_SIZE = 100;
44180
44208
  var NANGO_CONNECTION_MAX_PAGES = 20;
44181
44209
  var PROVIDER_IDENTITY_RETRY_MS = 6 * 60 * 60 * 1e3;
@@ -44214,6 +44242,15 @@ function retryAfterMsFromText(value) {
44214
44242
  function normalizeNangoClientError(error) {
44215
44243
  if (error instanceof MainNangoTransportError) return error;
44216
44244
  const detail = nangoClientErrorText(error);
44245
+ const structured = error && typeof error === "object" ? error : null;
44246
+ if (structured?.code === -32001 || structured?.name === "RequestTimeout" || /Request timed out|RequestTimeout|Maximum total timeout exceeded/i.test(detail)) {
44247
+ return new MainNangoTransportError(
44248
+ "The connected service operation timed out before returning a result. Retry failed items or use a smaller batch.",
44249
+ 503,
44250
+ "mcp_request_timeout",
44251
+ true
44252
+ );
44253
+ }
44217
44254
  if (/SERVICE_DISABLED|accessNotConfigured/i.test(detail)) {
44218
44255
  return new MainNangoTransportError(
44219
44256
  "The provider API required by this connection is disabled. Enable it in the provider project, wait for propagation, then retry.",
@@ -44244,6 +44281,12 @@ function normalizeNangoClientError(error) {
44244
44281
  }
44245
44282
  return new MainNangoTransportError("The service connection is temporarily unavailable.", 503, "connection_transport_unavailable");
44246
44283
  }
44284
+ async function callNangoToolWithBudget(client2, tool, input) {
44285
+ return client2.callTool(
44286
+ { name: tool, arguments: input },
44287
+ { timeout: NANGO_TOOL_CALL_TIMEOUT_MS }
44288
+ );
44289
+ }
44247
44290
  function asRecord(value) {
44248
44291
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
44249
44292
  }
@@ -44703,7 +44746,7 @@ async function callNangoToolDirect(args) {
44703
44746
  let result;
44704
44747
  let providerError;
44705
44748
  try {
44706
- result = await withNangoClient(connection, (client2) => client2.callTool({ name: args.tool, arguments: args.input }));
44749
+ result = await withNangoClient(connection, (client2) => callNangoToolWithBudget(client2, args.tool, args.input));
44707
44750
  } catch (error) {
44708
44751
  providerError = error;
44709
44752
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-scraper",
3
- "version": "0.66.4",
3
+ "version": "0.66.6",
4
4
  "description": "MCP server for MCP Scraper web intelligence tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",