@imenam/simple-scraper 1.0.23 → 1.0.27
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 +438 -398
- package/dist/browser.js +32 -10
- package/dist/cli/setup-mcp.js +2 -2
- package/dist/cookie-sync.js +67 -0
- package/dist/cookies.js +28 -40
- package/dist/data-dir.js +24 -0
- package/dist/gui.js +75 -85
- package/dist/index.js +36 -38
- package/dist/keep-alive.js +51 -0
- package/dist/login.js +139 -0
- package/dist/relay.js +11 -7
- package/dist/rpc.js +159 -0
- package/dist/sessions.js +23 -11
- package/dist/site-check.js +88 -0
- package/dist/site-store.js +210 -0
- package/package.json +2 -1
- package/public/dist/assets/index-CmU4YRqF.js +11 -0
- package/public/dist/assets/index-olIqry-_.css +1 -0
- package/public/dist/index.html +13 -13
- package/public/dist/assets/index-DAjr-PsH.js +0 -12
- package/public/dist/assets/index-IkSxq6_f.css +0 -1
package/README.md
CHANGED
|
@@ -1,398 +1,438 @@
|
|
|
1
|
-
# simple-scraper-mcp
|
|
2
|
-
|
|
3
|
-
A Model Context Protocol (MCP) server for web scraping and JavaScript execution using a headless browser (Puppeteer).
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **`scrape_page`** — Navigate to a URL and return the full rendered HTML of the page
|
|
8
|
-
- **`execute_js`** — Navigate to a URL and execute custom JavaScript in the page context
|
|
9
|
-
- **`get_page_inputs`** — Extract all form inputs from a page as a structured JSON object
|
|
10
|
-
- **`get_show_page`** — Parse a detail/show page and extract key-value blocks and tables as structured JSON
|
|
11
|
-
- **Interactive sessions** — Keep a browser page alive across multiple tool calls to navigate, click, type, run JS, and screenshot the page in any desired state
|
|
12
|
-
- **`screenshot`** — Capture a screenshot of any page or active session, with inline or file output
|
|
13
|
-
- **
|
|
14
|
-
- **Optional GUI** —
|
|
15
|
-
|
|
16
|
-
## Requirements
|
|
17
|
-
|
|
18
|
-
- Node.js >= 18
|
|
19
|
-
- Puppeteer will automatically download a compatible Chromium browser (~300 MB) on first install
|
|
20
|
-
|
|
21
|
-
## Installation
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npx @imenam/simple-scraper
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Or install globally:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
npm install -g @imenam/simple-scraper
|
|
31
|
-
simple-scraper
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## MCP Configuration
|
|
35
|
-
|
|
36
|
-
### Quick setup
|
|
37
|
-
|
|
38
|
-
From the repo you want to scrape from, generate a ready-to-fill `.mcp.json` in the current directory:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npx @imenam/simple-scraper --claude-setup-mcp
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
It creates the `simple-scraper-mcp` entry with the proxy variables pre-filled from the current
|
|
45
|
-
folder name (`PROXY_URL`, `APP_GROUP`, `PROXY_APP_NAME`, `PROXY_APP_PATH`) plus a 1920x1080
|
|
46
|
-
viewport, and prints the remaining optional variables. An empty variable is simply inactive
|
|
47
|
-
(no `PROXY_URL` = no GUI), so the generated config runs as-is. An existing `.mcp.json` is merged,
|
|
48
|
-
other servers are preserved, and an existing `simple-scraper-mcp` entry is only replaced when
|
|
49
|
-
`--force` is passed.
|
|
50
|
-
|
|
51
|
-
## Environment Variables
|
|
52
|
-
|
|
53
|
-
| Variable | Required | Default | Description |
|
|
54
|
-
|----------|----------|---------|-------------|
|
|
55
|
-
| `PUPPETEER_HEADLESS` | No | `true` | Run Chromium in headless mode. Set to `false` to display the browser window. |
|
|
56
|
-
| `PUPPETEER_TIMEOUT` | No | `30000` | Default timeout in milliseconds for page navigation and waits. |
|
|
57
|
-
| `PUPPETEER_VIEWPORT_WIDTH` | No | `1280` | Viewport width in CSS pixels, applied to every page. Affects responsive layouts and lazy-loading, not just screenshots. |
|
|
58
|
-
| `PUPPETEER_VIEWPORT_HEIGHT` | No | `800` | Viewport height in CSS pixels, applied to every page. |
|
|
59
|
-
| `PUPPETEER_DEVICE_SCALE_FACTOR` | No | `1` | Physical pixels per CSS pixel. Set to `2` for retina-density screenshots (same framing, twice the detail, ~4× the file size). |
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
#
|
|
83
|
-
# COOKIES_DIR
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
|
|
144
|
-
"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
"
|
|
161
|
-
"
|
|
162
|
-
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
| `
|
|
226
|
-
| `
|
|
227
|
-
| `
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
| `
|
|
249
|
-
| `
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
| `
|
|
274
|
-
| `
|
|
275
|
-
| `
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
362
|
-
| `
|
|
363
|
-
| `
|
|
364
|
-
| `
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
>
|
|
376
|
-
>
|
|
377
|
-
>
|
|
378
|
-
>
|
|
379
|
-
>
|
|
380
|
-
>
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
1
|
+
# simple-scraper-mcp
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server for web scraping and JavaScript execution using a headless browser (Puppeteer). Logged-in sites keep their session: cookies are saved per site, renewed automatically, kept alive on a schedule, and restored through an assisted login when the site ends the session. An optional GUI manages sites and shows live sessions.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **`scrape_page`** — Navigate to a URL and return the full rendered HTML of the page
|
|
8
|
+
- **`execute_js`** — Navigate to a URL and execute custom JavaScript in the page context
|
|
9
|
+
- **`get_page_inputs`** — Extract all form inputs from a page as a structured JSON object
|
|
10
|
+
- **`get_show_page`** — Parse a detail/show page and extract key-value blocks and tables as structured JSON
|
|
11
|
+
- **Interactive sessions** — Keep a browser page alive across multiple tool calls to navigate, click, type, run JS, and screenshot the page in any desired state
|
|
12
|
+
- **`screenshot`** — Capture a screenshot of any page or active session, with inline or file output
|
|
13
|
+
- **Sites** — Per-site cookies loaded into the browser, written back as the site renews them, kept alive on a schedule; assisted login in a visible window when a session is lost (see [Sites](#sites-connected-accounts))
|
|
14
|
+
- **Optional GUI** — Sites, live sessions and activity, available when integrated with the [MCP proxy](https://www.npmjs.com/package/@imenam/mcp-http-gateway)
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- Node.js >= 18
|
|
19
|
+
- Puppeteer will automatically download a compatible Chromium browser (~300 MB) on first install
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @imenam/simple-scraper
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or install globally:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g @imenam/simple-scraper
|
|
31
|
+
simple-scraper
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## MCP Configuration
|
|
35
|
+
|
|
36
|
+
### Quick setup
|
|
37
|
+
|
|
38
|
+
From the repo you want to scrape from, generate a ready-to-fill `.mcp.json` in the current directory:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx @imenam/simple-scraper --claude-setup-mcp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
It creates the `simple-scraper-mcp` entry with the proxy variables pre-filled from the current
|
|
45
|
+
folder name (`PROXY_URL`, `APP_GROUP`, `PROXY_APP_NAME`, `PROXY_APP_PATH`) plus a 1920x1080
|
|
46
|
+
viewport, and prints the remaining optional variables. An empty variable is simply inactive
|
|
47
|
+
(no `PROXY_URL` = no GUI), so the generated config runs as-is. An existing `.mcp.json` is merged,
|
|
48
|
+
other servers are preserved, and an existing `simple-scraper-mcp` entry is only replaced when
|
|
49
|
+
`--force` is passed.
|
|
50
|
+
|
|
51
|
+
## Environment Variables
|
|
52
|
+
|
|
53
|
+
| Variable | Required | Default | Description |
|
|
54
|
+
|----------|----------|---------|-------------|
|
|
55
|
+
| `PUPPETEER_HEADLESS` | No | `true` | Run Chromium in headless mode. Set to `false` to display the browser window. |
|
|
56
|
+
| `PUPPETEER_TIMEOUT` | No | `30000` | Default timeout in milliseconds for page navigation and waits. |
|
|
57
|
+
| `PUPPETEER_VIEWPORT_WIDTH` | No | `1280` | Viewport width in CSS pixels, applied to every page. Affects responsive layouts and lazy-loading, not just screenshots. |
|
|
58
|
+
| `PUPPETEER_VIEWPORT_HEIGHT` | No | `800` | Viewport height in CSS pixels, applied to every page. |
|
|
59
|
+
| `PUPPETEER_DEVICE_SCALE_FACTOR` | No | `1` | Physical pixels per CSS pixel. Set to `2` for retina-density screenshots (same framing, twice the detail, ~4× the file size). |
|
|
60
|
+
| `SCRAPER_DATA_DIR` | No | - | Absolute path to the folder where sites are stored (settings, cookies, activity). Created if missing. Without it, sites are disabled. See [Sites](#sites-connected-accounts). |
|
|
61
|
+
| `COOKIES_DIR` | No | - | Other name for `SCRAPER_DATA_DIR`, so existing configurations keep working. If both are set, they must point to the same folder, otherwise the server refuses to start. |
|
|
62
|
+
| `MCP_LOG_DIR` | No | `.mcp-gui/logs` | Absolute path to the directory where log files are written. |
|
|
63
|
+
| `PROXY_URL` | No | - | Base URL of the [MCP HTTP Gateway](https://www.npmjs.com/package/@imenam/mcp-http-gateway). Required to enable the GUI. |
|
|
64
|
+
| `PROXY_APP_PATH` | No | `/simple-scraper-mcp` | URL path under which the GUI is registered on the proxy. |
|
|
65
|
+
| `PROXY_APP_NAME` | No | `Simple Scraper MCP` | Display name shown in the proxy's app list. |
|
|
66
|
+
| `APP_GROUP` | No | - | Groups the app under a collapsible section (folded by default) in the proxy dashboard. Apps sharing the same value appear together; if unset, the app lands in the default "ungrouped" section. |
|
|
67
|
+
| `SCRAPER_MAX_SESSIONS` | No | `5` | Maximum number of concurrent interactive sessions. |
|
|
68
|
+
| `SCRAPER_SESSION_TTL_MS` | No | `600000` | Inactivity TTL for sessions in milliseconds (default: 10 minutes). Sessions unused beyond this duration are closed automatically. |
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
Copy `.env.example` to `.env` and configure the variables:
|
|
73
|
+
|
|
74
|
+
```env
|
|
75
|
+
# Puppeteer options (optional)
|
|
76
|
+
PUPPETEER_HEADLESS=true
|
|
77
|
+
PUPPETEER_TIMEOUT=30000
|
|
78
|
+
PUPPETEER_VIEWPORT_WIDTH=1280
|
|
79
|
+
PUPPETEER_VIEWPORT_HEIGHT=800
|
|
80
|
+
PUPPETEER_DEVICE_SCALE_FACTOR=1
|
|
81
|
+
|
|
82
|
+
# Optional: folder where sites are stored (settings, cookies, activity).
|
|
83
|
+
# COOKIES_DIR is accepted as another name for the same setting.
|
|
84
|
+
# SCRAPER_DATA_DIR=/path/to/scraper-data
|
|
85
|
+
|
|
86
|
+
# GUI (optional) — required to enable the web interface
|
|
87
|
+
# PROXY_URL=http://localhost:3000
|
|
88
|
+
# PROXY_APP_PATH=/simple-scraper-mcp
|
|
89
|
+
# PROXY_APP_NAME=Simple Scraper MCP
|
|
90
|
+
# Optional: groups this app under a collapsible section of the proxy dashboard
|
|
91
|
+
# APP_GROUP=Scraping
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### The process environment wins over `.env`
|
|
95
|
+
|
|
96
|
+
Any variable already set in the environment of the process that starts this MCP
|
|
97
|
+
(a shell `export`, a `claude_desktop_config.json` `env` block, or a supervisor
|
|
98
|
+
such as `@imenam/mcp-gateway-manager`) **takes precedence over the same key in
|
|
99
|
+
this repository's `.env`**. This is dotenv's default behaviour, and the usual
|
|
100
|
+
Unix convention: the caller wins.
|
|
101
|
+
|
|
102
|
+
The `.env` is still reloaded on the fly — the GUI writes to it and the change is
|
|
103
|
+
picked up without restarting the server — but that reload can no longer clobber
|
|
104
|
+
what the caller injected. Concretely, an `APP_GROUP=Scraping` line in this
|
|
105
|
+
`.env` no longer overrides an `APP_GROUP` passed in by a supervisor; it only
|
|
106
|
+
applies when nobody passed one.
|
|
107
|
+
|
|
108
|
+
To change a variable that the caller provides, change it where the caller sets
|
|
109
|
+
it; editing `.env` will have no effect on that key.
|
|
110
|
+
|
|
111
|
+
## Usage with Claude Desktop
|
|
112
|
+
|
|
113
|
+
Add the following to your `claude_desktop_config.json`. Full example with all available options:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"simple-scraper": {
|
|
119
|
+
"command": "npx",
|
|
120
|
+
"args": ["@imenam/simple-scraper"],
|
|
121
|
+
"env": {
|
|
122
|
+
"PUPPETEER_HEADLESS": "true",
|
|
123
|
+
"PUPPETEER_TIMEOUT": "30000",
|
|
124
|
+
"SCRAPER_DATA_DIR": "/path/to/your/scraper-data",
|
|
125
|
+
"MCP_LOG_DIR": "/path/to/your/logs",
|
|
126
|
+
"PROXY_URL": "http://localhost:4500",
|
|
127
|
+
"PROXY_APP_PATH": "/simple-scraper",
|
|
128
|
+
"PROXY_APP_NAME": "Simple Scraper"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
To use logged-in sites, add `SCRAPER_DATA_DIR` (see [Sites](#sites-connected-accounts)):
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"mcpServers": {
|
|
140
|
+
"simple-scraper": {
|
|
141
|
+
"command": "npx",
|
|
142
|
+
"args": ["@imenam/simple-scraper"],
|
|
143
|
+
"env": {
|
|
144
|
+
"PUPPETEER_HEADLESS": "true",
|
|
145
|
+
"SCRAPER_DATA_DIR": "/path/to/your/scraper-data"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Usage with Cursor
|
|
153
|
+
|
|
154
|
+
In Cursor, MCP servers are configured in `.cursor/mcp.json`. You can pass environment variables directly in the config. Full example with all available options:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"mcpServers": {
|
|
159
|
+
"simple-scraper": {
|
|
160
|
+
"command": "npx",
|
|
161
|
+
"args": ["-y", "@imenam/simple-scraper"],
|
|
162
|
+
"env": {
|
|
163
|
+
"PUPPETEER_HEADLESS": "true",
|
|
164
|
+
"PUPPETEER_TIMEOUT": "30000",
|
|
165
|
+
"SCRAPER_DATA_DIR": "/path/to/your/scraper-data",
|
|
166
|
+
"MCP_LOG_DIR": "/path/to/your/logs",
|
|
167
|
+
"PROXY_URL": "http://localhost:4500",
|
|
168
|
+
"PROXY_APP_PATH": "/simple-scraper",
|
|
169
|
+
"PROXY_APP_NAME": "Simple Scraper"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> **Note:** The `-y` flag in `args` avoids the interactive confirmation prompt when using `npx`.
|
|
177
|
+
|
|
178
|
+
## MCP Tools
|
|
179
|
+
|
|
180
|
+
### `scrape_page`
|
|
181
|
+
|
|
182
|
+
Navigate to a URL and return the full rendered HTML.
|
|
183
|
+
|
|
184
|
+
| Parameter | Type | Required | Description |
|
|
185
|
+
|-----------|------|----------|-------------|
|
|
186
|
+
| `url` | string | ✅ | URL of the page to scrape |
|
|
187
|
+
| `wait_for` | string | | CSS selector to wait for before capturing HTML |
|
|
188
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
189
|
+
|
|
190
|
+
### `execute_js`
|
|
191
|
+
|
|
192
|
+
Navigate to a URL and execute custom JavaScript in the page context.
|
|
193
|
+
|
|
194
|
+
The `script` parameter is executed as the body of a JavaScript function in the browser page context, equivalent to:
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
new Function(script)();
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
To return data from the tool, the script must use an explicit `return`. A bare expression such as `document.title` will evaluate but the tool will receive `undefined`.
|
|
201
|
+
|
|
202
|
+
Example:
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
return {
|
|
206
|
+
title: document.title,
|
|
207
|
+
url: window.location.href,
|
|
208
|
+
text: document.body.innerText.slice(0, 500)
|
|
209
|
+
};
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
For asynchronous work, return a promise, for example with an async IIFE:
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
return (async () => {
|
|
216
|
+
const response = await fetch('/api/data');
|
|
217
|
+
return await response.json();
|
|
218
|
+
})();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Returned objects and arrays are serialized as formatted JSON. Primitive values are returned as text.
|
|
222
|
+
|
|
223
|
+
| Parameter | Type | Required | Description |
|
|
224
|
+
|-----------|------|----------|-------------|
|
|
225
|
+
| `url` | string | ✅ | URL of the page |
|
|
226
|
+
| `script` | string | ✅ | JavaScript function body to execute in the page context. Use `return` to send a result back to the tool. |
|
|
227
|
+
| `wait_for` | string | | CSS selector to wait for before executing |
|
|
228
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
229
|
+
|
|
230
|
+
### `get_page_inputs`
|
|
231
|
+
|
|
232
|
+
Extract all form inputs from a page as a structured JSON object.
|
|
233
|
+
|
|
234
|
+
| Parameter | Type | Required | Description |
|
|
235
|
+
|-----------|------|----------|-------------|
|
|
236
|
+
| `url` | string | ✅ | URL of the page |
|
|
237
|
+
| `selector` | string | | CSS selector to scope the search (e.g. `#my-form`) |
|
|
238
|
+
| `wait_for` | string | | CSS selector to wait for before extracting |
|
|
239
|
+
| `show_hidden` | boolean | | Include `input[type=hidden]` fields (default: false) |
|
|
240
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
241
|
+
|
|
242
|
+
### `get_show_page`
|
|
243
|
+
|
|
244
|
+
Parse a detail page and extract key-value blocks and tables as structured JSON.
|
|
245
|
+
|
|
246
|
+
| Parameter | Type | Required | Description |
|
|
247
|
+
|-----------|------|----------|-------------|
|
|
248
|
+
| `url` | string | ✅ | URL of the page |
|
|
249
|
+
| `keys_map` | object | | Map of HTML label → JS key for field name translation |
|
|
250
|
+
| `box_selector` | string | | CSS selector for section containers (default: `.box.box-primary`) |
|
|
251
|
+
| `tables_max_items` | number | | Max rows per table (default: 2) |
|
|
252
|
+
| `wait_for` | string | | CSS selector to wait for before extraction |
|
|
253
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Interactive Sessions
|
|
258
|
+
|
|
259
|
+
Interactive sessions let you keep a browser page alive across multiple tool calls, so you can bring the page into the exact state you need before extracting data or taking a screenshot.
|
|
260
|
+
|
|
261
|
+
### Typical workflow
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
open_session → session_click / session_type / session_evaluate → screenshot / session_html → close_session
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### `open_session`
|
|
268
|
+
|
|
269
|
+
Open a persistent browser session. Returns a `session_id` to use with all `session_*` tools and `screenshot`.
|
|
270
|
+
|
|
271
|
+
| Parameter | Type | Required | Description |
|
|
272
|
+
|-----------|------|----------|-------------|
|
|
273
|
+
| `url` | string | ✅ | URL to navigate to |
|
|
274
|
+
| `wait_for` | string | | CSS selector to wait for before the session is considered ready |
|
|
275
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
276
|
+
| `viewport` | object | | Viewport override for this session, applied before navigation: `{ width, height, device_scale_factor }`. Omitted fields fall back to the server defaults. |
|
|
277
|
+
|
|
278
|
+
### `close_session`
|
|
279
|
+
|
|
280
|
+
Close a session and free its resources. Always call this when you are done.
|
|
281
|
+
|
|
282
|
+
| Parameter | Type | Required | Description |
|
|
283
|
+
|-----------|------|----------|-------------|
|
|
284
|
+
| `session_id` | string | ✅ | Session ID returned by `open_session` |
|
|
285
|
+
|
|
286
|
+
### `list_sessions`
|
|
287
|
+
|
|
288
|
+
List all currently active sessions with their IDs and timestamps. No parameters.
|
|
289
|
+
|
|
290
|
+
### `session_goto`
|
|
291
|
+
|
|
292
|
+
Navigate the session to a new URL without closing it.
|
|
293
|
+
|
|
294
|
+
| Parameter | Type | Required | Description |
|
|
295
|
+
|-----------|------|----------|-------------|
|
|
296
|
+
| `session_id` | string | ✅ | Session ID |
|
|
297
|
+
| `url` | string | ✅ | URL to navigate to |
|
|
298
|
+
| `wait_for` | string | | CSS selector to wait for after navigation |
|
|
299
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
300
|
+
|
|
301
|
+
### `session_click`
|
|
302
|
+
|
|
303
|
+
Click an element in the session page.
|
|
304
|
+
|
|
305
|
+
| Parameter | Type | Required | Description |
|
|
306
|
+
|-----------|------|----------|-------------|
|
|
307
|
+
| `session_id` | string | ✅ | Session ID |
|
|
308
|
+
| `selector` | string | ✅ | CSS selector of the element to click |
|
|
309
|
+
| `timeout` | number | | Timeout in ms to wait for the element (default: 30000) |
|
|
310
|
+
|
|
311
|
+
### `session_type`
|
|
312
|
+
|
|
313
|
+
Type text into an input element in the session page.
|
|
314
|
+
|
|
315
|
+
| Parameter | Type | Required | Description |
|
|
316
|
+
|-----------|------|----------|-------------|
|
|
317
|
+
| `session_id` | string | ✅ | Session ID |
|
|
318
|
+
| `selector` | string | ✅ | CSS selector of the input element |
|
|
319
|
+
| `text` | string | ✅ | Text to type |
|
|
320
|
+
| `clear` | boolean | | Clear the field before typing (default: false) |
|
|
321
|
+
| `timeout` | number | | Timeout in ms to wait for the element (default: 30000) |
|
|
322
|
+
|
|
323
|
+
### `session_wait_for`
|
|
324
|
+
|
|
325
|
+
Wait for a CSS selector to appear in the session page.
|
|
326
|
+
|
|
327
|
+
| Parameter | Type | Required | Description |
|
|
328
|
+
|-----------|------|----------|-------------|
|
|
329
|
+
| `session_id` | string | ✅ | Session ID |
|
|
330
|
+
| `selector` | string | ✅ | CSS selector to wait for |
|
|
331
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
332
|
+
|
|
333
|
+
### `session_evaluate`
|
|
334
|
+
|
|
335
|
+
Execute JavaScript in the context of the session page. Same conventions as `execute_js`.
|
|
336
|
+
|
|
337
|
+
| Parameter | Type | Required | Description |
|
|
338
|
+
|-----------|------|----------|-------------|
|
|
339
|
+
| `session_id` | string | ✅ | Session ID |
|
|
340
|
+
| `script` | string | ✅ | JavaScript function body. Use `return` to get a result back. |
|
|
341
|
+
| `wait_for` | string | | CSS selector to wait for before executing |
|
|
342
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
343
|
+
|
|
344
|
+
### `session_html`
|
|
345
|
+
|
|
346
|
+
Return the current full rendered HTML of the session page.
|
|
347
|
+
|
|
348
|
+
| Parameter | Type | Required | Description |
|
|
349
|
+
|-----------|------|----------|-------------|
|
|
350
|
+
| `session_id` | string | ✅ | Session ID |
|
|
351
|
+
|
|
352
|
+
### `screenshot`
|
|
353
|
+
|
|
354
|
+
Capture a screenshot of a page. Use `session_id` to capture an active session in its current state, or `url` for a one-shot capture.
|
|
355
|
+
|
|
356
|
+
The capture area is resolved by precedence: `selector` → `clip` → `full_page` → the visible viewport.
|
|
357
|
+
|
|
358
|
+
| Parameter | Type | Required | Description |
|
|
359
|
+
|-----------|------|----------|-------------|
|
|
360
|
+
| `session_id` | string | | Session ID. If provided, `url` is ignored and the current page state is captured. |
|
|
361
|
+
| `url` | string | | URL for a one-shot screenshot. Required if `session_id` is not provided. |
|
|
362
|
+
| `wait_for` | string | | CSS selector to wait for (one-shot mode only) |
|
|
363
|
+
| `timeout` | number | | Timeout in ms (default: 30000) |
|
|
364
|
+
| `selector` | string | | CSS selector of a specific element to capture |
|
|
365
|
+
| `clip` | object | | Arbitrary pixel region `{ x, y, width, height }` in CSS pixels, measured from the top-left of the page. May extend below the visible viewport. Ignored when `selector` is set; cannot be combined with `full_page`. |
|
|
366
|
+
| `viewport` | object | | Viewport override for this capture: `{ width, height, device_scale_factor }`. For a session, the previous viewport is restored afterwards. |
|
|
367
|
+
| `full_page` | boolean | | Capture the full scrollable page height (default: false, ignored when `selector` or `clip` is provided) |
|
|
368
|
+
| `format` | `png` \| `jpeg` | | Image format (default: `png`) |
|
|
369
|
+
| `output` | `inline` \| `file` \| `both` | ✅ | `inline` embeds the image in the response, `file` writes it on the agent machine, `both` does both |
|
|
370
|
+
| `destination_path` | string | ⚠️ | **Absolute directory** on the agent machine where the image is written. Created if missing. Required when `output` is `file` or `both`, except behind the relay, which keeps it on the agent side and only forwards `filename` |
|
|
371
|
+
| `filename` | string | ⚠️ | Name the image gets there, e.g. `home.png`. No path separators. Required when `output` is `file` or `both` |
|
|
372
|
+
| `destination_overwrite` | boolean | | Replace the destination file if it exists (default: `false`) |
|
|
373
|
+
| `destination_relay` | boolean | | Filled in by the mcp-http-gateway relay, never by the agent |
|
|
374
|
+
|
|
375
|
+
> **Where the file lands.** There is no default destination: one would resolve on *this
|
|
376
|
+
> server's* disk, which is not necessarily the agent's — a file nobody finds rather than an
|
|
377
|
+
> error. In stdio the server writes it itself; behind
|
|
378
|
+
> [`@imenam/mcp-http-gateway`](https://www.npmjs.com/package/@imenam/mcp-http-gateway) it
|
|
379
|
+
> returns the bytes and the relay, which runs on the agent machine, writes them at
|
|
380
|
+
> `destination_path`. That path requires `GATEWAY_INLINE_WRITE_ROOTS` in the relay's `env`
|
|
381
|
+
> block. The image never passes through the conversation unless `output` includes `inline`.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Sites (connected accounts)
|
|
386
|
+
|
|
387
|
+
A **site** is an account the scraper uses while logged in: a name, the domains it covers, its login page and the sign that proves a page is seen logged in. Sites are stored in the data folder (`SCRAPER_DATA_DIR`, or `COOKIES_DIR` under its other name) and managed from the GUI (its labels are in French).
|
|
388
|
+
|
|
389
|
+
### How cookies are used
|
|
390
|
+
|
|
391
|
+
- When the shared browser starts, it loads the cookies of every site. Any tool (`scrape_page`, `execute_js`, `open_session`, `screenshot`…) visiting one of a site's domains is therefore logged in, with nothing to pass to the tool.
|
|
392
|
+
- After each page closes, and every 5 minutes, the cookies the browser holds for each site's domains are written back to that site: cookies renewed by the site are kept, cookies it deleted are removed. Session cookies (no expiry date) are kept too, so a login survives a restart of the MCP.
|
|
393
|
+
|
|
394
|
+
### Login sign
|
|
395
|
+
|
|
396
|
+
The sign tells the scraper whether a page is seen logged in:
|
|
397
|
+
|
|
398
|
+
- **L'adresse contient** (the address contains): the page address (host and path, without query or anchor) contains the value, e.g. `crm.example.com/app`;
|
|
399
|
+
- **Un élément est présent** (an element is present): a CSS selector that only exists once logged in, e.g. `#user-menu`.
|
|
400
|
+
|
|
401
|
+
### Assisted login
|
|
402
|
+
|
|
403
|
+
**Se reconnecter** opens a visible Chromium window, on a blank temporary profile, at the site's login page, on the machine running the MCP. You log in there yourself (credentials, two-factor authentication, SSO). As soon as the login sign appears, the window's cookies are saved for the site and the window closes; **Je suis connecté** saves them without waiting for the sign. Credentials never go through the MCP. **Tout reconnecter** chains every site to reconnect, one after the other.
|
|
404
|
+
|
|
405
|
+
### Keep-alive
|
|
406
|
+
|
|
407
|
+
When enabled, the keep-alive visits the site's **Page visitée** at a fixed interval (5 min to 1 h), day and night, so that the session does not expire from inactivity. Each visit is also a check: if the login sign no longer appears, the site is marked **À reconnecter**, shown in the banner of the Sites page (unless disabled for that site), and the keep-alive stops visiting it until the next login. The visited page is also used by **Vérifier maintenant**.
|
|
408
|
+
|
|
409
|
+
The keep-alive cannot prevent a logout the site imposes on its own schedule (e.g. every night): it only avoids inactivity timeouts. After such a logout, the assisted login takes a few seconds per site.
|
|
410
|
+
|
|
411
|
+
### Data folder layout
|
|
412
|
+
|
|
413
|
+
| Path | Content |
|
|
414
|
+
|------|---------|
|
|
415
|
+
| `sites.json` | Settings and state of every site |
|
|
416
|
+
| `events.json` | Activity: checks, lost sessions, logins, imports (last 1000 events) |
|
|
417
|
+
| `cookies/<site id>.json` | Cookies of each site |
|
|
418
|
+
|
|
419
|
+
Netscape cookie files (`.txt`) placed in this folder are not loaded. To start from an exported file, open the site and use **Importer cookies**.
|
|
420
|
+
|
|
421
|
+
## GUI (Optional)
|
|
422
|
+
|
|
423
|
+
When `PROXY_URL` is set, a web interface is registered with the MCP proxy:
|
|
424
|
+
|
|
425
|
+
- **Sites** — every site with its state (logged in, to reconnect, not checked), its session and its keep-alive; banner and **Tout reconnecter** when sessions are lost; assisted login with a live preview of the login window.
|
|
426
|
+
- **Site page** — domains, login page, login sign, keep-alive (interval, visited page), recent activity, cookie import and **Effacer la session**.
|
|
427
|
+
- **Sessions** — the sessions opened by the agent, with a live view (refreshed every 2.5 s, can be paused), the last action, the matching site and the console messages.
|
|
428
|
+
- **Activity** — the history of every site, filterable by site.
|
|
429
|
+
|
|
430
|
+
The interface refreshes by polling: no connection stays open.
|
|
431
|
+
|
|
432
|
+
### Network exposure
|
|
433
|
+
|
|
434
|
+
The GUI listens on `127.0.0.1` only: other machines reach it through the proxy or the gateway manager. A request guard from [`@imenam/mcp-gui-interface`](https://www.npmjs.com/package/@imenam/mcp-gui-interface) answers `403` to any request whose `Host` header is not `localhost`, `127.0.0.1` or `::1` (DNS rebinding protection), and to modifying requests (`POST`, `DELETE`…) sent from another site (foreign `Sec-Fetch-Site` or `Origin`).
|
|
435
|
+
|
|
436
|
+
## License
|
|
437
|
+
|
|
438
|
+
ISC
|