mcp-scraper 0.2.19 → 0.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -5
- package/dist/bin/api-server.cjs +1072 -349
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/browser-agent-stdio-server.cjs +1274 -75
- package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
- package/dist/bin/browser-agent-stdio-server.js +4 -2
- package/dist/bin/browser-agent-stdio-server.js.map +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +659 -210
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +108 -9
- package/dist/bin/mcp-scraper-cli.js.map +1 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs +2104 -566
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.js +7 -4
- package/dist/bin/mcp-scraper-combined-stdio-server.js.map +1 -1
- package/dist/bin/mcp-scraper-install.cjs +3 -3
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +726 -387
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -2
- package/dist/bin/mcp-stdio-server.js.map +1 -1
- package/dist/bin/paa-harvest.cjs +5 -3
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +5 -2
- package/dist/bin/paa-harvest.js.map +1 -1
- package/dist/{chunk-TL7YTFLH.js → chunk-DBQDG7EH.js} +99 -27
- package/dist/chunk-DBQDG7EH.js.map +1 -0
- package/dist/chunk-DUEW4EOO.js +214 -0
- package/dist/chunk-DUEW4EOO.js.map +1 -0
- package/dist/{chunk-F44RBOJ5.js → chunk-H2R232HK.js} +216 -108
- package/dist/chunk-H2R232HK.js.map +1 -0
- package/dist/chunk-HS6OKELW.js +1786 -0
- package/dist/chunk-HS6OKELW.js.map +1 -0
- package/dist/{chunk-CQTAKXBN.js → chunk-IPW4LFOT.js} +11 -116
- package/dist/chunk-IPW4LFOT.js.map +1 -0
- package/dist/chunk-LFATOGDF.js +111 -0
- package/dist/chunk-LFATOGDF.js.map +1 -0
- package/dist/{chunk-MCBOZ2JF.js → chunk-MLNCKQ2B.js} +3 -3
- package/dist/chunk-MLNCKQ2B.js.map +1 -0
- package/dist/{chunk-4UEVYYDW.js → chunk-O5J7E4VX.js} +394 -57
- package/dist/chunk-O5J7E4VX.js.map +1 -0
- package/dist/{chunk-BSYPATSM.js → chunk-SXTXMFEQ.js} +2 -2
- package/dist/chunk-WN7PBKMV.js +28 -0
- package/dist/chunk-WN7PBKMV.js.map +1 -0
- package/dist/chunk-XKUDVN2E.js +7 -0
- package/dist/chunk-XKUDVN2E.js.map +1 -0
- package/dist/{db-P5X6UQ3E.js → db-BE4JVB3V.js} +8 -2
- package/dist/index.cjs +5 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/{server-CRUSZA2Q.js → server-24XIQ6W6.js} +248 -40
- package/dist/server-24XIQ6W6.js.map +1 -0
- package/dist/{worker-OZSWIS3F.js → worker-SLQ375UG.js} +8 -5
- package/dist/{worker-OZSWIS3F.js.map → worker-SLQ375UG.js.map} +1 -1
- package/docs/adr/0001-in-page-graphql-interception-for-anti-bot-scraping.md +2 -2
- package/docs/mcp-tool-craft-lint.generated.md +51 -0
- package/docs/mcp-tool-manifest.generated.json +1534 -0
- package/docs/specs/local-competitive-audit-spec.md +1 -2
- package/docs/specs/mcp-tool-definition-quality-audit-spec.md +1602 -0
- package/package.json +4 -1
- package/dist/chunk-4UEVYYDW.js.map +0 -1
- package/dist/chunk-76P4DKWR.js +0 -793
- package/dist/chunk-76P4DKWR.js.map +0 -1
- package/dist/chunk-CQTAKXBN.js.map +0 -1
- package/dist/chunk-F44RBOJ5.js.map +0 -1
- package/dist/chunk-MCBOZ2JF.js.map +0 -1
- package/dist/chunk-RU2HZD55.js +0 -7
- package/dist/chunk-RU2HZD55.js.map +0 -1
- package/dist/chunk-TL7YTFLH.js.map +0 -1
- package/dist/server-CRUSZA2Q.js.map +0 -1
- /package/dist/{chunk-BSYPATSM.js.map → chunk-SXTXMFEQ.js.map} +0 -0
- /package/dist/{db-P5X6UQ3E.js.map → db-BE4JVB3V.js.map} +0 -0
|
@@ -6,10 +6,16 @@ import {
|
|
|
6
6
|
openWorkflowReport,
|
|
7
7
|
runWorkflow,
|
|
8
8
|
workflowOutputBaseDir
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-H2R232HK.js";
|
|
10
|
+
import "../chunk-LFATOGDF.js";
|
|
11
|
+
import {
|
|
12
|
+
importChromeProfile,
|
|
13
|
+
listLocalChromeProfiles,
|
|
14
|
+
syncImportedChromeProfile
|
|
15
|
+
} from "../chunk-DUEW4EOO.js";
|
|
10
16
|
import {
|
|
11
17
|
PACKAGE_VERSION
|
|
12
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-XKUDVN2E.js";
|
|
13
19
|
|
|
14
20
|
// src/cli/human-cli.ts
|
|
15
21
|
import { Command } from "commander";
|
|
@@ -27,18 +33,37 @@ function packageSpec(options) {
|
|
|
27
33
|
function combinedNpxArgs(options = {}) {
|
|
28
34
|
return ["-y", "-p", packageSpec(options), "mcp-scraper-combined"];
|
|
29
35
|
}
|
|
36
|
+
function envConfig(options) {
|
|
37
|
+
const env = { MCP_SCRAPER_API_KEY: apiKeyValue(options) };
|
|
38
|
+
const profileName = options.browserProfileName?.trim();
|
|
39
|
+
if (options.browserMode === "local") {
|
|
40
|
+
env.MCP_SCRAPER_BROWSER_MODE = "local";
|
|
41
|
+
if (profileName) env.MCP_SCRAPER_BROWSER_PROFILE = profileName;
|
|
42
|
+
const executablePath = options.browserExecutablePath?.trim();
|
|
43
|
+
if (executablePath) env.MCP_SCRAPER_BROWSER_EXECUTABLE = executablePath;
|
|
44
|
+
} else {
|
|
45
|
+
if (profileName) env.BROWSER_AGENT_PROFILE_NAME = profileName;
|
|
46
|
+
if (options.browserProfileSaveChanges === true) env.BROWSER_AGENT_PROFILE_SAVE_CHANGES = "true";
|
|
47
|
+
}
|
|
48
|
+
return env;
|
|
49
|
+
}
|
|
50
|
+
function tomlInlineTable(value) {
|
|
51
|
+
const entries = Object.entries(value).map(([key, item]) => `${key} = ${JSON.stringify(item)}`);
|
|
52
|
+
return `{ ${entries.join(", ")} }`;
|
|
53
|
+
}
|
|
30
54
|
function renderCodexConfig(options = {}) {
|
|
31
55
|
return [
|
|
32
56
|
"[mcp_servers.mcp-scraper]",
|
|
33
57
|
'command = "npx"',
|
|
34
58
|
`args = ${JSON.stringify(combinedNpxArgs(options))}`,
|
|
35
|
-
`env =
|
|
59
|
+
`env = ${tomlInlineTable(envConfig(options))}`
|
|
36
60
|
].join("\n");
|
|
37
61
|
}
|
|
38
62
|
function renderClaudeCommand(options = {}) {
|
|
63
|
+
const env = Object.entries(envConfig(options)).map(([key, value]) => ` --env ${key}=${value}`);
|
|
39
64
|
return [
|
|
40
65
|
"claude mcp add mcp-scraper --scope user",
|
|
41
|
-
|
|
66
|
+
...env,
|
|
42
67
|
` -- npx ${combinedNpxArgs(options).join(" ")}`
|
|
43
68
|
].join(" \\\n");
|
|
44
69
|
}
|
|
@@ -48,9 +73,7 @@ function renderClaudeDesktopConfig(options = {}) {
|
|
|
48
73
|
"mcp-scraper": {
|
|
49
74
|
command: "npx",
|
|
50
75
|
args: combinedNpxArgs(options),
|
|
51
|
-
env:
|
|
52
|
-
MCP_SCRAPER_API_KEY: apiKeyValue(options)
|
|
53
|
-
}
|
|
76
|
+
env: envConfig(options)
|
|
54
77
|
}
|
|
55
78
|
}
|
|
56
79
|
}, null, 2);
|
|
@@ -440,11 +463,87 @@ function buildHumanCli() {
|
|
|
440
463
|
result.next_step ?? "Complete checkout, then retry the MCP request."
|
|
441
464
|
].join("\n"), false);
|
|
442
465
|
});
|
|
466
|
+
const browser = program.command("browser").description("Inspect and manage browser-agent profile setup helpers.");
|
|
467
|
+
browser.command("profiles").description("List local Chrome profiles and suggested managed browser profile names.").option("--email <email>", "Filter by Chrome account email or displayed profile name").option("--user-data-dir <path>", "Chrome user data directory").option("--json", "Print machine-readable JSON").action(async (opts) => {
|
|
468
|
+
const profiles = await listLocalChromeProfiles(opts.userDataDir, opts.email);
|
|
469
|
+
if (opts.json) {
|
|
470
|
+
writeOutput({ profiles }, true);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (!profiles.length) {
|
|
474
|
+
writeOutput("No matching Chrome profiles found.", false);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const lines = [
|
|
478
|
+
"Local Chrome profiles:",
|
|
479
|
+
...profiles.map((profile) => [
|
|
480
|
+
`${profile.email || "(no email)"} ${profile.chromeProfileDirectory} ${profile.displayName}`,
|
|
481
|
+
` suggested profile name: ${profile.recommendedKernelProfileName}`,
|
|
482
|
+
` local Chrome path: ${profile.chromeProfilePath}`
|
|
483
|
+
].join("\n")),
|
|
484
|
+
"",
|
|
485
|
+
"To clone a real local Chrome profile for MCP local browser mode:",
|
|
486
|
+
" mcp-scraper-cli browser import-chrome --email you@example.com --name <suggested profile name>",
|
|
487
|
+
"Then generate config with:",
|
|
488
|
+
" mcp-scraper-cli agent install claude-desktop --browser-mode local --browser-profile <suggested profile name>"
|
|
489
|
+
];
|
|
490
|
+
writeOutput(lines.join("\n"), false);
|
|
491
|
+
});
|
|
492
|
+
browser.command("import-chrome").description("Clone a local Chrome profile into MCP Scraper managed local browser storage.").option("--email <email>", "Chrome account email or displayed profile name to import").option("--name <name>", "Managed MCP Scraper browser profile name").option("--chrome-profile <directory>", "Chrome profile directory, for example Default or Profile 1").option("--user-data-dir <path>", "Source Chrome user data directory").option("--output-dir <path>", "Managed profile base directory").option("--browser-executable <path>", "Chrome executable path for local launches").option("--overwrite", "Overwrite an existing managed profile clone").option("--json", "Print machine-readable JSON").action(async (opts) => {
|
|
493
|
+
const result = await importChromeProfile({
|
|
494
|
+
email: opts.email,
|
|
495
|
+
name: opts.name,
|
|
496
|
+
chromeProfileDirectory: opts.chromeProfile,
|
|
497
|
+
sourceUserDataDir: opts.userDataDir,
|
|
498
|
+
outputDir: opts.outputDir,
|
|
499
|
+
browserExecutablePath: opts.browserExecutable,
|
|
500
|
+
overwrite: opts.overwrite
|
|
501
|
+
});
|
|
502
|
+
if (opts.json) {
|
|
503
|
+
writeOutput(result, true);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
writeOutput([
|
|
507
|
+
`Imported Chrome profile: ${result.profile.name}`,
|
|
508
|
+
`Source: ${result.sourceProfile.email || result.sourceProfile.displayName || result.sourceProfile.chromeProfileDirectory} (${result.sourceProfile.chromeProfileDirectory})`,
|
|
509
|
+
`Managed user data dir: ${result.profile.userDataDir}`,
|
|
510
|
+
"",
|
|
511
|
+
"Install/config command:",
|
|
512
|
+
` mcp-scraper-cli agent install codex --browser-mode local --browser-profile ${result.profile.name}`,
|
|
513
|
+
"",
|
|
514
|
+
"Restart the MCP client after updating config. Re-run sync-profile after signing into new sites in normal Chrome."
|
|
515
|
+
].join("\n"), false);
|
|
516
|
+
});
|
|
517
|
+
browser.command("sync-profile <name>").description("Refresh a managed local browser profile from its recorded source Chrome profile.").option("--output-dir <path>", "Managed profile base directory").option("--browser-executable <path>", "Chrome executable path for local launches").option("--json", "Print machine-readable JSON").action(async (name, opts) => {
|
|
518
|
+
const result = await syncImportedChromeProfile(name, {
|
|
519
|
+
outputDir: opts.outputDir,
|
|
520
|
+
browserExecutablePath: opts.browserExecutable
|
|
521
|
+
});
|
|
522
|
+
if (opts.json) {
|
|
523
|
+
writeOutput(result, true);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
writeOutput([
|
|
527
|
+
`Synced Chrome profile: ${result.profile.name}`,
|
|
528
|
+
`Source: ${result.sourceProfile.email || result.sourceProfile.displayName || result.sourceProfile.chromeProfileDirectory} (${result.sourceProfile.chromeProfileDirectory})`,
|
|
529
|
+
`Managed user data dir: ${result.profile.userDataDir}`,
|
|
530
|
+
"Restart any local browser sessions that were using this profile."
|
|
531
|
+
].join("\n"), false);
|
|
532
|
+
});
|
|
443
533
|
const agent = program.command("agent").description("Generate AI-agent install configs and workflow prompts.");
|
|
444
|
-
agent.command("install <host>").description("Print install/config instructions for codex, claude, or claude-desktop.").option("--api-key <key>", "API key to place in generated config").option("--package <spec>", "npm package spec", "mcp-scraper@latest").option("--json", "Print machine-readable JSON").action((host, opts) => {
|
|
534
|
+
agent.command("install <host>").description("Print install/config instructions for codex, claude, 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-mode <mode>", "Browser mode: hosted or local", "hosted").option("--browser-profile <name>", "Default browser profile for browser_open sessions. In local mode this is a managed MCP Scraper profile name; in hosted mode it is a Kernel profile name.").option("--browser-executable <path>", "Chrome executable path for local browser mode").option("--save-browser-profile-changes", "Persist cookies/local storage back to the named browser profile when sessions close").option("--json", "Print machine-readable JSON").action((host, opts) => {
|
|
445
535
|
const valid = ["codex", "claude", "claude-desktop"];
|
|
446
536
|
if (!valid.includes(host)) throw new Error(`Unknown host "${host}". Use: ${valid.join(", ")}`);
|
|
447
|
-
const
|
|
537
|
+
const browserMode = String(opts.browserMode ?? "hosted");
|
|
538
|
+
if (!["hosted", "local"].includes(browserMode)) throw new Error("Unknown browser mode. Use: hosted or local");
|
|
539
|
+
const text = renderAgentInstall(host, {
|
|
540
|
+
apiKey: opts.apiKey,
|
|
541
|
+
packageSpec: opts.package,
|
|
542
|
+
browserMode,
|
|
543
|
+
browserProfileName: opts.browserProfile,
|
|
544
|
+
browserProfileSaveChanges: opts.saveBrowserProfileChanges,
|
|
545
|
+
browserExecutablePath: opts.browserExecutable
|
|
546
|
+
});
|
|
448
547
|
writeOutput(opts.json ? { host, text } : text, opts.json);
|
|
449
548
|
});
|
|
450
549
|
agent.command("prompt [name]").description("Print an agent prompt template.").option("--json", "Print machine-readable JSON").action((name, opts) => {
|
|
@@ -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 { renderAgentInstall, type AgentHost } 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 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 local 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 install/config instructions for codex, claude, 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('--json', 'Print machine-readable JSON')\n .action((host: AgentHost, opts) => {\n const valid = ['codex', 'claude', 'claude-desktop']\n if (!valid.includes(host)) throw new Error(`Unknown host \"${host}\". Use: ${valid.join(', ')}`)\n const text = renderAgentInstall(host, { apiKey: opts.apiKey, packageSpec: opts.package })\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-desktop'\n\nexport interface AgentConfigOptions {\n apiKey?: string\n packageSpec?: string\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-combined']\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 = { MCP_SCRAPER_API_KEY = \"${apiKeyValue(options)}\" }`,\n ].join('\\n')\n}\n\nexport function renderClaudeCommand(options: AgentConfigOptions = {}): string {\n return [\n 'claude mcp add mcp-scraper --scope user',\n ` --env MCP_SCRAPER_API_KEY=${apiKeyValue(options)}`,\n ` -- npx ${combinedNpxArgs(options).join(' ')}`,\n ].join(' \\\\\\n')\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: {\n MCP_SCRAPER_API_KEY: apiKeyValue(options),\n },\n },\n },\n }, null, 2)\n}\n\nexport function renderAgentInstall(host: AgentHost, options: AgentConfigOptions = {}): string {\n const restart = 'Restart the MCP client so it starts a fresh npx process.'\n if (host === 'codex') {\n return [\n '# Codex MCP config',\n renderCodexConfig(options),\n '',\n restart,\n ].join('\\n')\n }\n if (host === 'claude') {\n return [\n '# Claude Code command',\n renderClaudeCommand(options),\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\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":";;;;;;;;;;;;;;AAAA,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,SAAS,SAAAA,QAAO,iBAAiB;AACjC,SAAS,UAAU,QAAAC,aAAY;;;ACI/B,SAAS,YAAY,SAAqC;AACxD,SAAO,QAAQ,QAAQ,KAAK,KAAK;AACnC;AAEA,SAAS,YAAY,SAAqC;AACxD,SAAO,QAAQ,aAAa,KAAK,KAAK;AACxC;AAEO,SAAS,gBAAgB,UAA8B,CAAC,GAAa;AAC1E,SAAO,CAAC,MAAM,MAAM,YAAY,OAAO,GAAG,sBAAsB;AAClE;AAEO,SAAS,kBAAkB,UAA8B,CAAC,GAAW;AAC1E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,KAAK,UAAU,gBAAgB,OAAO,CAAC,CAAC;AAAA,IAClD,kCAAkC,YAAY,OAAO,CAAC;AAAA,EACxD,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,oBAAoB,UAA8B,CAAC,GAAW;AAC5E,SAAO;AAAA,IACL;AAAA,IACA,+BAA+B,YAAY,OAAO,CAAC;AAAA,IACnD,YAAY,gBAAgB,OAAO,EAAE,KAAK,GAAG,CAAC;AAAA,EAChD,EAAE,KAAK,OAAO;AAChB;AAEO,SAAS,0BAA0B,UAA8B,CAAC,GAAW;AAClF,SAAO,KAAK,UAAU;AAAA,IACpB,YAAY;AAAA,MACV,eAAe;AAAA,QACb,SAAS;AAAA,QACT,MAAM,gBAAgB,OAAO;AAAA,QAC7B,KAAK;AAAA,UACH,qBAAqB,YAAY,OAAO;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,MAAM,CAAC;AACZ;AAEO,SAAS,mBAAmB,MAAiB,UAA8B,CAAC,GAAW;AAC5F,QAAM,UAAU;AAChB,MAAI,SAAS,SAAS;AACpB,WAAO;AAAA,MACL;AAAA,MACA,kBAAkB,OAAO;AAAA,MACzB;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACA,MAAI,SAAS,UAAU;AACrB,WAAO;AAAA,MACL;AAAA,MACA,oBAAoB,OAAO;AAAA,MAC3B;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACA,SAAO;AAAA,IACL;AAAA,IACA,0BAA0B,OAAO;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;;;AC3EA,SAAS,QAAQ,OAAO,gBAAgB;AACxC,SAAS,eAAe;AACxB,SAAS,YAAY;AAiCrB,SAAS,OAAO,IAAa,OAAO,OAAqB;AACvD,MAAI,GAAI,QAAO;AACf,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,WAAW,SAAyB;AAC3C,SAAO,OAAO,QAAQ,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC;AAC5D;AAEA,eAAe,cAAsC;AACnD,QAAM,OAAO,QAAQ,IAAI,sBAAsB,KAAK,KAAK,KAAK,QAAQ,GAAG,kBAAkB;AAC3F,MAAI;AACF,UAAM,SAAS,MAAM,SAAS,MAAM,MAAM,GAAG,KAAK;AAClD,WAAO,SAAS;AAAA,EAClB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,UAAU,WAAiD;AACxE,MAAI;AACF,UAAM,MAAM,MAAM,UAAU,iDAAiD;AAAA,MAC3E,QAAQ,YAAY,QAAQ,GAAK;AAAA,IACnC,CAAC;AACD,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,WAAW;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,UAAU,UAAyB,CAAC,GAA0B;AAClF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,UAAU,QAAQ,UAAU,QAAQ,IAAI,uBAAuB,0BAA0B,QAAQ,OAAO,EAAE;AAChH,QAAM,YAAY,QAAQ,aAAa,QAAQ,IAAI,0BAA0B,KAAK,QAAQ,GAAG,aAAa,aAAa;AACvH,QAAM,gBAAgB,QAAQ,QAAQ,KAAK,KAAK,QAAQ,IAAI,qBAAqB,KAAK,KAAK,MAAM,YAAY;AAC7G,QAAM,SAAS,MAAM,UAAU,SAAS;AAExC,QAAM,SAAwB,CAAC;AAC/B,QAAM,YAAY,WAAW,QAAQ,OAAO;AAC5C,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ,OAAO,aAAa,EAAE;AAAA,IAC9B,QAAQ,QAAQ;AAAA,IAChB,KAAK,aAAa,KAAK,SAAY;AAAA,EACrC,CAAC;AAED,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ,UAAU,WAAW,kBAAkB,SAAS;AAAA,IACxD,QAAQ,SAAS,SAAS,eAAe,gBAAgB,MAAM,KAAK,SAAS,eAAe;AAAA,IAC5F,KAAK,UAAU,WAAW,kBAAkB,uDAAuD;AAAA,EACrG,CAAC;AAED,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ,gBAAgB,SAAS;AAAA,IACjC,QAAQ,gBAAgB,eAAe;AAAA,IACvC,KAAK,gBAAgB,SAAY;AAAA,EACnC,CAAC;AAED,MAAI;AACF,UAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,UAAM,OAAO,SAAS;AACtB,WAAO,KAAK,EAAE,IAAI,cAAc,OAAO,oBAAoB,QAAQ,QAAQ,QAAQ,UAAU,CAAC;AAAA,EAChG,SAAS,KAAK;AACZ,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,KAAK,eAAe,QAAQ,IAAI,UAAU;AAAA,IAC5C,CAAC;AAAA,EACH;AAEA,MAAI,eAAe;AACjB,QAAI;AACF,YAAM,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO;AAAA,QAC1C,SAAS,EAAE,aAAa,cAAc;AAAA,QACtC,QAAQ,YAAY,QAAQ,GAAK;AAAA,MACnC,CAAC;AACD,aAAO,KAAK;AAAA,QACV,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ,IAAI,KAAK,SAAS;AAAA,QAC1B,QAAQ,GAAG,MAAM,gBAAgB,IAAI,MAAM;AAAA,QAC3C,KAAK,IAAI,KAAK,SAAY;AAAA,MAC5B,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,aAAO,KAAK;AAAA,QACV,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACvD,KAAK;AAAA,MACP,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AACL,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAEA,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ,OAAO,gBAAgB,EAAE,KAAK,GAAG,CAAC;AAAA,IAC1C,KAAK;AAAA,EACP,CAAC;AAED,SAAO;AAAA,IACL,IAAI,OAAO,MAAM,WAAS,MAAM,WAAW,UAAU,MAAM,WAAW,MAAM;AAAA,IAC5E,SAAS;AAAA,IACT,WAAW;AAAA,IACX;AAAA,IACA,mBAAmB;AAAA,MACjB,SAAS;AAAA,MACT,MAAM,gBAAgB;AAAA,MACtB,KAAK,EAAE,qBAAqB,gBAAgB,yBAAyB,mBAAmB;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,SAAS,aAAa,QAA8B;AACzD,QAAM,OAAqC,EAAE,MAAM,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,OAAO;AACpG,QAAM,QAAQ;AAAA,IACZ,uBAAuB,OAAO,OAAO;AAAA,IACrC;AAAA,IACA,GAAG,OAAO,OAAO,IAAI,WAAS;AAC5B,YAAM,MAAM,MAAM,MAAM;AAAA,WAAc,MAAM,GAAG,KAAK;AACpD,aAAO,IAAI,KAAK,MAAM,MAAM,CAAC,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,GAAG,GAAG;AAAA,IACtE,CAAC;AAAA,IACD;AAAA,IACA,gCAAgC,OAAO,kBAAkB,KAAK,KAAK,GAAG,CAAC;AAAA,EACzE;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACnLO,IAAM,gBAAwC;AAAA,EACnD,gBAAgB;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,2BAA2B;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,sBAAsB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,kBAAkB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,mBAAmB;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,uBAAuB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,wBAAwB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,uBAAuB;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAAA,EACX,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,cAAwB;AACtC,SAAO,OAAO,KAAK,aAAa,EAAE,KAAK;AACzC;AAEO,SAAS,aAAa,MAAsB;AACjD,QAAM,SAAS,cAAc,IAAI;AACjC,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,mBAAmB,IAAI,iBAAiB,YAAY,EAAE,KAAK,IAAI,CAAC,EAAE;AAC/F,SAAO;AACT;;;AHzDA,SAAS,UAAU,OAAoC;AACrD,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI,QAAO;AAClE,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;AAEA,SAAS,WAAW,OAAqC;AACvD,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,UAAW,QAAO;AACvC,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,aAAa,OAAyD;AAC7E,SAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAC5F;AAEA,SAAS,cAAc,IAAY,MAAwD;AACzF,MAAI,OAAO,kBAAkB,OAAO,qBAAqB,OAAO,wBAAwB;AACtF,WAAO,aAAa;AAAA,MAClB,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,KAAK,KAAK;AAAA,MACV,UAAU,KAAK;AAAA,MACf,YAAY,UAAU,KAAK,UAAU;AAAA,MACrC,cAAc,UAAU,KAAK,YAAY;AAAA,MACzC,YAAY,UAAU,KAAK,UAAU;AAAA,MACrC,aAAa,KAAK,SAAS,QAAQ,QAAQ;AAAA,MAC3C,YAAY,KAAK,QAAQ,QAAQ,QAAQ;AAAA,MACzC,mBAAmB,WAAW,KAAK,iBAAiB;AAAA,MACpD,eAAe,KAAK,kBAAkB,QAAQ,QAAQ;AAAA,IACxD,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,uBAAuB;AAChC,WAAO,aAAa;AAAA,MAClB,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,cAAc,UAAU,KAAK,YAAY;AAAA,MACzC,OAAO,UAAU,KAAK,KAAK;AAAA,MAC3B,eAAe,KAAK,kBAAkB,QAAQ,QAAQ;AAAA,IACxD,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,eAAe,OAAO,6BAA6B,OAAO,kBAAkB;AACrF,WAAO,aAAa;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,eAAe,UAAU,KAAK,UAAU,KAAK,aAAa;AAAA,MAC1D,WAAW,UAAU,KAAK,SAAS;AAAA,MACnC,mBAAmB,UAAU,KAAK,WAAW,KAAK,qBAAqB,KAAK,UAAU;AAAA,MACtF,aAAa,UAAU,KAAK,WAAW;AAAA,MACvC,WAAW,KAAK;AAAA,MAChB,YAAY,OAAO,6BAA6B,OAAO,mBAAmB,UAAU,KAAK,UAAU,IAAI;AAAA,MACvG,YAAY,OAAO,6BAA6B,OAAO,mBAAmB,UAAU,KAAK,WAAW,KAAK,UAAU,IAAI;AAAA,MACvH,eAAe,KAAK,kBAAkB,QAAQ,QAAQ;AAAA,IACxD,CAAC;AAAA,EACH;AAEA,SAAO,aAAa,IAAI;AAC1B;AAEA,SAAS,YAAY,MAAe,MAAiC;AACnE,MAAI,MAAM;AACR,YAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,EAC3D,WAAW,OAAO,SAAS,UAAU;AACnC,YAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI;AAAA,EAClC,OAAO;AACL,YAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,EAC3D;AACF;AAEA,SAAS,WAAW,MAA+D;AACjF,MAAI,KAAK,MAAO,QAAO;AACvB,MAAI,KAAK,QAAS,QAAO;AACzB,SAAO;AACT;AAEA,SAAS,WAAW,MAAmE;AACrF,QAAM,SAAS,OAAO,KAAK,UAAU,QAAQ,IAAI,uBAAuB,EAAE,EAAE,KAAK;AACjF,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,kFAAkF;AAC/G,SAAO;AAAA,IACL,QAAQ,OAAO,KAAK,UAAU,QAAQ,IAAI,uBAAuB,wBAAwB,EAAE,QAAQ,OAAO,EAAE;AAAA,IAC5G;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,KAAsB;AAC7C,QAAM,UAAU,QAAQ,aAAa,WACjC,SACA,QAAQ,aAAa,UACnB,QACA;AACN,QAAM,OAAO,QAAQ,aAAa,UAAU,CAAC,MAAM,SAAS,IAAI,GAAG,IAAI,CAAC,GAAG;AAC3E,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,MAAM,EAAE,UAAU,MAAM,OAAO,SAAS,CAAC;AACtE,UAAM,MAAM;AACZ,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,WAAc,MAAc,QAAgB,MAA+B,MAA4B;AACpH,QAAM,EAAE,QAAQ,OAAO,IAAI,WAAW,IAAI;AAC1C,QAAM,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,IAAI,IAAI;AAAA,IAC1C;AAAA,IACA,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACf;AAAA,IACA,MAAM,QAAQ,OAAO,SAAY,KAAK,UAAU,IAAI;AAAA,EACtD,CAAC;AACD,QAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,UAAU,OAAQ,KAA6B,UAAU,WAC1D,KAA2B,QAC5B,2BAA2B,IAAI,MAAM;AACzC,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AACA,SAAO;AACT;AAEA,SAAS,wBAAwB,SAA2B;AAC1D,SAAO,QACJ,OAAO,uBAAuB,sBAAsB,EACpD,OAAO,qBAAqB,eAAe,EAC3C,OAAO,eAAe,iBAAiB,EACvC,OAAO,yBAAyB,iBAAiB,EACjD,OAAO,qBAAqB,8BAA8B,EAC1D,OAAO,uBAAuB,uBAAuB,EACrD,OAAO,qBAAqB,+CAA+C,EAC3E,OAAO,eAAe,qBAAqB,EAC3C,OAAO,aAAa,qCAAqC,EACzD,OAAO,YAAY,oCAAoC,EACvD,OAAO,mBAAmB,qCAAqC,EAC/D,OAAO,mBAAmB,UAAU,EACpC,OAAO,iBAAiB,yBAAyB,EACjD,OAAO,oBAAoB,yBAAyB,EACpD,OAAO,kBAAkB,uBAAuB,EAChD,OAAO,qBAAqB,yBAAyB,EACrD,OAAO,uBAAuB,2CAA2C,EACzE,OAAO,qBAAqB,qDAAqD,EACjF,OAAO,iBAAiB,8CAA8C,EACtE,OAAO,uBAAuB,2CAA2C;AAC9E;AAEO,SAAS,gBAAyB;AACvC,QAAM,UAAU,IAAI,QAAQ;AAC5B,UACG,KAAK,iBAAiB,EACtB,YAAY,qFAAqF,EACjG,QAAQ,eAAe;AAE1B,UAAQ,QAAQ,QAAQ,EACrB,YAAY,4FAA4F,EACxG,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,uBAAuB,0BAA0B,EACxD,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAAS;AACtB,UAAM,SAAS,MAAM,UAAU,EAAE,QAAQ,KAAK,QAAQ,QAAQ,KAAK,QAAQ,WAAW,KAAK,UAAU,CAAC;AACtG,gBAAY,KAAK,OAAO,SAAS,aAAa,MAAM,GAAG,KAAK,IAAI;AAChE,QAAI,CAAC,OAAO,GAAI,SAAQ,WAAW;AAAA,EACrC,CAAC;AAEH,QAAM,UAAU,QAAQ,QAAQ,SAAS,EAAE,YAAY,2CAA2C;AAClG,QAAM,qBAAqB,QAAQ,QAAQ,aAAa,EAAE,YAAY,uCAAuC;AAE7G,qBAAmB,QAAQ,MAAM,EAC9B,YAAY,sDAAsD,EAClE,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAAS;AACtB,UAAM,SAAS,MAAM,WAAqD,oBAAoB,QAAQ,MAAM,CAAC,CAAC;AAC9G,QAAI,KAAK,KAAM,aAAY,OAAO,aAAa,IAAI;AAAA,SAC9C;AACH,YAAM,UAAU,OAAO,aAAa;AACpC,kBAAY;AAAA,QACV,kBAAkB,OAAO,aAAa,iBAAiB,SAAS;AAAA,QAChE,gBAAgB,OAAO,aAAa,uBAAuB,SAAS;AAAA,QACpE,2BAA2B,SAAS,eAAe,UAAU;AAAA,QAC7D,oBAAoB,SAAS,oBAAoB,8CAA8C;AAAA,MACjG,EAAE,KAAK,IAAI,GAAG,KAAK;AAAA,IACrB;AAAA,EACF,CAAC;AAEH,qBAAmB,QAAQ,UAAU,EAClC,YAAY,iEAAiE,EAC7E,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,aAAa,kDAAkD,EACtE,OAAO,OAAO,SAAS;AACtB,UAAM,SAAS,MAAM,WAA2F,0CAA0C,QAAQ,MAAM,CAAC,CAAC;AAC1K,QAAI,KAAK,MAAM;AACb,kBAAY,QAAQ,IAAI;AACxB;AAAA,IACF;AACA,UAAM,SAAS,KAAK,SAAS,SAAS,gBAAgB,OAAO,YAAY;AACzE,gBAAY;AAAA,MACV,2BAA2B,OAAO,OAAO,eAAe,UAAU;AAAA,MAClE,SAAS,oBAAoB,OAAO,YAAY,KAAK,iBAAiB,OAAO,YAAY;AAAA,MACzF,OAAO,aAAa;AAAA,IACtB,EAAE,KAAK,IAAI,GAAG,KAAK;AAAA,EACrB,CAAC;AAEH,QAAM,QAAQ,QAAQ,QAAQ,OAAO,EAAE,YAAY,yDAAyD;AAC5G,QAAM,QAAQ,gBAAgB,EAC3B,YAAY,yEAAyE,EACrF,OAAO,mBAAmB,sCAAsC,EAChE,OAAO,oBAAoB,oBAAoB,oBAAoB,EACnE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,CAAC,MAAiB,SAAS;AACjC,UAAM,QAAQ,CAAC,SAAS,UAAU,gBAAgB;AAClD,QAAI,CAAC,MAAM,SAAS,IAAI,EAAG,OAAM,IAAI,MAAM,iBAAiB,IAAI,WAAW,MAAM,KAAK,IAAI,CAAC,EAAE;AAC7F,UAAM,OAAO,mBAAmB,MAAM,EAAE,QAAQ,KAAK,QAAQ,aAAa,KAAK,QAAQ,CAAC;AACxF,gBAAY,KAAK,OAAO,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA,EAC1D,CAAC;AAEH,QAAM,QAAQ,eAAe,EAC1B,YAAY,iCAAiC,EAC7C,OAAO,UAAU,6BAA6B,EAC9C,OAAO,CAAC,MAA0B,SAAS;AAC1C,QAAI,CAAC,MAAM;AACT,kBAAY,KAAK,OAAO,EAAE,SAAS,YAAY,EAAE,IAAI,YAAY,EAAE,KAAK,IAAI,GAAG,KAAK,IAAI;AACxF;AAAA,IACF;AACA,UAAM,OAAO,aAAa,IAAI;AAC9B,gBAAY,KAAK,OAAO,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA,EAC1D,CAAC;AAEH,QAAM,WAAW,QAAQ,QAAQ,UAAU,EAAE,YAAY,0BAA0B;AACnF,WAAS,QAAQ,MAAM,EACpB,YAAY,2BAA2B,EACvC,OAAO,UAAU,6BAA6B,EAC9C,OAAO,CAAC,SAAS;AAChB,UAAM,OAAO,wBAAwB;AACrC,QAAI,KAAK,KAAM,aAAY,EAAE,WAAW,KAAK,GAAG,IAAI;AAAA,QAC/C,aAAY,KAAK,IAAI,SAAO,GAAG,IAAI,EAAE,IAAK,IAAI,KAAK;AAAA,IAAO,IAAI,WAAW,EAAE,EAAE,KAAK,IAAI,GAAG,KAAK;AAAA,EACrG,CAAC;AAEH,WAAS,QAAQ,UAAU,EACxB,YAAY,0CAA0C,EACtD,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,uBAAuB,2BAA2B,EACzD,OAAO,UAAU,6BAA6B,EAC9C,OAAO,uBAAuB,sBAAsB,EACpD,OAAO,qBAAqB,eAAe,EAC3C,OAAO,eAAe,iBAAiB,EACvC,OAAO,yBAAyB,iBAAiB,EACjD,OAAO,qBAAqB,8BAA8B,EAC1D,OAAO,uBAAuB,uBAAuB,EACrD,OAAO,qBAAqB,+CAA+C,EAC3E,OAAO,eAAe,qBAAqB,EAC3C,OAAO,aAAa,qCAAqC,EACzD,OAAO,YAAY,oCAAoC,EACvD,OAAO,mBAAmB,qCAAqC,EAC/D,OAAO,mBAAmB,UAAU,EACpC,OAAO,iBAAiB,yBAAyB,EACjD,OAAO,oBAAoB,yBAAyB,EACpD,OAAO,kBAAkB,uBAAuB,EAChD,OAAO,qBAAqB,yBAAyB,EACrD,OAAO,uBAAuB,2CAA2C,EACzE,OAAO,qBAAqB,qDAAqD,EACjF,OAAO,iBAAiB,8CAA8C,EACtE,OAAO,uBAAuB,2CAA2C,EACzE,OAAO,OAAO,IAAY,SAAS;AAClC,UAAM,UAAU,MAAM,YAAY,IAAI,cAAc,IAAI,IAAI,GAAG;AAAA,MAC7D,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,IAClB,CAAC;AACD,QAAI,KAAK,KAAM,aAAY,SAAS,IAAI;AAAA,SACnC;AACH,kBAAY;AAAA,QACV,GAAG,QAAQ,KAAK,KAAK,QAAQ,MAAM;AAAA,QACnC,QAAQ;AAAA,QACR,QAAQ,aAAa,WAAW,QAAQ,UAAU,KAAK;AAAA,QACvD,QAAQ,SAAS,SAAS;AAAA,EAAc,QAAQ,SAAS,IAAI,OAAK,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,MAC7F,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,GAAG,KAAK;AAAA,IACrC;AAAA,EACF,CAAC;AAEH,QAAM,SAAS,QAAQ,QAAQ,QAAQ,EAAE,YAAY,uCAAuC;AAC5F,SAAO,QAAQ,MAAM,EAClB,YAAY,+BAA+B,EAC3C,OAAO,uBAAuB,2BAA2B,EACzD,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAAS;AACtB,UAAM,UAAU,MAAM,oBAAoB,KAAK,SAAS;AACxD,gBAAY,KAAK,OAAO,EAAE,QAAQ,IAAI,QAAQ,IAAI,OAAK,GAAG,EAAE,SAAS,IAAK,EAAE,QAAQ,IAAK,EAAE,MAAM,IAAK,EAAE,cAAc,EAAE,YAAY,EAAE,EAAE,KAAK,IAAI,GAAG,KAAK,IAAI;AAAA,EAC/J,CAAC;AACH,SAAO,QAAQ,WAAW,EACvB,YAAY,wCAAwC,EACpD,OAAO,uBAAuB,2BAA2B,EACzD,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,KAAK,QAAQ,SAAS;AACnC,UAAM,QAAQ,MAAM,mBAAmB,IAAI,KAAK,SAAS;AACzD,QAAI,CAAC,OAAO,WAAY,OAAM,IAAI,MAAM,wBAAwB,EAAE,GAAG;AACrE,gBAAY,KAAK,OAAO,EAAE,MAAM,MAAM,YAAY,KAAK,MAAM,IAAI,MAAM,YAAY,KAAK,IAAI;AAAA,EAC9F,CAAC;AACH,SAAO,QAAQ,WAAW,EACvB,YAAY,kCAAkC,EAC9C,OAAO,uBAAuB,2BAA2B,EACzD,OAAO,UAAU,gDAAgD,EACjE,OAAO,OAAO,KAAK,QAAQ,SAAS;AACnC,QAAI,KAAK,MAAM;AACb,YAAM,QAAQ,MAAM,mBAAmB,IAAI,KAAK,SAAS;AACzD,UAAI,CAAC,OAAO,WAAY,OAAM,IAAI,MAAM,wBAAwB,EAAE,GAAG;AACrE,kBAAY,EAAE,MAAM,MAAM,YAAY,KAAK,MAAM,GAAG,IAAI;AACxD;AAAA,IACF;AACA,UAAM,OAAO,MAAM,mBAAmB,IAAI,KAAK,SAAS;AACxD,gBAAY,WAAW,IAAI,IAAI,KAAK;AAAA,EACtC,CAAC;AAEH,QAAM,WAAW,QAAQ,QAAQ,UAAU,EAAE,YAAY,8CAA8C;AACvG,0BAAwB,SAAS,QAAQ,qBAAqB,EAC3D,YAAY,8CAA8C,EAC1D,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,iBAAiB,eAAe,EACvC,OAAO,WAAW,WAAW,EAC7B,OAAO,YAAY,YAAY,EAC/B,OAAO,aAAa,aAAa,EACjC,OAAO,mBAAmB,qBAAqB,KAAK,EACpD,OAAO,mBAAmB,mBAAmB,EAC7C,OAAO,uBAAuB,oCAAoC,EAClE,OAAO,UAAU,6BAA6B,CAAC,EAC/C,OAAO,OAAO,YAAoB,SAAS;AAC1C,UAAM,SAAS,MAAM,WAAW,wBAAwB,QAAQ,MAAM;AAAA,MACpE;AAAA,MACA,MAAM,KAAK;AAAA,MACX,OAAO,cAAc,YAAY,IAAI;AAAA,MACrC,SAAS,WAAW,IAAI;AAAA,MACxB,UAAU,KAAK;AAAA,MACf,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,IAClB,CAAC;AACD,gBAAY,QAAQ,KAAK,IAAI;AAAA,EAC/B,CAAC;AAEH,WAAS,QAAQ,MAAM,EACpB,YAAY,iCAAiC,EAC7C,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAAS;AACtB,UAAM,SAAS,MAAM,WAA0D,wBAAwB,OAAO,IAAI;AAClH,QAAI,KAAK,KAAM,aAAY,QAAQ,IAAI;AAAA,QAClC,aAAY,OAAO,UAAU,IAAI,iBAAe,GAAG,YAAY,EAAE,IAAK,YAAY,MAAM,IAAK,YAAY,WAAW,IAAK,YAAY,eAAe,EAAE,EAAE,EAAE,KAAK,IAAI,GAAG,KAAK;AAAA,EAClL,CAAC;AAEH,WAAS,QAAQ,YAAY,EAC1B,YAAY,mCAAmC,EAC/C,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,IAAY,SAAS,YAAY,MAAM,WAAW,wBAAwB,EAAE,IAAI,SAAS,MAAM,EAAE,QAAQ,SAAS,CAAC,GAAG,KAAK,IAAI,CAAC;AAEjJ,WAAS,QAAQ,aAAa,EAC3B,YAAY,oCAAoC,EAChD,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,IAAY,SAAS,YAAY,MAAM,WAAW,wBAAwB,EAAE,IAAI,SAAS,MAAM,EAAE,QAAQ,SAAS,CAAC,GAAG,KAAK,IAAI,CAAC;AAEjJ,WAAS,QAAQ,aAAa,EAC3B,YAAY,oCAAoC,EAChD,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,IAAY,SAAS,YAAY,MAAM,WAAW,wBAAwB,EAAE,IAAI,UAAU,IAAI,GAAG,KAAK,IAAI,CAAC;AAE5H,WAAS,QAAQ,UAAU,EACxB,YAAY,qCAAqC,EACjD,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,IAAY,SAAS,YAAY,MAAM,WAAW,wBAAwB,EAAE,QAAQ,QAAQ,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC;AAElI,QAAM,OAAO,QAAQ,QAAQ,MAAM,EAAE,YAAY,4CAA4C;AAC7F,OAAK,QAAQ,MAAM,EAChB,YAAY,4BAA4B,EACxC,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAAS;AACtB,UAAM,SAAS,MAAM,WAAqD,mBAAmB,OAAO,IAAI;AACxG,QAAI,KAAK,KAAM,aAAY,QAAQ,IAAI;AAAA,QAClC,aAAY,OAAO,KAAK,IAAI,SAAO,GAAG,IAAI,EAAE,IAAK,IAAI,MAAM,IAAK,IAAI,WAAW,IAAK,IAAI,SAAS,EAAE,EAAE,KAAK,IAAI,GAAG,KAAK;AAAA,EAC7H,CAAC;AAEH,OAAK,QAAQ,aAAa,EACvB,YAAY,6BAA6B,EACzC,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,IAAY,SAAS,YAAY,MAAM,WAAW,mBAAmB,EAAE,IAAI,OAAO,IAAI,GAAG,KAAK,IAAI,CAAC;AAEpH,OAAK,QAAQ,eAAe,EACzB,YAAY,yCAAyC,EACrD,OAAO,mBAAmB,qBAAqB,EAC/C,OAAO,mBAAmB,uBAAuB,wBAAwB,EACzE,OAAO,uBAAuB,oBAAoB,EAClD,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,IAAY,SAAS;AAClC,UAAM,SAAS,MAAM,WAAoG,mBAAmB,EAAE,IAAI,OAAO,IAAI;AAC7J,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW,IAAI;AAC1C,UAAM,SAASC,MAAK,KAAK,aAAa,sBAAsB,GAAG,sBAAsB,EAAE;AACvF,UAAMC,OAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,UAAM,aAAuB,CAAC;AAC9B,eAAW,YAAY,OAAO,IAAI,aAAa,CAAC,GAAG;AACjD,YAAM,MAAM,MAAM,MAAM,GAAG,MAAM,mBAAmB,EAAE,cAAc,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,OAAO,EAAE,CAAC;AACvH,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,sBAAsB,SAAS,KAAK,UAAU,IAAI,MAAM,EAAE;AACvF,YAAM,OAAOD,MAAK,QAAQ,SAAS,SAAS,IAAI,CAAC;AACjD,YAAM,UAAU,MAAM,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC;AAC1D,iBAAW,KAAK,IAAI;AAAA,IACtB;AACA,gBAAY,KAAK,OAAO,EAAE,OAAO,IAAI,OAAO,WAAW,IAAI,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI;AAAA,EAC7F,CAAC;AAEH,SAAO;AACT;AAEA,eAAsB,YAAY,OAAO,QAAQ,MAAqB;AACpE,QAAM,cAAc,EAAE,WAAW,IAAI;AACvC;;;AIxbA,YAAY,EAAE,MAAM,CAAC,QAAQ;AAC3B,UAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,UAAQ,KAAK,CAAC;AAChB,CAAC;","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 { listLocalChromeProfiles } from '../lib/chrome-profiles.js'\nimport { importChromeProfile, syncImportedChromeProfile } from '../lib/local-browser-profiles.js'\nimport { renderAgentInstall, type AgentHost, type BrowserMode } 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 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 local 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 browser = program.command('browser').description('Inspect and manage browser-agent profile setup helpers.')\n browser.command('profiles')\n .description('List local Chrome profiles and suggested managed browser profile names.')\n .option('--email <email>', 'Filter by Chrome account email or displayed profile name')\n .option('--user-data-dir <path>', 'Chrome user data directory')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const profiles = await listLocalChromeProfiles(opts.userDataDir, opts.email)\n if (opts.json) {\n writeOutput({ profiles }, true)\n return\n }\n if (!profiles.length) {\n writeOutput('No matching Chrome profiles found.', false)\n return\n }\n const lines = [\n 'Local Chrome profiles:',\n ...profiles.map(profile => [\n `${profile.email || '(no email)'}\\t${profile.chromeProfileDirectory}\\t${profile.displayName}`,\n ` suggested profile name: ${profile.recommendedKernelProfileName}`,\n ` local Chrome path: ${profile.chromeProfilePath}`,\n ].join('\\n')),\n '',\n 'To clone a real local Chrome profile for MCP local browser mode:',\n ' mcp-scraper-cli browser import-chrome --email you@example.com --name <suggested profile name>',\n 'Then generate config with:',\n ' mcp-scraper-cli agent install claude-desktop --browser-mode local --browser-profile <suggested profile name>',\n ]\n writeOutput(lines.join('\\n'), false)\n })\n\n browser.command('import-chrome')\n .description('Clone a local Chrome profile into MCP Scraper managed local browser storage.')\n .option('--email <email>', 'Chrome account email or displayed profile name to import')\n .option('--name <name>', 'Managed MCP Scraper browser profile name')\n .option('--chrome-profile <directory>', 'Chrome profile directory, for example Default or Profile 1')\n .option('--user-data-dir <path>', 'Source Chrome user data directory')\n .option('--output-dir <path>', 'Managed profile base directory')\n .option('--browser-executable <path>', 'Chrome executable path for local launches')\n .option('--overwrite', 'Overwrite an existing managed profile clone')\n .option('--json', 'Print machine-readable JSON')\n .action(async (opts) => {\n const result = await importChromeProfile({\n email: opts.email,\n name: opts.name,\n chromeProfileDirectory: opts.chromeProfile,\n sourceUserDataDir: opts.userDataDir,\n outputDir: opts.outputDir,\n browserExecutablePath: opts.browserExecutable,\n overwrite: opts.overwrite,\n })\n if (opts.json) {\n writeOutput(result, true)\n return\n }\n writeOutput([\n `Imported Chrome profile: ${result.profile.name}`,\n `Source: ${result.sourceProfile.email || result.sourceProfile.displayName || result.sourceProfile.chromeProfileDirectory} (${result.sourceProfile.chromeProfileDirectory})`,\n `Managed user data dir: ${result.profile.userDataDir}`,\n '',\n 'Install/config command:',\n ` mcp-scraper-cli agent install codex --browser-mode local --browser-profile ${result.profile.name}`,\n '',\n 'Restart the MCP client after updating config. Re-run sync-profile after signing into new sites in normal Chrome.',\n ].join('\\n'), false)\n })\n\n browser.command('sync-profile <name>')\n .description('Refresh a managed local browser profile from its recorded source Chrome profile.')\n .option('--output-dir <path>', 'Managed profile base directory')\n .option('--browser-executable <path>', 'Chrome executable path for local launches')\n .option('--json', 'Print machine-readable JSON')\n .action(async (name: string, opts) => {\n const result = await syncImportedChromeProfile(name, {\n outputDir: opts.outputDir,\n browserExecutablePath: opts.browserExecutable,\n })\n if (opts.json) {\n writeOutput(result, true)\n return\n }\n writeOutput([\n `Synced Chrome profile: ${result.profile.name}`,\n `Source: ${result.sourceProfile.email || result.sourceProfile.displayName || result.sourceProfile.chromeProfileDirectory} (${result.sourceProfile.chromeProfileDirectory})`,\n `Managed user data dir: ${result.profile.userDataDir}`,\n 'Restart any local browser sessions that were using this profile.',\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 install/config instructions for codex, claude, 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-mode <mode>', 'Browser mode: hosted or local', 'hosted')\n .option('--browser-profile <name>', 'Default browser profile for browser_open sessions. In local mode this is a managed MCP Scraper profile name; in hosted mode it is a Kernel profile name.')\n .option('--browser-executable <path>', 'Chrome executable path for local browser mode')\n .option('--save-browser-profile-changes', 'Persist cookies/local storage back to the named browser profile when sessions close')\n .option('--json', 'Print machine-readable JSON')\n .action((host: AgentHost, opts) => {\n const valid = ['codex', 'claude', 'claude-desktop']\n if (!valid.includes(host)) throw new Error(`Unknown host \"${host}\". Use: ${valid.join(', ')}`)\n const browserMode = String(opts.browserMode ?? 'hosted') as BrowserMode\n if (!['hosted', 'local'].includes(browserMode)) throw new Error('Unknown browser mode. Use: hosted or local')\n const text = renderAgentInstall(host, {\n apiKey: opts.apiKey,\n packageSpec: opts.package,\n browserMode,\n browserProfileName: opts.browserProfile,\n browserProfileSaveChanges: opts.saveBrowserProfileChanges,\n browserExecutablePath: opts.browserExecutable,\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-desktop'\nexport type BrowserMode = 'hosted' | 'local'\n\nexport interface AgentConfigOptions {\n apiKey?: string\n packageSpec?: string\n browserMode?: BrowserMode\n browserProfileName?: string\n browserProfileSaveChanges?: boolean\n browserExecutablePath?: string\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-combined']\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 (options.browserMode === 'local') {\n env.MCP_SCRAPER_BROWSER_MODE = 'local'\n if (profileName) env.MCP_SCRAPER_BROWSER_PROFILE = profileName\n const executablePath = options.browserExecutablePath?.trim()\n if (executablePath) env.MCP_SCRAPER_BROWSER_EXECUTABLE = executablePath\n } else {\n if (profileName) env.BROWSER_AGENT_PROFILE_NAME = profileName\n if (options.browserProfileSaveChanges === true) env.BROWSER_AGENT_PROFILE_SAVE_CHANGES = 'true'\n }\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 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 restart = 'Restart the MCP client so it starts a fresh npx process.'\n if (host === 'codex') {\n return [\n '# Codex MCP config',\n renderCodexConfig(options),\n '',\n restart,\n ].join('\\n')\n }\n if (host === 'claude') {\n return [\n '# Claude Code command',\n renderClaudeCommand(options),\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"]}
|