mcp-scraper 0.3.11 → 0.3.13
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 +2 -2
- package/dist/bin/api-server.cjs +98 -24
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/browser-agent-stdio-server.cjs +198 -27
- package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
- package/dist/bin/browser-agent-stdio-server.js +3 -2
- package/dist/bin/browser-agent-stdio-server.js.map +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-combined-stdio-server.cjs +275 -68
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.js +4 -3
- package/dist/bin/mcp-scraper-combined-stdio-server.js.map +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 +62 -13
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -2
- package/dist/bin/mcp-stdio-server.js.map +1 -1
- package/dist/bin/paa-harvest.cjs +21 -1
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +1 -1
- package/dist/chunk-3YGKXXUG.js +133 -0
- package/dist/chunk-3YGKXXUG.js.map +1 -0
- package/dist/{chunk-UWSG3C5J.js → chunk-4OPKIDON.js} +22 -2
- package/dist/chunk-4OPKIDON.js.map +1 -0
- package/dist/chunk-BEZJ4G32.js +7 -0
- package/dist/chunk-BEZJ4G32.js.map +1 -0
- package/dist/{chunk-L27GJQV7.js → chunk-QAOIH5U2.js} +28 -5
- package/dist/chunk-QAOIH5U2.js.map +1 -0
- package/dist/{chunk-VMH7SRWY.js → chunk-YGV2XZDT.js} +54 -14
- package/dist/chunk-YGV2XZDT.js.map +1 -0
- package/dist/index.cjs +21 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{server-3SA5Q4OF.js → server-LX65PB7D.js} +42 -151
- package/dist/server-LX65PB7D.js.map +1 -0
- package/dist/{worker-56IXWOQU.js → worker-FG7ZWEGA.js} +2 -2
- package/docs/mcp-tool-craft-lint.generated.md +1 -1
- package/docs/mcp-tool-manifest.generated.json +1 -1
- package/package.json +1 -1
- package/dist/chunk-L27GJQV7.js.map +0 -1
- package/dist/chunk-RRE7WVHQ.js +0 -7
- package/dist/chunk-RRE7WVHQ.js.map +0 -1
- package/dist/chunk-UWSG3C5J.js.map +0 -1
- package/dist/chunk-VMH7SRWY.js.map +0 -1
- package/dist/server-3SA5Q4OF.js.map +0 -1
- /package/dist/{worker-56IXWOQU.js.map → worker-FG7ZWEGA.js.map} +0 -0
package/README.md
CHANGED
|
@@ -186,8 +186,8 @@ env = { MCP_SCRAPER_API_KEY = "sk_live_your_key" }
|
|
|
186
186
|
- `facebook_page_intel`
|
|
187
187
|
- `facebook_ad_transcribe` — transcribe a direct Facebook ad video URL returned by `facebook_page_intel`.
|
|
188
188
|
- `facebook_video_transcribe` — transcribe an organic Facebook reel, video, watch, post, or share URL, including `fb.watch` links. The tool renders the page, extracts the best matching public Facebook CDN MP4 URL, then returns transcript text, timestamped chunks, selected quality, video metadata, and the extracted MP4 URL for follow-up download.
|
|
189
|
-
- `instagram_profile_content` — discover Instagram profile grid content links for a handle or profile URL. Returns collected post/reel/tv URLs, profile counts, type counts, shortcodes, browser details, pagination attempts, stop reason, and limitations.
|
|
190
|
-
- `instagram_media_download` — extract and download one Instagram post/reel/tv URL. Returns text/caption, image URL/downloads, selected video/audio MP4 tracks, optional muxed MP4 when `ffmpeg` is available, optional transcript, and browser details.
|
|
189
|
+
- `instagram_profile_content` — discover Instagram profile grid content links for a handle or profile URL, optionally through a saved hosted browser `profile` for authenticated access. Returns collected post/reel/tv URLs, profile counts, type counts, shortcodes, browser details, pagination attempts, stop reason, and limitations.
|
|
190
|
+
- `instagram_media_download` — extract and download one Instagram post/reel/tv URL, optionally through a saved hosted browser `profile` for authenticated access. Returns text/caption, image URL/downloads, selected video/audio MP4 tracks, optional muxed MP4 when `ffmpeg` is available, optional transcript, and browser details.
|
|
191
191
|
- `maps_search` — search Google Maps for multiple business/profile candidates. Use for GMB/GBP prospect lists, competitors, categories, and anything needing more than the Google 3-pack. In default `proxyMode: "location"`, retryable failures rotate to a new residential proxy and new browser session for up to 5 attempts. `maxResults` defaults to 10 and is capped at 50.
|
|
192
192
|
- `maps_place_intel` — hydrate one known/named Google Maps business with profile details and optional reviews. Use after `maps_search` when a selected candidate needs full details.
|
|
193
193
|
- `directory_workflow` — build city-by-city directory/prospecting datasets from Census place selection plus Google Maps searches. Use it for requests like "all cities over 100k population in Tennessee, then get 20 roofers from Maps." In default `proxyMode: "location"`, each city search rotates retryable failures to a new residential proxy and new browser session for up to 5 attempts. The saved CSV includes `source_location`, `result_position`, `business_name`, `review_stars`, `review_count`, `category`, `address`, `phone`, `hours_status`, `website_url`, `directions_url`, `place_url`, `cid`, `cid_decimal`, Census population, and ZIP groups.
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -9164,6 +9164,16 @@ function proxyIdSuffix(proxyId) {
|
|
|
9164
9164
|
function errorText(err) {
|
|
9165
9165
|
return err instanceof Error ? err.message : String(err);
|
|
9166
9166
|
}
|
|
9167
|
+
function isKernelProfileConflict(err) {
|
|
9168
|
+
return /\b409\b|conflict|already exists/i.test(errorText(err));
|
|
9169
|
+
}
|
|
9170
|
+
async function ensureKernelProfile(kernelClient, name) {
|
|
9171
|
+
try {
|
|
9172
|
+
await kernelClient.profiles.create({ name });
|
|
9173
|
+
} catch (err) {
|
|
9174
|
+
if (!isKernelProfileConflict(err)) throw err;
|
|
9175
|
+
}
|
|
9176
|
+
}
|
|
9167
9177
|
function rankCheckContextOptions(config) {
|
|
9168
9178
|
return {
|
|
9169
9179
|
viewport: config.viewport,
|
|
@@ -9266,10 +9276,19 @@ var init_BrowserDriver = __esm({
|
|
|
9266
9276
|
if (config.kernelApiKey) {
|
|
9267
9277
|
this.kernelClient = new import_sdk4.default({ apiKey: config.kernelApiKey });
|
|
9268
9278
|
const timeoutSeconds = positiveIntFromEnv("KERNEL_BROWSER_TIMEOUT_SECONDS", DEFAULT_KERNEL_BROWSER_TIMEOUT_SECONDS);
|
|
9279
|
+
if (config.kernelProfileName && config.kernelProfileSaveChanges === true) {
|
|
9280
|
+
await ensureKernelProfile(this.kernelClient, config.kernelProfileName);
|
|
9281
|
+
}
|
|
9269
9282
|
const kernelBrowser = await this.kernelClient.browsers.create({
|
|
9270
9283
|
stealth: true,
|
|
9271
9284
|
timeout_seconds: timeoutSeconds,
|
|
9272
|
-
...config.kernelProxyId ? { proxy_id: config.kernelProxyId } : {}
|
|
9285
|
+
...config.kernelProxyId ? { proxy_id: config.kernelProxyId } : {},
|
|
9286
|
+
...config.kernelProfileName ? {
|
|
9287
|
+
profile: {
|
|
9288
|
+
name: config.kernelProfileName,
|
|
9289
|
+
...typeof config.kernelProfileSaveChanges === "boolean" ? { save_changes: config.kernelProfileSaveChanges } : {}
|
|
9290
|
+
}
|
|
9291
|
+
} : {}
|
|
9273
9292
|
});
|
|
9274
9293
|
this.kernelSessionId = kernelBrowser.session_id;
|
|
9275
9294
|
let defaultProxyDisabled = null;
|
|
@@ -9313,6 +9332,7 @@ var init_BrowserDriver = __esm({
|
|
|
9313
9332
|
timeout_seconds: timeoutSeconds,
|
|
9314
9333
|
proxy_mode: proxyMode,
|
|
9315
9334
|
proxy_id_present: Boolean(config.kernelProxyId),
|
|
9335
|
+
profile_name_present: Boolean(config.kernelProfileName),
|
|
9316
9336
|
proxy_resolution_source: config.kernelProxyResolution?.source
|
|
9317
9337
|
}));
|
|
9318
9338
|
if (this.debugEnabled) {
|
|
@@ -13121,8 +13141,8 @@ function ownerFromMetadata(metadata) {
|
|
|
13121
13141
|
return match?.[1]?.trim() || null;
|
|
13122
13142
|
}
|
|
13123
13143
|
async function collectInstagramProfileContentFromPage(page, opts) {
|
|
13124
|
-
const maxItems = Math.min(
|
|
13125
|
-
const maxScrolls = Math.min(
|
|
13144
|
+
const maxItems = Math.min(2e3, Math.max(1, opts.maxItems ?? 50));
|
|
13145
|
+
const maxScrolls = Math.min(250, Math.max(0, opts.maxScrolls ?? 10));
|
|
13126
13146
|
const scrollDelayMs = Math.min(5e3, Math.max(250, opts.scrollDelayMs ?? 1200));
|
|
13127
13147
|
const stableScrollLimit = Math.min(10, Math.max(1, opts.stableScrollLimit ?? 4));
|
|
13128
13148
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13343,21 +13363,32 @@ var init_InstagramContentExtractor = __esm({
|
|
|
13343
13363
|
function invalidRequest2(message) {
|
|
13344
13364
|
return { error_code: "invalid_request", message };
|
|
13345
13365
|
}
|
|
13346
|
-
|
|
13366
|
+
function resolveSaveProfileChanges(body) {
|
|
13367
|
+
return body.saveProfileChanges ?? body.save_profile_changes ?? browserServiceProfileSaveChanges();
|
|
13368
|
+
}
|
|
13369
|
+
function resolveProfileName(body) {
|
|
13370
|
+
const explicit = body.profile?.trim();
|
|
13371
|
+
return explicit || browserServiceProfileName();
|
|
13372
|
+
}
|
|
13373
|
+
async function kernelLaunchOptsDirect(profileName, saveProfileChanges) {
|
|
13347
13374
|
return {
|
|
13348
13375
|
headless: true,
|
|
13349
13376
|
kernelApiKey: browserServiceApiKey(),
|
|
13377
|
+
...profileName ? { kernelProfileName: profileName } : {},
|
|
13378
|
+
...typeof saveProfileChanges === "boolean" ? { kernelProfileSaveChanges: saveProfileChanges } : {},
|
|
13350
13379
|
viewport: { width: 1280, height: 900 },
|
|
13351
13380
|
locale: "en-US"
|
|
13352
13381
|
};
|
|
13353
13382
|
}
|
|
13354
|
-
async function resolveInstagramLaunch() {
|
|
13383
|
+
async function resolveInstagramLaunch(body) {
|
|
13384
|
+
const profileName = resolveProfileName(body);
|
|
13385
|
+
const saveProfileChanges = resolveSaveProfileChanges(body);
|
|
13355
13386
|
return {
|
|
13356
|
-
config: await kernelLaunchOptsDirect(),
|
|
13387
|
+
config: await kernelLaunchOptsDirect(profileName, saveProfileChanges),
|
|
13357
13388
|
browser: {
|
|
13358
13389
|
mode: "hosted",
|
|
13359
13390
|
requestedMode: "hosted",
|
|
13360
|
-
profileName: null,
|
|
13391
|
+
profileName: profileName ?? null,
|
|
13361
13392
|
profileSource: "hosted",
|
|
13362
13393
|
profileDirConfigured: false,
|
|
13363
13394
|
executablePathConfigured: false
|
|
@@ -13449,8 +13480,11 @@ var init_instagram_routes = __esm({
|
|
|
13449
13480
|
InstagramProfileContentBodySchema = import_zod17.z.object({
|
|
13450
13481
|
handle: import_zod17.z.string().trim().optional(),
|
|
13451
13482
|
url: import_zod17.z.string().trim().optional(),
|
|
13452
|
-
|
|
13453
|
-
|
|
13483
|
+
profile: import_zod17.z.string().trim().min(1).optional(),
|
|
13484
|
+
saveProfileChanges: import_zod17.z.boolean().optional(),
|
|
13485
|
+
save_profile_changes: import_zod17.z.boolean().optional(),
|
|
13486
|
+
maxItems: import_zod17.z.number().int().min(1).max(2e3).default(50),
|
|
13487
|
+
maxScrolls: import_zod17.z.number().int().min(0).max(250).default(10),
|
|
13454
13488
|
scrollDelayMs: import_zod17.z.number().int().min(250).max(5e3).default(1200),
|
|
13455
13489
|
stableScrollLimit: import_zod17.z.number().int().min(1).max(10).default(4)
|
|
13456
13490
|
}).refine((d) => !!d.handle || !!d.url, {
|
|
@@ -13459,6 +13493,9 @@ var init_instagram_routes = __esm({
|
|
|
13459
13493
|
InstagramMediaTypeSchema = import_zod17.z.enum(["image", "video", "audio"]);
|
|
13460
13494
|
InstagramMediaDownloadBodySchema = import_zod17.z.object({
|
|
13461
13495
|
url: import_zod17.z.string().trim().min(1, "url is required"),
|
|
13496
|
+
profile: import_zod17.z.string().trim().min(1).optional(),
|
|
13497
|
+
saveProfileChanges: import_zod17.z.boolean().optional(),
|
|
13498
|
+
save_profile_changes: import_zod17.z.boolean().optional(),
|
|
13462
13499
|
mediaTypes: import_zod17.z.array(InstagramMediaTypeSchema).default(["image", "video", "audio"]),
|
|
13463
13500
|
downloadMedia: import_zod17.z.boolean().default(true),
|
|
13464
13501
|
downloadAllTracks: import_zod17.z.boolean().default(false),
|
|
@@ -13489,7 +13526,7 @@ var init_instagram_routes = __esm({
|
|
|
13489
13526
|
const { ok, balance_mc } = await debitMc(user.id, MC_COSTS.instagram_profile, LedgerOperation.INSTAGRAM_PROFILE, target.profileUrl);
|
|
13490
13527
|
if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.instagram_profile), 402);
|
|
13491
13528
|
debited = true;
|
|
13492
|
-
const launch = await resolveInstagramLaunch();
|
|
13529
|
+
const launch = await resolveInstagramLaunch(body);
|
|
13493
13530
|
await driver.launch(launch.config);
|
|
13494
13531
|
await driver.navigateTo(target.profileUrl);
|
|
13495
13532
|
const page = driver.getPage();
|
|
@@ -13536,7 +13573,7 @@ var init_instagram_routes = __esm({
|
|
|
13536
13573
|
const { ok, balance_mc } = await debitMc(user.id, MC_COSTS.instagram_media, LedgerOperation.INSTAGRAM_MEDIA, sourceUrl.href);
|
|
13537
13574
|
if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.instagram_media), 402);
|
|
13538
13575
|
mediaDebited = true;
|
|
13539
|
-
const launch = await resolveInstagramLaunch();
|
|
13576
|
+
const launch = await resolveInstagramLaunch(body);
|
|
13540
13577
|
await driver.launch(launch.config);
|
|
13541
13578
|
const page = driver.getPage();
|
|
13542
13579
|
const capturedMediaUrls = [];
|
|
@@ -16133,7 +16170,7 @@ function formatInstagramProfileContent(raw, input) {
|
|
|
16133
16170
|
const itemRows = items.slice(0, 100).map(
|
|
16134
16171
|
(item, i) => `| ${i + 1} | ${item.type} | \`${item.shortcode}\` | ${item.url} | ${cell(item.firstSeenStage ?? "")} |`
|
|
16135
16172
|
).join("\n");
|
|
16136
|
-
const browserLabel = "hosted browser";
|
|
16173
|
+
const browserLabel = browser.profileName ? `hosted browser profile ${browser.profileName}` : "hosted browser";
|
|
16137
16174
|
const full = [
|
|
16138
16175
|
`# Instagram Profile Content: ${d.handle ?? input.handle ?? input.url ?? "profile"}`,
|
|
16139
16176
|
`**Collected:** ${items.length} items \xB7 posts ${typeCounts?.post ?? 0} \xB7 reels ${typeCounts?.reel ?? 0} \xB7 tv ${typeCounts?.tv ?? 0}`,
|
|
@@ -16208,7 +16245,7 @@ function formatInstagramMediaDownload(raw, input) {
|
|
|
16208
16245
|
const transcriptText = transcript?.text ?? "";
|
|
16209
16246
|
const chunks = transcript?.chunks ?? [];
|
|
16210
16247
|
const browser = structuredInstagramBrowser(d.browser);
|
|
16211
|
-
const browserLabel = "hosted browser";
|
|
16248
|
+
const browserLabel = browser.profileName ? `hosted browser profile ${browser.profileName}` : "hosted browser";
|
|
16212
16249
|
const downloadRows = downloads.map((download, i) => {
|
|
16213
16250
|
const status = download.error ? `error: ${cell(download.error)}` : `${download.sizeBytes ?? 0} bytes`;
|
|
16214
16251
|
return `| ${i + 1} | ${download.kind} | ${download.savedPath ? `\`${download.savedPath}\`` : "\u2014"} | ${status} |`;
|
|
@@ -21921,7 +21958,7 @@ var PACKAGE_VERSION;
|
|
|
21921
21958
|
var init_version = __esm({
|
|
21922
21959
|
"src/version.ts"() {
|
|
21923
21960
|
"use strict";
|
|
21924
|
-
PACKAGE_VERSION = "0.3.
|
|
21961
|
+
PACKAGE_VERSION = "0.3.13";
|
|
21925
21962
|
}
|
|
21926
21963
|
});
|
|
21927
21964
|
|
|
@@ -21992,13 +22029,17 @@ var init_mcp_tool_schemas = __esm({
|
|
|
21992
22029
|
InstagramProfileContentInputSchema = {
|
|
21993
22030
|
handle: import_zod27.z.string().min(1).optional().describe("Instagram handle, with or without @. Provide handle or url."),
|
|
21994
22031
|
url: import_zod27.z.string().url().optional().describe("Instagram profile URL, e.g. https://www.instagram.com/nasaartemis/. Provide handle or url."),
|
|
21995
|
-
|
|
21996
|
-
|
|
22032
|
+
profile: import_zod27.z.string().min(1).optional().describe("Optional saved hosted browser profile name to load authenticated Instagram access. If omitted, the server uses its configured default profile when present."),
|
|
22033
|
+
saveProfileChanges: import_zod27.z.boolean().optional().describe("Whether to save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login session."),
|
|
22034
|
+
maxItems: import_zod27.z.number().int().min(1).max(2e3).default(50).describe("Maximum profile grid post/reel/tv URLs to collect. Default 50, maximum 2000. Use higher values only when the user asks for a fuller archive."),
|
|
22035
|
+
maxScrolls: import_zod27.z.number().int().min(0).max(250).default(10).describe("Maximum pagination scroll attempts. Default 10, maximum 250. Increase for long profiles when Instagram continues loading more grid links."),
|
|
21997
22036
|
scrollDelayMs: import_zod27.z.number().int().min(250).max(5e3).default(1200).describe("Delay after each pagination scroll before collecting newly loaded links. Default 1200ms. Increase to 2000-3000ms when Instagram loads slowly."),
|
|
21998
22037
|
stableScrollLimit: import_zod27.z.number().int().min(1).max(10).default(4).describe("Stop after this many consecutive scrolls with no new links or scroll progress. Default 4.")
|
|
21999
22038
|
};
|
|
22000
22039
|
InstagramMediaDownloadInputSchema = {
|
|
22001
22040
|
url: import_zod27.z.string().url().describe("Instagram post, reel, or tv URL, e.g. https://www.instagram.com/reel/SHORTCODE/. The tool renders the page, extracts text, image metadata, and Instagram CDN media tracks."),
|
|
22041
|
+
profile: import_zod27.z.string().min(1).optional().describe("Optional saved hosted browser profile name to load authenticated Instagram access. If omitted, the server uses its configured default profile when present."),
|
|
22042
|
+
saveProfileChanges: import_zod27.z.boolean().optional().describe("Whether to save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login session."),
|
|
22002
22043
|
mediaTypes: import_zod27.z.array(import_zod27.z.enum(["image", "video", "audio"])).default(["image", "video", "audio"]).describe("Which media types to download when downloadMedia is true. Reels commonly expose separate video-only and audio-only MP4 tracks."),
|
|
22003
22044
|
downloadMedia: import_zod27.z.boolean().default(true).describe("Download extracted text/media files to the MCP Scraper output directory when the API server can write files. Always returns extracted media URLs even when false."),
|
|
22004
22045
|
downloadAllTracks: import_zod27.z.boolean().default(false).describe("Download every captured Instagram MP4 track instead of only the selected best video and audio tracks. Use false by default to avoid duplicate bitrates."),
|
|
@@ -22410,8 +22451,8 @@ var init_mcp_tool_schemas = __esm({
|
|
|
22410
22451
|
executablePathConfigured: import_zod27.z.boolean()
|
|
22411
22452
|
});
|
|
22412
22453
|
InstagramPaginationOutput = import_zod27.z.object({
|
|
22413
|
-
maxItems: import_zod27.z.number().int().min(1).max(
|
|
22414
|
-
maxScrolls: import_zod27.z.number().int().min(0).max(
|
|
22454
|
+
maxItems: import_zod27.z.number().int().min(1).max(2e3),
|
|
22455
|
+
maxScrolls: import_zod27.z.number().int().min(0).max(250),
|
|
22415
22456
|
attemptedScrolls: import_zod27.z.number().int().min(0),
|
|
22416
22457
|
stableScrolls: import_zod27.z.number().int().min(0),
|
|
22417
22458
|
stableScrollLimit: import_zod27.z.number().int().min(1).max(10),
|
|
@@ -23288,11 +23329,44 @@ function youtubeVideoIdFromUrl(url) {
|
|
|
23288
23329
|
}
|
|
23289
23330
|
return null;
|
|
23290
23331
|
}
|
|
23332
|
+
async function readResponseData(res) {
|
|
23333
|
+
const text = await res.text();
|
|
23334
|
+
if (!text.trim()) return null;
|
|
23335
|
+
try {
|
|
23336
|
+
return JSON.parse(text);
|
|
23337
|
+
} catch {
|
|
23338
|
+
return text;
|
|
23339
|
+
}
|
|
23340
|
+
}
|
|
23341
|
+
function httpErrorPayload(path6, res, data) {
|
|
23342
|
+
const objectData = data && typeof data === "object" && !Array.isArray(data) ? data : null;
|
|
23343
|
+
const bodyMessage = objectData ? objectData.message ?? objectData.error ?? objectData.error_code : data;
|
|
23344
|
+
return {
|
|
23345
|
+
...objectData ?? { body: data },
|
|
23346
|
+
error: objectData?.error ?? objectData?.error_code ?? "mcp_http_error",
|
|
23347
|
+
error_type: "http",
|
|
23348
|
+
retryable: res.status === 429 || res.status >= 500,
|
|
23349
|
+
status: res.status,
|
|
23350
|
+
statusText: res.statusText,
|
|
23351
|
+
path: path6,
|
|
23352
|
+
message: typeof bodyMessage === "string" && bodyMessage.trim() ? bodyMessage : `MCP Scraper HTTP ${res.status}${res.statusText ? ` ${res.statusText}` : ""} for ${path6}`
|
|
23353
|
+
};
|
|
23354
|
+
}
|
|
23355
|
+
function withDefaultHostedProfile(input) {
|
|
23356
|
+
const profile = input.profile?.trim() || browserServiceProfileName();
|
|
23357
|
+
const saveProfileChanges = input.saveProfileChanges ?? browserServiceProfileSaveChanges();
|
|
23358
|
+
return {
|
|
23359
|
+
...input,
|
|
23360
|
+
...profile ? { profile } : {},
|
|
23361
|
+
...typeof saveProfileChanges === "boolean" ? { saveProfileChanges } : {}
|
|
23362
|
+
};
|
|
23363
|
+
}
|
|
23291
23364
|
var HttpMcpToolExecutor;
|
|
23292
23365
|
var init_http_mcp_tool_executor = __esm({
|
|
23293
23366
|
"src/mcp/http-mcp-tool-executor.ts"() {
|
|
23294
23367
|
"use strict";
|
|
23295
23368
|
init_harvest_timeout();
|
|
23369
|
+
init_browser_service_env();
|
|
23296
23370
|
HttpMcpToolExecutor = class {
|
|
23297
23371
|
baseUrl;
|
|
23298
23372
|
apiKey;
|
|
@@ -23320,9 +23394,9 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
23320
23394
|
body: JSON.stringify(body),
|
|
23321
23395
|
signal: AbortSignal.timeout(timeoutMs)
|
|
23322
23396
|
});
|
|
23323
|
-
const data = await res
|
|
23397
|
+
const data = await readResponseData(res);
|
|
23324
23398
|
if (!res.ok) {
|
|
23325
|
-
return { content: [{ type: "text", text: JSON.stringify(data) }], isError: true };
|
|
23399
|
+
return { content: [{ type: "text", text: JSON.stringify(httpErrorPayload(path6, res, data)) }], isError: true };
|
|
23326
23400
|
}
|
|
23327
23401
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
23328
23402
|
} catch (err) {
|
|
@@ -23355,9 +23429,9 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
23355
23429
|
},
|
|
23356
23430
|
signal: AbortSignal.timeout(timeoutMs)
|
|
23357
23431
|
});
|
|
23358
|
-
const data = await res
|
|
23432
|
+
const data = await readResponseData(res);
|
|
23359
23433
|
if (!res.ok) {
|
|
23360
|
-
return { content: [{ type: "text", text: JSON.stringify(data) }], isError: true };
|
|
23434
|
+
return { content: [{ type: "text", text: JSON.stringify(httpErrorPayload(path6, res, data)) }], isError: true };
|
|
23361
23435
|
}
|
|
23362
23436
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
23363
23437
|
} catch (err) {
|
|
@@ -23447,10 +23521,10 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
23447
23521
|
return this.call("/facebook/video-transcribe", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
23448
23522
|
}
|
|
23449
23523
|
instagramProfileContent(input) {
|
|
23450
|
-
return this.call("/instagram/profile-content", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
23524
|
+
return this.call("/instagram/profile-content", withDefaultHostedProfile(input), this.httpTimeoutOverrideMs ?? 24e4);
|
|
23451
23525
|
}
|
|
23452
23526
|
instagramMediaDownload(input) {
|
|
23453
|
-
return this.call("/instagram/media-download", input, this.httpTimeoutOverrideMs ?? 3e5);
|
|
23527
|
+
return this.call("/instagram/media-download", withDefaultHostedProfile(input), this.httpTimeoutOverrideMs ?? 3e5);
|
|
23454
23528
|
}
|
|
23455
23529
|
mapsPlaceIntel(input) {
|
|
23456
23530
|
return this.call("/maps/place", input);
|