mcp-scraper 0.2.20 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +34 -3
  2. package/dist/bin/api-server.cjs +53 -2
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +2 -2
  5. package/dist/bin/browser-agent-stdio-server.cjs +961 -21
  6. package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
  7. package/dist/bin/browser-agent-stdio-server.js +4 -2
  8. package/dist/bin/browser-agent-stdio-server.js.map +1 -1
  9. package/dist/bin/mcp-scraper-cli.cjs +343 -48
  10. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  11. package/dist/bin/mcp-scraper-cli.js +106 -8
  12. package/dist/bin/mcp-scraper-cli.js.map +1 -1
  13. package/dist/bin/mcp-scraper-combined-stdio-server.cjs +977 -37
  14. package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
  15. package/dist/bin/mcp-scraper-combined-stdio-server.js +5 -3
  16. package/dist/bin/mcp-scraper-combined-stdio-server.js.map +1 -1
  17. package/dist/bin/mcp-scraper-install.cjs +1 -1
  18. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  19. package/dist/bin/mcp-scraper-install.js +1 -1
  20. package/dist/bin/mcp-stdio-server.cjs +1 -1
  21. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  22. package/dist/bin/mcp-stdio-server.js +2 -2
  23. package/dist/bin/paa-harvest.cjs.map +1 -1
  24. package/dist/bin/paa-harvest.js +4 -2
  25. package/dist/bin/paa-harvest.js.map +1 -1
  26. package/dist/{chunk-L4OWOUGR.js → chunk-2H365TJ6.js} +738 -4
  27. package/dist/chunk-2H365TJ6.js.map +1 -0
  28. package/dist/chunk-DUEW4EOO.js +214 -0
  29. package/dist/chunk-DUEW4EOO.js.map +1 -0
  30. package/dist/{chunk-XGUDTDZ2.js → chunk-IPW4LFOT.js} +5 -13
  31. package/dist/chunk-IPW4LFOT.js.map +1 -0
  32. package/dist/{chunk-O5J7E4VX.js → chunk-Q5XUNDN5.js} +2 -2
  33. package/dist/chunk-RXUIQTDU.js +7 -0
  34. package/dist/chunk-RXUIQTDU.js.map +1 -0
  35. package/dist/chunk-WN7PBKMV.js +28 -0
  36. package/dist/chunk-WN7PBKMV.js.map +1 -0
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.js +2 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/{server-7NE45K2A.js → server-3LDQCOIN.js} +42 -8
  41. package/dist/server-3LDQCOIN.js.map +1 -0
  42. package/dist/{worker-MIYG2B2I.js → worker-SLQ375UG.js} +5 -3
  43. package/dist/{worker-MIYG2B2I.js.map → worker-SLQ375UG.js.map} +1 -1
  44. package/docs/mcp-tool-manifest.generated.json +132 -4
  45. package/package.json +1 -1
  46. package/dist/chunk-L4OWOUGR.js.map +0 -1
  47. package/dist/chunk-XGUDTDZ2.js.map +0 -1
  48. package/dist/chunk-XKUDVN2E.js +0 -7
  49. package/dist/chunk-XKUDVN2E.js.map +0 -1
  50. package/dist/server-7NE45K2A.js.map +0 -1
  51. /package/dist/{chunk-O5J7E4VX.js.map → chunk-Q5XUNDN5.js.map} +0 -0
package/README.md CHANGED
@@ -36,7 +36,10 @@ Run setup checks and generate agent wiring:
36
36
 
37
37
  ```bash
38
38
  npx -y -p mcp-scraper@latest mcp-scraper-cli doctor
39
+ npx -y -p mcp-scraper@latest mcp-scraper-cli browser profiles --email seo@example.com
40
+ npx -y -p mcp-scraper@latest mcp-scraper-cli browser import-chrome --email seo@example.com --name seo-example-com
39
41
  npx -y -p mcp-scraper@latest mcp-scraper-cli agent install codex
42
+ npx -y -p mcp-scraper@latest mcp-scraper-cli agent install claude-desktop --browser-mode local --browser-profile seo-example-com
40
43
  npx -y -p mcp-scraper@latest mcp-scraper-cli agent prompt agent-packet
41
44
  ```
42
45
 
@@ -102,7 +105,10 @@ Claude Desktop:
102
105
  "command": "npx",
103
106
  "args": ["-y", "-p", "mcp-scraper@latest", "mcp-scraper-combined"],
