mcp-scraper 0.3.42 → 0.3.44
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/dist/bin/api-server.cjs +1469 -1255
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- 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 +58 -12
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/chunk-3Q2NSHSR.js +7 -0
- package/dist/chunk-3Q2NSHSR.js.map +1 -0
- package/dist/{chunk-KPF64WST.js → chunk-NONBSIES.js} +59 -13
- package/dist/chunk-NONBSIES.js.map +1 -0
- package/dist/{chunk-RXJHXBGG.js → chunk-X53SOJSL.js} +20 -3
- package/dist/chunk-X53SOJSL.js.map +1 -0
- package/dist/{server-CZT7EULY.js → server-AN6QUH6C.js} +503 -368
- package/dist/server-AN6QUH6C.js.map +1 -0
- package/dist/{worker-FNSBPP7Y.js → worker-H4EUD2Q5.js} +2 -2
- package/package.json +4 -2
- package/dist/chunk-KPF64WST.js.map +0 -1
- package/dist/chunk-OUZZNW3I.js +0 -7
- package/dist/chunk-OUZZNW3I.js.map +0 -1
- package/dist/chunk-RXJHXBGG.js.map +0 -1
- package/dist/server-CZT7EULY.js.map +0 -1
- /package/dist/{worker-FNSBPP7Y.js.map → worker-H4EUD2Q5.js.map} +0 -0
|
@@ -101,7 +101,7 @@ function renderInstallTerminal(options) {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
// src/version.ts
|
|
104
|
-
var PACKAGE_VERSION = "0.3.
|
|
104
|
+
var PACKAGE_VERSION = "0.3.44";
|
|
105
105
|
|
|
106
106
|
// bin/mcp-scraper-install.ts
|
|
107
107
|
var noColor = process.argv.includes("--no-color") || process.env.NO_COLOR !== void 0 || process.env.FORCE_COLOR === "0" || !process.stdout.isTTY;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/install-terminal.ts","../../src/version.ts","../../bin/mcp-scraper-install.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(48 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n","export const PACKAGE_VERSION = '0.3.
|
|
1
|
+
{"version":3,"sources":["../../src/install-terminal.ts","../../src/version.ts","../../bin/mcp-scraper-install.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(48 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n","export const PACKAGE_VERSION = '0.3.44'\n","#!/usr/bin/env node\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\n\nconst noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\nconst help = process.argv.includes('--help') || process.argv.includes('-h')\nif (help) {\n process.stdout.write([\n 'Usage: mcp-scraper-install [--no-color]',\n '',\n 'Prints the branded MCP Scraper terminal install card and copyable install commands.',\n 'mcp-scraper prints the same card in a human terminal and runs as the MCP stdio server in clients.',\n '',\n ].join('\\n'))\n process.exit(0)\n}\n\nprocess.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n}))\n"],"mappings":"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","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "../chunk-T3VZD2I4.js";
|
|
5
5
|
import {
|
|
6
6
|
PACKAGE_VERSION
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-3Q2NSHSR.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;
|
|
@@ -264,6 +264,12 @@ var HttpMcpToolExecutor = class {
|
|
|
264
264
|
redditThread(input) {
|
|
265
265
|
return this.call("/reddit/thread", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
266
266
|
}
|
|
267
|
+
videoFrameAnalysis(input) {
|
|
268
|
+
return this.call("/video/analyze", input);
|
|
269
|
+
}
|
|
270
|
+
videoFrameAnalysisStatus(input) {
|
|
271
|
+
return this.call("/video/status", input);
|
|
272
|
+
}
|
|
267
273
|
facebookAdTranscribe(input) {
|
|
268
274
|
return this.call("/facebook/transcribe", input);
|
|
269
275
|
}
|
|
@@ -468,7 +474,7 @@ render();
|
|
|
468
474
|
}
|
|
469
475
|
|
|
470
476
|
// src/version.ts
|
|
471
|
-
var PACKAGE_VERSION = "0.3.
|
|
477
|
+
var PACKAGE_VERSION = "0.3.44";
|
|
472
478
|
|
|
473
479
|
// src/mcp/browser-agent-tool-schemas.ts
|
|
474
480
|
var import_zod = require("zod");
|
|
@@ -4658,14 +4664,14 @@ var RawMapsAboutAttributeSchema = import_zod2.z.object({
|
|
|
4658
4664
|
|
|
4659
4665
|
// src/mcp/mcp-tool-schemas.ts
|
|
4660
4666
|
var HarvestPaaInputSchema = {
|
|
4661
|
-
query: import_zod3.z.string().min(1).describe('
|
|
4662
|
-
location: import_zod3.z.string().optional().describe('City, region, or country for geo
|
|
4667
|
+
query: import_zod3.z.string().min(1).describe('The search query. For localized results, KEEP the place in the query text \u2014 if the user says "best hvac company in Denver CO", use query="best hvac company Denver CO" (and also set location="Denver, CO"). City-in-query is what localizes results reliably; do not strip it out.'),
|
|
4668
|
+
location: import_zod3.z.string().optional().describe('City, region, or country for geo signals (uule + location evidence), e.g. "Denver, CO", "Tokyo, Japan". Set it alongside a city-in-query wording; on its own it does NOT reliably localize results.'),
|
|
4663
4669
|
maxQuestions: import_zod3.z.number().int().min(1).max(200).default(30).describe("Number of PAA questions to extract. Default 30. Maximum 200. Use 10 for quick probes, 30 for normal research, 100-200 when the user asks for everything/full/deep research. Larger harvests get a longer server time budget (151-200 questions \u2192 up to 280s). Credits are charged by extracted question; unused request hold is refunded."),
|
|
4664
4670
|
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location or user language. Examples: United States us, United Kingdom gb, Japan jp, Canada ca, Australia au."),
|
|
4665
4671
|
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from the user request. Use en unless the user asks for another language or locale."),
|
|
4666
4672
|
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use desktop by default; use mobile only when the user asks for mobile rankings."),
|
|
4667
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset \u2014
|
|
4668
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe(
|
|
4673
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress \u2014 reliable). Do NOT set "location" just because the user named a city; localized results come from city-in-query wording. "location" forces a residential geo-IP for rank-tracking fidelity only, is frequently CAPTCHA-blocked, and should be used only when the user explicitly demands as-seen-from-the-city results and accepts failures.'),
|
|
4674
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location" (see its warning); ignored otherwise.'),
|
|
4669
4675
|
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/session/location diagnostics in the response. Use true when debugging localization, CAPTCHA, or proxy behavior.")
|
|
4670
4676
|
};
|
|
4671
4677
|
var ExtractUrlInputSchema = {
|
|
@@ -4722,6 +4728,16 @@ var RedditThreadInputSchema = {
|
|
|
4722
4728
|
url: import_zod3.z.string().min(1).describe("A reddit.com thread/post URL (www, old, or new Reddit, or a redd.it link). The service fetches it via old.reddit through a residential proxy and returns the post plus its comment tree."),
|
|
4723
4729
|
maxComments: import_zod3.z.number().int().min(1).max(2e3).optional().describe("Optional cap on comments returned. Omit to return all captured comments.")
|
|
4724
4730
|
};
|
|
4731
|
+
var VideoFrameAnalysisInputSchema = {
|
|
4732
|
+
sourceUrl: import_zod3.z.string().min(1).describe("A DIRECT video file URL (.mp4/.webm/.mov). Not a YouTube/Facebook/Instagram page URL \u2014 resolve those to a direct media URL first. Videos up to 30 minutes are supported."),
|
|
4733
|
+
intervalS: import_zod3.z.number().min(1).max(30).optional().describe("Preferred seconds between sampled frames (1-30, default 2). Automatically widened for long videos so the whole duration is covered within the frame budget."),
|
|
4734
|
+
maxFrames: import_zod3.z.number().int().min(1).max(120).optional().describe("Max frames analyzed (<=120, default 120). Frames are spread evenly across the whole video."),
|
|
4735
|
+
detail: import_zod3.z.enum(["fast", "standard", "deep"]).optional().describe("Analysis depth. Default standard."),
|
|
4736
|
+
vault: import_zod3.z.string().min(1).optional().describe('Memory vault to save the finished breakdown into. Default "Library".')
|
|
4737
|
+
};
|
|
4738
|
+
var VideoFrameAnalysisStatusInputSchema = {
|
|
4739
|
+
runId: import_zod3.z.string().min(1).describe("The runId returned by video_frame_analysis.")
|
|
4740
|
+
};
|
|
4725
4741
|
var FacebookAdTranscribeInputSchema = {
|
|
4726
4742
|
videoUrl: import_zod3.z.string().url().describe("Direct Facebook CDN video URL from a facebook_page_intel ad result. Do not pass a public Facebook reel/post/share URL here; use facebook_video_transcribe for organic Facebook URLs.")
|
|
4727
4743
|
};
|
|
@@ -5151,6 +5167,22 @@ var FacebookAdSearchOutputSchema = {
|
|
|
5151
5167
|
sampleLibraryId: NullableString2
|
|
5152
5168
|
}))
|
|
5153
5169
|
};
|
|
5170
|
+
var VideoFrameAnalysisOutputSchema = {
|
|
5171
|
+
ok: import_zod3.z.boolean(),
|
|
5172
|
+
runId: NullableString2,
|
|
5173
|
+
status: NullableString2,
|
|
5174
|
+
message: NullableString2
|
|
5175
|
+
};
|
|
5176
|
+
var VideoFrameAnalysisStatusOutputSchema = {
|
|
5177
|
+
ok: import_zod3.z.boolean(),
|
|
5178
|
+
runId: NullableString2,
|
|
5179
|
+
status: NullableString2,
|
|
5180
|
+
progress: import_zod3.z.object({ analyzed: import_zod3.z.number().int(), total: import_zod3.z.number().int() }).nullable().optional(),
|
|
5181
|
+
frameCount: import_zod3.z.number().int().nullable().optional(),
|
|
5182
|
+
artifactPath: NullableString2,
|
|
5183
|
+
report: NullableString2,
|
|
5184
|
+
error: NullableString2
|
|
5185
|
+
};
|
|
5154
5186
|
var RedditThreadOutputSchema = {
|
|
5155
5187
|
sourceUrl: NullableString2,
|
|
5156
5188
|
oldRedditUrl: NullableString2,
|
|
@@ -5498,24 +5530,24 @@ var WorkflowArtifactReadOutputSchema = {
|
|
|
5498
5530
|
text: import_zod3.z.string()
|
|
5499
5531
|
};
|
|
5500
5532
|
var SearchSerpInputSchema = {
|
|
5501
|
-
query: import_zod3.z.string().min(1).describe('
|
|
5502
|
-
location: import_zod3.z.string().optional().describe("City, region, or country for geo-
|
|
5533
|
+
query: import_zod3.z.string().min(1).describe('The search query. For localized results, KEEP the place in the query text \u2014 "best dentist in Brooklyn NY" stays query="best dentist Brooklyn NY" (and also set location="Brooklyn, NY"). City-in-query is what localizes results reliably; do not strip it out.'),
|
|
5534
|
+
location: import_zod3.z.string().optional().describe("City, region, or country for geo signals (uule + location evidence). Set it alongside a city-in-query wording; on its own it does NOT reliably localize results."),
|
|
5503
5535
|
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location or user language."),
|
|
5504
5536
|
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from user request."),
|
|
5505
5537
|
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use desktop by default; use mobile only when the user asks for mobile rankings."),
|
|
5506
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset \u2014
|
|
5507
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe(
|
|
5538
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress \u2014 reliable). Do NOT set "location" just because the user named a city; localized results come from city-in-query wording. "location" forces a residential geo-IP for rank-tracking fidelity only, is frequently CAPTCHA-blocked, and should be used only when the user explicitly demands as-seen-from-the-city results and accepts failures.'),
|
|
5539
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location" (see its warning); ignored otherwise.'),
|
|
5508
5540
|
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/session/location diagnostics in the response. Use true when debugging localization, CAPTCHA, or proxy behavior."),
|
|
5509
5541
|
pages: import_zod3.z.number().int().min(1).max(2).default(1).describe("Number of result pages to fetch (1\u20132)")
|
|
5510
5542
|
};
|
|
5511
5543
|
var CaptureSerpSnapshotInputSchema = {
|
|
5512
|
-
query: import_zod3.z.string().min(1).describe(
|
|
5544
|
+
query: import_zod3.z.string().min(1).describe('Search query to capture as a structured SERP Intelligence snapshot. For localized captures, KEEP the place in the query text (e.g. "botox clinic austin tx") and also set location; city-in-query is what localizes results reliably.'),
|
|
5513
5545
|
location: import_zod3.z.string().optional().describe("City, region, country, or service area used for localized Google results. MCP Scraper records location evidence; UULE alone is not proof of localization."),
|
|
5514
5546
|
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from the requested market, e.g. us, gb, ca, au."),
|
|
5515
5547
|
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from the user request."),
|
|
5516
5548
|
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only when the user asks for mobile rankings or mobile SERP evidence."),
|
|
5517
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset \u2014
|
|
5518
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe(
|
|
5549
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress \u2014 reliable). Do NOT set "location" just because a city was named; localized captures come from city-in-query wording. "location" forces a residential geo-IP (rank-tracking fidelity only), is frequently CAPTCHA-blocked, and should be used only when the user explicitly needs as-seen-from-the-city evidence and accepts failures.'),
|
|
5550
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location" (see its warning); ignored otherwise.'),
|
|
5519
5551
|
pages: import_zod3.z.number().int().min(1).max(2).default(1).describe("Number of Google result pages to capture. Use 1 normally and 2 only when the user needs deeper ranking evidence."),
|
|
5520
5552
|
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser, proxy, and location diagnostics. Use true when debugging localization, CAPTCHA, proxy selection, or capture reliability."),
|
|
5521
5553
|
includePageSnapshots: import_zod3.z.boolean().default(false).describe("Also capture ranking-page snapshots for selected SERP URLs through the same product capture path."),
|
|
@@ -6012,6 +6044,20 @@ function registerPaaExtractorMcpTools(server2, executor, options = {}) {
|
|
|
6012
6044
|
outputSchema: RedditThreadOutputSchema,
|
|
6013
6045
|
annotations: liveWebToolAnnotations("Reddit Thread + Comments")
|
|
6014
6046
|
}, async (input) => formatRedditThread(await executor.redditThread(input), input));
|
|
6047
|
+
server2.registerTool("video_frame_analysis", {
|
|
6048
|
+
title: "Video Breakdown (frame-by-frame + transcript)",
|
|
6049
|
+
description: `Produce a deep, structured breakdown of a video: what happens on screen, what is said, how it is paced, and how to make one like it. Use this when the user wants to analyze, break down, study, reverse-engineer, or "figure out how they made" a video (an ad, a YouTube video, a reel, a competitor's content). It samples up to 120 frames spread across the whole video (up to 30 minutes), runs vision AI on every frame, transcribes the audio, and returns a report with: Summary, Pacing & Energy, Words-per-Minute & delivery, Topic Outline, Key Points, Hook Analysis, Visual Style, and a step-by-step "How to Replicate This Video" recipe \u2014 all quality-checked. Pass a DIRECT video file URL (.mp4/.webm/.mov); for a YouTube/Facebook/Instagram link, resolve it to a direct media URL first (e.g. facebook_page_intel returns a videoUrl). This runs asynchronously and costs a flat $1 (refunded if it fails): it returns a runId immediately \u2014 then call video_frame_analysis_status with that runId every few seconds until status is "done" to get the finished report.`,
|
|
6050
|
+
inputSchema: VideoFrameAnalysisInputSchema,
|
|
6051
|
+
outputSchema: VideoFrameAnalysisOutputSchema,
|
|
6052
|
+
annotations: { title: "Video Breakdown", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
|
|
6053
|
+
}, async (input) => executor.videoFrameAnalysis(input));
|
|
6054
|
+
server2.registerTool("video_frame_analysis_status", {
|
|
6055
|
+
title: "Video Breakdown Status",
|
|
6056
|
+
description: 'Check the progress of a video breakdown started with video_frame_analysis, using the runId it returned. Poll this every few seconds. While running it reports the current phase and how many frames have been analyzed; when status is "done" it returns the full breakdown report (Markdown) and the memory vault path where it was saved. Free to call. Stop polling when status is "done" or "failed".',
|
|
6057
|
+
inputSchema: VideoFrameAnalysisStatusInputSchema,
|
|
6058
|
+
outputSchema: VideoFrameAnalysisStatusOutputSchema,
|
|
6059
|
+
annotations: { title: "Video Breakdown Status", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
6060
|
+
}, async (input) => executor.videoFrameAnalysisStatus(input));
|
|
6015
6061
|
server2.registerTool("facebook_ad_transcribe", {
|
|
6016
6062
|
title: "Facebook Ad Transcription",
|
|
6017
6063
|
description: "Transcribe audio from a Facebook ad video CDN URL. Use this when facebook_page_intel returned a direct videoUrl and the user asks what the ad says, what claims it makes, or wants ad-message extraction. Returns full transcript, timestamped chunks, word count, and resolvedInputs. Use only with the direct videoUrl value from facebook_page_intel results; do not pass public Facebook post/reel/share URLs. Use facebook_video_transcribe for organic Facebook URLs, and facebook_page_intel first when you only have a brand/page/ad library handle.",
|