mcp-scraper 0.4.2 → 0.4.4
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 +2386 -1816
- 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 +164 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-NVUBFCJK.js → chunk-4ZZWFI6L.js} +2 -2
- package/dist/{chunk-4MFYMUIF.js → chunk-5LO6EHEH.js} +25 -3
- package/dist/chunk-5LO6EHEH.js.map +1 -0
- package/dist/chunk-TZRPP45I.js +7 -0
- package/dist/chunk-TZRPP45I.js.map +1 -0
- package/dist/{chunk-GFY6XHZS.js → chunk-Z34NGK64.js} +165 -2
- package/dist/chunk-Z34NGK64.js.map +1 -0
- package/dist/{server-6IYQQK6X.js → server-IKT3QVFB.js} +556 -198
- package/dist/server-IKT3QVFB.js.map +1 -0
- package/dist/{site-extract-repository-4NVO5KQA.js → site-extract-repository-THBVEXMP.js} +3 -3
- package/dist/{worker-7XRZNLKB.js → worker-YHKUJR5P.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-4MFYMUIF.js.map +0 -1
- package/dist/chunk-7HICT4GY.js +0 -7
- package/dist/chunk-7HICT4GY.js.map +0 -1
- package/dist/chunk-GFY6XHZS.js.map +0 -1
- package/dist/server-6IYQQK6X.js.map +0 -1
- /package/dist/{chunk-NVUBFCJK.js.map → chunk-4ZZWFI6L.js.map} +0 -0
- /package/dist/{site-extract-repository-4NVO5KQA.js.map → site-extract-repository-THBVEXMP.js.map} +0 -0
- /package/dist/{worker-7XRZNLKB.js.map → worker-YHKUJR5P.js.map} +0 -0
|
@@ -102,7 +102,7 @@ function renderInstallTerminal(options) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// src/version.ts
|
|
105
|
-
var PACKAGE_VERSION = "0.4.
|
|
105
|
+
var PACKAGE_VERSION = "0.4.4";
|
|
106
106
|
|
|
107
107
|
// bin/mcp-scraper-install.ts
|
|
108
108
|
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('(128 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 toolRow('memory', ['memory-put', 'memory-get', 'memory-search', 'list-vaults', 'record-fact', 'list-scheduled-actions'], 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.4.2'\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":[]}
|
|
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('(128 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 toolRow('memory', ['memory-put', 'memory-get', 'memory-search', 'list-vaults', 'record-fact', 'list-scheduled-actions'], 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.4.4'\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-5HNHYUJ5.js";
|
|
5
5
|
import {
|
|
6
6
|
PACKAGE_VERSION
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-TZRPP45I.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;
|
|
@@ -297,6 +297,12 @@ var HttpMcpToolExecutor = class {
|
|
|
297
297
|
mapsSearch(input) {
|
|
298
298
|
return this.call("/maps/search", input);
|
|
299
299
|
}
|
|
300
|
+
trustpilotReviews(input) {
|
|
301
|
+
return this.call("/trustpilot/reviews", input, this.httpTimeoutOverrideMs ?? 3e5);
|
|
302
|
+
}
|
|
303
|
+
g2Reviews(input) {
|
|
304
|
+
return this.call("/g2/reviews", input, this.httpTimeoutOverrideMs ?? 3e5);
|
|
305
|
+
}
|
|
300
306
|
directoryWorkflow(input) {
|
|
301
307
|
const cityCount = typeof input.maxCities === "number" ? input.maxCities : 25;
|
|
302
308
|
const concurrency = typeof input.concurrency === "number" && input.concurrency > 0 ? input.concurrency : 5;
|
|
@@ -474,7 +480,7 @@ render();
|
|
|
474
480
|
}
|
|
475
481
|
|
|
476
482
|
// src/version.ts
|
|
477
|
-
var PACKAGE_VERSION = "0.4.
|
|
483
|
+
var PACKAGE_VERSION = "0.4.4";
|
|
478
484
|
|
|
479
485
|
// src/mcp/browser-agent-tool-schemas.ts
|
|
480
486
|
var import_zod = require("zod");
|
|
@@ -4111,6 +4117,97 @@ ${rows}`,
|
|
|
4111
4117
|
}
|
|
4112
4118
|
};
|
|
4113
4119
|
}
|
|
4120
|
+
function formatTrustpilotReviews(raw, input) {
|
|
4121
|
+
const parsed = parseData(raw);
|
|
4122
|
+
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
4123
|
+
const d = parsed.data;
|
|
4124
|
+
const domain = d.domain ?? input.domain;
|
|
4125
|
+
const reviewUrl = d.reviewUrl;
|
|
4126
|
+
const extractedAt = d.extractedAt;
|
|
4127
|
+
const requestedMaxPages = d.requestedMaxPages ?? input.maxPages ?? 5;
|
|
4128
|
+
const pagesFetched = d.pagesFetched;
|
|
4129
|
+
const reviews = d.reviews ?? [];
|
|
4130
|
+
const durationMs = d.durationMs;
|
|
4131
|
+
const rows = reviews.map((r) => {
|
|
4132
|
+
const stars = r.rating != null ? "\u2605".repeat(r.rating) + "\u2606".repeat(r.ratingScale - r.rating) : "\u2014";
|
|
4133
|
+
const answer = r.body[0]?.answer ?? "";
|
|
4134
|
+
return `| ${cell(r.reviewer.name ?? "Anonymous")} | ${stars} | ${cell(r.title)} | ${cell(r.date ? r.date.slice(0, 10) : null)} | ${r.flags.origin ?? "\u2014"} | ${r.flags.companyReplied ? "yes" : "no"} | ${cell(truncate(answer, 100))} |`;
|
|
4135
|
+
}).join("\n");
|
|
4136
|
+
const full = [
|
|
4137
|
+
`# Trustpilot Reviews: ${domain}`,
|
|
4138
|
+
`**Collected:** ${reviews.length} review${reviews.length === 1 ? "" : "s"} across ${pagesFetched ?? 0}/${requestedMaxPages} page${requestedMaxPages === 1 ? "" : "s"}`,
|
|
4139
|
+
reviewUrl ? `**Source:** ${reviewUrl}` : null,
|
|
4140
|
+
`
|
|
4141
|
+
## Reviews
|
|
4142
|
+
| Reviewer | Rating | Title | Date | Origin | Company Replied | Excerpt |
|
|
4143
|
+
|----------|--------|-------|------|--------|------------------|---------|
|
|
4144
|
+
${rows}`,
|
|
4145
|
+
`
|
|
4146
|
+
---
|
|
4147
|
+
\u{1F4A1} **Note:** sampling tool, default 5 pages (~100 reviews), max 50. For full-corpus export use Trustpilot's official Business API.`,
|
|
4148
|
+
durationMs != null ? `
|
|
4149
|
+
*Extracted in ${(durationMs / 1e3).toFixed(1)}s*` : null
|
|
4150
|
+
].filter(Boolean).join("\n");
|
|
4151
|
+
return {
|
|
4152
|
+
...oneBlock(full),
|
|
4153
|
+
structuredContent: {
|
|
4154
|
+
domain,
|
|
4155
|
+
reviewUrl: reviewUrl ?? null,
|
|
4156
|
+
extractedAt: extractedAt ?? null,
|
|
4157
|
+
requestedMaxPages,
|
|
4158
|
+
pagesFetched: pagesFetched ?? 0,
|
|
4159
|
+
reviewCount: reviews.length,
|
|
4160
|
+
reviews,
|
|
4161
|
+
durationMs: durationMs ?? 0
|
|
4162
|
+
}
|
|
4163
|
+
};
|
|
4164
|
+
}
|
|
4165
|
+
function formatG2Reviews(raw, input) {
|
|
4166
|
+
const parsed = parseData(raw);
|
|
4167
|
+
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
4168
|
+
const d = parsed.data;
|
|
4169
|
+
const product = d.product ?? input.product;
|
|
4170
|
+
const reviewUrl = d.reviewUrl;
|
|
4171
|
+
const extractedAt = d.extractedAt;
|
|
4172
|
+
const requestedMaxPages = d.requestedMaxPages ?? input.maxPages ?? 5;
|
|
4173
|
+
const pagesFetched = d.pagesFetched;
|
|
4174
|
+
const reviews = d.reviews ?? [];
|
|
4175
|
+
const durationMs = d.durationMs;
|
|
4176
|
+
const rows = reviews.map((r) => {
|
|
4177
|
+
const stars = r.rating != null ? "\u2605".repeat(Math.round(r.rating)) + "\u2606".repeat(r.ratingScale - Math.round(r.rating)) : "\u2014";
|
|
4178
|
+
const verified = [r.flags.currentUser ? "current-user" : null, r.flags.validated ? "validated" : null, r.flags.incentivized ? "incentivized" : null].filter(Boolean).join(", ") || "\u2014";
|
|
4179
|
+
const firstAnswer = r.body[0]?.answer ?? "";
|
|
4180
|
+
return `| ${cell(r.reviewer.name ?? "Anonymous")} | ${cell(r.reviewer.title)} | ${cell(r.reviewer.companySegment)} | ${stars} | ${cell(r.title)} | ${cell(r.date ? r.date.slice(0, 10) : null)} | ${r.flags.origin ?? "\u2014"} | ${verified} | ${cell(truncate(firstAnswer, 100))} |`;
|
|
4181
|
+
}).join("\n");
|
|
4182
|
+
const full = [
|
|
4183
|
+
`# G2 Reviews: ${product}`,
|
|
4184
|
+
`**Collected:** ${reviews.length} review${reviews.length === 1 ? "" : "s"} across ${pagesFetched ?? 0}/${requestedMaxPages} page${requestedMaxPages === 1 ? "" : "s"}`,
|
|
4185
|
+
reviewUrl ? `**Source:** ${reviewUrl}` : null,
|
|
4186
|
+
`
|
|
4187
|
+
## Reviews
|
|
4188
|
+
| Reviewer | Title | Company Size | Rating | Review Title | Date | Origin | Verification | Excerpt |
|
|
4189
|
+
|----------|-------|---------------|--------|--------------|------|--------|---------------|---------|
|
|
4190
|
+
${rows}`,
|
|
4191
|
+
`
|
|
4192
|
+
---
|
|
4193
|
+
\u{1F4A1} **Note:** sampling tool, default 5 pages (~50 reviews), max 50. Each review's full body has up to 3 Q&A sections (like/dislike/problems solved) \u2014 see structuredContent.reviews[].body for the complete text. For full-corpus export use G2's official API.`,
|
|
4194
|
+
durationMs != null ? `
|
|
4195
|
+
*Extracted in ${(durationMs / 1e3).toFixed(1)}s*` : null
|
|
4196
|
+
].filter(Boolean).join("\n");
|
|
4197
|
+
return {
|
|
4198
|
+
...oneBlock(full),
|
|
4199
|
+
structuredContent: {
|
|
4200
|
+
product,
|
|
4201
|
+
reviewUrl: reviewUrl ?? null,
|
|
4202
|
+
extractedAt: extractedAt ?? null,
|
|
4203
|
+
requestedMaxPages,
|
|
4204
|
+
pagesFetched: pagesFetched ?? 0,
|
|
4205
|
+
reviewCount: reviews.length,
|
|
4206
|
+
reviews,
|
|
4207
|
+
durationMs: durationMs ?? 0
|
|
4208
|
+
}
|
|
4209
|
+
};
|
|
4210
|
+
}
|
|
4114
4211
|
async function formatDirectoryWorkflow(raw, input, ctx) {
|
|
4115
4212
|
const parsed = parseData(raw);
|
|
4116
4213
|
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
@@ -5070,6 +5167,38 @@ var MapsPlaceIntelInputSchema = {
|
|
|
5070
5167
|
maxReviews: import_zod3.z.number().int().min(1).max(500).default(50).describe("Max review cards when includeReviews is true. Default 50, maximum 500."),
|
|
5071
5168
|
includeServices: import_zod3.z.boolean().default(false).describe("Fetch the business's configured services list and areas-served list, when the profile has them. Adds one extra page visit; not present for every business.")
|
|
5072
5169
|
};
|
|
5170
|
+
var TrustpilotReviewsInputSchema = {
|
|
5171
|
+
domain: import_zod3.z.string().min(1).describe(`The business's domain as it appears in its Trustpilot URL, e.g. "www.bhphotovideo.com" (include the www. if the site uses it \u2014 pass the domain as-is, do not guess).`),
|
|
5172
|
+
maxPages: import_zod3.z.number().int().min(1).max(50).default(5).describe("Review pages to fetch (~20 reviews per page). Default 5 (~100 reviews). Maximum 50 \u2014 large companies can have 1,000+ pages; this tool is for sampling, not full-corpus export.")
|
|
5173
|
+
};
|
|
5174
|
+
var G2ReviewsInputSchema = {
|
|
5175
|
+
product: import_zod3.z.string().min(1).describe(`The product's G2 URL slug, e.g. "notion" from g2.com/products/notion/reviews (also accepts a full g2.com product URL).`),
|
|
5176
|
+
maxPages: import_zod3.z.number().int().min(1).max(50).default(5).describe("Review pages to fetch (~10 reviews per page). Default 5 (~50 reviews). Maximum 50 \u2014 this tool is for sampling, not full-corpus export.")
|
|
5177
|
+
};
|
|
5178
|
+
var ReviewCardSchema = import_zod3.z.object({
|
|
5179
|
+
source: import_zod3.z.enum(["trustpilot", "g2"]),
|
|
5180
|
+
sourceReviewId: import_zod3.z.string().nullable(),
|
|
5181
|
+
reviewUrl: import_zod3.z.string().nullable(),
|
|
5182
|
+
reviewer: import_zod3.z.object({
|
|
5183
|
+
name: import_zod3.z.string().nullable(),
|
|
5184
|
+
profileId: import_zod3.z.string().nullable(),
|
|
5185
|
+
title: import_zod3.z.string().nullable(),
|
|
5186
|
+
companySegment: import_zod3.z.string().nullable()
|
|
5187
|
+
}),
|
|
5188
|
+
rating: import_zod3.z.number().nullable(),
|
|
5189
|
+
ratingScale: import_zod3.z.number(),
|
|
5190
|
+
title: import_zod3.z.string().nullable(),
|
|
5191
|
+
date: import_zod3.z.string().nullable(),
|
|
5192
|
+
body: import_zod3.z.array(import_zod3.z.object({ question: import_zod3.z.string().nullable(), answer: import_zod3.z.string() })),
|
|
5193
|
+
truncated: import_zod3.z.boolean(),
|
|
5194
|
+
flags: import_zod3.z.object({
|
|
5195
|
+
origin: import_zod3.z.string().nullable(),
|
|
5196
|
+
incentivized: import_zod3.z.boolean().nullable(),
|
|
5197
|
+
validated: import_zod3.z.boolean().nullable(),
|
|
5198
|
+
currentUser: import_zod3.z.boolean().nullable(),
|
|
5199
|
+
companyReplied: import_zod3.z.boolean().nullable()
|
|
5200
|
+
})
|
|
5201
|
+
});
|
|
5073
5202
|
var MapsSearchInputSchema = {
|
|
5074
5203
|
query: import_zod3.z.string().min(1).describe('Business category, niche, or search term, e.g. "roofers". Do not include location here \u2014 use location instead.'),
|
|
5075
5204
|
location: import_zod3.z.string().optional().describe('City, region, country, or service area, e.g. "Denver, CO".'),
|
|
@@ -5386,6 +5515,26 @@ var MapsPlaceIntelOutputSchema = {
|
|
|
5386
5515
|
areasServed: import_zod3.z.array(import_zod3.z.string()),
|
|
5387
5516
|
servicesStatus: import_zod3.z.string()
|
|
5388
5517
|
};
|
|
5518
|
+
var TrustpilotReviewsOutputSchema = {
|
|
5519
|
+
domain: import_zod3.z.string(),
|
|
5520
|
+
reviewUrl: import_zod3.z.string(),
|
|
5521
|
+
extractedAt: import_zod3.z.string(),
|
|
5522
|
+
requestedMaxPages: import_zod3.z.number().int(),
|
|
5523
|
+
pagesFetched: import_zod3.z.number().int(),
|
|
5524
|
+
reviewCount: import_zod3.z.number().int(),
|
|
5525
|
+
reviews: import_zod3.z.array(ReviewCardSchema),
|
|
5526
|
+
durationMs: import_zod3.z.number()
|
|
5527
|
+
};
|
|
5528
|
+
var G2ReviewsOutputSchema = {
|
|
5529
|
+
product: import_zod3.z.string(),
|
|
5530
|
+
reviewUrl: import_zod3.z.string(),
|
|
5531
|
+
extractedAt: import_zod3.z.string(),
|
|
5532
|
+
requestedMaxPages: import_zod3.z.number().int(),
|
|
5533
|
+
pagesFetched: import_zod3.z.number().int(),
|
|
5534
|
+
reviewCount: import_zod3.z.number().int(),
|
|
5535
|
+
reviews: import_zod3.z.array(ReviewCardSchema),
|
|
5536
|
+
durationMs: import_zod3.z.number()
|
|
5537
|
+
};
|
|
5389
5538
|
var CreditsInfoOutputSchema = {
|
|
5390
5539
|
balanceCredits: import_zod3.z.number().nullable(),
|
|
5391
5540
|
matchedCost: import_zod3.z.object({
|
|
@@ -6437,6 +6586,20 @@ function registerPaaExtractorMcpTools(server2, executor, options = {}) {
|
|
|
6437
6586
|
outputSchema: recordOutputSchema("maps_search", MapsSearchOutputSchema),
|
|
6438
6587
|
annotations: liveWebToolAnnotations("Google Maps Business Search")
|
|
6439
6588
|
}, async (input) => formatMapsSearch(await executor.mapsSearch(input), input));
|
|
6589
|
+
server2.registerTool("trustpilot_reviews", {
|
|
6590
|
+
title: "Trustpilot Review Harvest",
|
|
6591
|
+
description: "Extract customer reviews for a business from Trustpilot \u2014 reviewer, rating, title, body, date, invited/organic origin, company-reply flag. Sampling tool, not a full-corpus export: default 5 pages (~100 reviews), max 50 pages. For bulk/complete extraction across thousands of pages, use Trustpilot's official Business API instead.",
|
|
6592
|
+
inputSchema: TrustpilotReviewsInputSchema,
|
|
6593
|
+
outputSchema: recordOutputSchema("trustpilot_reviews", TrustpilotReviewsOutputSchema),
|
|
6594
|
+
annotations: liveWebToolAnnotations("Trustpilot Review Harvest")
|
|
6595
|
+
}, async (input) => formatTrustpilotReviews(await executor.trustpilotReviews(input), input));
|
|
6596
|
+
server2.registerTool("g2_reviews", {
|
|
6597
|
+
title: "G2 Review Harvest",
|
|
6598
|
+
description: `Extract customer reviews for a software product from G2 \u2014 reviewer (name, job title, company size), rating, title, date, structured like/dislike/problems-solved Q&A body, and verification flags (incentivized, validated, current user, invite source). Sampling tool, not a full-corpus export: default 5 pages (~50 reviews), max 50 pages. Requires the product's G2 URL slug (e.g. "notion"), not a company name. For bulk/complete extraction, use G2's official API instead.`,
|
|
6599
|
+
inputSchema: G2ReviewsInputSchema,
|
|
6600
|
+
outputSchema: recordOutputSchema("g2_reviews", G2ReviewsOutputSchema),
|
|
6601
|
+
annotations: liveWebToolAnnotations("G2 Review Harvest")
|
|
6602
|
+
}, async (input) => formatG2Reviews(await executor.g2Reviews(input), input));
|
|
6440
6603
|
server2.registerTool("directory_workflow", {
|
|
6441
6604
|
title: "Directory Workflow: Markets + Maps",
|
|
6442
6605
|
description: `Build directory/prospecting datasets: selects US city markets from Census population data, optionally joins configured ZIP groups, then runs Google Maps business searches per city in parallel. Use for "all cities over 100k population in a state" or market+Maps workflows. ${fileBehavior("Saves a CSV of results per city.", "Large results are stored as a retrievable artifact \u2014 you get an inline summary plus an artifactId for report_artifact_read.")}`,
|