104
107
  "env": {
105
- "MCP_SCRAPER_API_KEY": "sk_live_your_key"
108
+ "MCP_SCRAPER_API_KEY": "sk_live_your_key",
109
+ "MCP_SCRAPER_BROWSER_MODE": "local",
110
+ "MCP_SCRAPER_BROWSER_PROFILE": "work-accounts",
111
+ "MCP_SCRAPER_BROWSER_EXECUTABLE": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
106
112
  }
107
113
  }
108
114
  }
@@ -111,6 +117,21 @@ Claude Desktop:
111
117
 
112
118
  Existing MCP configs that use only `npx -y mcp-scraper` still work for the web intelligence server, but they do not automatically add browser tools. Switch to `mcp-scraper-combined` or add the second `browser-agent` config entry if you want browser tools. Use `mcp-scraper@latest` to force npm to resolve the newest published package whenever the MCP client starts a fresh `npx` process.
113
119
 
120
+ For local Chrome state, first clone a Chrome profile into MCP Scraper managed storage:
121
+
122
+ ```bash
123
+ mcp-scraper-cli browser import-chrome --email you@example.com --name work-accounts
124
+ mcp-scraper-cli agent install codex --browser-mode local --browser-profile work-accounts
125
+ ```
126
+
127
+ `browser import-chrome` copies the selected local Chrome profile into `~/.mcp-scraper/browser-profiles/<name>/user-data`, skipping cache and lock files. The managed clone can include cookies, local storage, history, session storage, and Chrome password database files. It does not upload the profile. Re-run `mcp-scraper-cli browser sync-profile <name>` after logging into new sites in normal Chrome.
128
+
129
+ Set `MCP_SCRAPER_BROWSER_MODE=local` and `MCP_SCRAPER_BROWSER_PROFILE=<name>` when you want `browser_open` to launch local Google Chrome against that managed clone. A `profile` argument passed directly to `browser_open` overrides the default for that one session.
130
+
131
+ Hosted browser profiles are still available. `BROWSER_AGENT_PROFILE_NAME` sets the default saved Kernel browser profile for hosted sessions. For first-time hosted setup, set `BROWSER_AGENT_PROFILE_SAVE_CHANGES=true`, open a browser with the profile, complete login through the watch URL, then call `browser_close` to persist cookies/local storage into the hosted Kernel profile.
132
+
133
+ Inside MCP clients, use `browser_profile_list` to inspect local Chrome account/profile metadata, `browser_profile_import` to clone a profile for local browser mode, `browser_profile_sync` to refresh an existing clone, and `browser_profile_onboard` only for hosted Kernel setup.
134
+
114
135
  Claude Code:
115
136
 
116
137
  ```bash
@@ -175,7 +196,11 @@ env = { MCP_SCRAPER_API_KEY = "sk_live_your_key" }
175
196
 
176
197
  ### Browser-agent tools
177
198
 
178
- - `browser_open` — open a live cloud browser session. Returns a `session_id`, a human `watch_url`, and the raw `live_view_url` when available.
199
+ - `browser_open` — open a browser session. Hosted mode returns a human `watch_url`; local mode opens Google Chrome on this machine against an imported managed profile.
200
+ - `browser_profile_list` — list local Chrome account/profile metadata and suggested managed profile names. This does not read cookies, passwords, browsing history, or copy local Chrome state.
201
+ - `browser_profile_import` — clone a local Chrome profile into `~/.mcp-scraper/browser-profiles` for local browser mode. This copies browser state files but skips cache and locks.
202
+ - `browser_profile_sync` — refresh an existing managed local profile clone from its recorded source Chrome profile.
203
+ - `browser_profile_onboard` — create or load a hosted Kernel browser profile and open a setup browser with profile saving enabled. The user logs in through the `watch_url`, then `browser_close` persists cookies/local storage into the hosted Kernel profile.
179
204
  - `browser_screenshot` — capture a screenshot plus visible text and clickable element center coordinates and DOM bounds.
180
205
  - `browser_read` — read the current page text and elements with center coordinates and DOM bounds, without an image.
181
206
  - `browser_locate` — locate exact visible DOM elements or text ranges and return screenshot-pixel bounds.
@@ -203,7 +228,7 @@ The MCPB bundle and `mcp-scraper-combined` expose both sections through one loca
203
228
 
204
229
  All local and hosted MCP tools expose output schemas and return `structuredContent` with the IDs, URLs, CSV paths, transcripts, browser session handles, replay paths, artifacts, recipe fields, or blueprint fields needed by the next step. Browser Agent tools keep a JSON text block for older clients, but structured data is the primary contract. All tools carry MCP annotations; file-writing tools such as replay downloads and annotations state their local file side effects.
205
230
 
206
- The canonical tool inventory is generated at `docs/mcp-tool-manifest.generated.json`. The split local `mcp-scraper` stdio server exposes 22 web-intelligence/workflow tools. The split `browser-agent` stdio server exposes 17 browser tools. The combined local stdio server exposes 39 tools. The hosted MCP endpoint at `https://mcpscraper.dev/mcp` exposes the 22 web-intelligence/workflow tools plus `capture_serp_snapshot` and `capture_serp_page_snapshots` (24 total). Across all public local and hosted surfaces there are 41 unique tool names.
231
+ The canonical tool inventory is generated at `docs/mcp-tool-manifest.generated.json`. The split local `mcp-scraper` stdio server exposes 22 web-intelligence/workflow tools. The split `browser-agent` stdio server exposes 21 browser tools. The combined local stdio server exposes 43 tools. The hosted MCP endpoint at `https://mcpscraper.dev/mcp` exposes the 22 web-intelligence/workflow tools plus `capture_serp_snapshot` and `capture_serp_page_snapshots` (24 total). Across all public local and hosted surfaces there are 45 unique tool names.
207
232
 
