mcp-scraper 0.3.20 → 0.3.22

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.
Files changed (34) hide show
  1. package/dist/bin/api-server.cjs +163 -155
  2. package/dist/bin/api-server.cjs.map +1 -1
  3. package/dist/bin/api-server.js +3 -3
  4. package/dist/bin/mcp-scraper-cli.cjs +18 -1
  5. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +18 -1
  7. package/dist/bin/mcp-scraper-cli.js.map +1 -1
  8. package/dist/bin/mcp-scraper-install.cjs +1 -1
  9. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  10. package/dist/bin/mcp-scraper-install.js +1 -1
  11. package/dist/bin/mcp-stdio-server.cjs +1 -1
  12. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  13. package/dist/bin/mcp-stdio-server.js +2 -2
  14. package/dist/chunk-2IXMOXDH.js +7 -0
  15. package/dist/chunk-2IXMOXDH.js.map +1 -0
  16. package/dist/{chunk-IORA5BFI.js → chunk-3KYRG7O7.js} +24 -2
  17. package/dist/chunk-3KYRG7O7.js.map +1 -0
  18. package/dist/{chunk-YZAYOFJV.js → chunk-7PQFU7TV.js} +13 -20
  19. package/dist/chunk-7PQFU7TV.js.map +1 -0
  20. package/dist/{chunk-6N6USFMH.js → chunk-FEUCMGIJ.js} +2 -2
  21. package/dist/{db-ZWV4Y43C.js → db-EG5ETPTY.js} +4 -2
  22. package/dist/{server-NKZW2SEV.js → server-G7PVVOH3.js} +138 -141
  23. package/dist/server-G7PVVOH3.js.map +1 -0
  24. package/dist/{worker-PR7GODIV.js → worker-AITQTXHM.js} +3 -3
  25. package/docs/mcp-tool-manifest.generated.json +1 -1
  26. package/package.json +1 -1
  27. package/dist/chunk-IORA5BFI.js.map +0 -1
  28. package/dist/chunk-XLHBBA3U.js +0 -7
  29. package/dist/chunk-XLHBBA3U.js.map +0 -1
  30. package/dist/chunk-YZAYOFJV.js.map +0 -1
  31. package/dist/server-NKZW2SEV.js.map +0 -1
  32. /package/dist/{chunk-6N6USFMH.js.map → chunk-FEUCMGIJ.js.map} +0 -0
  33. /package/dist/{db-ZWV4Y43C.js.map → db-EG5ETPTY.js.map} +0 -0
  34. /package/dist/{worker-PR7GODIV.js.map → worker-AITQTXHM.js.map} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  } from "../chunk-H2R232HK.js";
10
10
  import {
11
11
  PACKAGE_VERSION
12
- } from "../chunk-XLHBBA3U.js";
12
+ } from "../chunk-2IXMOXDH.js";
13
13
  import "../chunk-LFATOGDF.js";
14
14
 
15
15
  // src/cli/human-cli.ts
@@ -500,6 +500,23 @@ function buildHumanCli() {
500
500
  result.next_step ?? "Complete checkout, then retry the MCP request."
501
501
  ].join("\n"), false);
502
502
  });
503
+ billing.command("subscribe <tier>").description("Subscribe to a plan (starter | growth | scale) via a hosted Stripe checkout link.").option("--api-key <key>", "MCP Scraper API key").option("--api-url <url>", "MCP Scraper API URL", "https://mcpscraper.dev").option("--json", "Print machine-readable JSON").option("--no-open", "Print the checkout URL without opening a browser").action(async (tier, opts) => {
504
+ const result = await apiRequest("/billing/subscribe/terminal-checkout", "POST", opts, { tier: String(tier).toLowerCase() });
505
+ if (opts.json) {
506
+ writeOutput(result, true);
507
+ return;
508
+ }
509
+ if (result.updated) {
510
+ writeOutput(result.message ?? `Switched to ${result.tier}.`, false);
511
+ return;
512
+ }
513
+ const opened = opts.open !== false && !!result.checkout_url && openExternalUrl(result.checkout_url);
514
+ writeOutput([
515
+ `Plan: ${result.label ?? tier} \u2014 $${result.monthly_usd}/mo \xB7 ${result.credits_per_month?.toLocaleString()} credits/mo \xB7 ${result.concurrency} concurrency${result.intro ? ` \xB7 ${result.intro}` : ""}`,
516
+ opened ? `Opened checkout: ${result.checkout_url}` : `Checkout URL: ${result.checkout_url}`,
517
+ result.next_step ?? "Complete payment in the browser."
518
+ ].join("\n"), false);
519
+ });
503
520
  const agent = program.command("agent").description("Generate AI-agent install configs and workflow prompts.");
