mcp-scraper 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/bin/api-server.cjs +934 -221
  2. package/dist/bin/api-server.cjs.map +1 -1
  3. package/dist/bin/api-server.js +2 -2
  4. package/dist/bin/mcp-scraper-cli.cjs +2 -1
  5. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  6. package/dist/bin/mcp-scraper-cli.js +3 -3
  7. package/dist/bin/mcp-scraper-install.cjs +3 -2
  8. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  9. package/dist/bin/mcp-scraper-install.js +2 -2
  10. package/dist/bin/mcp-stdio-server.cjs +83 -22
  11. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  12. package/dist/bin/mcp-stdio-server.js +4 -4
  13. package/dist/bin/paa-harvest.cjs +1 -0
  14. package/dist/bin/paa-harvest.cjs.map +1 -1
  15. package/dist/bin/paa-harvest.js +2 -2
  16. package/dist/{chunk-6TDUY7CA.js → chunk-4MFYMUIF.js} +25 -3
  17. package/dist/chunk-4MFYMUIF.js.map +1 -0
  18. package/dist/{chunk-T3VZD2I4.js → chunk-5HNHYUJ5.js} +3 -2
  19. package/dist/chunk-5HNHYUJ5.js.map +1 -0
  20. package/dist/chunk-7HICT4GY.js +7 -0
  21. package/dist/chunk-7HICT4GY.js.map +1 -0
  22. package/dist/{chunk-NNEIXK5L.js → chunk-FUWZWKGO.js} +2 -2
  23. package/dist/{chunk-3NIPPJGP.js → chunk-GFY6XHZS.js} +80 -21
  24. package/dist/chunk-GFY6XHZS.js.map +1 -0
  25. package/dist/{chunk-HBC4C75S.js → chunk-NJK5BTUK.js} +2 -2
  26. package/dist/{chunk-JOEZJL4I.js → chunk-NVUBFCJK.js} +2 -2
  27. package/dist/{chunk-BP27CZ5Q.js → chunk-XGIPATLV.js} +2 -1
  28. package/dist/chunk-XGIPATLV.js.map +1 -0
  29. package/dist/index.cjs +1 -0
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.js +2 -2
  32. package/dist/{server-Z4WKTE6F.js → server-6IYQQK6X.js} +793 -210
  33. package/dist/server-6IYQQK6X.js.map +1 -0
  34. package/dist/{site-extract-repository-2MQBAOX5.js → site-extract-repository-4NVO5KQA.js} +3 -3
  35. package/dist/{worker-RVZXIALX.js → worker-7XRZNLKB.js} +4 -4
  36. package/package.json +2 -1
  37. package/dist/chunk-3NIPPJGP.js.map +0 -1
  38. package/dist/chunk-6TDUY7CA.js.map +0 -1
  39. package/dist/chunk-BP27CZ5Q.js.map +0 -1
  40. package/dist/chunk-IXDYL7TE.js +0 -7
  41. package/dist/chunk-IXDYL7TE.js.map +0 -1
  42. package/dist/chunk-T3VZD2I4.js.map +0 -1
  43. package/dist/server-Z4WKTE6F.js.map +0 -1
  44. /package/dist/{chunk-NNEIXK5L.js.map → chunk-FUWZWKGO.js.map} +0 -0
  45. /package/dist/{chunk-HBC4C75S.js.map → chunk-NJK5BTUK.js.map} +0 -0
  46. /package/dist/{chunk-JOEZJL4I.js.map → chunk-NVUBFCJK.js.map} +0 -0
  47. /package/dist/{site-extract-repository-2MQBAOX5.js.map → site-extract-repository-4NVO5KQA.js.map} +0 -0
  48. /package/dist/{worker-RVZXIALX.js.map → worker-7XRZNLKB.js.map} +0 -0
@@ -6,12 +6,12 @@ import {
6
6
  openWorkflowReport,
7
7
  runWorkflow,
8
8
  workflowOutputBaseDir
9
- } from "../chunk-NNEIXK5L.js";
9
+ } from "../chunk-FUWZWKGO.js";
10
10
  import "../chunk-K443GQY5.js";
11
- import "../chunk-BP27CZ5Q.js";
11
+ import "../chunk-XGIPATLV.js";
12
12
  import {
13
13
  PACKAGE_VERSION
14
- } from "../chunk-IXDYL7TE.js";
14
+ } from "../chunk-7HICT4GY.js";
15
15
 
