mcp-scraper 0.2.20 → 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 +34 -3
- package/dist/bin/api-server.cjs +52 -1
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/browser-agent-stdio-server.cjs +960 -20
- package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
- package/dist/bin/browser-agent-stdio-server.js +3 -1
- package/dist/bin/browser-agent-stdio-server.js.map +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +342 -47
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +105 -7
- package/dist/bin/mcp-scraper-cli.js.map +1 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs +976 -36
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.js +3 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.js.map +1 -1
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +4 -2
- package/dist/bin/paa-harvest.js.map +1 -1
- package/dist/chunk-DUEW4EOO.js +214 -0
- package/dist/chunk-DUEW4EOO.js.map +1 -0
- package/dist/{chunk-L4OWOUGR.js → chunk-HS6OKELW.js} +737 -3
- package/dist/chunk-HS6OKELW.js.map +1 -0
- package/dist/{chunk-XGUDTDZ2.js → chunk-IPW4LFOT.js} +5 -13
- package/dist/chunk-IPW4LFOT.js.map +1 -0
- package/dist/chunk-WN7PBKMV.js +28 -0
- package/dist/chunk-WN7PBKMV.js.map +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/{server-7NE45K2A.js → server-24XIQ6W6.js} +40 -6
- package/dist/server-24XIQ6W6.js.map +1 -0
- package/dist/{worker-MIYG2B2I.js → worker-SLQ375UG.js} +5 -3
- package/dist/{worker-MIYG2B2I.js.map → worker-SLQ375UG.js.map} +1 -1
- package/docs/mcp-tool-manifest.generated.json +132 -4
- package/package.json +1 -1
- package/dist/chunk-L4OWOUGR.js.map +0 -1
- package/dist/chunk-XGUDTDZ2.js.map +0 -1
- package/dist/server-7NE45K2A.js.map +0 -1
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
|
|
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
|
|
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
|
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -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();
|
|
@@ -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
|
-
...
|
|
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
|
|