smooth-operator-mcp 2.1.0

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.
@@ -0,0 +1,427 @@
1
+ # SmoothOperator MCP server
2
+
3
+ This document is the operational reference for the standalone Node.js server.
4
+ It assumes that an MCP client is already installed and can launch a local
5
+ stdio process or connect to a Streamable HTTP endpoint.
6
+
7
+ ## What the server owns
8
+
9
+ SmoothOperator is a protocol server, not an autonomous application. The client
10
+ decides when to call a tool and how to reason about its result. The server
11
+ validates each request, applies the same policy again at the browser and file
12
+ boundaries, performs the requested operation, and returns bounded MCP content.
13
+ It has no model credentials, model selection, or hidden planning cycle.
14
+
15
+ At runtime the composition is:
16
+
17
+ ```text
18
+ MCP client
19
+ ├─ stdio transport, or Streamable HTTP transport
20
+ └─ MCP registry (tools, resources, prompts)
21
+ └─ ServerRuntime
22
+ ├─ SecurityPolicy (URL, DNS, file, and capability checks)
23
+ ├─ BrowserService (Puppeteer over Chrome DevTools Protocol)
24
+ ├─ ResearchService (bounded DuckDuckGo retrieval)
25
+ └─ Logger and safe error boundary
26
+ ```
27
+
28
+ `src/server/main.ts` owns transport startup, authentication, signal handling,
29
+ and graceful shutdown. `src/server/mcp.ts` registers the public protocol
30
+ surface. `src/server/runtime.ts` owns dependency lifecycle. Browser operations
31
+ are in `src/server/browser/service.ts`; policy and configuration are in
32
+ `src/server/policy.ts` and `src/server/config.ts`.
33
+
34
+ ## Install and start
35
+
36
+ Use Node.js 22.23.2 and npm 10.9.8 for the reproducible project baseline. A
37
+ published package includes the built executable:
38
+
39
+ ```sh
40
+ npm install -g smooth-operator-mcp
41
+ smooth-operator --help
42
+ ```
43
+
44
+ (The registry package is `smooth-operator-mcp`; plain `smooth-operator` is an unrelated library. You can also install straight from GitHub: `npm install -g github:Gitshop77/Smooth-Operator`.)
45
+
46
+ From a checkout:
47
+
48
+ ```sh
49
+ npm ci
50
+ npm run build
51
+ node dist/smooth-operator.mjs --help
52
+ ```
53
+
54
+ The default transport is stdio. `npm start` runs the TypeScript source through
55
+ `tsx`; a published install runs `dist/smooth-operator.mjs` through its npm bin.
56
+ The process writes protocol messages to stdout and structured diagnostics to
57
+ stderr. Do not redirect ordinary logs into stdout while using stdio.
58
+
59
+ ## Stdio transport
60
+
61
+ Stdio is the preferred local integration because no listening socket is
62
+ created. An MCP client launches the executable and speaks JSON-RPC over its
63
+ stdin/stdout pipes. A generic server entry looks like this:
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "SmoothOperator": {
69
+ "command": "smooth-operator",
70
+ "args": []
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ If the client starts with a restricted `PATH`, use an absolute Node executable
77
+ and absolute bundled entrypoint instead:
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "SmoothOperator": {
83
+ "command": "/absolute/path/to/node",
84
+ "args": ["/absolute/path/to/dist/smooth-operator.mjs"]
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ The built-in installer uses this absolute form for GUI configuration files
91
+ when it is running from the published bundle. Command-line harnesses retain
92
+ their native CLI command and the portable `smooth-operator` name. See
93
+ [harnesses.md](harnesses.md) for each client.
94
+
95
+ Useful command-line forms:
96
+
97
+ ```sh
98
+ smooth-operator --version
99
+ smooth-operator --help
100
+ smooth-operator --transport stdio
101
+ smooth-operator --transport stdio --config /absolute/path/config.json
102
+ ```
103
+
104
+ `--config`, `--transport`, `--host`, and `--port` accept one value each. An
105
+ unknown option or duplicate option fails closed before the runtime starts.
106
+
107
+ ## Streamable HTTP transport
108
+
109
+ HTTP is opt-in and uses the MCP Streamable HTTP adapter. Keep it on loopback
110
+ for local clients:
111
+
112
+ ```sh
113
+ SMOOTH_OPERATOR_TRANSPORT=http \
114
+ SMOOTH_OPERATOR_HTTP_HOST=127.0.0.1 \
115
+ SMOOTH_OPERATOR_HTTP_PORT=3344 \
116
+ SMOOTH_OPERATOR_HTTP_TOKEN="$(openssl rand -hex 32)" \
117
+ smooth-operator
118
+ ```
119
+
120
+ The endpoint is `/mcp` by default. Every request must pass the configured Host
121
+ and Origin validation and include `Authorization: Bearer <token>`. The token
122
+ is compared in constant time. Request bodies are bounded to 2,000,000 bytes by
123
+ default and concurrent requests are capped. The process drains in-flight work
124
+ for a short bounded period on SIGINT/SIGTERM, then closes the MCP handler,
125
+ browser, and HTTP server.
126
+
127
+ Remote binding is deliberately guarded:
128
+
129
+ ```sh
130
+ SMOOTH_OPERATOR_TRANSPORT=http \
131
+ SMOOTH_OPERATOR_HTTP_HOST=0.0.0.0 \
132
+ SMOOTH_OPERATOR_ALLOW_REMOTE_HTTP=true \
133
+ SMOOTH_OPERATOR_HTTP_TOKEN="$(openssl rand -hex 32)" \
134
+ SMOOTH_OPERATOR_ALLOWED_HOSTS=example.internal \
135
+ SMOOTH_OPERATOR_ALLOWED_ORIGINS=https://example.internal \
136
+ smooth-operator
137
+ ```
138
+
139
+ Remote mode is rejected unless the token is at least 32 characters. Do not
140
+ use a token from a shell history, checked-in file, or shared log. A reverse
141
+ proxy can add TLS and network access controls, but it does not replace the
142
+ application token, Host/Origin allowlists, or request-size limit.
143
+
144
+ ## Browser lifecycle
145
+
146
+ The server manages one headed, persistent private agent-Chrome session by
147
+ default. On the first browser tool call it discovers an installed Google Chrome,
148
+ launches it with `${SMOOTH_OPERATOR_DATA_DIR}/browser` as a non-default profile,
149
+ and records its loopback DevTools endpoint for later reattachment. Sign in once
150
+ in the visible window; its sessions persist in that private profile. The
151
+ `browser_doctor` tool reports executable resolution and endpoint state without
152
+ evaluating page content.
153
+
154
+ Managed Chrome is headed by default for sign-in and human handoff. On CI or a
155
+ displayless host, explicitly set `SMOOTH_OPERATOR_BROWSER_HEADLESS=true` or use
156
+ Xvfb. The server never adds fingerprint spoofing, CAPTCHA solving, proxy
157
+ rotation, or other evasion behavior.
158
+
159
+ ### Managed mode (default)
160
+
161
+ `SMOOTH_OPERATOR_BROWSER_MODE=managed` needs no browser setup in ordinary installs.
162
+ It checks its private `DevToolsActivePort` file, reattaches only after a bounded
163
+ loopback probe succeeds, and otherwise discovers Chrome then launches it. Set
164
+ `SMOOTH_OPERATOR_BROWSER_EXECUTABLE` only to override discovery. A second
165
+ SmoothOperator process using the same private profile is rejected by the profile lease.
166
+
167
+ `SMOOTH_OPERATOR_BROWSER_AUTO_LAUNCH` is retained for backward compatibility but is
168
+ ignored in managed mode.
169
+
170
+ Browser actions share a bounded operation queue and deadline. Browser startup
171
+ uses one in-flight connection promise, so concurrent callers wait for the same
172
+ reattach/launch attempt instead of starting duplicate processes. Newly
173
+ auto-attached top-level targets are held at the CDP boundary until the
174
+ navigation policy guard is installed; targets whose attachment ownership
175
+ cannot be determined are blocked or closed. These controls reduce races but do
176
+ not make a host browser or network firewall trustworthy by themselves.
177
+
178
+ Managed and launch modes create owner-only data, files, downloads, and browser
179
+ profile directories below `SMOOTH_OPERATOR_DATA_DIR` (unless an explicit profile
180
+ path is supplied), reject unsafe symlink components, and hold a profile lease
181
+ for the runtime lifetime. A second owner receives `BROWSER_PROFILE_IN_USE`; an
182
+ incomplete shutdown retains the lock for explicit operator recovery.
183
+
184
+ ### Connect mode
185
+
186
+ Connect mode remains available for advanced, externally managed browser setups.
187
+ Chrome 144+ also offers an opt-in route through the remote-debugging toggle at
188
+ `chrome://inspect`; attach with connect mode and its reported endpoint only when
189
+ you intentionally want to control that daily profile.
190
+
191
+ For the classic route, start a dedicated browser profile with remote debugging
192
+ enabled, then point the server at the endpoint:
193
+
194
+ ```sh
195
+ google-chrome \
196
+ --remote-debugging-port=9222 \
197
+ --user-data-dir="$HOME/.smooth-operator/browser-profile"
198
+ SMOOTH_OPERATOR_BROWSER_MODE=connect \
199
+ SMOOTH_OPERATOR_BROWSER_URL=http://127.0.0.1:9222 \
200
+ smooth-operator
201
+ ```
202
+
203
+ `SMOOTH_OPERATOR_BROWSER_WS_ENDPOINT` can be used instead when a WebSocket endpoint
204
+ is already available. A connection mode server does not own or close an
205
+ externally managed browser process.
206
+
207
+ ### Launch mode
208
+
209
+ Launch mode gives the server ownership of a private browser process. Supply an
210
+ explicit executable and use an isolated profile:
211
+
212
+ ```sh
213
+ SMOOTH_OPERATOR_BROWSER_MODE=launch \
214
+ SMOOTH_OPERATOR_BROWSER_EXECUTABLE=/path/to/chrome-for-testing/chrome \
215
+ SMOOTH_OPERATOR_BROWSER_USER_DATA_DIR="$HOME/.smooth-operator/browser-profile" \
216
+ smooth-operator
217
+ ```
218
+
219
+ The default profile is `${SMOOTH_OPERATOR_DATA_DIR}/browser`. Do not point it at a
220
+ personal profile containing passwords, cookies, or active sessions. Launch mode
221
+ preserves its explicit executable requirement. `SMOOTH_OPERATOR_BROWSER_AUTO_LAUNCH=true`
222
+ remains an explicit connect-mode recovery option and still requires an executable.
223
+
224
+ ### Disabled mode
225
+
226
+ `SMOOTH_OPERATOR_BROWSER_MODE=disabled` keeps the MCP process available for health,
227
+ search, protocol, and configuration checks without opening a browser. Browser
228
+ tools return a bounded disabled error until the process is restarted with a
229
+ browser mode.
230
+
231
+ ## Configuration and precedence
232
+
233
+ Configuration can come from a JSON file selected by `--config` or
234
+ `SMOOTH_OPERATOR_CONFIG`, environment variables, and a small set of command-line
235
+ flags. The effective precedence is:
236
+
237
+ 1. command-line values (`--config`, `--transport`, `--host`, `--port`);
238
+ 2. environment variables;
239
+ 3. values from the JSON file;
240
+ 4. documented defaults.
241
+
242
+ The file is an object with nested `http`, `browser`, and `security` sections.
243
+ Unknown keys fail validation. Keep the file owner-readable only (`chmod 600`);
244
+ the loader rejects group/world-readable configuration files and rejects
245
+ symlinked data directories.
246
+
247
+ Example:
248
+
249
+ ```json
250
+ {
251
+ "transport": "stdio",
252
+ "dataDir": "~/.smooth-operator",
253
+ "browser": {
254
+ "mode": "managed",
255
+ "actionTimeoutMs": 15000
256
+ },
257
+ "security": {
258
+ "allowedDomains": ["example.com", "*.example.org"],
259
+ "blockedDomains": ["admin.example.org"],
260
+ "allowPrivateNetwork": false,
261
+ "allowEval": false
262
+ }
263
+ }
264
+ ```
265
+
266
+ Environment names correspond to the fields in `.env.example`. Notable
267
+ variables include:
268
+
269
+ | Setting | Default | Notes |
270
+ | --- | --- | --- |
271
+ | `SMOOTH_OPERATOR_TRANSPORT` | `stdio` | `stdio` or `http` |
272
+ | `SMOOTH_OPERATOR_DATA_DIR` | `~/.smooth-operator` | Private data, file, and download roots |
273
+ | `SMOOTH_OPERATOR_BROWSER_MODE` | `managed` | `managed`, `disabled`, `connect`, or `launch` |
274
+ | `SMOOTH_OPERATOR_BROWSER_URL` | `http://127.0.0.1:9222` | DevTools HTTP endpoint |
275
+ | `SMOOTH_OPERATOR_BROWSER_EXECUTABLE` | unset | Managed-mode override; required for explicit launch mode |
276
+ | `SMOOTH_OPERATOR_BROWSER_USER_DATA_DIR` | `${SMOOTH_OPERATOR_DATA_DIR}/browser` | Dedicated persistent agent-Chrome profile |
277
+ | `SMOOTH_OPERATOR_BROWSER_HEADLESS` | `false` | Set `true` for CI/displayless managed or launch use |
278
+ | `SMOOTH_OPERATOR_ALLOWED_DOMAINS` | unset | Comma-separated allowlist |
279
+ | `SMOOTH_OPERATOR_BLOCKED_DOMAINS` | unset | Comma-separated denylist |
280
+ | `SMOOTH_OPERATOR_ALLOWED_FILE_ROOTS` | data `files`, `downloads` | Explicit roots replace defaults |
281
+ | `SMOOTH_OPERATOR_ALLOW_PRIVATE_NETWORK` | `false` | Allows non-loopback private targets when true |
282
+ | `SMOOTH_OPERATOR_ALLOW_EVAL` | `false` | Required, with full policy, for page JavaScript |
283
+ | `SMOOTH_OPERATOR_HTTP_TOKEN` | unset | Required for HTTP; 32+ chars for remote mode |
284
+ | `SMOOTH_OPERATOR_ALLOW_REMOTE_HTTP` | `false` | Allows non-loopback HTTP only with a strong token |
285
+ | `SMOOTH_OPERATOR_HTTP_MAX_BODY_BYTES` | `2000000` | Bounded HTTP request body |
286
+ | `SMOOTH_OPERATOR_LOG_LEVEL` | `info` | `debug`, `info`, `warn`, or `error` |
287
+
288
+ ## Security enforcement layers
289
+
290
+ There are no client-selectable permissiveness tiers. The following controls
291
+ are always applied, with explicit opt-ins where documented:
292
+
293
+ - HTTP binds to loopback unless remote mode is enabled and authenticated.
294
+ - Navigation is restricted to HTTP(S), rejects embedded credentials, applies
295
+ domain rules, and blocks private/link-local/multicast destinations by default.
296
+ - Hostname navigation performs a DNS/private-address preflight and rejects
297
+ redirects that leave policy. The browser's own later DNS resolution is not
298
+ fully controllable by this process; DNS rebinding is therefore a limitation,
299
+ not a guarantee that a network firewall can be omitted.
300
+ - Upload and PDF destinations must stay within configured file roots after
301
+ realpath and symlink checks. Download paths and generated files are bounded.
302
+ - Page JavaScript is disabled by default. It is available only when the full
303
+ security policy and `SMOOTH_OPERATOR_ALLOW_EVAL=true` are configured; enabling it
304
+ lets page code observe and mutate page state with the browser's privileges.
305
+ - Page text, HTML, titles, attributes, search snippets, cookies, and logs are
306
+ treated as untrusted data, normalized, bounded, and redacted before output.
307
+ - CAPTCHA and anti-bot markers are reported for human handoff. The server does
308
+ not bypass them, rotate identities, or solve challenges.
309
+
310
+ Run the server with a dedicated browser profile and the smallest domain and
311
+ file-root allowlists that fit the task. Browser automation can still perform
312
+ irreversible actions on a site; the MCP client and operator remain responsible
313
+ for confirming destructive calls.
314
+
315
+ ## MCP capabilities
316
+
317
+ ### Tools
318
+
319
+ The registry includes these groups of tools. Every input is schema-validated;
320
+ individual descriptions and limits are returned by `tools/list`.
321
+
322
+ **Observation and extraction:** `browser_snapshot`, `browser_tabs`,
323
+ `browser_list_tabs`, `browser_list_sessions`, `browser_get_state`,
324
+ `browser_page_info`, `browser_interactive`, `browser_frames`,
325
+ `browser_accessibility_snapshot`, `browser_extract`, `browser_extract_content`,
326
+ `browser_find_text`, `browser_search_page`, `browser_find_elements`,
327
+ `browser_dropdown_options`, `browser_computed_style`, `browser_page_next`,
328
+ `browser_get_html`, `browser_challenge`, `browser_doctor`, and `server_health`.
329
+
330
+ **Navigation and interaction:** `browser_navigate`, `browser_back`,
331
+ `browser_go_back`, `browser_forward`, `browser_reload`, `browser_switch_tab`,
332
+ `browser_close_tab`, `browser_click`, `browser_input`, `browser_select`,
333
+ `browser_scroll`, `browser_scroll_to_bottom`, `browser_key`,
334
+ `browser_wait`, `browser_wait_for_element`, `browser_wait_for_text`, `browser_wait_for_url`,
335
+ `browser_wait_for_network_idle`, `browser_hover`, `browser_press_and_hold`,
336
+ `browser_type`, `browser_close`, and `browser_close_all`.
337
+
338
+ **Explicitly gated capabilities:** `browser_screenshot`, `browser_pdf`,
339
+ `browser_upload`, `browser_downloads`, `browser_network_log`,
340
+ `browser_console_log`, `browser_dialog`, `browser_cookies`,
341
+ `browser_storage`, `browser_evaluate`, `browser_batch`,
342
+ `browser_exec`, `browser_wait_for_human`, `browser_close_session`, and
343
+ the explicit browser-session lifecycle controls.
344
+
345
+ `browser_evaluate` is page JavaScript and is disabled by default. `browser_exec`
346
+ accepts only a JSON array of validated browser actions; it is not a shell,
347
+ Python, or arbitrary code runner. Destructive batch actions require explicit
348
+ confirmation. `browser_wait_for_human` pauses for an operator to complete a
349
+ visible sign-in or challenge, and `browser_close_session` closes the one
350
+ native browser session by its explicit session identifier.
351
+
352
+ `web_search` performs bounded DuckDuckGo retrieval. Search titles, URLs, and
353
+ snippets are untrusted observations, not instructions or proof of claims. Its
354
+ `maxResults` input is capped at 10, and `maxChars` (500–4,000 through the MCP
355
+ schema) is one aggregate budget across the returned title and snippet text,
356
+ not a per-result multiplier. URL fields and fixed untrusted-data wrapper
357
+ markers are outside that text budget. The response body is bounded before
358
+ parsing, redirects are rejected, cancellation and timeout are propagated, and
359
+ credentials/query secret placeholders are removed from result URLs.
360
+
361
+ ### Resources
362
+
363
+ The server publishes read-only resources:
364
+
365
+ - `smooth-operator://server/capabilities`
366
+ - `smooth-operator://browser/tabs`
367
+ - `smooth-operator://browser/page/current`
368
+ - `smooth-operator://browser/page/{pageId}`
369
+ - `smooth-operator://browser/downloads`
370
+ - `smooth-operator://browser/logs/network`
371
+ - `smooth-operator://browser/logs/console`
372
+
373
+ Resource output is bounded and follows the same redaction and policy rules as
374
+ tool output.
375
+
376
+ ### Prompts
377
+
378
+ The user-facing prompt templates are `agent-chrome-setup`, `browser-workflow`,
379
+ `extract-page`, and `research-question`. They are short starting points for the
380
+ MCP client's own conversation; they are not hidden instructions or a planning
381
+ engine.
382
+
383
+ ## Lifecycle and cleanup
384
+
385
+ At startup the process validates arguments and configuration, creates private
386
+ data directories, constructs the runtime, and registers the MCP surface. The
387
+ browser is connected or launched only when a browser operation requires it.
388
+
389
+ On SIGINT/SIGTERM, the server stops accepting HTTP requests, waits for active
390
+ requests up to a bounded grace period, closes the MCP transport, closes pages,
391
+ and terminates a browser process that it owns. A browser connected in `connect`
392
+ mode remains under the operator's ownership.
393
+
394
+ To clean up a local installation:
395
+
396
+ ```sh
397
+ smooth-operator install claude-desktop # inspect config before removal
398
+ npm uninstall -g smooth-operator-mcp
399
+ ```
400
+
401
+ Remove the corresponding `SmoothOperator` entry from a harness config and delete
402
+ `SMOOTH_OPERATOR_DATA_DIR` only after preserving any downloads or PDFs you need.
403
+ The installer creates owner-only, uniquely named `.bak` files when changing an
404
+ existing JSON/JSONC harness config; retain or remove those backups according
405
+ to your local recovery policy.
406
+
407
+ ## Troubleshooting
408
+
409
+ - **No browser tabs:** verify the DevTools URL, that the browser is running,
410
+ and that `SMOOTH_OPERATOR_BROWSER_MODE` is not `disabled`.
411
+ - **Launch fails:** provide an executable path and a new writable profile;
412
+ `puppeteer-core` does not download Chrome.
413
+ - **HTTP 401/403:** check the bearer token, Host/Origin allowlists, and that
414
+ remote mode was explicitly enabled for a non-loopback bind.
415
+ - **Private target blocked:** keep the default deny unless the target is an
416
+ intentional private service, then set `SMOOTH_OPERATOR_ALLOW_PRIVATE_NETWORK=true`
417
+ and use a narrow domain allowlist.
418
+ - **File rejected:** configure an allowed root and use a path beneath it;
419
+ symlink escapes are rejected after resolution.
420
+ - **MCP client shows no tools:** inspect stderr separately from stdout, run
421
+ `smooth-operator --version`, and perform a fresh client handshake after
422
+ changing the config.
423
+ - **GUI client cannot spawn the server:** use the absolute Node-plus-bundled
424
+ entrypoint form shown above; GUI applications often have a smaller PATH.
425
+
426
+ For harness-specific CLI syntax, config paths, and the OpenCode interactive
427
+ CLI limitation, read [harnesses.md](harnesses.md).
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "smooth-operator-mcp",
3
+ "version": "2.1.0",
4
+ "type": "module",
5
+ "packageManager": "npm@10.9.8",
6
+ "description": "A lightweight, production-grade MCP server for secure browser automation.",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Gitshop77/Smooth-Operator.git"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "docs/mcp-server.md",
15
+ "docs/harnesses.md",
16
+ "README.md",
17
+ "LICENSE",
18
+ ".env.example"
19
+ ],
20
+ "bin": {
21
+ "smooth-operator": "dist/smooth-operator.mjs"
22
+ },
23
+ "scripts": {
24
+ "start": "tsx src/server/main.ts",
25
+ "dev": "tsx watch src/server/main.ts",
26
+ "build": "esbuild src/server/main.ts --bundle --platform=node --format=esm --packages=external --banner:js='#!/usr/bin/env node' --outfile=dist/smooth-operator.mjs --sourcemap --sources-content=false",
27
+ "postbuild": "node scripts/set-executable.mjs dist/smooth-operator.mjs",
28
+ "lint": "eslint .",
29
+ "typecheck": "tsc --noEmit",
30
+ "test": "vitest run",
31
+ "test:browser:live": "node scripts/test-browser-live.mjs",
32
+ "test:watch": "vitest",
33
+ "test:coverage": "vitest run --coverage",
34
+ "dead-code": "knip --include files,exports,dependencies,unlisted --no-progress",
35
+ "mcp:stdio": "npm run start -- --transport stdio",
36
+ "mcp:http": "npm run start -- --transport http",
37
+ "benchmark:mcp": "node scripts/benchmark-mcp.mjs",
38
+ "benchmark:mcp:live": "node scripts/benchmark-mcp.mjs --live",
39
+ "benchmark:mcp:dist": "node scripts/benchmark-mcp.mjs --dist",
40
+ "package:smoke": "npm run build && node scripts/verify-package.mjs",
41
+ "package:smoke:install": "npm run build && node scripts/verify-package.mjs --install",
42
+ "release:smoke": "npm run package:smoke:install && npm run benchmark:mcp:dist",
43
+ "prepack": "npm run build",
44
+ "prepare": "npm run build"
45
+ },
46
+ "dependencies": {
47
+ "@modelcontextprotocol/node": "^2.0.0",
48
+ "@modelcontextprotocol/server": "^2.0.0",
49
+ "puppeteer-core": "^25.8.0",
50
+ "zod": "^4.4.3"
51
+ },
52
+ "devDependencies": {
53
+ "@modelcontextprotocol/client": "^2.0.0",
54
+ "@types/node": "^26.2.0",
55
+ "@typescript-eslint/eslint-plugin": "^8.67.0",
56
+ "@typescript-eslint/parser": "^8.67.0",
57
+ "@vitest/coverage-v8": "^4.1.11",
58
+ "esbuild": "^0.28.2",
59
+ "eslint": "^10.9.0",
60
+ "knip": "^6.32.2",
61
+ "tsx": "^4.23.12",
62
+ "typescript": "^6.0.3",
63
+ "vitest": "^4.1.11"
64
+ },
65
+ "engines": {
66
+ "node": ">=22.23.2",
67
+ "npm": ">=10.9.8"
68
+ }
69
+ }