16
16
  // src/cli/human-cli.ts
17
17
  import { Command } from "commander";
@@ -53,13 +53,14 @@ function renderInstallTerminal(options) {
53
53
  "1/1 install surfaces ready",
54
54
  colorize("Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.", "lime", color),
55
55
  "",
56
- `${colorize("Tools", "cyan", color)} ${colorize("(48 MCP tools)", "muted", color)}`,
56
+ `${colorize("Tools", "cyan", color)} ${colorize("(128 MCP tools)", "muted", color)}`,
57
57
  toolRow("search", ["harvest_paa", "search_serp", "maps_search", "maps_place_intel"], color),
58
58
  toolRow("extract", ["extract_url", "map_site_urls", "extract_site", "audit_site", "directory_workflow"], color),
59
59
  toolRow("build", ["rank_tracker_workflow", "cron plan", "database prompt"], color),
60
60
  toolRow("media", ["youtube_harvest", "youtube_transcribe", "facebook_ad_search", "facebook_page_intel", "facebook_ad_transcribe", "facebook_video_transcribe", "instagram_profile_content", "instagram_media_download", "reddit_thread"], color),
61
61
  toolRow("browser", ["browser_open", "browser_profile_connect", "browser_profile_list", "browser_close", "browser_screenshot", "browser_read", "browser_locate", "browser_replay_mark", "browser_replay_annotate"], color),
62
62
  toolRow("account", ["credits_info", "reports", "MCP resources"], color),
63
+ toolRow("memory", ["memory-put", "memory-get", "memory-search", "list-vaults", "record-fact", "list-scheduled-actions"], color),
63
64
  `${colorize("Workflows", "cyan", color)} ${colorize("(MCP + CLI + API)", "muted", color)}`,
64
65
  toolRow("route", ["workflow_list", "workflow_suggest", "workflow_run", "workflow_step", "workflow_status", "workflow_artifact_read"], color),
65
66
  toolRow("seo", ["directory", "agent-packet", "competitive audit", "map/serp comparison", "PAA/AIO briefs", "scheduled runs"], color),
@@ -101,7 +102,7 @@ function renderInstallTerminal(options) {
101
102
  }
102
103
 
103
104
  // src/version.ts
104
- var PACKAGE_VERSION = "0.4.0";
105
+ var PACKAGE_VERSION = "0.4.2";
105
106
 
106
107
  // bin/mcp-scraper-install.ts
107
108
  var noColor = process.argv.includes("--no-color") || process.env.NO_COLOR !== void 0 || process.env.FORCE_COLOR === "0" || !process.stdout.isTTY;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/install-terminal.ts","../../src/version.ts","../../bin/mcp-scraper-install.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(48 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n","export const PACKAGE_VERSION = '0.4.0'\n","#!/usr/bin/env node\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\n\nconst noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\nconst help = process.argv.includes('--help') || process.argv.includes('-h')\nif (help) {\n process.stdout.write([\n 'Usage: mcp-scraper-install [--no-color]',\n '',\n 'Prints the branded MCP Scraper terminal install card and copyable install commands.',\n 'mcp-scraper prints the same card in a human terminal and runs as the MCP stdio server in clients.',\n '',\n ].join('\\n'))\n process.exit(0)\n}\n\nprocess.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n}))\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/install-terminal.ts","../../src/version.ts","../../bin/mcp-scraper-install.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(128 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'audit_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_workflow', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download', 'reddit_thread'], color),\n toolRow('browser', ['browser_open', 'browser_profile_connect', 'browser_profile_list', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n toolRow('memory', ['memory-put', 'memory-get', 'memory-search', 'list-vaults', 'record-fact', 'list-scheduled-actions'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_connect, send the watch_url, let the user sign in, then call browser_profile_list until AUTHENTICATED.',\n 'Stack logins / reconnect: run browser_profile_connect again with the same profile name and another domain to add accounts or refresh a login.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_connect with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_list, then browser_open with the returned profile. Add more logins by calling browser_profile_connect again with the same profile and a new domain.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n","export const PACKAGE_VERSION = '0.4.2'\n","#!/usr/bin/env node\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\n\nconst noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\nconst help = process.argv.includes('--help') || process.argv.includes('-h')\nif (help) {\n process.stdout.write([\n 'Usage: mcp-scraper-install [--no-color]',\n '',\n 'Prints the branded MCP Scraper terminal install card and copyable install commands.',\n 'mcp-scraper prints the same card in a human terminal and runs as the MCP stdio server in clients.',\n '',\n ].join('\\n'))\n process.exit(0)\n}\n\nprocess.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n}))\n"],"mappings":"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","names":[]}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  renderInstallTerminal
4
- } from "../chunk-T3VZD2I4.js";
4
+ } from "../chunk-5HNHYUJ5.js";
5
5
  import {
6
6
  PACKAGE_VERSION
7
- } from "../chunk-IXDYL7TE.js";
7
+ } from "../chunk-7HICT4GY.js";
8
8
 
