@pinepaper.studio/mcp-server 1.6.24 → 1.6.25

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 (158) hide show
  1. package/README.md +130 -14
  2. package/dist/browser/puppeteer-controller.d.ts +6 -0
  3. package/dist/browser/puppeteer-controller.d.ts.map +1 -1
  4. package/dist/browser/puppeteer-controller.js +97 -69
  5. package/dist/browser/puppeteer-controller.js.map +1 -1
  6. package/dist/build-info.json +2 -2
  7. package/dist/cli.js +7 -5
  8. package/dist/cli.js.map +1 -1
  9. package/dist/design/design-systems.js +2 -2
  10. package/dist/design/design-systems.js.map +1 -1
  11. package/dist/i18n/locales/en.js +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +51 -11
  15. package/dist/index.js.map +1 -1
  16. package/dist/mcp/index.d.ts +5 -0
  17. package/dist/mcp/index.d.ts.map +1 -0
  18. package/dist/mcp/index.js +5 -0
  19. package/dist/mcp/index.js.map +1 -0
  20. package/dist/mcp/server.d.ts +86 -0
  21. package/dist/mcp/server.d.ts.map +1 -0
  22. package/dist/mcp/server.js +159 -0
  23. package/dist/mcp/server.js.map +1 -0
  24. package/dist/mcp/stdio.d.ts +20 -0
  25. package/dist/mcp/stdio.d.ts.map +1 -0
  26. package/dist/mcp/stdio.js +82 -0
  27. package/dist/mcp/stdio.js.map +1 -0
  28. package/dist/mcp/types.d.ts +598 -0
  29. package/dist/mcp/types.d.ts.map +1 -0
  30. package/dist/mcp/types.js +140 -0
  31. package/dist/mcp/types.js.map +1 -0
  32. package/dist/metrics/performance-tracker.d.ts.map +1 -1
  33. package/dist/metrics/performance-tracker.js +4 -3
  34. package/dist/metrics/performance-tracker.js.map +1 -1
  35. package/dist/ontology/hints.d.ts.map +1 -1
  36. package/dist/ontology/hints.js +3 -1
  37. package/dist/ontology/hints.js.map +1 -1
  38. package/dist/ontology/upstream-vocabulary.d.ts +2 -2
  39. package/dist/ontology/upstream-vocabulary.d.ts.map +1 -1
  40. package/dist/ontology/upstream-vocabulary.js +8 -2
  41. package/dist/ontology/upstream-vocabulary.js.map +1 -1
  42. package/dist/server/index.d.ts +1 -1
  43. package/dist/server/index.d.ts.map +1 -1
  44. package/dist/server/index.js +1 -1
  45. package/dist/server/index.js.map +1 -1
  46. package/dist/tools/batch-macros.d.ts.map +1 -1
  47. package/dist/tools/batch-macros.js +2 -1
  48. package/dist/tools/batch-macros.js.map +1 -1
  49. package/dist/tools/compact-descriptions.d.ts.map +1 -1
  50. package/dist/tools/compact-descriptions.js +7 -6
  51. package/dist/tools/compact-descriptions.js.map +1 -1
  52. package/dist/tools/craft-tools.d.ts +1 -1
  53. package/dist/tools/craft-tools.d.ts.map +1 -1
  54. package/dist/tools/create-known-keys.d.ts +2 -0
  55. package/dist/tools/create-known-keys.d.ts.map +1 -0
  56. package/dist/tools/create-known-keys.js +24 -0
  57. package/dist/tools/create-known-keys.js.map +1 -0
  58. package/dist/tools/definitions.d.ts +3 -1
  59. package/dist/tools/definitions.d.ts.map +1 -1
  60. package/dist/tools/definitions.js +43 -22
  61. package/dist/tools/definitions.js.map +1 -1
  62. package/dist/tools/effect-check.d.ts +1 -1
  63. package/dist/tools/effect-check.d.ts.map +1 -1
  64. package/dist/tools/effect-check.js +4 -0
  65. package/dist/tools/effect-check.js.map +1 -1
  66. package/dist/tools/engine-lists.d.ts +4 -1
  67. package/dist/tools/engine-lists.d.ts.map +1 -1
  68. package/dist/tools/engine-lists.js +9 -1
  69. package/dist/tools/engine-lists.js.map +1 -1
  70. package/dist/tools/engine-methods.d.ts.map +1 -1
  71. package/dist/tools/engine-methods.js +1 -0
  72. package/dist/tools/engine-methods.js.map +1 -1
  73. package/dist/tools/engine-surface.d.ts +1 -1
  74. package/dist/tools/engine-surface.d.ts.map +1 -1
  75. package/dist/tools/engine-surface.js +18 -3
  76. package/dist/tools/engine-surface.js.map +1 -1
  77. package/dist/tools/export-file-receipt.d.ts +12 -0
  78. package/dist/tools/export-file-receipt.d.ts.map +1 -1
  79. package/dist/tools/export-file-receipt.js +21 -1
  80. package/dist/tools/export-file-receipt.js.map +1 -1
  81. package/dist/tools/handlers/beats.d.ts +1 -1
  82. package/dist/tools/handlers/beats.d.ts.map +1 -1
  83. package/dist/tools/handlers/camera.d.ts +1 -1
  84. package/dist/tools/handlers/camera.d.ts.map +1 -1
  85. package/dist/tools/handlers/export.d.ts +1 -1
  86. package/dist/tools/handlers/export.d.ts.map +1 -1
  87. package/dist/tools/handlers/export.js +3 -2
  88. package/dist/tools/handlers/export.js.map +1 -1
  89. package/dist/tools/handlers/font.d.ts +1 -1
  90. package/dist/tools/handlers/font.d.ts.map +1 -1
  91. package/dist/tools/handlers/font.js +8 -7
  92. package/dist/tools/handlers/font.js.map +1 -1
  93. package/dist/tools/handlers/generate.d.ts +1 -1
  94. package/dist/tools/handlers/generate.d.ts.map +1 -1
  95. package/dist/tools/handlers/generate.js +4 -3
  96. package/dist/tools/handlers/generate.js.map +1 -1
  97. package/dist/tools/handlers/maps.d.ts +1 -1
  98. package/dist/tools/handlers/maps.d.ts.map +1 -1
  99. package/dist/tools/handlers/ontology.d.ts +1 -1
  100. package/dist/tools/handlers/ontology.d.ts.map +1 -1
  101. package/dist/tools/handlers/tool-guide.d.ts +1 -1
  102. package/dist/tools/handlers/tool-guide.d.ts.map +1 -1
  103. package/dist/tools/handlers.d.ts +15 -3
  104. package/dist/tools/handlers.d.ts.map +1 -1
  105. package/dist/tools/handlers.js +71 -31
  106. package/dist/tools/handlers.js.map +1 -1
  107. package/dist/tools/lane.d.ts +11 -6
  108. package/dist/tools/lane.d.ts.map +1 -1
  109. package/dist/tools/lane.js +46 -9
  110. package/dist/tools/lane.js.map +1 -1
  111. package/dist/tools/minimal-descriptions.js +1 -1
  112. package/dist/tools/minimal-descriptions.js.map +1 -1
  113. package/dist/tools/p5-compat/p5-helpers.d.ts +1 -1
  114. package/dist/tools/p5-compat/p5-helpers.js +1 -1
  115. package/dist/tools/shape-params.d.ts +2 -2
  116. package/dist/tools/shape-params.d.ts.map +1 -1
  117. package/dist/tools/shape-params.js +8 -2
  118. package/dist/tools/shape-params.js.map +1 -1
  119. package/dist/tools/stick-vocabulary.d.ts +2 -2
  120. package/dist/tools/stick-vocabulary.js +2 -2
  121. package/dist/tools/timeline.d.ts +2 -2
  122. package/dist/tools/timeline.d.ts.map +1 -1
  123. package/dist/tools/timeline.js +6 -1
  124. package/dist/tools/timeline.js.map +1 -1
  125. package/dist/tools/toolkits.d.ts +22 -7
  126. package/dist/tools/toolkits.d.ts.map +1 -1
  127. package/dist/tools/toolkits.js +102 -20
  128. package/dist/tools/toolkits.js.map +1 -1
  129. package/dist/types/code-generator.d.ts +25 -0
  130. package/dist/types/code-generator.d.ts.map +1 -1
  131. package/dist/types/code-generator.js +402 -157
  132. package/dist/types/code-generator.js.map +1 -1
  133. package/dist/types/schemas.d.ts +52 -47
  134. package/dist/types/schemas.d.ts.map +1 -1
  135. package/dist/types/schemas.js +7 -5
  136. package/dist/types/schemas.js.map +1 -1
  137. package/dist/utils/asset-paths.d.ts.map +1 -1
  138. package/dist/utils/asset-paths.js +4 -4
  139. package/dist/utils/asset-paths.js.map +1 -1
  140. package/dist/utils/env.d.ts +9 -0
  141. package/dist/utils/env.d.ts.map +1 -0
  142. package/dist/utils/env.js +11 -0
  143. package/dist/utils/env.js.map +1 -0
  144. package/dist/utils/export-dir.d.ts +36 -0
  145. package/dist/utils/export-dir.d.ts.map +1 -0
  146. package/dist/utils/export-dir.js +86 -0
  147. package/dist/utils/export-dir.js.map +1 -0
  148. package/dist/utils/js-literal.d.ts +4 -0
  149. package/dist/utils/js-literal.d.ts.map +1 -0
  150. package/dist/utils/js-literal.js +25 -0
  151. package/dist/utils/js-literal.js.map +1 -0
  152. package/dist/utils/mcp-log.d.ts +1 -1
  153. package/dist/utils/mcp-log.d.ts.map +1 -1
  154. package/dist/version.d.ts.map +1 -1
  155. package/dist/version.js +5 -12
  156. package/dist/version.js.map +1 -1
  157. package/manifest.json +42 -63
  158. package/package.json +8 -6
