mcp-scraper 0.57.1 → 0.57.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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/dist/bin/api-server.cjs +36 -10
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +3 -3
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/chunk-LHH3GX3W.js +7 -0
- package/dist/chunk-LHH3GX3W.js.map +1 -0
- package/dist/{chunk-2KL4MSZP.js → chunk-QSUSTYB3.js} +4 -4
- package/dist/chunk-QSUSTYB3.js.map +1 -0
- package/dist/{server-DSCKFM7K.js → server-EP2SK2ID.js} +35 -9
- package/dist/server-EP2SK2ID.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2KL4MSZP.js.map +0 -1
- package/dist/chunk-VTBJVKBE.js +0 -7
- package/dist/chunk-VTBJVKBE.js.map +0 -1
- package/dist/server-DSCKFM7K.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to MCP Scraper are documented here. The format is based on [
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.57.3] - 2026-08-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Local Sourcebook exact-place matching no longer rejects a Google listing that appends a service tagline to the business name. `nameOverlap` divided the intersection by the larger token set, so "Meljestic Spa" against "Meljestic Spa: Laser hair removal and Skincare" scored 0.33 against a 0.6 threshold and could never publish — even though the submitted name is fully contained in the Google name and Maps linked the same domain. Identity now also accepts containment of the smaller token set (which must carry two distinctive tokens) or a Maps listing that links the submitted domain. Wrong domain, wrong state, missing address, and single-generic-token still reject.
|
|
12
|
+
- `acquisition_error` is now returned as `acquisitionError` on the submission. It was written on every failure and never selected back, so no response explained why a listing failed.
|
|
13
|
+
- `local_sourcebook_submission_status` and `local_sourcebook_refresh` now state what a failed status means, that coverage counters are only written on success (so zeroed counters do not mean the crawl never ran), and that a replayed refresh still re-runs acquisition.
|
|
14
|
+
|
|
15
|
+
## [0.57.2] - 2026-08-16
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Blob storage no longer falls back to the local filesystem on a serverless deployment. `BLOB_READ_WRITE_TOKEN` was empty in production, so `getBlobStore()` returned a local store and every write through it — the scrape-vault fallback document and Instagram media downloads — was saved to an ephemeral path inside the function and handed back as a `file://` URL no request could read. Without a token a serverless deployment now returns a store that refuses to write and says why.
|
|
20
|
+
|
|
7
21
|
## [0.57.1] - 2026-08-16
|
|
8
22
|
|
|
9
23
|
### Fixed
|
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ Build the branded one-click bundle:
|
|
|
90
90
|
npm run build:mcpb
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
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.57.
|
|
93
|
+
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.57.3`, SHA-256 `b1edddd21790e7e5f24bacad85d992d8e995199c5d7e1d314500ba0abaab117c`). 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.
|
|
94
94
|
|
|
95
95
|
The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
|
|
96
96
|
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -29050,6 +29050,7 @@ function mapSubmission(row) {
|
|
|
29050
29050
|
businessName: String(rowValue(row, "business_name")),
|
|
29051
29051
|
websiteUrl: String(rowValue(row, "website_url")),
|
|
29052
29052
|
status: String(rowValue(row, "status")),
|
|
29053
|
+
acquisitionError: rowValue(row, "acquisition_error") == null ? null : String(rowValue(row, "acquisition_error")),
|
|
29053
29054
|
draftRevision: Number(rowValue(row, "draft_revision")),
|
|
29054
29055
|
publishedRevision: rowValue(row, "published_revision") == null ? null : Number(rowValue(row, "published_revision")),
|
|
29055
29056
|
coverage: parseJson2(rowValue(row, "coverage_json")),
|
|
@@ -30915,6 +30916,15 @@ function nameOverlap(left, right) {
|
|
|
30915
30916
|
const intersection = [...a].filter((token6) => b.has(token6)).length;
|
|
30916
30917
|
return intersection / Math.max(a.size, b.size);
|
|
30917
30918
|
}
|
|
30919
|
+
function nameContainment(left, right) {
|
|
30920
|
+
const a = tokens(left);
|
|
30921
|
+
const b = tokens(right);
|
|
30922
|
+
if (!a.size || !b.size) return 0;
|
|
30923
|
+
const smaller = a.size <= b.size ? a : b;
|
|
30924
|
+
if (smaller.size < 2) return 0;
|
|
30925
|
+
const intersection = [...a].filter((token6) => b.has(token6)).length;
|
|
30926
|
+
return intersection / smaller.size;
|
|
30927
|
+
}
|
|
30918
30928
|
function validateLocalSourcebookMapsIdentity(submission, maps) {
|
|
30919
30929
|
const expectedHost = host(submission.websiteUrl);
|
|
30920
30930
|
const mapsHost = host(maps.website);
|
|
@@ -30924,7 +30934,9 @@ function validateLocalSourcebookMapsIdentity(submission, maps) {
|
|
|
30924
30934
|
if (mapsHost && expectedHost && mapsHost !== expectedHost && !mapsHost.endsWith(`.${expectedHost}`) && !expectedHost.endsWith(`.${mapsHost}`)) {
|
|
30925
30935
|
throw new Error(`Exact-place match rejected: Google Maps linked ${mapsHost}, not the submitted domain ${expectedHost}.`);
|
|
30926
30936
|
}
|
|
30927
|
-
|
|
30937
|
+
const containment = nameContainment(submission.businessName, actualName);
|
|
30938
|
+
const domainConfirmsIdentity = Boolean(mapsHost && expectedHost);
|
|
30939
|
+
if (overlap < 0.6 && containment < 0.9 && !domainConfirmsIdentity) {
|
|
30928
30940
|
throw new Error(`Exact-place match rejected: Google Maps returned \u201C${actualName},\u201D which does not sufficiently match \u201C${submission.businessName}.\u201D`);
|
|
30929
30941
|
}
|
|
30930
30942
|
if (addressState && addressState !== submission.state.toLowerCase()) {
|
|
@@ -37303,16 +37315,21 @@ function byteLength(data) {
|
|
|
37303
37315
|
function localBaseDir2() {
|
|
37304
37316
|
return process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || (0, import_node_path11.join)((0, import_node_os7.homedir)(), "Downloads", "mcp-scraper");
|
|
37305
37317
|
}
|
|
37318
|
+
function runsWithoutLocalDisk(env = process.env) {
|
|
37319
|
+
return Boolean(env.VERCEL || env.AWS_LAMBDA_FUNCTION_NAME);
|
|
37320
|
+
}
|
|
37321
|
+
function resolveBlobStore(env = process.env) {
|
|
37322
|
+
const token6 = env.BLOB_READ_WRITE_TOKEN?.trim();
|
|
37323
|
+
if (token6) return new VercelBlobStore(token6);
|
|
37324
|
+
if (runsWithoutLocalDisk(env)) return new UnconfiguredBlobStore();
|
|
37325
|
+
return new LocalBlobStore(localBaseDir2());
|
|
37326
|
+
}
|
|
37306
37327
|
function getBlobStore() {
|
|
37307
37328
|
if (cached) return cached;
|
|
37308
|
-
|
|
37309
|
-
cached = new VercelBlobStore(process.env.BLOB_READ_WRITE_TOKEN);
|
|
37310
|
-
} else {
|
|
37311
|
-
cached = new LocalBlobStore(localBaseDir2());
|
|
37312
|
-
}
|
|
37329
|
+
cached = resolveBlobStore();
|
|
37313
37330
|
return cached;
|
|
37314
37331
|
}
|
|
37315
|
-
var import_node_fs7, import_node_os7, import_node_path11, LocalBlobStore, cached, VercelBlobStore;
|
|
37332
|
+
var import_node_fs7, import_node_os7, import_node_path11, LocalBlobStore, cached, UnconfiguredBlobStore, VercelBlobStore;
|
|
37316
37333
|
var init_blob_store = __esm({
|
|
37317
37334
|
"src/api/blob-store.ts"() {
|
|
37318
37335
|
"use strict";
|
|
@@ -37342,6 +37359,15 @@ var init_blob_store = __esm({
|
|
|
37342
37359
|
}
|
|
37343
37360
|
};
|
|
37344
37361
|
cached = null;
|
|
37362
|
+
UnconfiguredBlobStore = class {
|
|
37363
|
+
kind = "unconfigured";
|
|
37364
|
+
async put() {
|
|
37365
|
+
throw new Error("Blob storage is not configured on this deployment: set BLOB_READ_WRITE_TOKEN. Refusing to write to a local path that no request can read back.");
|
|
37366
|
+
}
|
|
37367
|
+
async get() {
|
|
37368
|
+
return null;
|
|
37369
|
+
}
|
|
37370
|
+
};
|
|
37345
37371
|
VercelBlobStore = class {
|
|
37346
37372
|
constructor(token6) {
|
|
37347
37373
|
this.token = token6;
|
|
@@ -44624,7 +44650,7 @@ var PACKAGE_VERSION;
|
|
|
44624
44650
|
var init_version = __esm({
|
|
44625
44651
|
"src/version.ts"() {
|
|
44626
44652
|
"use strict";
|
|
44627
|
-
PACKAGE_VERSION = "0.57.
|
|
44653
|
+
PACKAGE_VERSION = "0.57.3";
|
|
44628
44654
|
}
|
|
44629
44655
|
});
|
|
44630
44656
|
|
|
@@ -50633,14 +50659,14 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50633
50659
|
}, async (input) => executor.localSourcebookCapture(input));
|
|
50634
50660
|
server.registerTool("local_sourcebook_submission_status", {
|
|
50635
50661
|
title: "Local Sourcebook Submission Status",
|
|
50636
|
-
description: "Read the authenticated caller\u2019s listing draft, enrichment coverage, immutable revision number, publication state, and exact live LocalSourcebook.com profile and reviews URLs.",
|
|
50662
|
+
description: "Read the authenticated caller\u2019s listing draft, enrichment coverage, immutable revision number, publication state, and exact live LocalSourcebook.com profile and reviews URLs. When status is failed, acquisitionError states why in plain language \u2014 read it before retrying, because a refresh repeats the same acquisition and will fail the same way until the cause is fixed. Coverage counters are written only when acquisition succeeds, so a failed listing still shows the pre-run crawl block; zeroed counters do not mean the crawl never ran.",
|
|
50637
50663
|
inputSchema: LocalSourcebookSubmissionStatusInputSchema,
|
|
50638
50664
|
outputSchema: recordOutputSchema("local_sourcebook_submission_status", LocalSourcebookOutputSchema),
|
|
50639
50665
|
annotations: localPlanningToolAnnotations("Local Sourcebook Submission Status")
|
|
50640
50666
|
}, async (input) => executor.localSourcebookSubmissionStatus(input));
|
|
50641
50667
|
server.registerTool("local_sourcebook_refresh", {
|
|
50642
50668
|
title: "Refresh a Local Sourcebook Listing",
|
|
50643
|
-
description: "Queue a new broad crawl and review/media acquisition pass for a listing owned by the authenticated MCP Scraper account. A refresh costs 2 Credits total, including acquisition; idempotent retries are not charged twice. The last published revision remains public until the refreshed evidence revision completes and auto-publishes.",
|
|
50669
|
+
description: "Queue a new broad crawl and review/media acquisition pass for a listing owned by the authenticated MCP Scraper account. A refresh costs 2 Credits total, including acquisition; idempotent retries are not charged twice, and a replayed retry still re-runs the acquisition, so a failed listing is always recoverable. Read local_sourcebook_submission_status first: a refresh repeats the same acquisition, so fix whatever acquisitionError reports before spending another pass. The last published revision remains public until the refreshed evidence revision completes and auto-publishes.",
|
|
50644
50670
|
inputSchema: LocalSourcebookRefreshInputSchema,
|
|
50645
50671
|
outputSchema: recordOutputSchema("local_sourcebook_refresh", LocalSourcebookOutputSchema),
|
|
50646
50672
|
annotations: liveWebToolAnnotations("Refresh a Local Sourcebook Listing")
|