9
9
  // bin/mcp-scraper-install.ts
10
10
  var noColor = process.argv.includes("--no-color") || process.env.NO_COLOR !== void 0 || process.env.FORCE_COLOR === "0" || !process.stdout.isTTY;
@@ -474,7 +474,7 @@ render();
474
474
  }
475
475
 
476
476
  // src/version.ts
477
- var PACKAGE_VERSION = "0.4.0";
477
+ var PACKAGE_VERSION = "0.4.2";
478
478
 
479
479
  // src/mcp/browser-agent-tool-schemas.ts
480
480
  var import_zod = require("zod");
@@ -696,7 +696,7 @@ var BrowserProfileLogin = import_zod.z.object({
696
696
  var BrowserProfileConnectOutputSchema = {
697
697
  ok: import_zod.z.boolean(),
698
698
  tool: import_zod.z.literal("browser_profile_connect"),
699
- session_id: NullableString,
699
+ session_id: NullableString.describe("The underlying live browser session id backing this sign-in."),
700
700
  auth_connection_id: import_zod.z.string(),
701
701
  watch_url: import_zod.z.string().describe("mcpscraper.dev sign-in link to give the user so they can complete this login."),
702
702
  live_view_url: NullableString.describe("Deprecated; always null. Open watch_url to view the sign-in."),
@@ -706,10 +706,10 @@ var BrowserProfileConnectOutputSchema = {
706
706
  account_email: NullableString,
707
707
  note: NullableString,
708
708
  status: import_zod.z.string(),
709
- flow_status: NullableString,
710
- flow_step: NullableString,
711
- flow_expires_at: NullableString,
712
- post_login_url: NullableString,
709
+ flow_status: NullableString.describe("Deprecated; always null."),
710
+ flow_step: NullableString.describe("Deprecated; always null."),
711
+ flow_expires_at: NullableString.describe("Deprecated; always null."),
712
+ post_login_url: NullableString.describe("Deprecated; always null."),
713
713
  connected_logins: import_zod.z.array(BrowserProfileLogin).describe("Every login currently saved in this profile, so you can see what else is connected."),
714
714
  next_steps: import_zod.z.array(import_zod.z.string()),
715
715
  raw: BrowserRawObject.optional()
@@ -1198,6 +1198,11 @@ function slugPart(value) {
1198
1198
  if (!trimmed) return null;
1199
1199
  return trimmed.replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/.*$/, "").replace(/[^a-z0-9._-]+/g, "-").replace(/[._-]+/g, "-").replace(/^-+|-+$/g, "");
1200
1200
  }
1201
+ function normalizeDomain(value) {
1202
+ const trimmed = value?.trim().toLowerCase();
1203
+ if (!trimmed) return null;
1204
+ return trimmed.replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/.*$/, "").replace(/[^a-z0-9.-]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
1205
+ }
1201
1206
  function savedProfileNameFromEmail(email) {
1202
1207
  const value = slugPart(email);
1203
1208
  if (!value) return null;
@@ -1307,13 +1312,13 @@ function registerBrowserAgentMcpTools(server2, opts) {
1307
1312
  "browser_profile_connect",
1308
1313
  {
1309
1314
  title: "Save a Site Login to a Profile",
1310
- description: "Save a logged-in browser session so this server can reuse a site the user is signed into (ChatGPT, Claude, Reddit, any account-gated site). Returns a watch_url; the user signs in fresh (existing browser cookies are NOT imported) and cookies save to a named profile. ONE profile holds MANY logins \u2014 call again with the same profile and a different domain to stack another account. NOT for one-off scraping (use extract_url) or driving the browser (use browser_open). After sign-in, poll browser_profile_list until AUTHENTICATED, then browser_open with the profile.",
1315
+ description: 'Open a live hosted browser session so the user can sign into a site (ChatGPT, Claude, Reddit, any account-gated site) directly in their own browser tab, then save the login to a named profile. Returns a watch_url \u2014 give it to the user; they sign in fresh on the real site (existing browser cookies are NOT imported), then click "Done" on that page to save the session and close it. ONE profile holds MANY logins \u2014 call again with the same profile and a different domain to stack another account. NOT for one-off scraping (use extract_url) or driving the browser (use browser_open). Billed at the standard live-browser rate while the sign-in session stays open. After the user clicks Done, poll browser_profile_list until AUTHENTICATED, then browser_open with the profile.',
1311
1316
  inputSchema: BrowserProfileConnectInputSchema,
1312
1317
  outputSchema: recordOutputSchema("browser_profile_connect", BrowserProfileConnectOutputSchema),
1313
1318
  annotations: annotations("Save a Site Login to a Profile")
1314
1319
  },
1315
1320
  async (input) => {
1316
- const domain = slugPart(input.domain) || "chatgpt.com";
1321
+ const domain = normalizeDomain(input.domain) || "chatgpt.com";
1317
1322
  const setupUrl = input.login_url ?? input.url ?? (domain === "chatgpt.com" ? "https://chatgpt.com/" : `https://${domain}/`);
1318
1323
  const profile = input.profile?.trim() || savedProfileNameFromEmail(input.email) || browserServiceProfileName();
1319
1324
  if (!profile) {
@@ -1329,14 +1334,15 @@ function registerBrowserAgentMcpTools(server2, opts) {
1329
1334
  domain,
1330
1335
  login_url: setupUrl,
1331
1336
  ...accountEmail ? { account_email: accountEmail } : {},
1332
- ...note ? { note } : {}
1337
+ ...note ? { note } : {},
1338
+ ...typeof input.timeout_seconds === "number" ? { timeout_seconds: input.timeout_seconds } : {}
1333
1339
  });
1334
1340
  if (!open.ok) return errorResult("browser_profile_connect", open.data);
1335
1341
  const connectedLogins = await fetchConnectedLogins(profile).catch(() => []);
1336
1342
  return structuredResult({
1337
1343
  ok: true,
1338
1344
  tool: "browser_profile_connect",
1339
- session_id: null,
1345
+ session_id: open.data.browser_session_id ?? null,
1340
1346
  auth_connection_id: open.data.connection_id,
1341
1347
  watch_url: `${consoleBase}/console/auth/${open.data.connection_id}`,
1342
1348
  live_view_url: null,
@@ -1346,13 +1352,13 @@ function registerBrowserAgentMcpTools(server2, opts) {
1346
1352
  account_email: accountEmail,
1347
1353
  note,
1348
1354
  status: open.data.status ?? null,
1349
- flow_status: open.data.flow_status ?? null,
1350
- flow_step: open.data.flow_step ?? null,
1351
- flow_expires_at: open.data.flow_expires_at ?? null,
1352
- post_login_url: open.data.post_login_url ?? null,
1355
+ flow_status: null,
1356
+ flow_step: null,
1357
+ flow_expires_at: null,
1358
+ post_login_url: null,
1353
1359
  connected_logins: connectedLogins,
1354
1360
  next_steps: [
1355
- `Give the user watch_url so they can sign in to ${domain}.`,
1361
+ `Give the user watch_url so they can sign in to ${domain} directly in that page, then click "Done \u2014 I'm signed in".`,
1356
1362
  "Poll browser_profile_list (with this profile) until the login reads AUTHENTICATED.",
1357
1363
  "To add another account to this same profile, call browser_profile_connect again with the same profile and a different domain.",
1358
1364
  "When authenticated, call browser_open with this profile to drive the logged-in session."
@@ -1377,7 +1383,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
1377
1383
  error: "profile or email is required when BROWSER_AGENT_PROFILE_NAME is not available"
1378
1384
  });
1379
1385
  }
1380
- const domain = slugPart(input.domain) || void 0;
1386
+ const domain = normalizeDomain(input.domain) || void 0;
1381
1387
  const res = await req("POST", "/agent/profiles/list", {
1382
1388
  profile,
1383
1389
  ...domain ? { domain } : {},
@@ -1976,6 +1982,17 @@ var WORKFLOW_RECIPES = [
1976
1982
  produces: ["content gaps", "page comparison CSV", "PAA questions CSV", "section map", "writer brief"],
1977
1983
  runHint: "Use workflow_run with workflowId serp-comparison for competitor gaps or paa-expansion-brief when the user mainly wants a section map from PAA data."
1978
1984
  },
1985
+ {
1986
+ id: "recurring_tracking_and_memory",
1987
+ title: "Recurring Tracking & Memory",
1988
+ description: "Run a check on a daily, weekly, or custom cadence with no external cron needed, and save each result somewhere searchable so you can compare against past runs later - rankings, prices, competitor changes, anything you would otherwise check by hand and forget to log.",
1989
+ primaryWorkflowId: null,
1990
+ recommendedTools: ["create-scheduled-action", "search_serp", "table-create", "table-insert-rows", "table-query", "memory-put", "memory-search", "list-scheduled-actions"],
1991
+ requiredInputs: ["plain-language description of what to check and how often"],
1992
+ optionalInputs: ["vault to save into", "timeOfDay", "timezone"],
1993
+ produces: ["a live scheduled action that runs automatically on cadence", "a table row or note per run for structured history", "a searchable trend you can compare run-over-run"],
1994
+ runHint: "Use create-scheduled-action with a plain description and cadence; the run itself checks list-vaults, uses table-insert-rows for repeating structured data (e.g. a keyword rank check) or memory-put for a one-off note, and reads prior runs with table-query or memory-search before writing the new one. For a one-time blueprint to build your own external cron/DB instead of a live scheduled action, use rank_tracker_workflow."
1995
+ },
1979
1996
  {
1980
1997
  id: "ai_search_visibility_audit",
1981
1998
  title: "AI Search Visibility Audit",
@@ -4195,6 +4212,9 @@ function formatMapsPlaceIntel(raw, input) {
4195
4212
  const about = d.aboutAttributes ?? [];
4196
4213
  const reviews = d.reviews ?? [];
4197
4214
  const reviewsStatus = d.reviewsStatus ?? "not_requested";
4215
+ const services = d.services ?? [];
4216
+ const areasServed = d.areasServed ?? [];
4217
+ const servicesStatus = d.servicesStatus ?? "not_requested";
4198
4218
  const hoursTable = d.hoursTable ?? [];
4199
4219
  const ratingLine = [rating, reviewCount ? `(${reviewCount} reviews)` : null].filter(Boolean).join(" ");
4200
4220
  const basicLines = [
@@ -4249,6 +4269,20 @@ ${reviews.map((r, i) => {
4249
4269
  ${r.text ?? ""}`;
4250
4270
  }).join("\n\n")}`;
4251
4271
  })();
4272
+ const servicesSection = (() => {
4273
+ if (servicesStatus === "not_requested") return "";
4274
+ if (servicesStatus === "unavailable") return "\n## Services & Areas Served\n> Could not be retrieved this run \u2014 retry with `includeServices: true`.";
4275
+ if (servicesStatus === "none_exist") return "\n## Services & Areas Served\n*Not listed on this business's profile.*";
4276
+ const parts = [
4277
+ services.length ? `**Services**
4278
+ ${services.map((s) => `- ${s}`).join("\n")}` : null,
4279
+ areasServed.length ? `**Areas Served**
4280
+ ${areasServed.map((a) => `- ${a}`).join("\n")}` : null
4281
+ ].filter(Boolean);
4282
+ return parts.length ? `
4283
+ ## Services & Areas Served
4284
+ ${parts.join("\n\n")}` : "";
4285
+ })();
4252
4286
  const full = [
4253
4287
  `# ${name}`,
4254
4288
  category ? `*${category}*` : null,
@@ -4264,6 +4298,7 @@ ${basicLines}` : null,
4264
4298
  ## Entity IDs
4265
4299
  ${entitySection}` : null,
4266
4300
  reviewsSection,
4301
+ servicesSection,
4267
4302
  durationMs != null ? `
4268
4303
  ---
4269
4304
  *Extracted in ${(durationMs / 1e3).toFixed(1)}s*` : null
@@ -4287,7 +4322,10 @@ ${entitySection}` : null,
4287
4322
  lng: lng ?? null,
4288
4323
  reviewsStatus,
4289
4324
  reviewsCollected: reviews.length,
4290
- reviewTopics: topics.map((t) => ({ label: String(t.label ?? ""), count: String(t.count ?? "") }))
4325
+ reviewTopics: topics.map((t) => ({ label: String(t.label ?? ""), count: String(t.count ?? "") })),
4326
+ services,
4327
+ areasServed,
4328
+ servicesStatus
4291
4329
  }
4292
4330
  };
4293
4331
  }
@@ -4782,6 +4820,23 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
4782
4820
  answers the question (plain search/extract before browser agents).
4783
4821
  - Large results are saved to disk or an artifact and returned as a summary plus a path or artifactId;
4784
4822
  read it back for full detail rather than expecting the whole payload inline.
4823
+
4824
+ ## Memory
4825
+ mcp-scraper also exposes 74 persistent per-user memory tools (notes, facts, vaults,
4826
+ scheduled actions, tables, channels) backed by memory.mcpscraper.dev. Every account starts with 13
4827
+ vaults \u2014 call **list-vaults** to see what exists before creating anything new. Pick the vault whose job
4828
+ matches the content: **Ideas** (unvalidated concepts), **Knowledge** (distilled lessons/how-tos),
4829
+ **Library** (raw source material \u2014 articles, transcripts), **People** (one durable note per person/org),
4830
+ **Communications** (individual conversation records), **Calendar** (time-anchored entries), **Tasks**
4831
+ (action items with a status), **Projects** (durable named initiatives), **Issues** (something broken),
4832
+ **Improvement Log** (receipts of changes made and whether they worked), **Experiments** (hypothesis +
4833
+ measured result), **Sprint** (current cycle's scope), **Inspiration** (other people's work worth
4834
+ studying).
4835
+ Before writing, call **memory-suggest** to check whether something's already captured and to find the
4836
+ right vault's hub note to link. Use **memory-put** for narrative notes (prose, a title, a body); use
4837
+ **table-create**/**table-insert-rows**/**table-query** instead when the caller wants row-shaped data
4838
+ they'll filter/sort by exact value. **memory-search** is meaning-based over full content (embeds, slower);
4839
+ **memory-list** filters one vault by kind/tags (fast, exact).
4785
4840
  `.trim();
4786
4841
  }
4787
4842
  var SERVER_INSTRUCTIONS = serverInstructions(true);
@@ -4823,6 +4878,7 @@ var MapsPlaceOptionsSchema = import_zod2.z.object({
4823
4878
  hl: import_zod2.z.string().length(2).default("en"),
4824
4879
  includeReviews: import_zod2.z.boolean().default(false),
4825
4880
  maxReviews: import_zod2.z.number().int().min(1).max(500).default(50),
4881
+ includeServices: import_zod2.z.boolean().default(false),
4826
4882
  kernelApiKey: import_zod2.z.string().optional(),
4827
4883
  kernelProxyId: import_zod2.z.string().optional(),
4828
4884
  headless: import_zod2.z.boolean().default(true)
@@ -5011,7 +5067,8 @@ var MapsPlaceIntelInputSchema = {
5011
5067
  gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location."),
5012
5068
  hl: import_zod3.z.string().length(2).default("en").describe("Language inferred from user request."),
5013
5069
  includeReviews: import_zod3.z.boolean().default(false).describe("Fetch individual review cards \u2014 for reviews, customer pain, complaints, or praise themes."),
5014
- maxReviews: import_zod3.z.number().int().min(1).max(500).default(50).describe("Max review cards when includeReviews is true. Default 50, maximum 500.")
5070
+ maxReviews: import_zod3.z.number().int().min(1).max(500).default(50).describe("Max review cards when includeReviews is true. Default 50, maximum 500."),
5071
+ includeServices: import_zod3.z.boolean().default(false).describe("Fetch the business's configured services list and areas-served list, when the profile has them. Adds one extra page visit; not present for every business.")
5015
5072
  };
5016
5073
  var MapsSearchInputSchema = {
5017
5074
  query: import_zod3.z.string().min(1).describe('Business category, niche, or search term, e.g. "roofers". Do not include location here \u2014 use location instead.'),
@@ -5324,7 +5381,10 @@ var MapsPlaceIntelOutputSchema = {
5324
5381
  reviewTopics: import_zod3.z.array(import_zod3.z.object({
5325
5382
  label: import_zod3.z.string(),
5326
5383
  count: import_zod3.z.string()
5327
- }))
5384
+ })),
5385
+ services: import_zod3.z.array(import_zod3.z.string()),
5386
+ areasServed: import_zod3.z.array(import_zod3.z.string()),
5387
+ servicesStatus: import_zod3.z.string()
5328
5388
  };
5329
5389
  var CreditsInfoOutputSchema = {
5330
5390
  balanceCredits: import_zod3.z.number().nullable(),
@@ -5827,7 +5887,7 @@ var ReportArtifactReadOutputSchema = {
5827
5887
 
5828
5888
  // src/mcp/rank-tracker-blueprint.ts
5829
5889
  var DEFAULT_MODES = ["maps", "organic", "ai_overview", "paa"];
5830
- function normalizeDomain(value) {
5890
+ function normalizeDomain2(value) {
5831
5891
  const trimmed = value?.trim();
5832
5892
  if (!trimmed) return null;
5833
5893
  try {
@@ -6089,7 +6149,7 @@ function buildPrompt(input, modes, tools, tables, jobs, metrics, expression, tar
6089
6149
  }
6090
6150
  function buildRankTrackerBlueprint(input) {
6091
6151
  const trackingModes = uniqueModes(input.trackingModes);
6092
- const targetDomain = normalizeDomain(input.targetDomain);
6152
+ const targetDomain = normalizeDomain2(input.targetDomain);
6093
6153
  const targetBusinessName = input.targetBusinessName?.trim() || null;
6094
6154
  const projectName = input.projectName?.trim() || "MCP Scraper Rank Tracker";
6095
6155
  const database = input.database || "postgres";
@@ -8588,13 +8648,14 @@ function renderInstallTerminal(options) {
8588
8648
  "1/1 install surfaces ready",
8589
8649
  colorize("Newest: saved browser profiles that hold MANY site logins. Share the watch_url, user signs in, then verify with browser_profile_list. Browser sessions are direct/no-proxy by default.", "lime", color),
8590
8650
  "",
8591
- `${colorize("Tools", "cyan", color)} ${colorize("(48 MCP tools)", "muted", color)}`,
8651
+ `${colorize("Tools", "cyan", color)} ${colorize("(128 MCP tools)", "muted", color)}`,
8592
8652
  toolRow("search", ["harvest_paa", "search_serp", "maps_search", "maps_place_intel"], color),
8593
8653
  toolRow("extract", ["extract_url", "map_site_urls", "extract_site", "audit_site", "directory_workflow"], color),
8594
8654
  toolRow("build", ["rank_tracker_workflow", "cron plan", "database prompt"], color),
8595
8655
  toolRow("media", ["youtube_harvest", "youtube_transcribe", "facebook_ad_search", "facebook_page_intel", "facebook_ad_transcribe", "facebook_video_transcribe", "instagram_profile_content", "instagram_media_download", "reddit_thread"], color),
8596
8656
  toolRow("browser", ["browser_open", "browser_profile_connect", "browser_profile_list", "browser_close", "browser_screenshot", "browser_read", "browser_locate", "browser_replay_mark", "browser_replay_annotate"], color),
8597
8657
  toolRow("account", ["credits_info", "reports", "MCP resources"], color),
8658
+ toolRow("memory", ["memory-put", "memory-get", "memory-search", "list-vaults", "record-fact", "list-scheduled-actions"], color),
8598
8659
  `${colorize("Workflows", "cyan", color)} ${colorize("(MCP + CLI + API)", "muted", color)}`,
8599
8660
  toolRow("route", ["workflow_list", "workflow_suggest", "workflow_run", "workflow_step", "workflow_status", "workflow_artifact_read"], color),
8600
8661
  toolRow("seo", ["directory", "agent-packet", "competitive audit", "map/serp comparison", "PAA/AIO briefs", "scheduled runs"], color),