package/README.md CHANGED
@@ -249,6 +249,124 @@ If you do not want an agent executing anything, `code` mode is a first-class pat
249
249
  - Puppeteer itself is an **optional** peer dependency, kept out of the default tree precisely because a headless browser plus an install script is what scanners flag hardest. Install it only if you want the executing mode.
250
250
  - The server itself fetches the images, SVGs and media a tool call names by URL, and reads local files named by path. URLs that resolve to loopback, private, link-local or reserved addresses are refused, redirects included, and so are cloud metadata addresses. Local files are read only from the working directory, the export folder, and folders listed in `PINEPAPER_ASSET_DIRS`. `PINEPAPER_ALLOW_PRIVATE_NETWORK=1` allows local and LAN hosts. Metadata addresses stay refused even with it set.
251
251
 
252
+ ## What's new in 1.6.25
253
+
254
+ ### Added
255
+
256
+ - `pinepaper_pattern` kinds `ring` and `orbit`: members spaced evenly round a
257
+ turning circle, with a fixed `center` or a `target` item the centre follows.
258
+ The list of kinds now comes from the studio, so a kind it adds appears here
259
+ too.
260
+
261
+ ### Changed
262
+
263
+ - The server speaks MCP itself instead of through the MCP SDK, so installing
264
+ it pulls in 2 packages (`zod` and `undici`) instead of 78. It behaves the
265
+ same on the wire: the same protocol versions (2024-10-07 to 2025-11-25),
266
+ errors, progress, cancellation and logging, checked against recordings of
267
+ the previous server. `createServer()` still accepts any MCP transport,
268
+ including the SDK's.
269
+ - The published code no longer uses `eval` or runs `git`, and it reads
270
+ environment variables in one place.
271
+ - New sessions start with a leaner tool list: the `core` toolkit, about half
272
+ the context of the previous default, with every craft tool the server
273
+ recommends. Other tools load when needed with `pinepaper_set_toolkit`
274
+ `{"load": ["map"]}` (a group) or a tool's name, and the list updates at
275
+ once. Claude Desktop, Cursor and Windsurf used to get all 178 tools.
276
+ `PINEPAPER_TOOLKIT=agent` or `full` restores a larger list.
277
+ - Exports are saved to `~/Downloads/PinePaper` instead of a temporary folder,
278
+ so Desktop users can find them (`PINEPAPER_EXPORT_DIR` still overrides it,
279
+ and machines without a Downloads folder keep the temporary folder). Each
280
+ saved file also comes back as a link the client can open, and
281
+ `resources/read` returns files up to 10 MB from the export folder.
282
+ - A Claude Desktop extension (`.mcpb`) can be built with `bun run
283
+ build:mcpb`: one file to open, no config to edit. It uses your installed
284
+ Chrome for the canvas tools. Without full `puppeteer`, the server now also
285
+ works with `puppeteer-core` and your installed Chrome, or another browser
286
+ set in `PINEPAPER_CHROME_PATH`.
287
+
288
+ ### Fixed
289
+
290
+ - `pinepaper_pattern` no longer warns "NO CHANGE" after a `create` or
291
+ `modify` that has not moved anything yet, such as a wave at time 0 or one
292
+ whose window starts later.
293
+ - A failed batch step addressed by `$N` names the item that `$N` resolved to,
294
+ not `"$N"`.
295
+ - Batch `animate` and `relation` operations quote their `animationType` and
296
+ `relationType` correctly in the generated code.
297
+ - The scene lint that batches and custom code run on every call no longer
298
+ checks every pair of items, which made each call on a large scene slower.
299
+ It reports the same warnings.
300
+ - A video export that goes over the bitrate you asked for says so: the studio
301
+ reports `bitrate_exceeded` with the bitrate the file actually has, and how
302
+ to land under the target.
303
+ - The agent toolkit's export description now says what each format returns:
304
+ only MP4 and WebM carry a frame digest, and a small SVG comes back inline
305
+ rather than as a file.
306
+ - `on_event_fire_if` is documented: its predicate is an ExpressionIR object
307
+ (comparisons, and/or/not, reads of an item's data, active or visible
308
+ state), and it fires the event in `params.event`, not its target. A
309
+ predicate written as a string, or a relation with no event to fire, is
310
+ refused with the shape that works, wherever the relation comes from:
311
+ `pinepaper_add_relation`, a batch `relation` step, `pinepaper_create_scene`,
312
+ `pinepaper_instantiate_ontology`, or an `on_event_add_relation` that adds
313
+ one later. Before, the relation silently never fired.
314
+ - An emitter given a `[min, max]` range for a key that takes one number
315
+ (such as `gravity`, `opacity` or `count`) now gets a warning: the key draws
316
+ one value for every particle, not a spread. Before, there was no warning.
317
+ - `pinepaper_import_image` takes a `name`, so a batch `patch` can address an
318
+ imported image by name.
319
+ - Custom code that returns nothing is reported as returning nothing, not as
320
+ `{}`, when the scene lint has warnings.
321
+ - An export whose file was saved but could not be hashed or read back says
322
+ so. It used to report the save as failed.
323
+ - A batch step other than `create` that carries a key it does not read
324
+ now gets an `IGNORED ARGUMENTS` note naming the step and the key. Before,
325
+ the key had no effect and nothing said so. The common mix-ups get a hint:
326
+ `params` on a `relation` step (it takes `relationOptions`), and `x`/`y` on
327
+ a `modify` step (changes go inside `properties`).
328
+ - Clearing the canvas starts item ids again at `item_1`
329
+ (`pinepaper_clear_canvas`, `pinepaper_agent_start_job` and
330
+ `pinepaper_agent_reset`), so a batch sent after a clear gets the same ids
331
+ every time. Before, the numbering carried on from the cleared items, and
332
+ only a server restart reset it.
333
+ - A `group` step in a batch now takes the next `$N`, as a `create` does, so
334
+ a later step can animate the group: in `[create, create, group, …]` the
335
+ group is `$2`. This renumbers batches that create items after a group:
336
+ in `[create, create, group, create]` the last item was `$2` and is now
337
+ `$3`. Before, a `$N` meant for the group failed with "it has created 2 so
338
+ far".
339
+ - An event reaction that shows or hides an item (`on_event_set_visibility`,
340
+ and its `on_enter_` and `on_exit_` forms) refuses `value` and asks for
341
+ `visible`, the field it reads. Before, `{"value": false}` showed the item
342
+ instead of hiding it.
343
+ - A PNG, JPG, WebP, SVG or PDF of a scene that is playing is its first frame
344
+ (time 0), the frame a video starts on, and the result says so. Before, it
345
+ was whatever frame playback had reached, so items moved by relations (an
346
+ orbit) were in a different place on every export. `time` still picks
347
+ another moment.
348
+ - A closed shape given a `strokeColor` and no fill is drawn as an outline.
349
+ Before, it got the default fill, or the active brand's colour.
350
+ - A batch no longer flags `ttl` or `bornAt` on a `line` as a likely typo.
351
+ - A line created with `from` and `to` reports where it actually is, and says
352
+ that `position` does not move it: `from` and `to` are canvas coordinates.
353
+ Before, the result reported the position asked for while the line was
354
+ drawn at the top left.
355
+ - `pinepaper_transform` `nudge` moves an item the way `pinepaper_modify_item`
356
+ does, so an item with a loop animation keeps its new place, and the
357
+ result no longer reports the move as no change.
358
+ - `create_item` documents `properties.id`: an id of your own, so replays
359
+ address the same items. An id with a quote, backslash or line break is
360
+ refused, since later calls could not address it.
361
+ - An item id containing a quote no longer breaks `pinepaper_modify_item`,
362
+ `pinepaper_delete_item`, `pinepaper_animate`,
363
+ `pinepaper_keyframe_animate`, `pinepaper_apply_effect` or
364
+ `pinepaper_query_relations`. Before, the call failed with a syntax error.
365
+ - The `lane` toolkit adds `pinepaper_event`, for things that happen at a
366
+ set time or on a click (a panel that hides at 3 s), and
367
+ `pinepaper_clear_canvas`, to start over. Its batch description shows how
368
+ to attach an event's reactions and triggers.
369
+
252
370
  ## What's new in 1.6.24