208
233
  ## Resources
209
234
 
@@ -216,6 +241,12 @@ The `mcp-scraper` and `mcp-scraper-combined` NPX stdio servers also expose saved
216
241
  - `MCP_SCRAPER_OUTPUT_DIR` is optional and defaults to `~/Downloads/mcp-scraper`.
217
242
  - `MCP_SCRAPER_SAVE_REPORTS=false` disables automatic Markdown report files.
218
243
  - `MCP_SCRAPER_KEY_PATH` is optional. When no API key env var is set, the server also reads `~/.mcp-scraper-key` for compatibility with older installs.
244
+ - `MCP_SCRAPER_BROWSER_MODE=local` makes `browser_open` use local Google Chrome instead of the hosted browser service.
245
+ - `MCP_SCRAPER_BROWSER_PROFILE` sets the default managed local browser profile name created by `mcp-scraper-cli browser import-chrome`.
246
+ - `MCP_SCRAPER_BROWSER_EXECUTABLE` optionally points local browser mode at a Chrome executable. On macOS, Google Chrome is recommended so Keychain-backed Chrome state works.
247
+ - `MCP_SCRAPER_BROWSER_PROFILE_DIR` optionally points local browser mode at a direct Chrome-compatible user data directory instead of a managed profile manifest.
248
+ - `BROWSER_AGENT_PROFILE_NAME` is optional and sets the default saved Kernel browser profile for hosted-mode `browser-agent` and `mcp-scraper-combined` stdio sessions. Aliases: `BROWSER_SERVICE_PROFILE_NAME`, `KERNEL_BROWSER_PROFILE_NAME`, `KERNEL_PROFILE_NAME`.
249
+ - `BROWSER_AGENT_PROFILE_SAVE_CHANGES=true` is optional hosted setup mode. It persists cookies and local storage back to the named profile when `browser_close` deletes the hosted browser session. Aliases: `BROWSER_SERVICE_PROFILE_SAVE_CHANGES`, `KERNEL_BROWSER_PROFILE_SAVE_CHANGES`, `KERNEL_PROFILE_SAVE_CHANGES`.
219
250
 
220
251
  Every web intelligence tool call made through `mcp-scraper` or `mcp-scraper-combined` saves a full Markdown report locally by default and returns the file path in the MCP response. The hosted `/mcp` endpoint returns reports inline only and never writes files. Browser replay downloads are saved by `browser_replay_download` under `MCP_SCRAPER_OUTPUT_DIR/browser-replays`.
221
252
 
@@ -59,6 +59,17 @@ function browserServiceProxyId() {
59
59
  const value = (process.env.BROWSER_SERVICE_PROXY_ID ?? process.env.KERNEL_PROXY_ID)?.trim();
60
60
  return value || void 0;
61
61
  }
