mcp-scraper 0.3.28 → 0.3.42
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 +2464 -1134
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- 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 +237 -6
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/bin/paa-harvest.cjs +109 -5
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +2 -2
- package/dist/{chunk-TRNSXR46.js → chunk-DVRPXPYH.js} +22 -3
- package/dist/chunk-DVRPXPYH.js.map +1 -0
- package/dist/{chunk-QSSH4RCX.js → chunk-GMTS35L6.js} +111 -7
- package/dist/chunk-GMTS35L6.js.map +1 -0
- package/dist/{chunk-NGD4ITAO.js → chunk-KPF64WST.js} +238 -7
- package/dist/chunk-KPF64WST.js.map +1 -0
- package/dist/chunk-OUZZNW3I.js +7 -0
- package/dist/chunk-OUZZNW3I.js.map +1 -0
- package/dist/{chunk-H74L743B.js → chunk-RXJHXBGG.js} +40 -3
- package/dist/chunk-RXJHXBGG.js.map +1 -0
- package/dist/{db-FP2ABUU4.js → db-LYQENFPW.js} +2 -2
- package/dist/index.cjs +109 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +2 -2
- package/dist/{server-IDDX7KGT.js → server-CZT7EULY.js} +1157 -246
- package/dist/server-CZT7EULY.js.map +1 -0
- package/dist/{worker-NV4GTIRG.js → worker-FNSBPP7Y.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-7MY2NSQX.js +0 -7
- package/dist/chunk-7MY2NSQX.js.map +0 -1
- package/dist/chunk-H74L743B.js.map +0 -1
- package/dist/chunk-NGD4ITAO.js.map +0 -1
- package/dist/chunk-QSSH4RCX.js.map +0 -1
- package/dist/chunk-TRNSXR46.js.map +0 -1
- package/dist/server-IDDX7KGT.js.map +0 -1
- /package/dist/{db-FP2ABUU4.js.map → db-LYQENFPW.js.map} +0 -0
- /package/dist/{worker-NV4GTIRG.js.map → worker-FNSBPP7Y.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.42";
|
|
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.42'\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-OUZZNW3I.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;
|
|
@@ -270,6 +270,15 @@ var HttpMcpToolExecutor = class {
|
|
|
270
270
|
facebookVideoTranscribe(input) {
|
|
271
271
|
return this.call("/facebook/video-transcribe", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
272
272
|
}
|
|
273
|
+
googleAdsSearch(input) {
|
|
274
|
+
return this.call("/google-ads/search", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
275
|
+
}
|
|
276
|
+
googleAdsPageIntel(input) {
|
|
277
|
+
return this.call("/google-ads/page-intel", input, this.httpTimeoutOverrideMs ?? 3e5);
|
|
278
|
+
}
|
|
279
|
+
googleAdsTranscribe(input) {
|
|
280
|
+
return this.call("/google-ads/transcribe", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
281
|
+
}
|
|
273
282
|
instagramProfileContent(input) {
|
|
274
283
|
return this.call("/instagram/profile-content", withDefaultHostedProfile(input), this.httpTimeoutOverrideMs ?? 24e4);
|
|
275
284
|
}
|
|
@@ -459,7 +468,7 @@ render();
|
|
|
459
468
|
}
|
|
460
469
|
|
|
461
470
|
// src/version.ts
|
|
462
|
-
var PACKAGE_VERSION = "0.3.
|
|
471
|
+
var PACKAGE_VERSION = "0.3.42";
|
|
463
472
|
|
|
464
473
|
// src/mcp/browser-agent-tool-schemas.ts
|
|
465
474
|
var import_zod = require("zod");
|
|
@@ -2700,7 +2709,9 @@ ${paaRows}` : "## People Also Ask\n*Google did not return a People Also Ask bloc
|
|
|
2700
2709
|
${serpRows}` : "";
|
|
2701
2710
|
const aiSection = aiOvw?.detected && aiOvw.text ? `
|
|
2702
2711
|
## AI Overview
|
|
2703
|
-
> ${truncate(aiOvw.text, 600)}`
|
|
2712
|
+
> ${truncate(aiOvw.text, 600)}` + (aiOvw.shareUrl ? `
|
|
2713
|
+
|
|
2714
|
+
**Shareable link:** ${aiOvw.shareUrl}` : "") : "";
|
|
2704
2715
|
const statsLine = durationMs ? `
|
|
2705
2716
|
## Stats
|
|
2706
2717
|
- Status: ${diagnostics?.completionStatus ?? (flat.length ? "paa_found" : "no_paa")} \xB7 Questions: ${flat.length} \xB7 Duration: ${(durationMs / 1e3).toFixed(1)}s` : "";
|
|
@@ -2733,7 +2744,7 @@ ${paaTable}${serpTable}${entityIdsSection(entityIds)}${aiSection}${statsLine}${d
|
|
|
2733
2744
|
domain: String(r.domain ?? ""),
|
|
2734
2745
|
snippet: r.snippet ?? null
|
|
2735
2746
|
})),
|
|
2736
|
-
aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null } : null,
|
|
2747
|
+
aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null, shareUrl: aiOvw.shareUrl ?? null } : null,
|
|
2737
2748
|
entityIds: entityIds ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] } : null,
|
|
2738
2749
|
durationMs: durationMs ?? null
|
|
2739
2750
|
}
|
|
@@ -2765,7 +2776,9 @@ ${serpRows}` : "## Organic Results\n*None found*";
|
|
|
2765
2776
|
${localRows}` : "";
|
|
2766
2777
|
const aiSection = aiOvw?.detected && aiOvw.text ? `
|
|
2767
2778
|
## AI Overview
|
|
2768
|
-
> ${truncate(aiOvw.text, 600)}`
|
|
2779
|
+
> ${truncate(aiOvw.text, 600)}` + (aiOvw.shareUrl ? `
|
|
2780
|
+
|
|
2781
|
+
**Shareable link:** ${aiOvw.shareUrl}` : "") : "";
|
|
2769
2782
|
const tips = `
|
|
2770
2783
|
---
|
|
2771
2784
|
\u{1F4A1} **Tips**
|
|
@@ -2794,7 +2807,7 @@ ${serpTable}${localSection}${entityIdsSection(entityIds)}${aiSection}${debugSect
|
|
|
2794
2807
|
reviewCount: b.reviewCount ?? null,
|
|
2795
2808
|
websiteUrl: b.websiteUrl ?? null
|
|
2796
2809
|
})),
|
|
2797
|
-
aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null } : null,
|
|
2810
|
+
aiOverview: aiOvw ? { detected: aiOvw.detected === true, text: aiOvw.text ?? null, shareUrl: aiOvw.shareUrl ?? null } : null,
|
|
2798
2811
|
entityIds: entityIds ? { entities: entityIds.entities ?? [], kgIds: entityIds.kgIds ?? [], cids: entityIds.cids ?? [], gcids: entityIds.gcids ?? [] } : null
|
|
2799
2812
|
}
|
|
2800
2813
|
};
|
|
@@ -3352,6 +3365,136 @@ ${rows}`,
|
|
|
3352
3365
|
}
|
|
3353
3366
|
};
|
|
3354
3367
|
}
|
|
3368
|
+
function formatGoogleAdsSearch(raw, input) {
|
|
3369
|
+
const parsed = parseData(raw);
|
|
3370
|
+
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
3371
|
+
const d = parsed.data;
|
|
3372
|
+
const advertisers = d.advertisers ?? [];
|
|
3373
|
+
const rows = advertisers.map(
|
|
3374
|
+
(a, i) => `| ${i + 1} | ${cell(a.name)} | ${cell(a.domain)} | ${a.approxAdCount ?? "\u2014"} | \`${a.advertiserId ?? "\u2014"}\` |`
|
|
3375
|
+
).join("\n");
|
|
3376
|
+
const full = [
|
|
3377
|
+
`# Google Ads Transparency Search: "${input.query}"`,
|
|
3378
|
+
`**${advertisers.length} advertisers found**${d.region ? ` \xB7 ${d.region}` : ""}`,
|
|
3379
|
+
`
|
|
3380
|
+
## Advertisers
|
|
3381
|
+
| # | Name | Domain | ~Ads | Advertiser ID |
|
|
3382
|
+
|---|------|--------|------|---------------|
|
|
3383
|
+
${rows}`,
|
|
3384
|
+
`
|
|
3385
|
+
---
|
|
3386
|
+
\u{1F4A1} **Tips**
|
|
3387
|
+
- Pull an advertiser's ads: use \`google_ads_page_intel\` with \`advertiserId\`
|
|
3388
|
+
- Or pass a \`domain\` directly to \`google_ads_page_intel\``
|
|
3389
|
+
].join("\n");
|
|
3390
|
+
return {
|
|
3391
|
+
...oneBlock(full),
|
|
3392
|
+
structuredContent: {
|
|
3393
|
+
query: input.query,
|
|
3394
|
+
region: d.region ?? "US",
|
|
3395
|
+
advertiserCount: advertisers.length,
|
|
3396
|
+
advertisers: advertisers.map((a) => ({
|
|
3397
|
+
advertiserId: a.advertiserId ?? null,
|
|
3398
|
+
name: a.name ?? null,
|
|
3399
|
+
domain: a.domain ?? null,
|
|
3400
|
+
approxAdCount: typeof a.approxAdCount === "number" ? a.approxAdCount : null,
|
|
3401
|
+
detailUrl: a.detailUrl ?? null
|
|
3402
|
+
}))
|
|
3403
|
+
}
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
function formatGoogleAdsPageIntel(raw, input) {
|
|
3407
|
+
const parsed = parseData(raw);
|
|
3408
|
+
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
3409
|
+
const d = parsed.data;
|
|
3410
|
+
const ads = d.ads ?? [];
|
|
3411
|
+
const rows = ads.map((a, i) => {
|
|
3412
|
+
const media = a.youtubeVideoId ? `yt:${a.youtubeVideoId}` : a.videoUrl ? "video" : a.imageUrls.length ? `${a.imageUrls.length} img` : "\u2014";
|
|
3413
|
+
return `| ${i + 1} | ${cell(a.format)} | ${media} | \`${a.creativeId ?? "\u2014"}\` |`;
|
|
3414
|
+
}).join("\n");
|
|
3415
|
+
const label = d.advertiserName ?? input.advertiserId ?? input.domain ?? "";
|
|
3416
|
+
const full = [
|
|
3417
|
+
`# Google Ads Transparency: ${label}`,
|
|
3418
|
+
`**${ads.length} creatives** \xB7 ${d.videoCount ?? 0} video \xB7 ${d.imageCount ?? 0} image \xB7 ${d.textCount ?? 0} text${d.region ? ` \xB7 ${d.region}` : ""}`,
|
|
3419
|
+
`
|
|
3420
|
+
## Creatives
|
|
3421
|
+
| # | Format | Media | Creative ID |
|
|
3422
|
+
|---|--------|-------|-------------|
|
|
3423
|
+
${rows}`,
|
|
3424
|
+
`
|
|
3425
|
+
---
|
|
3426
|
+
\u{1F4A1} **Tips**
|
|
3427
|
+
- Transcribe a video ad: pass its \`videoUrl\` to \`google_ads_transcribe\`, or its \`youtubeVideoId\` to \`youtube_transcribe\`
|
|
3428
|
+
- Full ad detail is at each creative's \`detailUrl\``
|
|
3429
|
+
].join("\n");
|
|
3430
|
+
return {
|
|
3431
|
+
...oneBlock(full),
|
|
3432
|
+
structuredContent: {
|
|
3433
|
+
advertiserId: d.advertiserId ?? null,
|
|
3434
|
+
advertiserName: d.advertiserName ?? null,
|
|
3435
|
+
domain: d.domain ?? null,
|
|
3436
|
+
region: d.region ?? "US",
|
|
3437
|
+
totalCreatives: typeof d.totalCreatives === "number" ? d.totalCreatives : ads.length,
|
|
3438
|
+
videoCount: d.videoCount ?? 0,
|
|
3439
|
+
imageCount: d.imageCount ?? 0,
|
|
3440
|
+
textCount: d.textCount ?? 0,
|
|
3441
|
+
ads: ads.map((a) => ({
|
|
3442
|
+
creativeId: a.creativeId ?? null,
|
|
3443
|
+
advertiserId: a.advertiserId ?? null,
|
|
3444
|
+
format: a.format ?? null,
|
|
3445
|
+
lastShown: a.lastShown ?? null,
|
|
3446
|
+
detailUrl: a.detailUrl ?? null,
|
|
3447
|
+
landingDomain: a.landingDomain ?? null,
|
|
3448
|
+
imageUrls: Array.isArray(a.imageUrls) ? a.imageUrls : [],
|
|
3449
|
+
youtubeVideoId: a.youtubeVideoId ?? null,
|
|
3450
|
+
videoUrl: a.videoUrl ?? null,
|
|
3451
|
+
variations: typeof a.variations === "number" ? a.variations : null
|
|
3452
|
+
}))
|
|
3453
|
+
}
|
|
3454
|
+
};
|
|
3455
|
+
}
|
|
3456
|
+
function formatGoogleAdsTranscribe(raw, input) {
|
|
3457
|
+
const parsed = parseData(raw);
|
|
3458
|
+
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
3459
|
+
const d = parsed.data;
|
|
3460
|
+
const text = d.text ?? "";
|
|
3461
|
+
const chunks = d.chunks ?? [];
|
|
3462
|
+
const durSec = d.durationMs ? (d.durationMs / 1e3).toFixed(0) : "\u2014";
|
|
3463
|
+
const words = wordCount(text);
|
|
3464
|
+
const chunkRows = chunks.slice(0, 50).map((c) => {
|
|
3465
|
+
const sec = Number.isFinite(c.timestamp[0]) ? Math.floor(c.timestamp[0]) : 0;
|
|
3466
|
+
const mm = String(Math.floor(sec / 60)).padStart(2, "0");
|
|
3467
|
+
const ss = String(sec % 60).padStart(2, "0");
|
|
3468
|
+
return `| ${mm}:${ss} | ${cell(truncate(c.text, 120))} |`;
|
|
3469
|
+
}).join("\n");
|
|
3470
|
+
const full = [
|
|
3471
|
+
`# Google Ad Transcript`,
|
|
3472
|
+
`**Duration:** ${durSec}s \xB7 **${words} words**`,
|
|
3473
|
+
`
|
|
3474
|
+
## Full Transcript
|
|
3475
|
+
${text}`,
|
|
3476
|
+
chunks.length ? `
|
|
3477
|
+
## Timestamped Chunks
|
|
3478
|
+
| Time | Text |
|
|
3479
|
+
|------|------|
|
|
3480
|
+
${chunkRows}` : "",
|
|
3481
|
+
`
|
|
3482
|
+
---
|
|
3483
|
+
\u{1F4A1} Get more ads from this advertiser: use \`google_ads_page_intel\`.`
|
|
3484
|
+
].filter(Boolean).join("\n");
|
|
3485
|
+
return {
|
|
3486
|
+
...oneBlock(full),
|
|
3487
|
+
structuredContent: {
|
|
3488
|
+
videoUrl: input.videoUrl,
|
|
3489
|
+
wordCount: words,
|
|
3490
|
+
chunkCount: chunks.length,
|
|
3491
|
+
durationMs: typeof d.durationMs === "number" ? d.durationMs : null,
|
|
3492
|
+
transcriptText: text,
|
|
3493
|
+
chunks: structuredTranscriptChunks(chunks),
|
|
3494
|
+
resolvedInputs: { videoUrl: input.videoUrl }
|
|
3495
|
+
}
|
|
3496
|
+
};
|
|
3497
|
+
}
|
|
3355
3498
|
function normalizeMapsAttempts(value) {
|
|
3356
3499
|
const attempts = Array.isArray(value) ? value : [];
|
|
3357
3500
|
return attempts.map((attempt, index) => ({
|
|
@@ -4370,6 +4513,13 @@ seam is noted so you can chain them.
|
|
|
4370
4513
|
- Transcribe an ad video -> **facebook_ad_transcribe** (takes a videoUrl from \`facebook_page_intel\`).
|
|
4371
4514
|
- Transcribe an organic reel/video/post -> **facebook_video_transcribe** (takes the Facebook url directly).
|
|
4372
4515
|
|
|
4516
|
+
## Google Ads (Ads Transparency Center)
|
|
4517
|
+
- Find advertisers by domain or brand -> **google_ads_search** (returns \`advertisers[]\` with advertiserId).
|
|
4518
|
+
- One advertiser's ads -> **google_ads_page_intel** (takes advertiserId or domain; returns \`ads[]\` with
|
|
4519
|
+
format, imageUrls, youtubeVideoId, and videoUrl).
|
|
4520
|
+
- Transcribe a video ad -> **google_ads_transcribe** (takes a googlevideo \`videoUrl\` from
|
|
4521
|
+
\`google_ads_page_intel\`), or **youtube_transcribe** for a returned \`youtubeVideoId\`.
|
|
4522
|
+
|
|
4373
4523
|
## Instagram
|
|
4374
4524
|
- Profile inventory -> **instagram_profile_content** (returns post/reel/tv urls).
|
|
4375
4525
|
- One post or reel -> **instagram_media_download** (takes a url from \`instagram_profile_content\`, or a
|
|
@@ -4579,6 +4729,20 @@ var FacebookVideoTranscribeInputSchema = {
|
|
|
4579
4729
|
url: import_zod3.z.string().url().describe("Organic Facebook reel, video, watch, post, or share URL from facebook.com, m.facebook.com, or fb.watch. The tool renders the page, extracts the best matching public Facebook CDN MP4 URL, then transcribes it. Use this when the user pastes a normal Facebook video page URL and asks for the transcript or downloadable MP4."),
|
|
4580
4730
|
quality: import_zod3.z.enum(["best", "hd", "sd"]).default("best").describe("Preferred progressive MP4 quality. Use best by default; hd prefers the highest HD progressive URL; sd forces the SD URL.")
|
|
4581
4731
|
};
|
|
4732
|
+
var GoogleAdsSearchInputSchema = {
|
|
4733
|
+
query: import_zod3.z.string().min(1).describe("A domain (e.g. getviktor.com) or advertiser/brand name to look up in the Google Ads Transparency Center. Domains resolve to the advertisers running ads that point to that site."),
|
|
4734
|
+
region: import_zod3.z.string().length(2).default("US").describe("Two-letter region code for where the ads are shown. Default US. Examples: US, CA, GB, AU."),
|
|
4735
|
+
maxResults: import_zod3.z.number().int().min(1).max(20).default(10).describe("Maximum advertisers to return. Default 10, maximum 20.")
|
|
4736
|
+
};
|
|
4737
|
+
var GoogleAdsPageIntelInputSchema = {
|
|
4738
|
+
advertiserId: import_zod3.z.string().optional().describe("Google Ads Transparency advertiser ID (starts with AR...). Use one returned by google_ads_search; do not construct one yourself."),
|
|
4739
|
+
domain: import_zod3.z.string().optional().describe("A domain (e.g. getviktor.com) whose primary advertiser to inspect when advertiserId is unknown. One of advertiserId or domain is required."),
|
|
4740
|
+
region: import_zod3.z.string().length(2).default("US").describe("Two-letter region code for where the ads are shown. Default US."),
|
|
4741
|
+
maxAds: import_zod3.z.number().int().min(1).max(200).default(50).describe("Maximum creatives to inspect and hydrate. Default 50, maximum 200. Prefer 25-50 for focused scans.")
|
|
4742
|
+
};
|
|
4743
|
+
var GoogleAdsTranscribeInputSchema = {
|
|
4744
|
+
videoUrl: import_zod3.z.string().url().describe("Direct googlevideo.com playback URL from a google_ads_page_intel video ad result (the videoUrl field). For YouTube-hosted ads use youtube_transcribe with the returned youtubeVideoId instead.")
|
|
4745
|
+
};
|
|
4582
4746
|
var InstagramProfileContentInputSchema = {
|
|
4583
4747
|
handle: import_zod3.z.string().min(1).optional().describe("Instagram handle, with or without @. Provide handle or url."),
|
|
4584
4748
|
url: import_zod3.z.string().url().optional().describe("Instagram profile URL, e.g. https://www.instagram.com/nasaartemis/. Provide handle or url."),
|
|
@@ -4789,7 +4953,8 @@ var OrganicResultOutput = import_zod3.z.object({
|
|
|
4789
4953
|
});
|
|
4790
4954
|
var AiOverviewOutput = import_zod3.z.object({
|
|
4791
4955
|
detected: import_zod3.z.boolean(),
|
|
4792
|
-
text: NullableString2
|
|
4956
|
+
text: NullableString2,
|
|
4957
|
+
shareUrl: NullableString2.optional()
|
|
4793
4958
|
}).nullable();
|
|
4794
4959
|
var EntityIdsOutput = import_zod3.z.object({
|
|
4795
4960
|
entities: import_zod3.z.array(import_zod3.z.object({
|
|
@@ -5023,6 +5188,40 @@ var FacebookPageIntelOutputSchema = {
|
|
|
5023
5188
|
variations: import_zod3.z.number().int().nullable()
|
|
5024
5189
|
}))
|
|
5025
5190
|
};
|
|
5191
|
+
var GoogleAdsSearchOutputSchema = {
|
|
5192
|
+
query: import_zod3.z.string(),
|
|
5193
|
+
region: import_zod3.z.string(),
|
|
5194
|
+
advertiserCount: import_zod3.z.number().int().min(0),
|
|
5195
|
+
advertisers: import_zod3.z.array(import_zod3.z.object({
|
|
5196
|
+
advertiserId: NullableString2,
|
|
5197
|
+
name: NullableString2,
|
|
5198
|
+
domain: NullableString2,
|
|
5199
|
+
approxAdCount: import_zod3.z.number().int().nullable(),
|
|
5200
|
+
detailUrl: NullableString2
|
|
5201
|
+
}))
|
|
5202
|
+
};
|
|
5203
|
+
var GoogleAdsPageIntelOutputSchema = {
|
|
5204
|
+
advertiserId: NullableString2,
|
|
5205
|
+
advertiserName: NullableString2,
|
|
5206
|
+
domain: NullableString2,
|
|
5207
|
+
region: import_zod3.z.string(),
|
|
5208
|
+
totalCreatives: import_zod3.z.number().int().min(0),
|
|
5209
|
+
videoCount: import_zod3.z.number().int().min(0),
|
|
5210
|
+
imageCount: import_zod3.z.number().int().min(0),
|
|
5211
|
+
textCount: import_zod3.z.number().int().min(0),
|
|
5212
|
+
ads: import_zod3.z.array(import_zod3.z.object({
|
|
5213
|
+
creativeId: NullableString2,
|
|
5214
|
+
advertiserId: NullableString2,
|
|
5215
|
+
format: NullableString2,
|
|
5216
|
+
lastShown: NullableString2,
|
|
5217
|
+
detailUrl: NullableString2,
|
|
5218
|
+
landingDomain: NullableString2,
|
|
5219
|
+
imageUrls: import_zod3.z.array(import_zod3.z.string()),
|
|
5220
|
+
youtubeVideoId: NullableString2,
|
|
5221
|
+
videoUrl: NullableString2,
|
|
5222
|
+
variations: import_zod3.z.number().int().nullable()
|
|
5223
|
+
}))
|
|
5224
|
+
};
|
|
5026
5225
|
var FacebookVideoTranscribeOutputSchema = {
|
|
5027
5226
|
sourceUrl: import_zod3.z.string().url(),
|
|
5028
5227
|
pageUrl: import_zod3.z.string().url(),
|
|
@@ -5165,6 +5364,17 @@ var FacebookAdTranscribeOutputSchema = {
|
|
|
5165
5364
|
videoUrl: import_zod3.z.string().url()
|
|
5166
5365
|
})
|
|
5167
5366
|
};
|
|
5367
|
+
var GoogleAdsTranscribeOutputSchema = {
|
|
5368
|
+
videoUrl: import_zod3.z.string().url(),
|
|
5369
|
+
wordCount: import_zod3.z.number().int().min(0),
|
|
5370
|
+
chunkCount: import_zod3.z.number().int().min(0),
|
|
5371
|
+
durationMs: import_zod3.z.number().nullable(),
|
|
5372
|
+
transcriptText: import_zod3.z.string(),
|
|
5373
|
+
chunks: import_zod3.z.array(TranscriptChunkOutput),
|
|
5374
|
+
resolvedInputs: import_zod3.z.object({
|
|
5375
|
+
videoUrl: import_zod3.z.string().url()
|
|
5376
|
+
})
|
|
5377
|
+
};
|
|
5168
5378
|
var CaptureSerpSnapshotOutputSchema = {
|
|
5169
5379
|
schemaVersion: import_zod3.z.literal("serp-intelligence.capture.v1"),
|
|
5170
5380
|
status: import_zod3.z.string(),
|
|
@@ -5809,6 +6019,27 @@ function registerPaaExtractorMcpTools(server2, executor, options = {}) {
|
|
|
5809
6019
|
outputSchema: FacebookAdTranscribeOutputSchema,
|
|
5810
6020
|
annotations: liveWebToolAnnotations("Facebook Ad Transcription")
|
|
5811
6021
|
}, async (input) => formatFacebookAdTranscribe(await executor.facebookAdTranscribe(input), input));
|
|
6022
|
+
server2.registerTool("google_ads_search", {
|
|
6023
|
+
title: "Google Ads Transparency Search",
|
|
6024
|
+
description: withReportNote("Search the Google Ads Transparency Center to find advertisers running Google ads (Search, Display, YouTube) by domain or brand/advertiser name. Pass a domain like getviktor.com to see every advertiser account pointing ads at that site, or an advertiser name. Returns advertisers with their advertiser ID and an approximate ad count. Use this to discover an advertiserId, then pass it (or the domain) to google_ads_page_intel for the actual ad creatives."),
|
|
6025
|
+
inputSchema: GoogleAdsSearchInputSchema,
|
|
6026
|
+
outputSchema: GoogleAdsSearchOutputSchema,
|
|
6027
|
+
annotations: liveWebToolAnnotations("Google Ads Transparency Search")
|
|
6028
|
+
}, async (input) => formatGoogleAdsSearch(await executor.googleAdsSearch(input), input));
|
|
6029
|
+
server2.registerTool("google_ads_page_intel", {
|
|
6030
|
+
title: "Google Ads Advertiser Intel",
|
|
6031
|
+
description: withReportNote("Harvest an advertiser's ads from the Google Ads Transparency Center when the user wants a competitor's Google/YouTube ad creatives, copy angles, image URLs, or video ads. Accepts an advertiserId (from google_ads_search) or a domain directly. Returns each creative's format (text/image/video), image URLs, landing info, a detail URL, and \u2014 for video ads \u2014 the YouTube video ID and/or a direct video URL ready for transcription. Use google_ads_search first when you only have a brand name. Transcribe video ads with google_ads_transcribe (video URL) or youtube_transcribe (YouTube ID)."),
|
|
6032
|
+
inputSchema: GoogleAdsPageIntelInputSchema,
|
|
6033
|
+
outputSchema: GoogleAdsPageIntelOutputSchema,
|
|
6034
|
+
annotations: liveWebToolAnnotations("Google Ads Advertiser Intel")
|
|
6035
|
+
}, async (input) => formatGoogleAdsPageIntel(await executor.googleAdsPageIntel(input), input));
|
|
6036
|
+
server2.registerTool("google_ads_transcribe", {
|
|
6037
|
+
title: "Google Ad Video Transcription",
|
|
6038
|
+
description: "Transcribe audio from a Google video ad. Use this when google_ads_page_intel returned a direct videoUrl (a googlevideo.com playback URL) for a video creative and the user asks what the ad says or wants its claims/messaging. Returns full transcript, timestamped chunks, and word count. For YouTube-hosted ads, pass the returned youtubeVideoId to youtube_transcribe instead; run google_ads_page_intel first when you only have an advertiser/domain.",
|
|
6039
|
+
inputSchema: GoogleAdsTranscribeInputSchema,
|
|
6040
|
+
outputSchema: GoogleAdsTranscribeOutputSchema,
|
|
6041
|
+
annotations: liveWebToolAnnotations("Google Ad Video Transcription")
|
|
6042
|
+
}, async (input) => formatGoogleAdsTranscribe(await executor.googleAdsTranscribe(input), input));
|
|
5812
6043
|
server2.registerTool("facebook_video_transcribe", {
|
|
5813
6044
|
title: "Facebook Organic Video Transcription",
|
|
5814
6045
|
description: withReportNote("Transcribe audio from an organic Facebook reel, video, watch, post, or share URL, including fb.watch links. Use this when the user pastes a normal Facebook video page URL and wants the transcript or downloadable MP4. Renders the Facebook page in a browser, selects the best matching public Facebook CDN MP4 URL from page state, then returns sourceUrl, resolved pageUrl, videoId, ownerName, selectedQuality, bitrate, videoDurationSec, extracted MP4 URL, full transcript, and timestamped chunks."),
|