253
371
 
254
372
  ### Added
@@ -1717,27 +1835,20 @@ Fourteen new tools (121 → 135) and new actions across the surface — the rele
1717
1835
 
1718
1836
  | Profile | Contents |
1719
1837
  |---------|----------|
1838
+ | `core` | **The default.** The craft tools the server's instructions point to, the agent workflow, canvas and query tools, plus every tool those name, so no listed tool points at a missing one. About half the tokens of `agent`. Anything else loads on demand (below) |
1720
1839
  | `full` | Every tool, no filtering |
1721
- | `agent` | Every tool except the diagnostics (`pinepaper_get_performance_metrics`, `pinepaper_diagnostic_report`) and `pinepaper_register_item`. The default for a client not listed below |
1840
+ | `agent` | Every tool except the diagnostics (`pinepaper_get_performance_metrics`, `pinepaper_diagnostic_report`) and `pinepaper_register_item` |
1722
1841
  | `diagram` | Canvas + diagram + query/export |
1723
1842
  | `map` | Canvas + map + query/export |
1724
1843
  | `font` | Canvas + font + letter collage + export |
1725
1844
  | `minimal` | Agent, browser, canvas, and guide only |
1726
- | `lane` | **The agent lane**: exactly five tools — `pinepaper_agent_batch_execute`, `pinepaper_keyframe_animate`, `pinepaper_pattern`, `pinepaper_agent_export`, `pinepaper_lint_scene` — shown with descriptions that carry the rules an agent otherwise learns by failing (the keyframe shape, an item's words and look inside `properties`, a position being the item's centre, the export's 5 s default). The whole contract, instructions included, is ~3.3k tokens. For scripted builds of shapes, text, keyframes and relations; use `agent` for characters, styled scenes, maps, diagrams and sound |
1845
+ | `lane` | **The agent lane**: exactly seven tools — `pinepaper_agent_batch_execute`, `pinepaper_keyframe_animate`, `pinepaper_pattern`, `pinepaper_agent_export`, `pinepaper_lint_scene`, `pinepaper_event`, `pinepaper_clear_canvas` — shown with descriptions that carry the rules an agent otherwise learns by failing (the keyframe shape, an item's words and look inside `properties`, a position being the item's centre, the export's 5 s default). The whole contract, instructions included, is ~4.3k tokens. For scripted builds of shapes, text, keyframes and relations; use `core` for characters, styled scenes, maps, diagrams and sound |
1727
1846
 
1728
1847
  **Verbosity tiers** (`PINEPAPER_VERBOSITY`): `verbose`, `compact` (default), `minimal`.
1729
1848
 
1730
- **Client auto-detection.** When neither env var is set explicitly, the server picks a profile from the MCP `initialize` handshake:
1849
+ **Load on demand.** Every client starts on `core`. When a task needs more, the model calls `pinepaper_set_toolkit` with `load`: a group (`{"load": ["map"]}`, `["diagram"]`, `["font"]`, `["physics"]`, …) or a tool's own name. The tools are added for the session, along with any tools they mention, and the client is told the list changed. The server logs each client's name at start-up.
1731
1850
 
1732
- | Client | Toolkit | Verbosity |
1733
- |--------|---------|-----------|
1734
- | `claude-ai` | `minimal` | `compact` |
1735
- | `claude-desktop` | `full` | `compact` |
1736
- | `claude-code` | `agent` | `compact` |
1737
- | `cursor` | `full` | `compact` |
1738
- | `windsurf` | `full` | `compact` |
1739
-
1740
- Explicit env vars always win. You can also hand-pick tools with `PINEPAPER_TOOLS` (comma-separated names), or switch profiles at runtime with the `pinepaper_set_toolkit` tool. Start with `pinepaper_tool_guide` to have the server explain its own surface.
1851
+ `PINEPAPER_TOOLKIT` always wins. You can also hand-pick tools with `PINEPAPER_TOOLS` (comma-separated names), or switch profiles at runtime with the `pinepaper_set_toolkit` tool. Start with `pinepaper_tool_guide` to have the server explain its own surface.
1741
1852
 
1742
1853
  ## Features
1743
1854
 
@@ -2322,6 +2433,10 @@ bun install
2322
2433
  bun run build
2323
2434
  ```
2324
2435
 
2436
+ ### Claude Desktop extension (.mcpb)
2437
+
2438
+ `bun run build:mcpb` builds `mcpb/pinepaper-mcp-server-<version>.mcpb`, a one-file Claude Desktop extension: open it and Desktop installs the server, with no config file to edit. The extension drives your installed Google Chrome (choose another Chromium-based browser in its settings), and its settings also set the export folder and the tool list.
2439
+
2325
2440
  ### Test with MCP Client (Local)
2326
2441
 
2327
2442
  1. Build the server:
@@ -2437,9 +2552,10 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
2437
2552
  | `PINEPAPER_API_KEY` | Service-account key (`pp_sa_…`) for the cloud-backed tools (`pinepaper_generate`) | — |
2438
2553
  | `PINEPAPER_CLOUD_URL` | The PinePaper cloud those tools call | `https://cloud.pinepaper.studio` |
2439
2554
  | `PINEPAPER_EXECUTION_MODE` | `puppeteer` (execute in a real browser) or `code` (return generated code only) | `puppeteer` |
2440
- | `PINEPAPER_EXPORT_DIR` | Directory for exported files | `<tmpdir>/pinepaper-exports` |
2555
+ | `PINEPAPER_CHROME_PATH` | A Chromium-based browser for the canvas tools when full `puppeteer` is not installed (the Desktop extension uses your installed Chrome by default) | installed Google Chrome |
2556
+ | `PINEPAPER_EXPORT_DIR` | Directory for exported files | `~/Downloads/PinePaper` (`<tmpdir>/pinepaper-exports` where there is no Downloads folder) |
2441
2557
  | `PINEPAPER_LOCALE` | Language locale code | `en` |
2442
- | `PINEPAPER_TOOLKIT` | Toolkit profile (`full`/`agent`/`diagram`/`map`/`font`/`minimal`/`lane`) | auto-detected |
2558
+ | `PINEPAPER_TOOLKIT` | Toolkit profile (`core`/`full`/`agent`/`diagram`/`map`/`font`/`minimal`/`lane`) | `core` |
2443
2559
  | `PINEPAPER_TOOLS` | Explicit comma-separated tool allowlist | unset |
2444
2560
  | `PINEPAPER_VERBOSITY` | Description verbosity (`verbose`/`compact`/`minimal`) | `compact` |
2445
2561
  | `PINEPAPER_TOOL_VERBOSITY` | Deprecated alias for `PINEPAPER_VERBOSITY` | unset |
@@ -305,6 +305,12 @@ export declare class PinePaperBrowserController {
305
305
  /**
306
306
  * Execute JavaScript code in PinePaper Studio
307
307
  */
308
+ /**
309
+ * The ungoverned path: the code as a CDP Runtime.evaluate (Puppeteer's string form awaits a promise and keeps the
310
+ * script's trailing value), then the in-page bridgeSafe the governed path uses, so a value holding live Paper items
311
+ * still crosses. A throw comes back as { success: false, error }, as it did from eval.
312
+ */
313
+ private runUngoverned;
308
314
  executeCode(code: string, takeScreenshot?: boolean, options?: ExecuteCodeOptions): Promise<ExecuteResult>;
309
315
  /**
310
316
  * Take a screenshot of the current canvas
@@ -1 +1 @@
1
- {"version":3,"file":"puppeteer-controller.d.ts","sourceRoot":"","sources":["../../src/browser/puppeteer-controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"puppeteer-controller.d.ts","sourceRoot":"","sources":["../../src/browser/puppeteer-controller.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,WAAW,CAAC;AAS/C;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,kBAAkB,GAAG,cAAc,GAAG,cAAc,CAAC;AAE1F,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAAiE,CAAC;AAEtH,MAAM,WAAW,uBAAuB;IACtC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClC,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qEAAqE;IACrE,kBAAkB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAK1C;AAiCD;;;;;;;GAOG;AACH;;;;;GAKG;AACH,eAAO,MAAM,YAAY;;;CAAoC,CAAC;AA0C9D,qBAAa,0BAA0B;IACrC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA8B;gBAE3C,MAAM,GAAE,uBAA4B;IAyChD;;;OAGG;IACH,OAAO,CAAC,UAAU;IAgBlB,yEAAyE;IACzE,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAezD;;;;OAIG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAetC;;;;;OAKG;IACG,gBAAgB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAarE;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;;;OAIG;IACH,IAAI,kBAAkB,IAAI,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAEpE;IAED,6EAA6E;IAC7E,UAAU,IAAI,MAAM,EAAE;IAItB;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0F9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAKhC;;;;;;;;;;OAUG;YACW,aAAa;IAyB3B;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAkD;YAE1D,kBAAkB;IAYhC;;;;;OAKG;YACW,cAAc;IA6B5B,qEAAqE;IACrE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6E;IAC1G,OAAO,CAAC,YAAY,CAAS;YAEf,iBAAiB;IAK/B,kEAAkE;IAClE,OAAO,CAAC,eAAe;IAIvB;;;;;;OAMG;YACW,gBAAgB;IA6B9B,4EAA4E;YAC9D,eAAe;IAa7B;;OAEG;IACH;;;;OAIG;YACW,aAAa;IAiBrB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,UAAO,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,aAAa,CAAC;IAwOhH;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;YAQrC,eAAe;IA6B7B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIlD;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5C;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAU7B;;;OAGG;IACH;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC;QAAE,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAwC9G;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB7C;;;OAGG;IACG,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmIpE;;OAEG;YACW,gBAAgB;IAO9B;;;OAGG;IACG,YAAY,CAChB,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAC3D,OAAO,CAAC,kBAAkB,CAAC;IA4F9B;;OAEG;IACG,kBAAkB,CACtB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,cAAc,UAAQ,EACtB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC;IAsBzB;;OAEG;IACG,UAAU,CAAC,OAAO,GAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAgCxF;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;CAa9D;AAQD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,CAAC,EAAE,uBAAuB,GAC/B,0BAA0B,CAoC5B;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAU5D;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAKjD"}
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { mcpLog } from '../utils/mcp-log.js';
8
8
  import { LAZY_HEAVY_SUBSYSTEMS, LAZY_HEAVY_CLASSES, ENGINE_SURFACE } from '../tools/engine-surface.js';
9
+ import { env } from '../utils/env.js';
9
10
  export const PAGE_WAIT_UNTIL = ['load', 'domcontentloaded', 'networkidle0', 'networkidle2'];
10
11
  /**
11
12
  * Is PinePaper Studio actually usable? Evaluated IN THE PAGE, so it closes over
@@ -74,6 +75,46 @@ const BOOTSTRAP_SUBSYSTEMS = Object.freeze(Object.entries(ENGINE_SURFACE)
74
75
  * not go through executeOrGenerate (gate A2, 1.6.19).
75
76
  */
76
77
  export const BROWSER_TIME = { executeMs: 0, screenshotMs: 0 };
78
+ /**
79
+ * The browser driver. Puppeteer is an OPTIONAL peer (1.6.5): browser automation
80
+ * is a handful of tools, and a headless-browser download with an install script
81
+ * in the default tree is what supply-chain scanners flag hardest.
82
+ *
83
+ * Tried in order: `puppeteer` (its own Chrome), then `puppeteer-core` driving a
84
+ * browser already on the machine (1.6.25: the Claude Desktop bundle ships
85
+ * puppeteer-core, not a Chrome download): PINEPAPER_CHROME_PATH when set, else
86
+ * the installed Chrome. Neither present → the install instruction, not a crash.
87
+ */
88
+ async function loadPuppeteer() {
89
+ try {
90
+ const full = await import('puppeteer');
91
+ return { launch: (opts) => full.default.launch(opts) };
92
+ }
93
+ catch { /* not installed: try the core driver */ }
94
+ let core = null;
95
+ try {
96
+ const specifier = 'puppeteer-core'; // a variable, so the build does not need the package installed
97
+ core = await import(specifier);
98
+ }
99
+ catch { /* not installed either */ }
100
+ if (core) {
101
+ const executablePath = env('PINEPAPER_CHROME_PATH')?.trim();
102
+ return {
103
+ launch: async (opts) => {
104
+ try {
105
+ return await core.default.launch({ ...opts, ...(executablePath ? { executablePath } : { channel: 'chrome' }) });
106
+ }
107
+ catch (e) {
108
+ const why = e instanceof Error ? e.message.split('\n')[0] : String(e);
109
+ throw new Error(executablePath
110
+ ? `Could not start the browser at PINEPAPER_CHROME_PATH (${executablePath}): ${why}`
111
+ : `The canvas tools drive your installed Google Chrome, and it could not be started (${why}). Install Chrome from https://www.google.com/chrome/, or set PINEPAPER_CHROME_PATH to another Chromium-based browser (Edge, Brave, Chromium), then retry.`);
112
+ }
113
+ },
114
+ };
115
+ }
116
+ throw new Error('The browser tools need puppeteer, which is an optional install. Under npx, add it to the same call — args ["-y", "-p", "puppeteer", "-p", "@pinepaper.studio/mcp-server", "pinepaper-mcp"] — since a separate `npm i puppeteer` is not visible to npx\'s copy. Installed globally: `npm i -g puppeteer`; in a project: `npm i puppeteer`. Then retry. It is kept out of the default dependency tree for supply-chain hygiene.');
117
+ }
77
118
  export class PinePaperBrowserController {
78
119
  browser = null;
79
120
  page = null;
@@ -305,19 +346,9 @@ export class PinePaperBrowserController {
305
346
  this.browser = null;
306
347
  this.page = null;
307
348
  }
308
- // Puppeteer is an OPTIONAL peer (1.6.5): browser automation is 4 of 135
309
- // tools, and carrying a headless-browser + install-script dependency in
310
- // the default tree is what supply-chain scanners flag hardest. Absent →
311
- // a clear instruction, not a crash.
312
- let puppeteer;
313
- try {
314
- puppeteer = await import('puppeteer');
315
- }
316
- catch {
317
- throw new Error('The browser tools need puppeteer, which is an optional install. Under npx, add it to the same call — args ["-y", "-p", "puppeteer", "-p", "@pinepaper.studio/mcp-server", "pinepaper-mcp"] — since a separate `npm i puppeteer` is not visible to npx\'s copy. Installed globally: `npm i -g puppeteer`; in a project: `npm i puppeteer`. Then retry. It is kept out of the default dependency tree for supply-chain hygiene.');
318
- }
349
+ const puppeteer = await loadPuppeteer();
319
350
  console.error('[PinePaper] Launching browser...');
320
- this.browser = await puppeteer.default.launch(this.launchOptions(this.config.headless, this.launchArgs(this.config.viewportWidth, this.config.viewportHeight)));
351
+ this.browser = await puppeteer.launch(this.launchOptions(this.config.headless, this.launchArgs(this.config.viewportWidth, this.config.viewportHeight)));
321
352
  // Get existing pages first, reuse if available (avoid creating multiple tabs)
322
353
  const pages = await this.browser.pages();
323
354
  if (pages.length > 0) {
@@ -501,7 +532,7 @@ export class PinePaperBrowserController {
501
532
  async ensureStudioPage() {
502
533
  if (!this.page)
503
534
  return 'ok';
504
- let state = null;
535
+ let state;
505
536
  try {
506
537
  state = await this.page.evaluate(() => {
507
538
  const app = window.app || window.PinePaper;
@@ -548,6 +579,31 @@ export class PinePaperBrowserController {
548
579
  /**
549
580
  * Execute JavaScript code in PinePaper Studio
550
581
  */
582
+ /**
583
+ * The ungoverned path: the code as a CDP Runtime.evaluate (Puppeteer's string form awaits a promise and keeps the
584
+ * script's trailing value), then the in-page bridgeSafe the governed path uses, so a value holding live Paper items
585
+ * still crosses. A throw comes back as { success: false, error }, as it did from eval.
586
+ */
587
+ async runUngoverned(code) {
588
+ if (!this.page)
589
+ return { success: false, error: 'Browser not connected', executedVia: 'eval' };
590
+ let handle = null;
591
+ try {
592
+ handle = await this.page.evaluateHandle(code);
593
+ const value = await this.page.evaluate((v) => {
594
+ const safe = window.__ppBridgeSafe;
595
+ return safe ? safe(v) : v;
596
+ }, handle);
597
+ return { success: true, result: value, executedVia: 'eval' };
598
+ }
599
+ catch (e) {
600
+ return { success: false, error: e instanceof Error ? e.message : 'Execution error', executedVia: 'eval' };
601
+ }
602
+ finally {
603
+ if (handle)
604
+ await handle.dispose().catch(() => { });
605
+ }
606
+ }
551
607
  async executeCode(code, takeScreenshot = true, options = {}) {
552
608
  if (!this.page || !this.isConnected) {
553
609
  return {
@@ -611,7 +667,7 @@ export class PinePaperBrowserController {
611
667
  stage: options.stage ?? null,
612
668
  };
613
669
  const __evalStart = Date.now();
614
- const result = await this.page.evaluate(async (codeToRun, opts) => {
670
+ const evaluated = await this.page.evaluate(async (codeToRun, opts) => {
615
671
  // THE BRIDGE USES STRUCTURED CLONE, AND JSON.stringify DOES NOT PROVE IT.
616
672
  //
617
673
  // A result crosses CDP by structured clone, which refuses to carry a
@@ -715,25 +771,18 @@ export class PinePaperBrowserController {
715
771
  return { success: false, error: e instanceof Error ? e.message : 'Execution error', executedVia: 'governed' };
716
772
  }
717
773
  }
718
- // Fallback: raw eval — a pre-governor FxTool build, or an explicit
719
- // bypass. Both generated-code shapes are `(`-led expression statements,
720
- // so eval returns the same trailing value runGenerated captures.
721
- try {
722
- // eslint-disable-next-line no-eval
723
- const evalResult = eval(codeToRun);
724
- if (evalResult instanceof Promise) {
725
- return evalResult.then((r) => ({ success: true, result: bridgeSafe(r), executedVia: 'eval' }));
726
- }
727
- return { success: true, result: bridgeSafe(evalResult), executedVia: 'eval' };
728
- }
729
- catch (e) {
730
- return {
731
- success: false,
732
- error: e instanceof Error ? e.message : 'Execution error',
733
- executedVia: 'eval',
734
- };
735
- }
774
+ // Fallback: run ungoverned — a pre-governor FxTool build, or an explicit
775
+ // bypass. The code is run from the Node side as a CDP Runtime.evaluate
776
+ // (below), which returns the script's trailing value exactly as eval did:
777
+ // both generated-code shapes are `(`-led expression statements. It used
778
+ // to be eval() here; the published package then carried an eval call
779
+ // that supply-chain scanners flag, for what CDP already does.
780
+ window.__ppBridgeSafe = bridgeSafe;
781
+ return { success: true, __ppRaw: true, executedVia: 'eval' };
736
782
  }, code, runOptions);
783
+ let result = evaluated;
784
+ if (evaluated.__ppRaw)
785
+ result = await this.runUngoverned(code);
737
786
  BROWSER_TIME.executeMs += Date.now() - __evalStart;
738
787
  // Take screenshot if requested
739
788
  let screenshot;
@@ -981,23 +1030,13 @@ export class PinePaperBrowserController {
981
1030
  this.browser = null;
982
1031
  this.page = null;
983
1032
  }
984
- // Puppeteer is an OPTIONAL peer (1.6.5): browser automation is 4 of 135
985
- // tools, and carrying a headless-browser + install-script dependency in
986
- // the default tree is what supply-chain scanners flag hardest. Absent →
987
- // a clear instruction, not a crash.
988
- let puppeteer;
989
- try {
990
- puppeteer = await import('puppeteer');
991
- }
992
- catch {
993
- throw new Error('The browser tools need puppeteer, which is an optional install. Under npx, add it to the same call — args ["-y", "-p", "puppeteer", "-p", "@pinepaper.studio/mcp-server", "pinepaper-mcp"] — since a separate `npm i puppeteer` is not visible to npx\'s copy. Installed globally: `npm i -g puppeteer`; in a project: `npm i puppeteer`. Then retry. It is kept out of the default dependency tree for supply-chain hygiene.');
994
- }
1033
+ const puppeteer = await loadPuppeteer();
995
1034
  // Agent mode defaults to visible browser so user can see PinePaper Studio
996
1035
  const useHeadless = options.headless ?? this.config.headless;
997
1036
  const viewportWidth = options.viewportWidth ?? this.config.viewportWidth;
998
1037
  const viewportHeight = options.viewportHeight ?? this.config.viewportHeight;
999
1038
  console.error(`[PinePaper] Launching browser in agent mode (headless: ${useHeadless})...`);
1000
- this.browser = await puppeteer.default.launch(this.launchOptions(useHeadless, this.launchArgs(viewportWidth, viewportHeight, [
1039
+ this.browser = await puppeteer.launch(this.launchOptions(useHeadless, this.launchArgs(viewportWidth, viewportHeight, [
1001
1040
  // '--disable-gpu' USED TO BE HERE, AND IT TURNED OFF WEBGL.
1002
1041
  //
1003
1042
  // It was carried in as a headless convention under "optimization
@@ -1134,24 +1173,13 @@ ${codes.map((code, i) => `
1134
1173
  })();
1135
1174
  `.trim();
1136
1175
  try {
1137
- const result = await this.page.evaluate((codeToRun) => {
1138
- try {
1139
- // eslint-disable-next-line no-eval
1140
- const evalResult = eval(codeToRun);
1141
- if (evalResult instanceof Promise) {
1142
- return evalResult;
1143
- }
1144
- return evalResult;
1145
- }
1146
- catch (e) {
1147
- return {
1148
- success: false,
1149
- error: e instanceof Error ? e.message : 'Batch execution error',
1150
- results: [],
1151
- itemIds: [],
1152
- };
1153
- }
1154
- }, batchCode);
1176
+ // A string is run as a CDP Runtime.evaluate: the script's value, awaited, by value (no eval in this package).
1177
+ const result = await this.page.evaluate(batchCode).catch((e) => ({
1178
+ success: false,
1179
+ error: e instanceof Error ? e.message : 'Batch execution error',
1180
+ results: [],
1181
+ itemIds: [],
1182
+ }));
1155
1183
  const executionTime = Date.now() - startTime;
1156
1184
  // Take screenshot if requested
1157
1185
  let screenshot;
@@ -1268,25 +1296,25 @@ export function getBrowserController(config) {
1268
1296
  // Env resolution lives here, not in the controller: explicit config wins,
1269
1297
  // then the env var, then the default — the shape PINEPAPER_HEADLESS and
1270
1298
  // PINEPAPER_STUDIO_URL already use.
1271
- const envHeadless = process.env.PINEPAPER_HEADLESS;
1299
+ const envHeadless = env('PINEPAPER_HEADLESS');
1272
1300
  const headless = config?.headless ?? (envHeadless !== undefined ? envHeadless !== 'false' : true);
1273
- const envWaitUntil = process.env.PINEPAPER_WAIT_UNTIL?.trim();
1301
+ const envWaitUntil = env('PINEPAPER_WAIT_UNTIL')?.trim();
1274
1302
  if (envWaitUntil && !PAGE_WAIT_UNTIL.includes(envWaitUntil)) {
1275
1303
  // Loudly, because a typo here silently reinstates the hang it was set to
1276
1304
  // avoid — and a 30s connect failure looks nothing like a bad env var.
1277
1305
  console.error(`[PinePaper] PINEPAPER_WAIT_UNTIL="${envWaitUntil}" is not one of ${PAGE_WAIT_UNTIL.join(', ')} — ignoring it.`);
1278
1306
  }
1279
- const envTimeout = Number(process.env.PINEPAPER_TIMEOUT);
1280
- if (process.env.PINEPAPER_TIMEOUT && !Number.isFinite(envTimeout)) {
1281
- console.error(`[PinePaper] PINEPAPER_TIMEOUT="${process.env.PINEPAPER_TIMEOUT}" is not a number — ignoring it.`);
1307
+ const envTimeout = Number(env('PINEPAPER_TIMEOUT'));
1308
+ if (env('PINEPAPER_TIMEOUT') && !Number.isFinite(envTimeout)) {
1309
+ console.error(`[PinePaper] PINEPAPER_TIMEOUT="${env('PINEPAPER_TIMEOUT')}" is not a number — ignoring it.`);
1282
1310
  }
1283
1311
  const mcpConfig = {
1284
1312
  ...config,
1285
1313
  headless,
1286
1314
  waitUntil: config?.waitUntil ?? (envWaitUntil && PAGE_WAIT_UNTIL.includes(envWaitUntil) ? envWaitUntil : undefined),
1287
1315
  timeout: config?.timeout ?? (Number.isFinite(envTimeout) && envTimeout > 0 ? envTimeout : undefined),
1288
- proxy: config?.proxy ?? process.env.PINEPAPER_PROXY?.trim(),
1289
- governor: config?.governor ?? (process.env.PINEPAPER_GOVERNOR?.trim().toLowerCase() !== 'off'),
1316
+ proxy: config?.proxy ?? env('PINEPAPER_PROXY')?.trim(),
1317
+ governor: config?.governor ?? (env('PINEPAPER_GOVERNOR')?.trim().toLowerCase() !== 'off'),
1290
1318
  };
1291
1319
  globalController = new PinePaperBrowserController(mcpConfig);
1292
1320
  }