62
+ function browserServiceProfileName() {
63
+ const value = (process.env.BROWSER_AGENT_PROFILE_NAME ?? process.env.BROWSER_SERVICE_PROFILE_NAME ?? process.env.KERNEL_BROWSER_PROFILE_NAME ?? process.env.KERNEL_PROFILE_NAME)?.trim();
64
+ return value || void 0;
65
+ }
66
+ function browserServiceProfileSaveChanges() {
67
+ const value = (process.env.BROWSER_AGENT_PROFILE_SAVE_CHANGES ?? process.env.BROWSER_SERVICE_PROFILE_SAVE_CHANGES ?? process.env.KERNEL_BROWSER_PROFILE_SAVE_CHANGES ?? process.env.KERNEL_PROFILE_SAVE_CHANGES)?.trim().toLowerCase();
68
+ if (!value) return void 0;
69
+ if (["1", "true", "yes", "on"].includes(value)) return true;
70
+ if (["0", "false", "no", "off"].includes(value)) return false;
71
+ return void 0;
72
+ }
62
73
  var init_browser_service_env = __esm({
63
74
  "src/lib/browser-service-env.ts"() {
64
75
  "use strict";
@@ -2465,6 +2476,16 @@ var init_registry = __esm({
2465
2476
  }
2466
2477
  });
2467
2478
 
2479
+ // src/attribution-pixel.ts
2480
+ var ATTRIBUTION_PIXEL_SRC, ATTRIBUTION_PIXEL_SCRIPT;
2481
+ var init_attribution_pixel = __esm({
2482
+ "src/attribution-pixel.ts"() {
2483
+ "use strict";
2484
+ ATTRIBUTION_PIXEL_SRC = "https://hyros-attribution-crm.vercel.app/api/track/sdk?token=35c27ba33dd0c6cc640f9fef415ee3dc9ead67fefe99d269be602ee269900e25";
2485
+ ATTRIBUTION_PIXEL_SCRIPT = `<script src="${ATTRIBUTION_PIXEL_SRC}" async></script>`;
2486
+ }
2487
+ });
2488
+
2468
2489
  // src/blog/template.ts
2469
2490
  function faqJsonLd(post) {
2470
2491
  const firstFive = post.sections.flatMap((s) => s.cards).slice(0, 5);
@@ -2599,6 +2620,7 @@ function renderPost(post) {
2599
2620
  <script type="application/ld+json">${faqJsonLd(post)}</script>
2600
2621
  <script type="application/ld+json">${breadcrumbJsonLd(post)}</script>
2601
2622
 
2623
+ ${ATTRIBUTION_PIXEL_SCRIPT}
2602
2624
  <style>${CSS}</style>
2603
2625
  </head>
2604
2626
  <body>
@@ -2742,6 +2764,7 @@ var CSS;
2742
2764
  var init_template = __esm({
2743
2765
  "src/blog/template.ts"() {
2744
2766
  "use strict";
2767
+ init_attribution_pixel();
2745
2768
  CSS = `
2746
2769
  @font-face {
2747
2770
  font-family: "GT Flexa";
@@ -10706,6 +10729,7 @@ function buildTranscriptHtml(result) {
10706
10729
  (ch) => `<div class="chunk"><span class="ts">${fmtSecs(ch.timestamp[0])} \u2192 ${fmtSecs(ch.timestamp[1])}</span><span class="ct">${esc(ch.text.trim())}</span></div>`
10707
10730
  ).join("\n");
10708
10731
  return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
10732
+ ${ATTRIBUTION_PIXEL_SCRIPT}
10709
10733
  <style>body{font-family:system-ui,sans-serif;max-width:800px;margin:1.5rem auto;padding:0 1rem;color:#111;line-height:1.7}
10710
10734
  h1{font-size:1.2rem;margin-bottom:.25rem}.meta{color:#666;font-size:.85rem;margin-bottom:1.5rem}
10711
10735
  .full-text{background:#f5f5f3;border-radius:8px;padding:1rem 1.25rem;font-size:.875rem;white-space:pre-wrap;margin-bottom:2rem;word-break:break-word}
@@ -10735,6 +10759,7 @@ var init_youtube_routes = __esm({
10735
10759
  init_CaptionFetcher();
10736
10760
  init_BrowserDriver();
10737
10761
  init_errors();
10762
+ init_attribution_pixel();
10738
10763
  init_api_auth();
10739
10764
  init_server_schemas();
10740
10765
  init_concurrency_gates();
@@ -20977,7 +21002,7 @@ var PACKAGE_VERSION;
20977
21002
  var init_version = __esm({
20978
21003
  "src/version.ts"() {
20979
21004
  "use strict";
20980
- PACKAGE_VERSION = "0.2.20";
21005
+ PACKAGE_VERSION = "0.2.22";
20981
21006
  }
20982
21007
  });
20983
21008
 
@@ -22677,14 +22702,35 @@ function client() {
22677
22702
  if (!apiKey) throw new Error("Browser backend API key is required");
22678
22703
  return new import_sdk6.default({ apiKey });
22679
22704
  }
22705
+ function isProfileConflict(err) {
22706
+ const message = err instanceof Error ? err.message : String(err);
22707
+ return /\b409\b|conflict|already exists/i.test(message);
22708
+ }
22709
+ async function ensureProfile(k, name) {
22710
+ try {
22711
+ await k.profiles.create({ name });
22712
+ } catch (err) {
22713
+ if (!isProfileConflict(err)) throw err;
22714
+ }
22715
+ }
22680
22716
  async function createSession(opts = {}) {
22681
22717
  const k = client();
22682
22718
  const resolvedProxyId = opts.proxyId ?? browserServiceProxyId();
22719
+ const resolvedProfileName = opts.profileName ?? browserServiceProfileName();
22720
+ const resolvedSaveProfileChanges = opts.saveProfileChanges ?? browserServiceProfileSaveChanges();
22721
+ if (resolvedProfileName && resolvedSaveProfileChanges === true) {
22722
+ await ensureProfile(k, resolvedProfileName);
22723
+ }
22683
22724
  const browser = await k.browsers.create({
22684
22725
  stealth: opts.stealth ?? true,
22685
22726
  timeout_seconds: opts.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS,
22686
22727
  ...resolvedProxyId ? { proxy_id: resolvedProxyId } : {},
22687
- ...opts.profileName ? { profile: { name: opts.profileName } } : {}
22728
+ ...resolvedProfileName ? {
22729
+ profile: {
22730
+ name: resolvedProfileName,
22731
+ ...typeof resolvedSaveProfileChanges === "boolean" ? { save_changes: resolvedSaveProfileChanges } : {}
22732
+ }
22733
+ } : {}
22688
22734
  });
22689
22735
  const runtimeSessionId = browser.session_id;
22690
22736
  if (opts.disableDefaultProxy) {
@@ -23075,6 +23121,7 @@ function buildBrowserAgentRoutes() {
23075
23121
  timeoutSeconds,
23076
23122
  proxyId: typeof body.proxy_id === "string" ? body.proxy_id : void 0,
23077
23123
  profileName: typeof body.profile === "string" ? body.profile : void 0,
23124
+ saveProfileChanges: typeof body.save_profile_changes === "boolean" ? body.save_profile_changes : void 0,
23078
23125
  disableDefaultProxy: body.disable_default_proxy === true,
23079
23126
  viewport: body.viewport && typeof body.viewport === "object" ? body.viewport : void 0
23080
23127
  });
@@ -23450,6 +23497,7 @@ function renderConsoleHtml(initialSessionId) {
23450
23497
  .gate button { width: 100%; }
23451
23498
  .muted { color: #6b7689; font-size: 12px; }
23452
23499
  </style>
23500
+ ${ATTRIBUTION_PIXEL_SCRIPT}
23453
23501
  </head>
23454
23502
  <body>
23455
23503
  <div id="app"></div>
@@ -23599,6 +23647,7 @@ if (state.key) { refreshSessions(); if (state.current) selectSession(state.curre
23599
23647
  var init_browser_agent_console = __esm({
23600
23648
  "src/api/browser-agent-console.ts"() {
23601
23649
  "use strict";
23650
+ init_attribution_pixel();
23602
23651
  }
23603
23652
  });
23604
23653
 
@@ -24157,6 +24206,7 @@ var init_server = __esm({
24157
24206
  init_outbound_sanitize();
24158
24207
  init_registry();
24159
24208
  init_template();
24209
+ init_attribution_pixel();
24160
24210
  init_og();
24161
24211
  import_resend = require("resend");
24162
24212
  init_url_utils();
@@ -25000,6 +25050,7 @@ var init_server = __esm({
25000
25050
  .i6 em{font-family:"GTF";font-weight:700;font-style:italic}
25001
25051
  .i7 em{font-family:"GTF";font-weight:900;font-style:italic}
25002
25052
  </style>
25053
+ ${ATTRIBUTION_PIXEL_SCRIPT}
25003
25054
  </head>
25004
25055
  <body>
25005
25056