504
521
  agent.command("install <host>").description("Print or apply install/config instructions for codex, claude/claude-code, or claude-desktop.").option("--api-key <key>", "API key to place in generated config").option("--package <spec>", "npm package spec", "mcp-scraper@latest").option("--browser-profile <name>", "Default saved browser profile for browser_open sessions.").option("--save-browser-profile-changes", "Persist cookies and browser storage back to the named browser profile when sessions close").option("--apply", "Apply the config to this client when supported. For Claude Code, this upserts the user-scope mcp-scraper server.").option("--json", "Print machine-readable JSON").action(async (hostInput, opts) => {
505
522
  const host = normalizeAgentHost(hostInput);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/human-cli.ts","../../src/cli/agent-config.ts","../../src/cli/doctor.ts","../../src/cli/prompts.ts","../../bin/mcp-scraper-cli.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { basename, join } from 'node:path'\nimport { PACKAGE_VERSION } from '../version.js'\nimport {\n claudeMcpAddArgs,\n claudeMcpRemoveArgs,\n normalizeAgentHost,\n renderAgentInstall,\n type AgentHost,\n} from './agent-config.js'\nimport { renderDoctor, runDoctor } from './doctor.js'\nimport { listPrompts, renderPrompt } from './prompts.js'\nimport { workflowOutputBaseDir } from '../workflows/artifact-writer.js'\nimport { findWorkflowReport, listWorkflowDefinitions, listWorkflowReports, openWorkflowReport, runWorkflow } from '../workflows/registry.js'\n\nfunction numberOpt(value: unknown): number | undefined {\n if (value === undefined || value === null || value === '') return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nfunction booleanOpt(value: unknown): boolean | undefined {\n if (value === undefined) return undefined\n if (typeof value === 'boolean') return value\n if (value === 'true') return true\n if (value === 'false') return false\n return undefined\n}\n\nfunction compactInput(input: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined))\n}\n\nfunction workflowInput(id: string, opts: Record<string, unknown>): Record<string, unknown> {\n if (id === 'agent-packet' || id === 'serp-comparison' || id === 'ai-overview-language') {\n return compactInput({\n keyword: opts.keyword,\n domain: opts.domain,\n url: opts.url,\n location: opts.location,\n maxResults: numberOpt(opts.maxResults),\n maxQuestions: numberOpt(opts.maxQuestions),\n extractTop: numberOpt(opts.extractTop),\n includeSerp: opts.serp === false ? false : undefined,\n includePaa: opts.paa === false ? false : undefined,\n includeAiOverview: booleanOpt(opts.includeAiOverview),\n returnPartial: opts.returnPartial === false ? false : undefined,\n })\n }\n\n if (id === 'paa-expansion-brief') {\n return compactInput({\n keyword: opts.keyword,\n location: opts.location,\n maxQuestions: numberOpt(opts.maxQuestions),\n depth: numberOpt(opts.depth),\n returnPartial: opts.returnPartial === false ? false : undefined,\n })\n }\n\n if (id === 'directory' || id === 'local-competitive-audit' || id === 'map-comparison') {\n return compactInput({\n query: opts.query,\n location: opts.location,\n state: opts.state,\n minPopulation: numberOpt(opts.minPop ?? opts.minPopulation),\n maxCities: numberOpt(opts.maxCities),\n maxResultsPerCity: numberOpt(opts.perCity ?? opts.maxResultsPerCity ?? opts.maxResults),\n concurrency: numberOpt(opts.concurrency),\n proxyMode: opts.proxyMode,\n hydrateTop: id === 'local-competitive-audit' || id === 'map-comparison' ? numberOpt(opts.hydrateTop) : undefined,\n maxReviews: id === 'local-competitive-audit' || id === 'map-comparison' ? numberOpt(opts.reviews ?? opts.maxReviews) : undefined,\n returnPartial: opts.returnPartial === false ? false : undefined,\n })\n }\n\n return compactInput(opts)\n}\n\nfunction writeOutput(data: unknown, json: boolean | undefined): void {\n if (json) {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`)\n } else if (typeof data === 'string') {\n process.stdout.write(`${data}\\n`)\n } else {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`)\n }\n}\n\nfunction maskSecrets(value: string): string {\n return value.replace(/sk_[A-Za-z0-9_-]+/g, 'sk_***')\n}\n\nfunction runLocalCommand(command: string, args: string[]): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolve) => {\n const child = spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n const stdout: Buffer[] = []\n const stderr: Buffer[] = []\n let settled = false\n const done = (result: { code: number; stdout: string; stderr: string }) => {\n if (settled) return\n settled = true\n resolve(result)\n }\n child.stdout.on('data', chunk => stdout.push(Buffer.from(chunk)))\n child.stderr.on('data', chunk => stderr.push(Buffer.from(chunk)))\n child.on('error', err => {\n done({ code: 127, stdout: '', stderr: err.message })\n })\n child.on('close', code => {\n done({\n code: typeof code === 'number' ? code : 1,\n stdout: Buffer.concat(stdout).toString('utf8'),\n stderr: Buffer.concat(stderr).toString('utf8'),\n })\n })\n })\n}\n\nfunction cadenceOpt(opts: Record<string, unknown>): 'daily' | 'weekly' | 'monthly' {\n if (opts.daily) return 'daily'\n if (opts.monthly) return 'monthly'\n return 'weekly'\n}\n\nfunction apiOptions(opts: Record<string, unknown>): { apiUrl: string; apiKey: string } {\n const apiKey = String(opts.apiKey ?? process.env.MCP_SCRAPER_API_KEY ?? '').trim()\n if (!apiKey) throw new Error('MCP_SCRAPER_API_KEY is required. Pass --api-key or set the environment variable.')\n return {\n apiUrl: String(opts.apiUrl ?? process.env.MCP_SCRAPER_API_URL ?? 'https://mcpscraper.dev').replace(/\\/$/, ''),\n apiKey,\n }\n}\n\nfunction openExternalUrl(url: string): boolean {\n const command = process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'cmd'\n : 'xdg-open'\n const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url]\n try {\n const child = spawn(command, args, { detached: true, stdio: 'ignore' })\n child.unref()\n return true\n } catch {\n return false\n }\n}\n\nasync function apiRequest<T>(path: string, method: string, opts: Record<string, unknown>, body?: unknown): Promise<T> {\n const { apiUrl, apiKey } = apiOptions(opts)\n const res = await fetch(`${apiUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: body == null ? undefined : JSON.stringify(body),\n })\n const data = await res.json().catch(() => ({}))\n if (!res.ok) {\n const message = typeof (data as { error?: unknown }).error === 'string'\n ? (data as { error: string }).error\n : `API request failed with ${res.status}`\n throw new Error(message)\n }\n return data as T\n}\n\nfunction addWorkflowInputOptions(command: Command): Command {\n return command\n .option('--keyword <keyword>', 'Agent packet keyword')\n .option('--domain <domain>', 'Target domain')\n .option('--url <url>', 'Target page URL')\n .option('--location <location>', 'Target location')\n .option('--max-results <n>', 'Maximum SERP or Maps results')\n .option('--max-questions <n>', 'Maximum PAA questions')\n .option('--extract-top <n>', 'Top result pages or citation pages to extract')\n .option('--depth <n>', 'PAA expansion depth')\n .option('--no-serp', 'Skip SERP evidence for agent packet')\n .option('--no-paa', 'Skip PAA evidence for agent packet')\n .option('--query <query>', 'Business category or workflow query')\n .option('--state <state>', 'US state')\n .option('--min-pop <n>', 'Minimum city population')\n .option('--max-cities <n>', 'Maximum selected cities')\n .option('--per-city <n>', 'Maps results per city')\n .option('--concurrency <n>', 'City search concurrency')\n .option('--proxy-mode <mode>', 'Proxy mode: location, configured, or none')\n .option('--hydrate-top <n>', 'Profiles to hydrate per city for competitive audits')\n .option('--reviews <n>', 'Review cards to collect per hydrated profile')\n .option('--no-return-partial', 'Fail instead of writing partial artifacts')\n}\n\nexport function buildHumanCli(): Command {\n const program = new Command()\n program\n .name('mcp-scraper-cli')\n .description('Human CLI for MCP Scraper setup, workflows, reports, and agent-ready SEO artifacts.')\n .version(PACKAGE_VERSION)\n\n program.command('doctor')\n .description('Check setup, API key, output directory, package version, and recommended MCP config.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--output-dir <path>', 'Output directory to test')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const output = await runDoctor({ apiKey: opts.apiKey, apiUrl: opts.apiUrl, outputDir: opts.outputDir })\n writeOutput(opts.json ? output : renderDoctor(output), opts.json)\n if (!output.ok) process.exitCode = 1\n })\n\n const billing = program.command('billing').description('Inspect billing and start checkout flows.')\n const billingConcurrency = billing.command('concurrency').description('Manage MCP Scraper concurrency slots.')\n\n billingConcurrency.command('info')\n .description('Show current concurrency limit and extra-slot price.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await apiRequest<{ concurrency: Record<string, unknown> }>('/billing/credits', 'POST', opts, {})\n if (opts.json) writeOutput(result.concurrency, true)\n else {\n const upgrade = result.concurrency?.upgrade as Record<string, unknown> | undefined\n writeOutput([\n `Current limit: ${result.concurrency?.current_limit ?? 'unknown'} concurrent operations`,\n `Extra slots: ${result.concurrency?.current_extra_slots ?? 'unknown'}`,\n `Extra concurrency slot: ${upgrade?.price_label ?? '$5/month'}`,\n `Upgrade command: ${upgrade?.terminal_command ?? 'mcp-scraper-cli billing concurrency checkout'}`,\n ].join('\\n'), false)\n }\n })\n\n billingConcurrency.command('checkout')\n .description('Create a hosted Stripe checkout for one extra concurrency slot.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .option('--no-open', 'Print the checkout URL without opening a browser')\n .action(async (opts) => {\n const result = await apiRequest<{ checkout_url: string; price?: { price_label?: string }; next_step?: string }>('/billing/concurrency/terminal-checkout', 'POST', opts, {})\n if (opts.json) {\n writeOutput(result, true)\n return\n }\n const opened = opts.open !== false && openExternalUrl(result.checkout_url)\n writeOutput([\n `Extra concurrency slot: ${result.price?.price_label ?? '$5/month'}`,\n opened ? `Opened checkout: ${result.checkout_url}` : `Checkout URL: ${result.checkout_url}`,\n result.next_step ?? 'Complete checkout, then retry the MCP request.',\n ].join('\\n'), false)\n })\n\n const agent = program.command('agent').description('Generate AI-agent install configs and workflow prompts.')\n agent.command('install <host>')\n .description('Print or apply install/config instructions for codex, claude/claude-code, or claude-desktop.')\n .option('--api-key <key>', 'API key to place in generated config')\n .option('--package <spec>', 'npm package spec', 'mcp-scraper@latest')\n .option('--browser-profile <name>', 'Default saved browser profile for browser_open sessions.')\n .option('--save-browser-profile-changes', 'Persist cookies and browser storage back to the named browser profile when sessions close')\n .option('--apply', 'Apply the config to this client when supported. For Claude Code, this upserts the user-scope mcp-scraper server.')\n .option('--json', 'Print machine-readable JSON')\n .action(async (hostInput: AgentHost, opts) => {\n const host = normalizeAgentHost(hostInput)\n const apiKey = opts.apiKey ?? process.env.MCP_SCRAPER_API_KEY\n if (opts.apply) {\n if (host !== 'claude') throw new Error('--apply is currently supported for Claude Code only. Use host \"claude\" or \"claude-code\".')\n if (!apiKey?.trim()) {\n throw new Error('MCP_SCRAPER_API_KEY is required for --apply. Set it in the environment or pass --api-key.')\n }\n\n const configOptions = {\n apiKey,\n packageSpec: opts.package,\n browserProfileName: opts.browserProfile,\n browserProfileSaveChanges: opts.saveBrowserProfileChanges,\n }\n const remove = await runLocalCommand('claude', claudeMcpRemoveArgs())\n const add = await runLocalCommand('claude', claudeMcpAddArgs(configOptions))\n if (add.code !== 0) {\n const reason = maskSecrets([add.stderr, add.stdout].filter(Boolean).join('\\n').trim())\n throw new Error([\n 'Claude Code MCP registration failed.',\n reason || 'No error output returned.',\n 'Make sure Claude Code is installed and the `claude` command is on PATH.',\n ].join('\\n'))\n }\n const list = await runLocalCommand('claude', ['mcp', 'list'])\n const result = {\n host: 'claude',\n applied: true,\n replacedExisting: remove.code === 0,\n command: 'npx',\n args: ['-y', '-p', opts.package, 'mcp-scraper'],\n nextStep: 'Fully exit Claude Code, start a new Claude terminal, then run: claude mcp list',\n list: maskSecrets([list.stdout, list.stderr].filter(Boolean).join('\\n').trim()),\n }\n if (opts.json) {\n writeOutput(result, true)\n return\n }\n writeOutput([\n 'Applied Claude Code MCP config: mcp-scraper',\n remove.code === 0 ? 'Replaced existing mcp-scraper entry.' : 'No existing mcp-scraper entry found; added a new one.',\n 'Command: npx -y -p ' + opts.package + ' mcp-scraper',\n opts.browserProfile ? `Browser profile: ${opts.browserProfile}` : '',\n '',\n 'Next step: fully exit Claude Code, start a new Claude terminal, then run:',\n ' claude mcp list',\n '',\n result.list ? `Current Claude MCP list:\\n${result.list}` : '',\n ].filter(Boolean).join('\\n'), false)\n return\n }\n const text = renderAgentInstall(host, {\n apiKey: opts.apiKey,\n packageSpec: opts.package,\n browserProfileName: opts.browserProfile,\n browserProfileSaveChanges: opts.saveBrowserProfileChanges,\n })\n writeOutput(opts.json ? { host, text } : text, opts.json)\n })\n\n agent.command('prompt [name]')\n .description('Print an agent prompt template.')\n .option('--json', 'Print machine-readable JSON')\n .action((name: string | undefined, opts) => {\n if (!name) {\n writeOutput(opts.json ? { prompts: listPrompts() } : listPrompts().join('\\n'), opts.json)\n return\n }\n const text = renderPrompt(name)\n writeOutput(opts.json ? { name, text } : text, opts.json)\n })\n\n const workflow = program.command('workflow').description('Run named SEO workflows.')\n workflow.command('list')\n .description('List available workflows.')\n .option('--json', 'Print machine-readable JSON')\n .action((opts) => {\n const rows = listWorkflowDefinitions()\n if (opts.json) writeOutput({ workflows: rows }, true)\n else writeOutput(rows.map(row => `${row.id}\\t${row.title}\\n ${row.description}`).join('\\n'), false)\n })\n\n workflow.command('run <id>')\n .description('Run a workflow and save local artifacts.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON')\n .option('--keyword <keyword>', 'Agent packet keyword')\n .option('--domain <domain>', 'Target domain')\n .option('--url <url>', 'Target page URL')\n .option('--location <location>', 'Target location')\n .option('--max-results <n>', 'Maximum SERP or Maps results')\n .option('--max-questions <n>', 'Maximum PAA questions')\n .option('--extract-top <n>', 'Top result pages or citation pages to extract')\n .option('--depth <n>', 'PAA expansion depth')\n .option('--no-serp', 'Skip SERP evidence for agent packet')\n .option('--no-paa', 'Skip PAA evidence for agent packet')\n .option('--query <query>', 'Business category or workflow query')\n .option('--state <state>', 'US state')\n .option('--min-pop <n>', 'Minimum city population')\n .option('--max-cities <n>', 'Maximum selected cities')\n .option('--per-city <n>', 'Maps results per city')\n .option('--concurrency <n>', 'City search concurrency')\n .option('--proxy-mode <mode>', 'Proxy mode: location, configured, or none')\n .option('--hydrate-top <n>', 'Profiles to hydrate per city for competitive audits')\n .option('--reviews <n>', 'Review cards to collect per hydrated profile')\n .option('--no-return-partial', 'Fail instead of writing partial artifacts')\n .action(async (id: string, opts) => {\n const summary = await runWorkflow(id, workflowInput(id, opts), {\n apiKey: opts.apiKey,\n apiUrl: opts.apiUrl,\n outputDir: opts.outputDir,\n })\n if (opts.json) writeOutput(summary, true)\n else {\n writeOutput([\n `${summary.title}: ${summary.status}`,\n summary.summary,\n summary.reportPath ? `Report: ${summary.reportPath}` : '',\n summary.warnings.length ? `Warnings:\\n${summary.warnings.map(w => `- ${w}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n'), false)\n }\n })\n\n const report = program.command('report').description('List and open local workflow reports.')\n report.command('list')\n .description('List recent workflow reports.')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const reports = await listWorkflowReports(opts.outputDir)\n writeOutput(opts.json ? { reports } : reports.map(r => `${r.startedAt}\\t${r.workflow}\\t${r.status}\\t${r.reportPath ?? r.manifestPath}`).join('\\n'), opts.json)\n })\n report.command('path [id]')\n .description('Print a report path. Defaults to last.')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id = 'last', opts) => {\n const found = await findWorkflowReport(id, opts.outputDir)\n if (!found?.reportPath) throw new Error(`No report found for \"${id}\"`)\n writeOutput(opts.json ? { path: found.reportPath, run: found } : found.reportPath, opts.json)\n })\n report.command('open [id]')\n .description('Open a report. Defaults to last.')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON instead of opening')\n .action(async (id = 'last', opts) => {\n if (opts.json) {\n const found = await findWorkflowReport(id, opts.outputDir)\n if (!found?.reportPath) throw new Error(`No report found for \"${id}\"`)\n writeOutput({ path: found.reportPath, run: found }, true)\n return\n }\n const path = await openWorkflowReport(id, opts.outputDir)\n writeOutput(`Opened: ${path}`, false)\n })\n\n const schedule = program.command('schedule').description('Create and manage hosted workflow schedules.')\n addWorkflowInputOptions(schedule.command('create <workflowId>')\n .description('Create a recurring hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--name <name>', 'Schedule name')\n .option('--daily', 'Run daily')\n .option('--weekly', 'Run weekly')\n .option('--monthly', 'Run monthly')\n .option('--timezone <tz>', 'Schedule timezone', 'UTC')\n .option('--webhook <url>', 'HTTPS webhook URL')\n .option('--next-run-at <iso>', 'First run time as an ISO timestamp')\n .option('--json', 'Print machine-readable JSON'))\n .action(async (workflowId: string, opts) => {\n const result = await apiRequest('/workflows/schedules', 'POST', opts, {\n workflowId,\n name: opts.name,\n input: workflowInput(workflowId, opts),\n cadence: cadenceOpt(opts),\n timezone: opts.timezone,\n webhookUrl: opts.webhook,\n nextRunAt: opts.nextRunAt,\n })\n writeOutput(result, opts.json)\n })\n\n schedule.command('list')\n .description('List hosted workflow schedules.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await apiRequest<{ schedules: Array<Record<string, unknown>> }>('/workflows/schedules', 'GET', opts)\n if (opts.json) writeOutput(result, true)\n else writeOutput(result.schedules.map(scheduleRow => `${scheduleRow.id}\\t${scheduleRow.status}\\t${scheduleRow.workflow_id}\\t${scheduleRow.next_run_at ?? ''}`).join('\\n'), false)\n })\n\n schedule.command('pause <id>')\n .description('Pause a hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}`, 'PATCH', opts, { status: 'paused' }), opts.json))\n\n schedule.command('resume <id>')\n .description('Resume a hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}`, 'PATCH', opts, { status: 'active' }), opts.json))\n\n schedule.command('delete <id>')\n .description('Delete a hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}`, 'DELETE', opts), opts.json))\n\n schedule.command('run <id>')\n .description('Run a hosted workflow schedule now.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}/run`, 'POST', opts, {}), opts.json))\n\n const runs = program.command('runs').description('Inspect and download hosted workflow runs.')\n runs.command('list')\n .description('List hosted workflow runs.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await apiRequest<{ runs: Array<Record<string, unknown>> }>('/workflows/runs', 'GET', opts)\n if (opts.json) writeOutput(result, true)\n else writeOutput(result.runs.map(run => `${run.id}\\t${run.status}\\t${run.workflow_id}\\t${run.queued_at}`).join('\\n'), false)\n })\n\n runs.command('status <id>')\n .description('Show a hosted workflow run.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/runs/${id}`, 'GET', opts), opts.json))\n\n runs.command('download <id>')\n .description('Download hosted workflow run artifacts.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--output-dir <path>', 'Download directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => {\n const result = await apiRequest<{ run: { id: string; artifacts?: Array<{ id: string; label: string; path: string }> } }>(`/workflows/runs/${id}`, 'GET', opts)\n const { apiUrl, apiKey } = apiOptions(opts)\n const outDir = join(opts.outputDir ?? workflowOutputBaseDir(), 'workflow-downloads', id)\n await mkdir(outDir, { recursive: true })\n const downloaded: string[] = []\n for (const artifact of result.run.artifacts ?? []) {\n const res = await fetch(`${apiUrl}/workflows/runs/${id}/artifacts/${artifact.id}`, { headers: { 'x-api-key': apiKey } })\n if (!res.ok) throw new Error(`Failed to download ${artifact.label}: HTTP ${res.status}`)\n const file = join(outDir, basename(artifact.path))\n await writeFile(file, Buffer.from(await res.arrayBuffer()))\n downloaded.push(file)\n }\n writeOutput(opts.json ? { runId: id, files: downloaded } : downloaded.join('\\n'), opts.json)\n })\n\n return program\n}\n\nexport async function runHumanCli(argv = process.argv): Promise<void> {\n await buildHumanCli().parseAsync(argv)\n}\n","export type AgentHost = 'codex' | 'claude' | 'claude-code' | 'claude-desktop'\n\nexport interface AgentConfigOptions {\n apiKey?: string\n packageSpec?: string\n browserProfileName?: string\n browserProfileSaveChanges?: boolean\n}\n\nfunction apiKeyValue(options: AgentConfigOptions): string {\n return options.apiKey?.trim() || 'sk_live_your_key'\n}\n\nfunction packageSpec(options: AgentConfigOptions): string {\n return options.packageSpec?.trim() || 'mcp-scraper@latest'\n}\n\nexport function combinedNpxArgs(options: AgentConfigOptions = {}): string[] {\n return ['-y', '-p', packageSpec(options), 'mcp-scraper']\n}\n\nfunction envConfig(options: AgentConfigOptions): Record<string, string> {\n const env: Record<string, string> = { MCP_SCRAPER_API_KEY: apiKeyValue(options) }\n const profileName = options.browserProfileName?.trim()\n if (profileName) env.BROWSER_AGENT_PROFILE_NAME = profileName\n if (options.browserProfileSaveChanges === true) env.BROWSER_AGENT_PROFILE_SAVE_CHANGES = 'true'\n return env\n}\n\nfunction tomlInlineTable(value: Record<string, string>): string {\n const entries = Object.entries(value).map(([key, item]) => `${key} = ${JSON.stringify(item)}`)\n return `{ ${entries.join(', ')} }`\n}\n\nexport function renderCodexConfig(options: AgentConfigOptions = {}): string {\n return [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n `args = ${JSON.stringify(combinedNpxArgs(options))}`,\n `env = ${tomlInlineTable(envConfig(options))}`,\n ].join('\\n')\n}\n\nexport function renderClaudeCommand(options: AgentConfigOptions = {}): string {\n const env = Object.entries(envConfig(options)).map(([key, value]) => ` --env ${key}=${value}`)\n return [\n 'claude mcp add mcp-scraper --scope user',\n ...env,\n ` -- npx ${combinedNpxArgs(options).join(' ')}`,\n ].join(' \\\\\\n')\n}\n\nexport function claudeMcpRemoveArgs(): string[] {\n return ['mcp', 'remove', 'mcp-scraper', '-s', 'user']\n}\n\nexport function claudeMcpAddArgs(options: AgentConfigOptions = {}): string[] {\n const args = ['mcp', 'add', 'mcp-scraper', '--scope', 'user']\n for (const [key, value] of Object.entries(envConfig(options))) {\n args.push('--env', `${key}=${value}`)\n }\n args.push('--', 'npx', ...combinedNpxArgs(options))\n return args\n}\n\nexport function normalizeAgentHost(host: string): AgentHost {\n if (host === 'claude-code') return 'claude'\n if (host === 'claude' || host === 'codex' || host === 'claude-desktop') return host\n throw new Error('Unknown host \"' + host + '\". Use: codex, claude, claude-code, or claude-desktop')\n}\n\nexport function renderClaudeDesktopConfig(options: AgentConfigOptions = {}): string {\n return JSON.stringify({\n mcpServers: {\n 'mcp-scraper': {\n command: 'npx',\n args: combinedNpxArgs(options),\n env: envConfig(options),\n },\n },\n }, null, 2)\n}\n\nexport function renderAgentInstall(host: AgentHost, options: AgentConfigOptions = {}): string {\n const normalizedHost = normalizeAgentHost(host)\n const restart = 'Restart the MCP client so it starts a fresh npx process.'\n const applyCommand = `MCP_SCRAPER_API_KEY=${apiKeyValue(options)} npx -y -p mcp-scraper@latest mcp-scraper-cli agent install claude --apply`\n if (normalizedHost === 'codex') {\n return [\n '# Codex MCP config',\n renderCodexConfig(options),\n '',\n restart,\n ].join('\\n')\n }\n if (normalizedHost === 'claude') {\n return [\n '# Claude Code command',\n renderClaudeCommand(options),\n '',\n '# One-command Claude Code setup',\n applyCommand,\n '',\n restart,\n ].join('\\n')\n }\n return [\n '# Claude Desktop config',\n renderClaudeDesktopConfig(options),\n '',\n 'Desktop Extension: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n restart,\n ].join('\\n')\n}\n","import { access, mkdir, readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { PACKAGE_VERSION } from '../version.js'\nimport { combinedNpxArgs } from './agent-config.js'\n\nexport type DoctorStatus = 'pass' | 'warn' | 'fail' | 'skip'\n\nexport interface DoctorCheck {\n id: string\n label: string\n status: DoctorStatus\n detail: string\n fix?: string\n}\n\nexport interface DoctorOptions {\n apiKey?: string\n apiUrl?: string\n outputDir?: string\n fetchImpl?: typeof fetch\n}\n\nexport interface DoctorOutput {\n ok: boolean\n version: string\n npmLatest: string | null\n checks: DoctorCheck[]\n recommendedConfig: {\n command: 'npx'\n args: string[]\n env: Record<string, string>\n }\n}\n\nfunction status(ok: boolean, warn = false): DoctorStatus {\n if (ok) return 'pass'\n return warn ? 'warn' : 'fail'\n}\n\nfunction parseMajor(version: string): number {\n return Number(version.replace(/^v/, '').split('.')[0] ?? 0)\n}\n\nasync function readKeyFile(): Promise<string | null> {\n const path = process.env.MCP_SCRAPER_KEY_PATH?.trim() || join(homedir(), '.mcp-scraper-key')\n try {\n const value = (await readFile(path, 'utf8')).trim()\n return value || null\n } catch {\n return null\n }\n}\n\nasync function npmLatest(fetchImpl: typeof fetch): Promise<string | null> {\n try {\n const res = await fetchImpl('https://registry.npmjs.org/mcp-scraper/latest', {\n signal: AbortSignal.timeout(5_000),\n })\n if (!res.ok) return null\n const data = await res.json() as { version?: string }\n return data.version ?? null\n } catch {\n return null\n }\n}\n\nexport async function runDoctor(options: DoctorOptions = {}): Promise<DoctorOutput> {\n const fetchImpl = options.fetchImpl ?? fetch\n const apiUrl = (options.apiUrl ?? process.env.MCP_SCRAPER_API_URL ?? 'https://mcpscraper.dev').replace(/\\/$/, '')\n const outputDir = options.outputDir ?? process.env.MCP_SCRAPER_OUTPUT_DIR ?? join(homedir(), 'Downloads', 'mcp-scraper')\n const configuredKey = options.apiKey?.trim() || process.env.MCP_SCRAPER_API_KEY?.trim() || await readKeyFile()\n const latest = await npmLatest(fetchImpl)\n\n const checks: DoctorCheck[] = []\n const nodeMajor = parseMajor(process.version)\n checks.push({\n id: 'node',\n label: 'Node.js',\n status: status(nodeMajor >= 20),\n detail: process.version,\n fix: nodeMajor >= 20 ? undefined : 'Install Node.js 20 or newer.',\n })\n\n checks.push({\n id: 'package_version',\n label: 'Local package',\n status: latest && latest !== PACKAGE_VERSION ? 'warn' : 'pass',\n detail: latest ? `local ${PACKAGE_VERSION}, npm latest ${latest}` : `local ${PACKAGE_VERSION}, npm latest unavailable`,\n fix: latest && latest !== PACKAGE_VERSION ? 'Use mcp-scraper@latest and restart the MCP client.' : undefined,\n })\n\n checks.push({\n id: 'api_key',\n label: 'API key',\n status: configuredKey ? 'pass' : 'warn',\n detail: configuredKey ? 'configured' : 'not configured',\n fix: configuredKey ? undefined : 'Set MCP_SCRAPER_API_KEY or pass --api-key.',\n })\n\n try {\n await mkdir(outputDir, { recursive: true })\n await access(outputDir)\n checks.push({ id: 'output_dir', label: 'Output directory', status: 'pass', detail: outputDir })\n } catch (err) {\n checks.push({\n id: 'output_dir',\n label: 'Output directory',\n status: 'fail',\n detail: outputDir,\n fix: err instanceof Error ? err.message : 'Create a writable output directory.',\n })\n }\n\n if (configuredKey) {\n try {\n const res = await fetchImpl(`${apiUrl}/me`, {\n headers: { 'x-api-key': configuredKey },\n signal: AbortSignal.timeout(8_000),\n })\n checks.push({\n id: 'api_reachability',\n label: 'Hosted API',\n status: res.ok ? 'pass' : 'fail',\n detail: `${apiUrl}/me returned ${res.status}`,\n fix: res.ok ? undefined : 'Verify the API key and account status.',\n })\n } catch (err) {\n checks.push({\n id: 'api_reachability',\n label: 'Hosted API',\n status: 'fail',\n detail: err instanceof Error ? err.message : String(err),\n fix: 'Check network access and MCP_SCRAPER_API_URL.',\n })\n }\n } else {\n checks.push({\n id: 'api_reachability',\n label: 'Hosted API',\n status: 'skip',\n detail: 'skipped because no API key is configured',\n })\n }\n\n checks.push({\n id: 'mcp_config',\n label: 'MCP command',\n status: 'pass',\n detail: `npx ${combinedNpxArgs().join(' ')}`,\n fix: 'Restart the MCP client after package updates.',\n })\n\n return {\n ok: checks.every(check => check.status === 'pass' || check.status === 'skip'),\n version: PACKAGE_VERSION,\n npmLatest: latest,\n checks,\n recommendedConfig: {\n command: 'npx',\n args: combinedNpxArgs(),\n env: { MCP_SCRAPER_API_KEY: configuredKey ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key' },\n },\n }\n}\n\nexport function renderDoctor(output: DoctorOutput): string {\n const icon: Record<DoctorStatus, string> = { pass: 'PASS', warn: 'WARN', fail: 'FAIL', skip: 'SKIP' }\n const lines = [\n `mcp-scraper doctor v${output.version}`,\n '',\n ...output.checks.map(check => {\n const fix = check.fix ? `\\n Fix: ${check.fix}` : ''\n return `[${icon[check.status]}] ${check.label}: ${check.detail}${fix}`\n }),\n '',\n `Recommended MCP command: npx ${output.recommendedConfig.args.join(' ')}`,\n ]\n return lines.join('\\n')\n}\n\n","export const AGENT_PROMPTS: Record<string, string> = {\n 'agent-packet': [\n '# MCP Scraper Agent Packet Prompt',\n '',\n 'Use MCP Scraper as the evidence layer. Run the agent-packet workflow for the target keyword/domain, then treat `evidence.json`, `sources.csv`, and `competitors.csv` as source of truth.',\n '',\n 'Do not invent citations. If a recommendation is not supported by the packet, mark it as an assumption. Turn the evidence into a concise SEO brief, an implementation task list, and content recommendations tied to source rows.',\n ].join('\\n'),\n 'local-competitive-audit': [\n '# MCP Scraper Local Competitive Audit Prompt',\n '',\n 'Run the local-competitive-audit workflow for the niche and markets. Use the city summary, competitor CSV, and review-insight CSV to identify market difficulty, review themes, GBP category patterns, and weak competitors.',\n '',\n 'Ground recommendations in Maps rank position, review count, star rating, categories, profile details, and review topics. Do not overstate heuristic opportunity scores.',\n ].join('\\n'),\n 'directory-workflow': [\n '# MCP Scraper Directory Workflow Prompt',\n '',\n 'Use directory_workflow when the user wants cities selected by population and Google Maps candidates per city. Keep query and location separate. Preserve result_position, source_location, review stars/count, categories, and profile URLs for downstream CSV or directory use.',\n ].join('\\n'),\n 'map-comparison': [\n '# MCP Scraper Maps Comparison Prompt',\n '',\n 'Run the map-comparison workflow when the user wants to compare local Maps competitors in a city or across selected markets. Use `maps-results.csv`, `map-comparison.csv`, and `profile-insights.csv` as source of truth.',\n '',\n 'Ground recommendations in result_position, review_stars, review_count, category, website presence, review topics, and profile attributes. Treat review gaps and missing websites as opportunity signals, not guaranteed ranking factors.',\n ].join('\\n'),\n 'serp-comparison': [\n '# MCP Scraper SERP Comparison Prompt',\n '',\n 'Run the serp-comparison workflow when the user wants to know why competitors outrank a page or what the SERP rewards. Use organic results, extracted page headings, PAA questions, and AI Overview citations before making recommendations.',\n '',\n 'Tie each recommendation to `content-gaps.csv`, `page-comparison.csv`, `paa-questions.csv`, or `ai-overview-citations.csv`. Do not invent missing sections or citations.',\n ].join('\\n'),\n 'paa-expansion-brief': [\n '# MCP Scraper PAA Expansion Brief Prompt',\n '',\n 'Run the paa-expansion-brief workflow when the user wants to figure out what to write from People Also Ask expansion. Use `section-map.csv` to structure the brief and `paa-questions.csv` for exact customer-language headings.',\n '',\n 'Answer the highest-priority questions directly, preserve source URLs when present, and separate evidence-backed sections from assumptions.',\n ].join('\\n'),\n 'ai-overview-language': [\n '# MCP Scraper AI Overview Language Prompt',\n '',\n 'Run the ai-overview-language workflow when the user wants to know how to phrase content for AI Overview inclusion. Use `claim-patterns.csv`, `language-guidance.csv`, `ai-overview-citations.csv`, and PAA follow-ups as evidence.',\n '',\n 'Recommend concise answer blocks, criteria/step language, citation hooks, and follow-up sections. Do not claim the target will be cited; frame the output as evidence-based language guidance.',\n ].join('\\n'),\n 'ai-citation-monitor': [\n '# MCP Scraper AI Citation Monitor Prompt',\n '',\n 'Use search_serp and harvest_paa to check whether the target brand/domain appears in AI Overview citations, organic results, People Also Ask sources, local pack, forums, and videos. Save evidence before summarizing trends or gaps.',\n ].join('\\n'),\n 'serp-brief': [\n '# MCP Scraper SERP Brief Prompt',\n '',\n 'Use live SERP, PAA, AI Overview, forum, video, and source evidence to create a writer brief. Tie each recommended section to evidence rows and identify missing proof, entities, comparisons, and customer questions.',\n ].join('\\n'),\n}\n\nexport function listPrompts(): string[] {\n return Object.keys(AGENT_PROMPTS).sort()\n}\n\nexport function renderPrompt(name: string): string {\n const prompt = AGENT_PROMPTS[name]\n if (!prompt) throw new Error(`Unknown prompt \"${name}\". Available: ${listPrompts().join(', ')}`)\n return prompt\n}\n","#!/usr/bin/env node\nimport { runHumanCli } from '../src/cli/human-cli.js'\n\nrunHumanCli().catch((err) => {\n console.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n})\n\n"],"mappings":"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","names":["mkdir","join","join","mkdir"]}
1
+ {"version":3,"sources":["../../src/cli/human-cli.ts","../../src/cli/agent-config.ts","../../src/cli/doctor.ts","../../src/cli/prompts.ts","../../bin/mcp-scraper-cli.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { basename, join } from 'node:path'\nimport { PACKAGE_VERSION } from '../version.js'\nimport {\n claudeMcpAddArgs,\n claudeMcpRemoveArgs,\n normalizeAgentHost,\n renderAgentInstall,\n type AgentHost,\n} from './agent-config.js'\nimport { renderDoctor, runDoctor } from './doctor.js'\nimport { listPrompts, renderPrompt } from './prompts.js'\nimport { workflowOutputBaseDir } from '../workflows/artifact-writer.js'\nimport { findWorkflowReport, listWorkflowDefinitions, listWorkflowReports, openWorkflowReport, runWorkflow } from '../workflows/registry.js'\n\nfunction numberOpt(value: unknown): number | undefined {\n if (value === undefined || value === null || value === '') return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nfunction booleanOpt(value: unknown): boolean | undefined {\n if (value === undefined) return undefined\n if (typeof value === 'boolean') return value\n if (value === 'true') return true\n if (value === 'false') return false\n return undefined\n}\n\nfunction compactInput(input: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined))\n}\n\nfunction workflowInput(id: string, opts: Record<string, unknown>): Record<string, unknown> {\n if (id === 'agent-packet' || id === 'serp-comparison' || id === 'ai-overview-language') {\n return compactInput({\n keyword: opts.keyword,\n domain: opts.domain,\n url: opts.url,\n location: opts.location,\n maxResults: numberOpt(opts.maxResults),\n maxQuestions: numberOpt(opts.maxQuestions),\n extractTop: numberOpt(opts.extractTop),\n includeSerp: opts.serp === false ? false : undefined,\n includePaa: opts.paa === false ? false : undefined,\n includeAiOverview: booleanOpt(opts.includeAiOverview),\n returnPartial: opts.returnPartial === false ? false : undefined,\n })\n }\n\n if (id === 'paa-expansion-brief') {\n return compactInput({\n keyword: opts.keyword,\n location: opts.location,\n maxQuestions: numberOpt(opts.maxQuestions),\n depth: numberOpt(opts.depth),\n returnPartial: opts.returnPartial === false ? false : undefined,\n })\n }\n\n if (id === 'directory' || id === 'local-competitive-audit' || id === 'map-comparison') {\n return compactInput({\n query: opts.query,\n location: opts.location,\n state: opts.state,\n minPopulation: numberOpt(opts.minPop ?? opts.minPopulation),\n maxCities: numberOpt(opts.maxCities),\n maxResultsPerCity: numberOpt(opts.perCity ?? opts.maxResultsPerCity ?? opts.maxResults),\n concurrency: numberOpt(opts.concurrency),\n proxyMode: opts.proxyMode,\n hydrateTop: id === 'local-competitive-audit' || id === 'map-comparison' ? numberOpt(opts.hydrateTop) : undefined,\n maxReviews: id === 'local-competitive-audit' || id === 'map-comparison' ? numberOpt(opts.reviews ?? opts.maxReviews) : undefined,\n returnPartial: opts.returnPartial === false ? false : undefined,\n })\n }\n\n return compactInput(opts)\n}\n\nfunction writeOutput(data: unknown, json: boolean | undefined): void {\n if (json) {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`)\n } else if (typeof data === 'string') {\n process.stdout.write(`${data}\\n`)\n } else {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`)\n }\n}\n\nfunction maskSecrets(value: string): string {\n return value.replace(/sk_[A-Za-z0-9_-]+/g, 'sk_***')\n}\n\nfunction runLocalCommand(command: string, args: string[]): Promise<{ code: number; stdout: string; stderr: string }> {\n return new Promise((resolve) => {\n const child = spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] })\n const stdout: Buffer[] = []\n const stderr: Buffer[] = []\n let settled = false\n const done = (result: { code: number; stdout: string; stderr: string }) => {\n if (settled) return\n settled = true\n resolve(result)\n }\n child.stdout.on('data', chunk => stdout.push(Buffer.from(chunk)))\n child.stderr.on('data', chunk => stderr.push(Buffer.from(chunk)))\n child.on('error', err => {\n done({ code: 127, stdout: '', stderr: err.message })\n })\n child.on('close', code => {\n done({\n code: typeof code === 'number' ? code : 1,\n stdout: Buffer.concat(stdout).toString('utf8'),\n stderr: Buffer.concat(stderr).toString('utf8'),\n })\n })\n })\n}\n\nfunction cadenceOpt(opts: Record<string, unknown>): 'daily' | 'weekly' | 'monthly' {\n if (opts.daily) return 'daily'\n if (opts.monthly) return 'monthly'\n return 'weekly'\n}\n\nfunction apiOptions(opts: Record<string, unknown>): { apiUrl: string; apiKey: string } {\n const apiKey = String(opts.apiKey ?? process.env.MCP_SCRAPER_API_KEY ?? '').trim()\n if (!apiKey) throw new Error('MCP_SCRAPER_API_KEY is required. Pass --api-key or set the environment variable.')\n return {\n apiUrl: String(opts.apiUrl ?? process.env.MCP_SCRAPER_API_URL ?? 'https://mcpscraper.dev').replace(/\\/$/, ''),\n apiKey,\n }\n}\n\nfunction openExternalUrl(url: string): boolean {\n const command = process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'cmd'\n : 'xdg-open'\n const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url]\n try {\n const child = spawn(command, args, { detached: true, stdio: 'ignore' })\n child.unref()\n return true\n } catch {\n return false\n }\n}\n\nasync function apiRequest<T>(path: string, method: string, opts: Record<string, unknown>, body?: unknown): Promise<T> {\n const { apiUrl, apiKey } = apiOptions(opts)\n const res = await fetch(`${apiUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: body == null ? undefined : JSON.stringify(body),\n })\n const data = await res.json().catch(() => ({}))\n if (!res.ok) {\n const message = typeof (data as { error?: unknown }).error === 'string'\n ? (data as { error: string }).error\n : `API request failed with ${res.status}`\n throw new Error(message)\n }\n return data as T\n}\n\nfunction addWorkflowInputOptions(command: Command): Command {\n return command\n .option('--keyword <keyword>', 'Agent packet keyword')\n .option('--domain <domain>', 'Target domain')\n .option('--url <url>', 'Target page URL')\n .option('--location <location>', 'Target location')\n .option('--max-results <n>', 'Maximum SERP or Maps results')\n .option('--max-questions <n>', 'Maximum PAA questions')\n .option('--extract-top <n>', 'Top result pages or citation pages to extract')\n .option('--depth <n>', 'PAA expansion depth')\n .option('--no-serp', 'Skip SERP evidence for agent packet')\n .option('--no-paa', 'Skip PAA evidence for agent packet')\n .option('--query <query>', 'Business category or workflow query')\n .option('--state <state>', 'US state')\n .option('--min-pop <n>', 'Minimum city population')\n .option('--max-cities <n>', 'Maximum selected cities')\n .option('--per-city <n>', 'Maps results per city')\n .option('--concurrency <n>', 'City search concurrency')\n .option('--proxy-mode <mode>', 'Proxy mode: location, configured, or none')\n .option('--hydrate-top <n>', 'Profiles to hydrate per city for competitive audits')\n .option('--reviews <n>', 'Review cards to collect per hydrated profile')\n .option('--no-return-partial', 'Fail instead of writing partial artifacts')\n}\n\nexport function buildHumanCli(): Command {\n const program = new Command()\n program\n .name('mcp-scraper-cli')\n .description('Human CLI for MCP Scraper setup, workflows, reports, and agent-ready SEO artifacts.')\n .version(PACKAGE_VERSION)\n\n program.command('doctor')\n .description('Check setup, API key, output directory, package version, and recommended MCP config.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--output-dir <path>', 'Output directory to test')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const output = await runDoctor({ apiKey: opts.apiKey, apiUrl: opts.apiUrl, outputDir: opts.outputDir })\n writeOutput(opts.json ? output : renderDoctor(output), opts.json)\n if (!output.ok) process.exitCode = 1\n })\n\n const billing = program.command('billing').description('Inspect billing and start checkout flows.')\n const billingConcurrency = billing.command('concurrency').description('Manage MCP Scraper concurrency slots.')\n\n billingConcurrency.command('info')\n .description('Show current concurrency limit and extra-slot price.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await apiRequest<{ concurrency: Record<string, unknown> }>('/billing/credits', 'POST', opts, {})\n if (opts.json) writeOutput(result.concurrency, true)\n else {\n const upgrade = result.concurrency?.upgrade as Record<string, unknown> | undefined\n writeOutput([\n `Current limit: ${result.concurrency?.current_limit ?? 'unknown'} concurrent operations`,\n `Extra slots: ${result.concurrency?.current_extra_slots ?? 'unknown'}`,\n `Extra concurrency slot: ${upgrade?.price_label ?? '$5/month'}`,\n `Upgrade command: ${upgrade?.terminal_command ?? 'mcp-scraper-cli billing concurrency checkout'}`,\n ].join('\\n'), false)\n }\n })\n\n billingConcurrency.command('checkout')\n .description('Create a hosted Stripe checkout for one extra concurrency slot.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .option('--no-open', 'Print the checkout URL without opening a browser')\n .action(async (opts) => {\n const result = await apiRequest<{ checkout_url: string; price?: { price_label?: string }; next_step?: string }>('/billing/concurrency/terminal-checkout', 'POST', opts, {})\n if (opts.json) {\n writeOutput(result, true)\n return\n }\n const opened = opts.open !== false && openExternalUrl(result.checkout_url)\n writeOutput([\n `Extra concurrency slot: ${result.price?.price_label ?? '$5/month'}`,\n opened ? `Opened checkout: ${result.checkout_url}` : `Checkout URL: ${result.checkout_url}`,\n result.next_step ?? 'Complete checkout, then retry the MCP request.',\n ].join('\\n'), false)\n })\n\n billing.command('subscribe <tier>')\n .description('Subscribe to a plan (starter | growth | scale) via a hosted Stripe checkout link.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .option('--no-open', 'Print the checkout URL without opening a browser')\n .action(async (tier, opts) => {\n const result = await apiRequest<{ checkout_url?: string; updated?: boolean; tier?: string; label?: string; monthly_usd?: number; credits_per_month?: number; concurrency?: number; intro?: string | null; message?: string; next_step?: string }>('/billing/subscribe/terminal-checkout', 'POST', opts, { tier: String(tier).toLowerCase() })\n if (opts.json) { writeOutput(result, true); return }\n if (result.updated) { writeOutput(result.message ?? `Switched to ${result.tier}.`, false); return }\n const opened = opts.open !== false && !!result.checkout_url && openExternalUrl(result.checkout_url)\n writeOutput([\n `Plan: ${result.label ?? tier} — $${result.monthly_usd}/mo · ${result.credits_per_month?.toLocaleString()} credits/mo · ${result.concurrency} concurrency${result.intro ? ` · ${result.intro}` : ''}`,\n opened ? `Opened checkout: ${result.checkout_url}` : `Checkout URL: ${result.checkout_url}`,\n result.next_step ?? 'Complete payment in the browser.',\n ].join('\\n'), false)\n })\n\n const agent = program.command('agent').description('Generate AI-agent install configs and workflow prompts.')\n agent.command('install <host>')\n .description('Print or apply install/config instructions for codex, claude/claude-code, or claude-desktop.')\n .option('--api-key <key>', 'API key to place in generated config')\n .option('--package <spec>', 'npm package spec', 'mcp-scraper@latest')\n .option('--browser-profile <name>', 'Default saved browser profile for browser_open sessions.')\n .option('--save-browser-profile-changes', 'Persist cookies and browser storage back to the named browser profile when sessions close')\n .option('--apply', 'Apply the config to this client when supported. For Claude Code, this upserts the user-scope mcp-scraper server.')\n .option('--json', 'Print machine-readable JSON')\n .action(async (hostInput: AgentHost, opts) => {\n const host = normalizeAgentHost(hostInput)\n const apiKey = opts.apiKey ?? process.env.MCP_SCRAPER_API_KEY\n if (opts.apply) {\n if (host !== 'claude') throw new Error('--apply is currently supported for Claude Code only. Use host \"claude\" or \"claude-code\".')\n if (!apiKey?.trim()) {\n throw new Error('MCP_SCRAPER_API_KEY is required for --apply. Set it in the environment or pass --api-key.')\n }\n\n const configOptions = {\n apiKey,\n packageSpec: opts.package,\n browserProfileName: opts.browserProfile,\n browserProfileSaveChanges: opts.saveBrowserProfileChanges,\n }\n const remove = await runLocalCommand('claude', claudeMcpRemoveArgs())\n const add = await runLocalCommand('claude', claudeMcpAddArgs(configOptions))\n if (add.code !== 0) {\n const reason = maskSecrets([add.stderr, add.stdout].filter(Boolean).join('\\n').trim())\n throw new Error([\n 'Claude Code MCP registration failed.',\n reason || 'No error output returned.',\n 'Make sure Claude Code is installed and the `claude` command is on PATH.',\n ].join('\\n'))\n }\n const list = await runLocalCommand('claude', ['mcp', 'list'])\n const result = {\n host: 'claude',\n applied: true,\n replacedExisting: remove.code === 0,\n command: 'npx',\n args: ['-y', '-p', opts.package, 'mcp-scraper'],\n nextStep: 'Fully exit Claude Code, start a new Claude terminal, then run: claude mcp list',\n list: maskSecrets([list.stdout, list.stderr].filter(Boolean).join('\\n').trim()),\n }\n if (opts.json) {\n writeOutput(result, true)\n return\n }\n writeOutput([\n 'Applied Claude Code MCP config: mcp-scraper',\n remove.code === 0 ? 'Replaced existing mcp-scraper entry.' : 'No existing mcp-scraper entry found; added a new one.',\n 'Command: npx -y -p ' + opts.package + ' mcp-scraper',\n opts.browserProfile ? `Browser profile: ${opts.browserProfile}` : '',\n '',\n 'Next step: fully exit Claude Code, start a new Claude terminal, then run:',\n ' claude mcp list',\n '',\n result.list ? `Current Claude MCP list:\\n${result.list}` : '',\n ].filter(Boolean).join('\\n'), false)\n return\n }\n const text = renderAgentInstall(host, {\n apiKey: opts.apiKey,\n packageSpec: opts.package,\n browserProfileName: opts.browserProfile,\n browserProfileSaveChanges: opts.saveBrowserProfileChanges,\n })\n writeOutput(opts.json ? { host, text } : text, opts.json)\n })\n\n agent.command('prompt [name]')\n .description('Print an agent prompt template.')\n .option('--json', 'Print machine-readable JSON')\n .action((name: string | undefined, opts) => {\n if (!name) {\n writeOutput(opts.json ? { prompts: listPrompts() } : listPrompts().join('\\n'), opts.json)\n return\n }\n const text = renderPrompt(name)\n writeOutput(opts.json ? { name, text } : text, opts.json)\n })\n\n const workflow = program.command('workflow').description('Run named SEO workflows.')\n workflow.command('list')\n .description('List available workflows.')\n .option('--json', 'Print machine-readable JSON')\n .action((opts) => {\n const rows = listWorkflowDefinitions()\n if (opts.json) writeOutput({ workflows: rows }, true)\n else writeOutput(rows.map(row => `${row.id}\\t${row.title}\\n ${row.description}`).join('\\n'), false)\n })\n\n workflow.command('run <id>')\n .description('Run a workflow and save local artifacts.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON')\n .option('--keyword <keyword>', 'Agent packet keyword')\n .option('--domain <domain>', 'Target domain')\n .option('--url <url>', 'Target page URL')\n .option('--location <location>', 'Target location')\n .option('--max-results <n>', 'Maximum SERP or Maps results')\n .option('--max-questions <n>', 'Maximum PAA questions')\n .option('--extract-top <n>', 'Top result pages or citation pages to extract')\n .option('--depth <n>', 'PAA expansion depth')\n .option('--no-serp', 'Skip SERP evidence for agent packet')\n .option('--no-paa', 'Skip PAA evidence for agent packet')\n .option('--query <query>', 'Business category or workflow query')\n .option('--state <state>', 'US state')\n .option('--min-pop <n>', 'Minimum city population')\n .option('--max-cities <n>', 'Maximum selected cities')\n .option('--per-city <n>', 'Maps results per city')\n .option('--concurrency <n>', 'City search concurrency')\n .option('--proxy-mode <mode>', 'Proxy mode: location, configured, or none')\n .option('--hydrate-top <n>', 'Profiles to hydrate per city for competitive audits')\n .option('--reviews <n>', 'Review cards to collect per hydrated profile')\n .option('--no-return-partial', 'Fail instead of writing partial artifacts')\n .action(async (id: string, opts) => {\n const summary = await runWorkflow(id, workflowInput(id, opts), {\n apiKey: opts.apiKey,\n apiUrl: opts.apiUrl,\n outputDir: opts.outputDir,\n })\n if (opts.json) writeOutput(summary, true)\n else {\n writeOutput([\n `${summary.title}: ${summary.status}`,\n summary.summary,\n summary.reportPath ? `Report: ${summary.reportPath}` : '',\n summary.warnings.length ? `Warnings:\\n${summary.warnings.map(w => `- ${w}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n'), false)\n }\n })\n\n const report = program.command('report').description('List and open local workflow reports.')\n report.command('list')\n .description('List recent workflow reports.')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const reports = await listWorkflowReports(opts.outputDir)\n writeOutput(opts.json ? { reports } : reports.map(r => `${r.startedAt}\\t${r.workflow}\\t${r.status}\\t${r.reportPath ?? r.manifestPath}`).join('\\n'), opts.json)\n })\n report.command('path [id]')\n .description('Print a report path. Defaults to last.')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id = 'last', opts) => {\n const found = await findWorkflowReport(id, opts.outputDir)\n if (!found?.reportPath) throw new Error(`No report found for \"${id}\"`)\n writeOutput(opts.json ? { path: found.reportPath, run: found } : found.reportPath, opts.json)\n })\n report.command('open [id]')\n .description('Open a report. Defaults to last.')\n .option('--output-dir <path>', 'Workflow output directory')\n .option('--json', 'Print machine-readable JSON instead of opening')\n .action(async (id = 'last', opts) => {\n if (opts.json) {\n const found = await findWorkflowReport(id, opts.outputDir)\n if (!found?.reportPath) throw new Error(`No report found for \"${id}\"`)\n writeOutput({ path: found.reportPath, run: found }, true)\n return\n }\n const path = await openWorkflowReport(id, opts.outputDir)\n writeOutput(`Opened: ${path}`, false)\n })\n\n const schedule = program.command('schedule').description('Create and manage hosted workflow schedules.')\n addWorkflowInputOptions(schedule.command('create <workflowId>')\n .description('Create a recurring hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--name <name>', 'Schedule name')\n .option('--daily', 'Run daily')\n .option('--weekly', 'Run weekly')\n .option('--monthly', 'Run monthly')\n .option('--timezone <tz>', 'Schedule timezone', 'UTC')\n .option('--webhook <url>', 'HTTPS webhook URL')\n .option('--next-run-at <iso>', 'First run time as an ISO timestamp')\n .option('--json', 'Print machine-readable JSON'))\n .action(async (workflowId: string, opts) => {\n const result = await apiRequest('/workflows/schedules', 'POST', opts, {\n workflowId,\n name: opts.name,\n input: workflowInput(workflowId, opts),\n cadence: cadenceOpt(opts),\n timezone: opts.timezone,\n webhookUrl: opts.webhook,\n nextRunAt: opts.nextRunAt,\n })\n writeOutput(result, opts.json)\n })\n\n schedule.command('list')\n .description('List hosted workflow schedules.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await apiRequest<{ schedules: Array<Record<string, unknown>> }>('/workflows/schedules', 'GET', opts)\n if (opts.json) writeOutput(result, true)\n else writeOutput(result.schedules.map(scheduleRow => `${scheduleRow.id}\\t${scheduleRow.status}\\t${scheduleRow.workflow_id}\\t${scheduleRow.next_run_at ?? ''}`).join('\\n'), false)\n })\n\n schedule.command('pause <id>')\n .description('Pause a hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}`, 'PATCH', opts, { status: 'paused' }), opts.json))\n\n schedule.command('resume <id>')\n .description('Resume a hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}`, 'PATCH', opts, { status: 'active' }), opts.json))\n\n schedule.command('delete <id>')\n .description('Delete a hosted workflow schedule.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}`, 'DELETE', opts), opts.json))\n\n schedule.command('run <id>')\n .description('Run a hosted workflow schedule now.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/schedules/${id}/run`, 'POST', opts, {}), opts.json))\n\n const runs = program.command('runs').description('Inspect and download hosted workflow runs.')\n runs.command('list')\n .description('List hosted workflow runs.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await apiRequest<{ runs: Array<Record<string, unknown>> }>('/workflows/runs', 'GET', opts)\n if (opts.json) writeOutput(result, true)\n else writeOutput(result.runs.map(run => `${run.id}\\t${run.status}\\t${run.workflow_id}\\t${run.queued_at}`).join('\\n'), false)\n })\n\n runs.command('status <id>')\n .description('Show a hosted workflow run.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => writeOutput(await apiRequest(`/workflows/runs/${id}`, 'GET', opts), opts.json))\n\n runs.command('download <id>')\n .description('Download hosted workflow run artifacts.')\n .option('--api-key <key>', 'MCP Scraper API key')\n .option('--api-url <url>', 'MCP Scraper API URL', 'https://mcpscraper.dev')\n .option('--output-dir <path>', 'Download directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (id: string, opts) => {\n const result = await apiRequest<{ run: { id: string; artifacts?: Array<{ id: string; label: string; path: string }> } }>(`/workflows/runs/${id}`, 'GET', opts)\n const { apiUrl, apiKey } = apiOptions(opts)\n const outDir = join(opts.outputDir ?? workflowOutputBaseDir(), 'workflow-downloads', id)\n await mkdir(outDir, { recursive: true })\n const downloaded: string[] = []\n for (const artifact of result.run.artifacts ?? []) {\n const res = await fetch(`${apiUrl}/workflows/runs/${id}/artifacts/${artifact.id}`, { headers: { 'x-api-key': apiKey } })\n if (!res.ok) throw new Error(`Failed to download ${artifact.label}: HTTP ${res.status}`)\n const file = join(outDir, basename(artifact.path))\n await writeFile(file, Buffer.from(await res.arrayBuffer()))\n downloaded.push(file)\n }\n writeOutput(opts.json ? { runId: id, files: downloaded } : downloaded.join('\\n'), opts.json)\n })\n\n return program\n}\n\nexport async function runHumanCli(argv = process.argv): Promise<void> {\n await buildHumanCli().parseAsync(argv)\n}\n","export type AgentHost = 'codex' | 'claude' | 'claude-code' | 'claude-desktop'\n\nexport interface AgentConfigOptions {\n apiKey?: string\n packageSpec?: string\n browserProfileName?: string\n browserProfileSaveChanges?: boolean\n}\n\nfunction apiKeyValue(options: AgentConfigOptions): string {\n return options.apiKey?.trim() || 'sk_live_your_key'\n}\n\nfunction packageSpec(options: AgentConfigOptions): string {\n return options.packageSpec?.trim() || 'mcp-scraper@latest'\n}\n\nexport function combinedNpxArgs(options: AgentConfigOptions = {}): string[] {\n return ['-y', '-p', packageSpec(options), 'mcp-scraper']\n}\n\nfunction envConfig(options: AgentConfigOptions): Record<string, string> {\n const env: Record<string, string> = { MCP_SCRAPER_API_KEY: apiKeyValue(options) }\n const profileName = options.browserProfileName?.trim()\n if (profileName) env.BROWSER_AGENT_PROFILE_NAME = profileName\n if (options.browserProfileSaveChanges === true) env.BROWSER_AGENT_PROFILE_SAVE_CHANGES = 'true'\n return env\n}\n\nfunction tomlInlineTable(value: Record<string, string>): string {\n const entries = Object.entries(value).map(([key, item]) => `${key} = ${JSON.stringify(item)}`)\n return `{ ${entries.join(', ')} }`\n}\n\nexport function renderCodexConfig(options: AgentConfigOptions = {}): string {\n return [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n `args = ${JSON.stringify(combinedNpxArgs(options))}`,\n `env = ${tomlInlineTable(envConfig(options))}`,\n ].join('\\n')\n}\n\nexport function renderClaudeCommand(options: AgentConfigOptions = {}): string {\n const env = Object.entries(envConfig(options)).map(([key, value]) => ` --env ${key}=${value}`)\n return [\n 'claude mcp add mcp-scraper --scope user',\n ...env,\n ` -- npx ${combinedNpxArgs(options).join(' ')}`,\n ].join(' \\\\\\n')\n}\n\nexport function claudeMcpRemoveArgs(): string[] {\n return ['mcp', 'remove', 'mcp-scraper', '-s', 'user']\n}\n\nexport function claudeMcpAddArgs(options: AgentConfigOptions = {}): string[] {\n const args = ['mcp', 'add', 'mcp-scraper', '--scope', 'user']\n for (const [key, value] of Object.entries(envConfig(options))) {\n args.push('--env', `${key}=${value}`)\n }\n args.push('--', 'npx', ...combinedNpxArgs(options))\n return args\n}\n\nexport function normalizeAgentHost(host: string): AgentHost {\n if (host === 'claude-code') return 'claude'\n if (host === 'claude' || host === 'codex' || host === 'claude-desktop') return host\n throw new Error('Unknown host \"' + host + '\". Use: codex, claude, claude-code, or claude-desktop')\n}\n\nexport function renderClaudeDesktopConfig(options: AgentConfigOptions = {}): string {\n return JSON.stringify({\n mcpServers: {\n 'mcp-scraper': {\n command: 'npx',\n args: combinedNpxArgs(options),\n env: envConfig(options),\n },\n },\n }, null, 2)\n}\n\nexport function renderAgentInstall(host: AgentHost, options: AgentConfigOptions = {}): string {\n const normalizedHost = normalizeAgentHost(host)\n const restart = 'Restart the MCP client so it starts a fresh npx process.'\n const applyCommand = `MCP_SCRAPER_API_KEY=${apiKeyValue(options)} npx -y -p mcp-scraper@latest mcp-scraper-cli agent install claude --apply`\n if (normalizedHost === 'codex') {\n return [\n '# Codex MCP config',\n renderCodexConfig(options),\n '',\n restart,\n ].join('\\n')\n }\n if (normalizedHost === 'claude') {\n return [\n '# Claude Code command',\n renderClaudeCommand(options),\n '',\n '# One-command Claude Code setup',\n applyCommand,\n '',\n restart,\n ].join('\\n')\n }\n return [\n '# Claude Desktop config',\n renderClaudeDesktopConfig(options),\n '',\n 'Desktop Extension: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n restart,\n ].join('\\n')\n}\n","import { access, mkdir, readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { PACKAGE_VERSION } from '../version.js'\nimport { combinedNpxArgs } from './agent-config.js'\n\nexport type DoctorStatus = 'pass' | 'warn' | 'fail' | 'skip'\n\nexport interface DoctorCheck {\n id: string\n label: string\n status: DoctorStatus\n detail: string\n fix?: string\n}\n\nexport interface DoctorOptions {\n apiKey?: string\n apiUrl?: string\n outputDir?: string\n fetchImpl?: typeof fetch\n}\n\nexport interface DoctorOutput {\n ok: boolean\n version: string\n npmLatest: string | null\n checks: DoctorCheck[]\n recommendedConfig: {\n command: 'npx'\n args: string[]\n env: Record<string, string>\n }\n}\n\nfunction status(ok: boolean, warn = false): DoctorStatus {\n if (ok) return 'pass'\n return warn ? 'warn' : 'fail'\n}\n\nfunction parseMajor(version: string): number {\n return Number(version.replace(/^v/, '').split('.')[0] ?? 0)\n}\n\nasync function readKeyFile(): Promise<string | null> {\n const path = process.env.MCP_SCRAPER_KEY_PATH?.trim() || join(homedir(), '.mcp-scraper-key')\n try {\n const value = (await readFile(path, 'utf8')).trim()\n return value || null\n } catch {\n return null\n }\n}\n\nasync function npmLatest(fetchImpl: typeof fetch): Promise<string | null> {\n try {\n const res = await fetchImpl('https://registry.npmjs.org/mcp-scraper/latest', {\n signal: AbortSignal.timeout(5_000),\n })\n if (!res.ok) return null\n const data = await res.json() as { version?: string }\n return data.version ?? null\n } catch {\n return null\n }\n}\n\nexport async function runDoctor(options: DoctorOptions = {}): Promise<DoctorOutput> {\n const fetchImpl = options.fetchImpl ?? fetch\n const apiUrl = (options.apiUrl ?? process.env.MCP_SCRAPER_API_URL ?? 'https://mcpscraper.dev').replace(/\\/$/, '')\n const outputDir = options.outputDir ?? process.env.MCP_SCRAPER_OUTPUT_DIR ?? join(homedir(), 'Downloads', 'mcp-scraper')\n const configuredKey = options.apiKey?.trim() || process.env.MCP_SCRAPER_API_KEY?.trim() || await readKeyFile()\n const latest = await npmLatest(fetchImpl)\n\n const checks: DoctorCheck[] = []\n const nodeMajor = parseMajor(process.version)\n checks.push({\n id: 'node',\n label: 'Node.js',\n status: status(nodeMajor >= 20),\n detail: process.version,\n fix: nodeMajor >= 20 ? undefined : 'Install Node.js 20 or newer.',\n })\n\n checks.push({\n id: 'package_version',\n label: 'Local package',\n status: latest && latest !== PACKAGE_VERSION ? 'warn' : 'pass',\n detail: latest ? `local ${PACKAGE_VERSION}, npm latest ${latest}` : `local ${PACKAGE_VERSION}, npm latest unavailable`,\n fix: latest && latest !== PACKAGE_VERSION ? 'Use mcp-scraper@latest and restart the MCP client.' : undefined,\n })\n\n checks.push({\n id: 'api_key',\n label: 'API key',\n status: configuredKey ? 'pass' : 'warn',\n detail: configuredKey ? 'configured' : 'not configured',\n fix: configuredKey ? undefined : 'Set MCP_SCRAPER_API_KEY or pass --api-key.',\n })\n\n try {\n await mkdir(outputDir, { recursive: true })\n await access(outputDir)\n checks.push({ id: 'output_dir', label: 'Output directory', status: 'pass', detail: outputDir })\n } catch (err) {\n checks.push({\n id: 'output_dir',\n label: 'Output directory',\n status: 'fail',\n detail: outputDir,\n fix: err instanceof Error ? err.message : 'Create a writable output directory.',\n })\n }\n\n if (configuredKey) {\n try {\n const res = await fetchImpl(`${apiUrl}/me`, {\n headers: { 'x-api-key': configuredKey },\n signal: AbortSignal.timeout(8_000),\n })\n checks.push({\n id: 'api_reachability',\n label: 'Hosted API',\n status: res.ok ? 'pass' : 'fail',\n detail: `${apiUrl}/me returned ${res.status}`,\n fix: res.ok ? undefined : 'Verify the API key and account status.',\n })\n } catch (err) {\n checks.push({\n id: 'api_reachability',\n label: 'Hosted API',\n status: 'fail',\n detail: err instanceof Error ? err.message : String(err),\n fix: 'Check network access and MCP_SCRAPER_API_URL.',\n })\n }\n } else {\n checks.push({\n id: 'api_reachability',\n label: 'Hosted API',\n status: 'skip',\n detail: 'skipped because no API key is configured',\n })\n }\n\n checks.push({\n id: 'mcp_config',\n label: 'MCP command',\n status: 'pass',\n detail: `npx ${combinedNpxArgs().join(' ')}`,\n fix: 'Restart the MCP client after package updates.',\n })\n\n return {\n ok: checks.every(check => check.status === 'pass' || check.status === 'skip'),\n version: PACKAGE_VERSION,\n npmLatest: latest,\n checks,\n recommendedConfig: {\n command: 'npx',\n args: combinedNpxArgs(),\n env: { MCP_SCRAPER_API_KEY: configuredKey ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key' },\n },\n }\n}\n\nexport function renderDoctor(output: DoctorOutput): string {\n const icon: Record<DoctorStatus, string> = { pass: 'PASS', warn: 'WARN', fail: 'FAIL', skip: 'SKIP' }\n const lines = [\n `mcp-scraper doctor v${output.version}`,\n '',\n ...output.checks.map(check => {\n const fix = check.fix ? `\\n Fix: ${check.fix}` : ''\n return `[${icon[check.status]}] ${check.label}: ${check.detail}${fix}`\n }),\n '',\n `Recommended MCP command: npx ${output.recommendedConfig.args.join(' ')}`,\n ]\n return lines.join('\\n')\n}\n\n","export const AGENT_PROMPTS: Record<string, string> = {\n 'agent-packet': [\n '# MCP Scraper Agent Packet Prompt',\n '',\n 'Use MCP Scraper as the evidence layer. Run the agent-packet workflow for the target keyword/domain, then treat `evidence.json`, `sources.csv`, and `competitors.csv` as source of truth.',\n '',\n 'Do not invent citations. If a recommendation is not supported by the packet, mark it as an assumption. Turn the evidence into a concise SEO brief, an implementation task list, and content recommendations tied to source rows.',\n ].join('\\n'),\n 'local-competitive-audit': [\n '# MCP Scraper Local Competitive Audit Prompt',\n '',\n 'Run the local-competitive-audit workflow for the niche and markets. Use the city summary, competitor CSV, and review-insight CSV to identify market difficulty, review themes, GBP category patterns, and weak competitors.',\n '',\n 'Ground recommendations in Maps rank position, review count, star rating, categories, profile details, and review topics. Do not overstate heuristic opportunity scores.',\n ].join('\\n'),\n 'directory-workflow': [\n '# MCP Scraper Directory Workflow Prompt',\n '',\n 'Use directory_workflow when the user wants cities selected by population and Google Maps candidates per city. Keep query and location separate. Preserve result_position, source_location, review stars/count, categories, and profile URLs for downstream CSV or directory use.',\n ].join('\\n'),\n 'map-comparison': [\n '# MCP Scraper Maps Comparison Prompt',\n '',\n 'Run the map-comparison workflow when the user wants to compare local Maps competitors in a city or across selected markets. Use `maps-results.csv`, `map-comparison.csv`, and `profile-insights.csv` as source of truth.',\n '',\n 'Ground recommendations in result_position, review_stars, review_count, category, website presence, review topics, and profile attributes. Treat review gaps and missing websites as opportunity signals, not guaranteed ranking factors.',\n ].join('\\n'),\n 'serp-comparison': [\n '# MCP Scraper SERP Comparison Prompt',\n '',\n 'Run the serp-comparison workflow when the user wants to know why competitors outrank a page or what the SERP rewards. Use organic results, extracted page headings, PAA questions, and AI Overview citations before making recommendations.',\n '',\n 'Tie each recommendation to `content-gaps.csv`, `page-comparison.csv`, `paa-questions.csv`, or `ai-overview-citations.csv`. Do not invent missing sections or citations.',\n ].join('\\n'),\n 'paa-expansion-brief': [\n '# MCP Scraper PAA Expansion Brief Prompt',\n '',\n 'Run the paa-expansion-brief workflow when the user wants to figure out what to write from People Also Ask expansion. Use `section-map.csv` to structure the brief and `paa-questions.csv` for exact customer-language headings.',\n '',\n 'Answer the highest-priority questions directly, preserve source URLs when present, and separate evidence-backed sections from assumptions.',\n ].join('\\n'),\n 'ai-overview-language': [\n '# MCP Scraper AI Overview Language Prompt',\n '',\n 'Run the ai-overview-language workflow when the user wants to know how to phrase content for AI Overview inclusion. Use `claim-patterns.csv`, `language-guidance.csv`, `ai-overview-citations.csv`, and PAA follow-ups as evidence.',\n '',\n 'Recommend concise answer blocks, criteria/step language, citation hooks, and follow-up sections. Do not claim the target will be cited; frame the output as evidence-based language guidance.',\n ].join('\\n'),\n 'ai-citation-monitor': [\n '# MCP Scraper AI Citation Monitor Prompt',\n '',\n 'Use search_serp and harvest_paa to check whether the target brand/domain appears in AI Overview citations, organic results, People Also Ask sources, local pack, forums, and videos. Save evidence before summarizing trends or gaps.',\n ].join('\\n'),\n 'serp-brief': [\n '# MCP Scraper SERP Brief Prompt',\n '',\n 'Use live SERP, PAA, AI Overview, forum, video, and source evidence to create a writer brief. Tie each recommended section to evidence rows and identify missing proof, entities, comparisons, and customer questions.',\n ].join('\\n'),\n}\n\nexport function listPrompts(): string[] {\n return Object.keys(AGENT_PROMPTS).sort()\n}\n\nexport function renderPrompt(name: string): string {\n const prompt = AGENT_PROMPTS[name]\n if (!prompt) throw new Error(`Unknown prompt \"${name}\". Available: ${listPrompts().join(', ')}`)\n return prompt\n}\n","#!/usr/bin/env node\nimport { runHumanCli } from '../src/cli/human-cli.js'\n\nrunHumanCli().catch((err) => {\n console.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n})\n\n"],"mappings":"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","names":["mkdir","join","join","mkdir"]}
@@ -101,7 +101,7 @@ function renderInstallTerminal(options) {
101
101
  }
102
102
 
103
103
  // src/version.ts
104
- var PACKAGE_VERSION = "0.3.20";
104
+ var PACKAGE_VERSION = "0.3.22";
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('(45 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'], 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.20'\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('(45 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'], 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.22'\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-DE7WP4UU.js";
5
5
  import {
6
6
  PACKAGE_VERSION
7
- } from "../chunk-XLHBBA3U.js";
7
+ } from "../chunk-2IXMOXDH.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;
@@ -456,7 +456,7 @@ render();
456
456
  }
457
457
 
458
458
  // src/version.ts
459
- var PACKAGE_VERSION = "0.3.20";
459
+ var PACKAGE_VERSION = "0.3.22";
460
460
 
461
461
  // src/mcp/browser-agent-tool-schemas.ts
462
462
  var import_zod = require("zod");