@pinepaper.studio/mcp-server 1.6.30 → 1.6.32

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 (109) hide show
  1. package/README.de.md +1 -1
  2. package/README.es.md +1 -1
  3. package/README.fr.md +1 -1
  4. package/README.hi.md +1 -1
  5. package/README.ja.md +1 -1
  6. package/README.ko.md +1 -1
  7. package/README.md +131 -2
  8. package/README.pt-BR.md +1 -1
  9. package/README.zh-CN.md +1 -1
  10. package/SECURITY.md +15 -0
  11. package/dist/agent/types.d.ts +10 -10
  12. package/dist/browser/puppeteer-controller.d.ts.map +1 -1
  13. package/dist/browser/puppeteer-controller.js +83 -43
  14. package/dist/browser/puppeteer-controller.js.map +1 -1
  15. package/dist/build-info.json +2 -2
  16. package/dist/cli.js +2 -0
  17. package/dist/cli.js.map +1 -1
  18. package/dist/i18n/i18n-manager.d.ts.map +1 -1
  19. package/dist/i18n/i18n-manager.js +57 -3
  20. package/dist/i18n/i18n-manager.js.map +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/mcp/server.d.ts +12 -0
  25. package/dist/mcp/server.d.ts.map +1 -1
  26. package/dist/mcp/server.js +32 -2
  27. package/dist/mcp/server.js.map +1 -1
  28. package/dist/mcp/stdio.d.ts +4 -0
  29. package/dist/mcp/stdio.d.ts.map +1 -1
  30. package/dist/mcp/stdio.js +22 -0
  31. package/dist/mcp/stdio.js.map +1 -1
  32. package/dist/ontology/upstream-vocabulary.d.ts +2 -2
  33. package/dist/ontology/upstream-vocabulary.js +2 -2
  34. package/dist/ontology/vocabulary.d.ts.map +1 -1
  35. package/dist/ontology/vocabulary.js +18 -0
  36. package/dist/ontology/vocabulary.js.map +1 -1
  37. package/dist/tools/batch-op-names.d.ts +33 -0
  38. package/dist/tools/batch-op-names.d.ts.map +1 -0
  39. package/dist/tools/batch-op-names.js +140 -0
  40. package/dist/tools/batch-op-names.js.map +1 -0
  41. package/dist/tools/choreograph.d.ts +8 -0
  42. package/dist/tools/choreograph.d.ts.map +1 -1
  43. package/dist/tools/choreograph.js +9 -7
  44. package/dist/tools/choreograph.js.map +1 -1
  45. package/dist/tools/definitions.d.ts.map +1 -1
  46. package/dist/tools/definitions.js +109 -45
  47. package/dist/tools/definitions.js.map +1 -1
  48. package/dist/tools/effect-class.d.ts.map +1 -1
  49. package/dist/tools/effect-class.js +7 -0
  50. package/dist/tools/effect-class.js.map +1 -1
  51. package/dist/tools/engine-lists.d.ts +7 -4
  52. package/dist/tools/engine-lists.d.ts.map +1 -1
  53. package/dist/tools/engine-lists.js +17 -4
  54. package/dist/tools/engine-lists.js.map +1 -1
  55. package/dist/tools/engine-methods.d.ts.map +1 -1
  56. package/dist/tools/engine-methods.js +3 -0
  57. package/dist/tools/engine-methods.js.map +1 -1
  58. package/dist/tools/engine-surface.d.ts +1 -1
  59. package/dist/tools/engine-surface.d.ts.map +1 -1
  60. package/dist/tools/engine-surface.js +21 -4
  61. package/dist/tools/engine-surface.js.map +1 -1
  62. package/dist/tools/handlers/generate.d.ts +2 -2
  63. package/dist/tools/handlers.d.ts +7 -0
  64. package/dist/tools/handlers.d.ts.map +1 -1
  65. package/dist/tools/handlers.js +63 -4
  66. package/dist/tools/handlers.js.map +1 -1
  67. package/dist/tools/lane.d.ts +1 -1
  68. package/dist/tools/lane.d.ts.map +1 -1
  69. package/dist/tools/lane.js +1 -1
  70. package/dist/tools/lane.js.map +1 -1
  71. package/dist/tools/minimal-descriptions.js +1 -1
  72. package/dist/tools/minimal-descriptions.js.map +1 -1
  73. package/dist/tools/shape-params.d.ts +2 -2
  74. package/dist/tools/shape-params.d.ts.map +1 -1
  75. package/dist/tools/shape-params.js +8 -2
  76. package/dist/tools/shape-params.js.map +1 -1
  77. package/dist/tools/stick-vocabulary.d.ts +4 -4
  78. package/dist/tools/stick-vocabulary.d.ts.map +1 -1
  79. package/dist/tools/stick-vocabulary.js +15 -4
  80. package/dist/tools/stick-vocabulary.js.map +1 -1
  81. package/dist/types/code-generator.d.ts +25 -1
  82. package/dist/types/code-generator.d.ts.map +1 -1
  83. package/dist/types/code-generator.js +362 -105
  84. package/dist/types/code-generator.js.map +1 -1
  85. package/dist/types/schemas.d.ts +246 -105
  86. package/dist/types/schemas.d.ts.map +1 -1
  87. package/dist/types/schemas.js +70 -6
  88. package/dist/types/schemas.js.map +1 -1
  89. package/dist/utils/capabilities.d.ts.map +1 -1
  90. package/dist/utils/capabilities.js +3 -1
  91. package/dist/utils/capabilities.js.map +1 -1
  92. package/dist/utils/env.d.ts +19 -6
  93. package/dist/utils/env.d.ts.map +1 -1
  94. package/dist/utils/env.js +34 -6
  95. package/dist/utils/env.js.map +1 -1
  96. package/dist/utils/exit-when-client-gone.d.ts +10 -0
  97. package/dist/utils/exit-when-client-gone.d.ts.map +1 -0
  98. package/dist/utils/exit-when-client-gone.js +21 -0
  99. package/dist/utils/exit-when-client-gone.js.map +1 -0
  100. package/dist/utils/safe-fetch.d.ts +1 -0
  101. package/dist/utils/safe-fetch.d.ts.map +1 -1
  102. package/dist/utils/safe-fetch.js +3 -4
  103. package/dist/utils/safe-fetch.js.map +1 -1
  104. package/dist/vendor/design/design-style.d.ts +2 -2
  105. package/dist/vendor/design/design-style.d.ts.map +1 -1
  106. package/dist/vendor/design/design-style.js +5 -2
  107. package/dist/vendor/design/design-style.js.map +1 -1
  108. package/manifest.json +2 -2
  109. package/package.json +2 -2
package/README.de.md CHANGED
@@ -74,7 +74,7 @@ Bitten Sie Ihre KI zum Beispiel:
74
74
  **Lokal ist kostenlos und vollständig.** Alle Tools funktionieren, wenn Sie
75
75
  diesen Server selbst betreiben. Es gibt keine reduzierte Stufe.
76
76
 
77
- Benötigt: Node 18 oder neuer, rund **320 MB** Speicherplatz (Puppeteer lädt
77
+ Benötigt: Node 22.13 oder neuer, rund **320 MB** Speicherplatz (Puppeteer lädt
78
78
  Chrome herunter) und etwa 1 GB Arbeitsspeicher, solange ein Job läuft. Auf
79
79
  einem Laptop ist das unproblematisch, auf einem kleinen VPS oder einem
80
80
  gesperrten Arbeitsrechner eher nicht.
package/README.es.md CHANGED
@@ -74,7 +74,7 @@ Prueba a pedirle a tu IA:
74
74
  **Local es gratis y completo.** Todas las herramientas funcionan si ejecuta
75
75
  este servidor usted mismo. No hay una versión reducida.
76
76
 
77
- Necesita: Node 18 o superior, unos **320 MB** de disco (Puppeteer descarga
77
+ Necesita: Node 22.13 o superior, unos **320 MB** de disco (Puppeteer descarga
78
78
  Chrome) y alrededor de 1 GB de memoria mientras se ejecuta un trabajo. En un
79
79
  portátil no supone problema; en un VPS pequeño o un equipo de trabajo
80
80
  restringido, sí.
package/README.fr.md CHANGED
@@ -74,7 +74,7 @@ Essayez de demander à votre IA :
74
74
  **Le local est gratuit et complet.** Tous les outils fonctionnent si vous
75
75
  exécutez ce serveur vous-même. Il n'existe pas de version réduite.
76
76
 
77
- Il faut : Node 18 ou plus récent, environ **320 Mo** de disque (Puppeteer
77
+ Il faut : Node 22.13 ou plus récent, environ **320 Mo** de disque (Puppeteer
78
78
  télécharge Chrome) et à peu près 1 Go de mémoire pendant l'exécution d'une
79
79
  tâche. Sur un ordinateur portable, cela passe ; sur un petit VPS ou une machine
80
80
  de travail verrouillée, moins.
package/README.hi.md CHANGED
@@ -74,7 +74,7 @@ npm install -g @pinepaper.studio/mcp-server
74
74
  **लोकल मुफ़्त और पूरा है।** अगर आप यह सर्वर खुद चलाते हैं तो सारे टूल काम करते
75
75
  हैं। कोई सीमित संस्करण नहीं है।
76
76
 
77
- ज़रूरत: Node 18 या नया, लगभग **320 MB** डिस्क (Puppeteer क्रोम डाउनलोड करता है)
77
+ ज़रूरत: Node 22.13 या नया, लगभग **320 MB** डिस्क (Puppeteer क्रोम डाउनलोड करता है)
78
78
  और जॉब चलने के दौरान करीब 1 GB मेमोरी। लैपटॉप पर यह ठीक है; छोटे VPS या
79
79
  प्रतिबंधित ऑफ़िस मशीन पर मुश्किल।
80
80
 
package/README.ja.md CHANGED
@@ -74,7 +74,7 @@ AI にこう頼んでみてください:
74
74
  **ローカルは無料で、機能に制限はありません。** 自分でこのサーバーを動かせば、
75
75
  すべてのツールが使えます。制限版はありません。
76
76
 
77
- 必要なもの: Node 18 以降、約 **320 MB** のディスク (Puppeteer が Chrome を
77
+ 必要なもの: Node 22.13 以降、約 **320 MB** のディスク (Puppeteer が Chrome を
78
78
  ダウンロードします)、ジョブ実行中は約 1 GB のメモリ。ノート PC なら問題あり
79
79
  ませんが、小さな VPS や制限のある業務用マシンでは厳しいことがあります。
80
80
 
package/README.ko.md CHANGED
@@ -74,7 +74,7 @@ AI에게 이렇게 말해 보세요:
74
74
  **로컬은 무료이며 기능 제한이 없습니다.** 이 서버를 직접 실행하면 모든 도구가
75
75
  동작합니다. 축소된 버전은 없습니다.
76
76
 
77
- 필요한 것: Node 18 이상, 약 **320 MB** 디스크 (Puppeteer가 Chrome을
77
+ 필요한 것: Node 22.13 이상, 약 **320 MB** 디스크 (Puppeteer가 Chrome을
78
78
  내려받습니다), 작업 실행 중 약 1 GB 메모리. 노트북에서는 문제가 없지만 작은
79
79
  VPS나 제한된 업무용 컴퓨터에서는 부담스러울 수 있습니다.
80
80
 
package/README.md CHANGED
@@ -48,7 +48,7 @@ What it needs:
48
48
 
49
49
  | | |
50
50
  |---|---|
51
- | Node | 18 or newer |
51
+ | Node | 22.13 or newer (any supported Node release: 22, 24 or 26) |
52
52
  | Disk | With Puppeteer (below), Chrome is downloaded on install — roughly **320 MB** per version |
53
53
  | Memory | a Chrome process plus the Studio canvas, so budget ~1 GB while a job runs |
54
54
 
@@ -279,6 +279,135 @@ If you do not want an agent executing anything, `code` mode is a first-class pat
279
279
  - The npm package starts no process. Two export features use `ffprobe` and `ffmpeg`: checking a saved video against what the studio encoded, and joining the cached segments of a `perScene` export (`ffmpeg -f concat`). Only the Claude Desktop extension runs them, through a small runner it bundles that allows those two binaries alone, via `execFile` (no shell, argument lists the server writes, absolute paths). From npm, the check is skipped and said so, and a `perScene` export runs whole.
280
280
  - 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 with `PINEPAPER_ALLOW_LOCAL_FILES=1`, and then only from the working directory, the export folder, and folders listed in `PINEPAPER_ASSET_DIRS` (the export folder is readable without the switch). `PINEPAPER_ALLOW_PRIVATE_NETWORK=1` allows local and LAN hosts. Metadata addresses stay refused even with it set.
281
281
 
282
+ ## What's new in 1.6.32
283
+
284
+ ### Added
285
+
286
+ - Nine long-form relations from FxTool #162: `then` and `after` for cascading
287
+ sequential re-timing, collection relations `phase_wave`, `ring_forming` and
288
+ `flock` (boids simulation with per-member phase), event triggers `on_complete`
289
+ and `at_beat` on the unified hook clock, and shot and cue relations
290
+ `camera_tracks` (smooth tracking with rule-of-thirds framing and letterbox
291
+ integration) and `soundtrack_cue`.
292
+ - Text takes `wordSpacing`, `textTransform` (`uppercase`, `lowercase`,
293
+ `capitalize`), `textDecoration` (`underline`, `line-through`, `overline`,
294
+ combinable) and `textAlign: 'justify'` on create, modify and keyframes, on a
295
+ studio that draws them. They are no longer reported as ignored. The reply's
296
+ `typography` reads back what the item holds, and says so where the studio
297
+ does not draw them.
298
+ - `pinepaper_event` adds rules, state variables and bound text, on a studio
299
+ with the contraption engine; any other studio refuses them by name. A rule
300
+ (`add_contraption`) runs when an event fires or a variable changes: it can set
301
+ variables, change an item and fire the next event. `bind_text` keeps a text
302
+ showing variables, such as `Score: {score}`. A rule's changes stay, so use
303
+ `on_event_*` relations for anything in a video. Variables live in the page's
304
+ storage and survive `pinepaper_clear_canvas`, which removes rules.
305
+ - `pinepaper_agent_export` takes `audioCodec: 'aac'` for an MP4. Where the
306
+ browser has no AAC encoder (Chromium on Linux), the export is refused before
307
+ the first frame (`audio_codec_unavailable`) instead of writing a file whose
308
+ Opus soundtrack WhatsApp rejects. Without it, such an export carries Opus and
309
+ the `audio_codec_opus` warning, as before.
310
+
311
+ ### Fixed
312
+
313
+ - `pinepaper_lint_scene` and `pinepaper_query_relations` read back only the
314
+ parameters a relation was given. Before, a relation's params also carried the
315
+ studio's internal state, which took most of an `only: 'edit'` reply and could
316
+ overwrite live state when a ready-made op was sent back. A batch relation op
317
+ now drops `_`-prefixed keys and lists them in `droppedArguments`, as do
318
+ `pinepaper_add_relation` and the relations of `pinepaper_create_scene`.
319
+ - The `pinepaper_register_custom_relation` call in `edit.customRelations` now
320
+ works as given, with its parameter definitions in full.
321
+ - Replies now list ignored arguments in their JSON as `ignoredArguments`, and a
322
+ batch reply lists translated names as `translatedArguments`, so clients that
323
+ read `structuredContent` see them too.
324
+ - The server now exits when its client closes stdin or dies, and takes its
325
+ browser with it. Before, both kept running. A call already running gets up to
326
+ 5 s to answer, and is then cancelled.
327
+ - The `deterministic` docs state what a repeat export guarantees: identical
328
+ frames into the encoder (compare `frameDigest`), and a container identical
329
+ apart from the encoded samples. WebM is byte-identical; an MP4 is
330
+ byte-identical only where the export reports `bitExact: true`. The
331
+ `determinism_not_pinned` warning now says what still holds and names the
332
+ cause when the studio reports one.
333
+ - A custom relation now names an option it never reads, as built-in relations
334
+ do (`bobble does not read ampp, so it was ignored`). What it reads is worked
335
+ out when it is registered: its declared params and every `params.X` in its
336
+ code. If the code uses `params` another way, no list is kept and nothing is
337
+ named.
338
+ - `pinepaper_choreograph` reports, in `defaultsUsed`, each beat whose size you
339
+ left out (`height`, `arc`, `amount` or `intensity`) and the value it used, so
340
+ a beat drawn larger or smaller than you meant is visible in the reply.
341
+ - The relation docs say how a stepper starts: a current studio enters the
342
+ group's first member (or `relationOptions.initial`) at t=0 and runs its
343
+ `on_enter` reactions, and an older one starts with none entered.
344
+ - `pinepaper_import_image`'s `smoothing` docs say what Chromium shows: `low`,
345
+ `medium` and `high` draw the same, so the visible choice is `off` or not.
346
+ - `pinepaper_get_items` shows what create applied: each item's `name` (the
347
+ name a patch addresses it by), and its `scale`, `rotation` and `opacity`
348
+ when they are not the default.
349
+
350
+ ### Changed
351
+
352
+ - `edit.customRelations[]` offers the redefining `change` call only with
353
+ `withSource: true`, because that call needs the motion's source. Without it,
354
+ an entry lists the motion's name and parameters.
355
+ - The server reads the environment in one place, and only for a variable on its
356
+ fixed list (`src/utils/env.ts`), instead of one read per variable. The list
357
+ and what it allows are unchanged. 1.6.31's separate reads each counted as
358
+ their own finding in supply-chain scans.
359
+
360
+ ## What's new in 1.6.31
361
+
362
+ ### Changed
363
+
364
+ - **Requires Node 22.13 or newer.** Node 18 and 20 are end of life, and this
365
+ package's dependencies already needed 20.19 or 22.13, so `>=18` was never
366
+ really true. On an older Node, upgrade before updating.
367
+ - The server reads only a fixed list of environment variables, each by name
368
+ (`src/utils/env.ts`), and SECURITY.md lists what each capability of the
369
+ package is for and where it lives.
370
+ - Every module the package loads is named literally. `PINEPAPER_PUPPETEER_FROM`
371
+ now loads puppeteer from the folder you name with `createRequire`. The one
372
+ exception is the optional ffmpeg add-on that only the Claude Desktop
373
+ extension bundles.
374
+ - A `PINEPAPER_LOCALE` that is not a supported language falls back to English.
375
+ Before, the value became part of a file path.
376
+
377
+ ### Fixed
378
+
379
+ - A batch op now takes the parameter names its standalone tool takes, and the
380
+ reply lists each name it translated. Before, they were dropped, sometimes
381
+ without a word: `animationOptions: { intensity, speed, delay }` on an
382
+ `animate` op applied none of them. Relations, effects and generators take
383
+ `params`, masks take `preset` and `options`, generators take `region`,
384
+ `animate` takes `intensity` / `speed` / `delay` / `waveform` / `origin`,
385
+ and a `modify` op takes its changes beside `itemId`.
386
+ - A batch op's ignored-argument check now knows which keys each op type reads.
387
+ A key that only another op type uses (`speed` on `animate`, `preset` on a
388
+ mask, `itemId` on a generator) is reported instead of passing as known.
389
+ - An `animate` op names any `animationOptions` key the studio does not read,
390
+ with the likely intended name (`animationIntensty → animationIntensity?`).
391
+ The list comes from the studio's own code, so it follows the studio as it
392
+ changes.
393
+ - A batch `keyframe_animate` op gives the same warnings as
394
+ `pinepaper_keyframe_animate`: a key that leaves out a property another key
395
+ animates, `loop` in an export, easing on the first key, and `x` keyed beside
396
+ `fontSize` on an older studio. The batch op used to give none of them.
397
+ - An emitter warns about a `[min, max]` range only on keys that take one number
398
+ in every studio build (`count`, `aspect`, `strokeWidth`, `jitterHz`, the
399
+ fades). `gravity`, `drag`, `friction`, `opacity`, `sizeEnd` and `jitter` are
400
+ sampled per particle on the current studio, and an older one reports a range
401
+ it can't draw itself.
402
+ - `on_event_step_active` works without a `targetId` on the current studio. On
403
+ an older studio, which runs an event reaction only when it has a target, a
404
+ target-less one used to report success and never step; it is now refused
405
+ there, with the fix in the message (point it at any member of the group).
406
+ - The relation docs now say how a stepper or tab strip is built. Members join
407
+ an `exclusive_group` only through `exclusive_group` relations between them.
408
+ Being active has no look of its own: `on_enter_*` / `on_exit_*` reactions on
409
+ each member draw it, in exports too. `items` only sets the step order.
410
+
282
411
  ## What's new in 1.6.30
283
412
 
284
413
  ### Changed
@@ -1861,7 +1990,7 @@ The replacement enum was then built by scraping quoted strings out of `ThreadPai
1861
1990
  **New tool: `pinepaper_design_system`** — the design vocabulary as data, and eighteen styles that build a scene. Two different things, kept apart because they are not the same claim:
1862
1991
 
1863
1992
  - A **design system** is a real, licensed, versioned product — Material Design 3, IBM Carbon, Polaris, Fluent 2, Spectrum, Primer, USWDS, GOV.UK and more. Twenty-one of them, as W3C DTCG tokens. `list_easings` returns every motion curve across all of them as a named easing with its licence — and with `pinepaper:authored` on the three we had to fill in, so a vendor's published curve and one of ours are never mistaken for each other.
1864
- - An **aesthetic style** is a look: Bauhaus, Art Deco, Swiss, De Stijl, vaporwave, risograph, brutalist, Memphis, claymorphism, op art, pixel art. Thirty-eight named, eighteen of which `compose` a titled scene. `draw: false` returns the scene and the ops as data and draws nothing — read the composition before committing to it, the way `pinepaper_story`'s `distill` works.
1993
+ - An **aesthetic style** is a look: Bauhaus, Art Deco, Swiss, De Stijl, vaporwave, risograph, brutalist, Memphis, claymorphism, op art, pixel art. Forty-one named, eighteen of which `compose` a titled scene. `draw: false` returns the scene and the ops as data and draws nothing — read the composition before committing to it, the way `pinepaper_story`'s `distill` works.
1865
1994
 
1866
1995
  This runs in the server, not the browser: a design decision does not need the canvas to be open. The data is **vendored** from mcp-cloud by `scripts/sync-design-systems.mjs`, the same shape as the engine's stick-figure sync — one authored copy upstream, a mechanical mirror here, a sha256 in every header, and a provenance test that fails on a hand edit. A partial composition reports as a failure naming the elements that did not create, rather than as a success with half a poster.
1867
1996
 
package/README.pt-BR.md CHANGED
@@ -74,7 +74,7 @@ Experimente pedir à sua IA:
74
74
  **Local é gratuito e completo.** Todas as ferramentas funcionam se você mesmo
75
75
  executar este servidor. Não existe uma versão reduzida.
76
76
 
77
- Requisitos: Node 18 ou mais recente, cerca de **320 MB** de disco (o Puppeteer
77
+ Requisitos: Node 22.13 ou mais recente, cerca de **320 MB** de disco (o Puppeteer
78
78
  baixa o Chrome) e aproximadamente 1 GB de memória enquanto um trabalho roda. Em
79
79
  um notebook isso é tranquilo; em um VPS pequeno ou uma máquina de trabalho
80
80
  restrita, nem tanto.
package/README.zh-CN.md CHANGED
@@ -74,7 +74,7 @@ npm install -g @pinepaper.studio/mcp-server
74
74
  **本地运行免费且功能完整。** 只要你自己运行这个服务器,所有工具都可用,
75
75
  没有功能缩水的版本。
76
76
 
77
- 需要:Node 18 或更高版本、约 **320 MB** 磁盘空间(Puppeteer 会下载 Chrome),
77
+ 需要:Node 22.13 或更高版本、约 **320 MB** 磁盘空间(Puppeteer 会下载 Chrome),
78
78
  以及任务运行期间约 1 GB 内存。笔记本电脑没问题,小型 VPS 或受限的办公电脑
79
79
  则未必。
80
80
 
package/SECURITY.md CHANGED
@@ -58,3 +58,18 @@ Every outbound request goes through one file, `src/utils/safe-fetch.ts`, on Node
58
58
  **No child process in the npm package.** `ffprobe` and `ffmpeg` run through `packages/mcp-ffmpeg`, which is never published (`private`) and is copied only into the Claude Desktop extension's bundle. The server loads it by name when it is there. It runs those two binaries and nothing else, through `execFile` (no shell), with argument lists `src/tools/export-file-receipt.ts` writes and absolute file paths. Without it (any npm install) both features are unavailable and the server says so.
59
59
 
60
60
  The source contains no `eval` or `new Function`.
61
+
62
+ ## What this package does and why
63
+
64
+ Supply-chain scanners list the capabilities a package's own code uses. This is each one, where it is in `src/`, and why it is there. `src/__tests__/unit/supply-chain-surface.test.ts` and `capability-footprint.test.ts` fail if any of it spreads to another file.
65
+
66
+ | Capability | Where | Why |
67
+ |---|---|---|
68
+ | **Network access** | `src/utils/safe-fetch.ts` (the guarded fetch); `src/assets/repositories/` (fixed icon hosts); `src/tools/handlers/generate.ts` (PinePaper Cloud, opt-in) | Importing an image, SVG or font by URL, and searching the free icon repositories. Every user-supplied URL goes through the guarded fetch: private, loopback and link-local addresses and cloud metadata endpoints are refused, and each connection is pinned to the address that passed the check (no DNS rebinding). Generation calls the PinePaper Cloud only when you set `PINEPAPER_API_KEY`; the key is sent only to the cloud URL (`https://cloud.pinepaper.studio`, or `PINEPAPER_CLOUD_URL` if you set it). |
69
+ | **Shell access** | None in this package. `src/tools/export-file-receipt.ts` loads the optional add-on `@pinepaper.studio/mcp-ffmpeg` (`packages/mcp-ffmpeg`), which is private, never published, and bundled only in the Claude Desktop extension (`.mcpb`) | `ffprobe` reads a saved video back to confirm it is what the studio encoded, and `ffmpeg` joins per-scene segments for a `perScene` export. The add-on runs only those two binaries, through `execFile` with argument lists the server writes: no shell, nothing from a tool call is interpreted as a command. Without the add-on, the read-back is skipped and a per-scene export runs whole; `PINEPAPER_FFPROBE=off` turns the read-back off. |
70
+ | **Environment variables** | `src/utils/env.ts` (the complete list; the environment is read in one place, only for a listed name); one literal read of `PINEPAPER_ALLOW_PRIVATE_NETWORK` in `safe-fetch.ts` | Configuration only: `PINEPAPER_*` settings (browser, tool surface, export folder, asset folders, timeouts, the opt-in cloud key, the code and local-file switches) and the locale (`PINEPAPER_LOCALE`, `LC_ALL`, `LC_MESSAGES`, `LANG`). No value is sent anywhere except `PINEPAPER_API_KEY`, to the PinePaper Cloud, as above. |
71
+ | **Browser code** | `src/types/code-generator.ts` writes it; `src/browser/puppeteer-controller.ts` sends it | Each tool compiles to JavaScript that runs in PinePaper Studio, in a Chrome that puppeteer drives on your machine (or that you paste, in `code` mode). It is sent to that page over the DevTools protocol. Nothing is evaluated in the Node process: the source has no `eval`, `new Function`, `vm` or `inspector`. |
72
+ | **Dynamic import** | `src/browser/puppeteer-controller.ts`; `src/i18n/i18n-manager.ts`; `src/tools/export-file-receipt.ts` | Optional modules load on first use. `puppeteer` and `puppeteer-core` are imported by literal name, resolved from this package's own location (never the working directory, which can be an untrusted checkout). For strict pnpm/Yarn layouts, `PINEPAPER_PUPPETEER_FROM` names a folder they are required from by the same literal names (`createRequire`, Node ≥ 22.13). The one computed import is the ffmpeg add-on above: its name is held in a variable, so the published package never names a package it does not ship. Locale files load from a fixed table, so a locale name never becomes a file path. |
73
+ | **Async context** | `src/tools/handlers.ts` (`AsyncLocalStorage`) | Carries which tool is running to the check that a mutating call changed something, across concurrent calls. |
74
+
75
+ The package has no install scripts and one runtime dependency (`zod`).
@@ -258,8 +258,8 @@ export declare const PlatformSchema: z.ZodEnum<{
258
258
  "print-letter": "print-letter";
259
259
  }>;
260
260
  export declare const ExportFormatSchema: z.ZodEnum<{
261
- svg: "svg";
262
261
  png: "png";
262
+ svg: "svg";
263
263
  gif: "gif";
264
264
  mp4: "mp4";
265
265
  webm: "webm";
@@ -267,8 +267,8 @@ export declare const ExportFormatSchema: z.ZodEnum<{
267
267
  }>;
268
268
  export declare const ScreenshotPolicySchema: z.ZodEnum<{
269
269
  none: "none";
270
- on_error: "on_error";
271
270
  on_complete: "on_complete";
271
+ on_error: "on_error";
272
272
  on_request: "on_request";
273
273
  }>;
274
274
  export declare const JobOptionsSchema: z.ZodObject<{
@@ -276,8 +276,8 @@ export declare const JobOptionsSchema: z.ZodObject<{
276
276
  headless: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
277
277
  screenshotPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
278
278
  none: "none";
279
- on_error: "on_error";
280
279
  on_complete: "on_complete";
280
+ on_error: "on_error";
281
281
  on_request: "on_request";
282
282
  }>>>;
283
283
  canvasPreset: z.ZodOptional<z.ZodEnum<{
@@ -300,20 +300,20 @@ export declare const JobOptionsSchema: z.ZodObject<{
300
300
  }, z.core.$strip>;
301
301
  export declare const BatchOperationTypeSchema: z.ZodEnum<{
302
302
  animate: "animate";
303
- canvas: "canvas";
304
303
  create: "create";
305
- generator: "generator";
306
304
  modify: "modify";
305
+ canvas: "canvas";
306
+ generator: "generator";
307
307
  delete: "delete";
308
308
  relation: "relation";
309
309
  }>;
310
310
  export declare const BatchOperationSchema: z.ZodObject<{
311
311
  type: z.ZodEnum<{
312
312
  animate: "animate";
313
- canvas: "canvas";
314
313
  create: "create";
315
- generator: "generator";
316
314
  modify: "modify";
315
+ canvas: "canvas";
316
+ generator: "generator";
317
317
  delete: "delete";
318
318
  relation: "relation";
319
319
  }>;
@@ -326,10 +326,10 @@ export declare const BatchExecuteInputSchema: z.ZodObject<{
326
326
  operations: z.ZodArray<z.ZodObject<{
327
327
  type: z.ZodEnum<{
328
328
  animate: "animate";
329
- canvas: "canvas";
330
329
  create: "create";
331
- generator: "generator";
332
330
  modify: "modify";
331
+ canvas: "canvas";
332
+ generator: "generator";
333
333
  delete: "delete";
334
334
  relation: "relation";
335
335
  }>;
@@ -371,8 +371,8 @@ export declare const SmartExportOptionsSchema: z.ZodObject<{
371
371
  "print-letter": "print-letter";
372
372
  }>, z.ZodLiteral<"auto">]>>>;
373
373
  format: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
374
- svg: "svg";
375
374
  png: "png";
375
+ svg: "svg";
376
376
  gif: "gif";
377
377
  mp4: "mp4";
378
378
  webm: "webm";
@@ -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":"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"}
@@ -105,9 +105,9 @@ export const BROWSER_TIME = { executeMs: 0, screenshotMs: 0 };
105
105
  /**
106
106
  * The browser driver. Puppeteer is NOT a dependency of this package, not even an
107
107
  * optional peer (it was one up to 1.6.25): browser automation is a handful of tools, and a
108
- * headless-browser download with an install script is what supply-chain
109
- * scanners flag hardest. A declared peer, optional or not, still puts its whole
110
- * tree in a scanner's view of this package. The user installs it beside the
108
+ * headless-browser download with an install script is a large thing to put
109
+ * in every user's install. A declared peer, optional or not, still puts its whole
110
+ * tree in an audit of this package. The user installs it beside the
111
111
  * server when they want the executing mode (README, "Install").
112
112
  *
113
113
  * Tried in order: `puppeteer` (its own Chrome), then `puppeteer-core` driving a
@@ -117,23 +117,39 @@ export const BROWSER_TIME = { executeMs: 0, screenshotMs: 0 };
117
117
  */
118
118
  const PUPPETEER_MIN_MAJOR = 22;
119
119
  /**
120
- * Import a package this server does not depend on, by a name held in a
121
- * variable (so neither the build nor a scanner sees a dependency it does not
122
- * have). Resolution starts from THIS package, as a declared dependency's would:
123
- * `npx -p puppeteer -p @pinepaper.studio/mcp-server`, a global install of both,
124
- * and a project install all put puppeteer where that finds it.
120
+ * How each browser driver is found. Every module specifier is a string LITERAL, so a reader sees exactly which two
121
+ * packages this file can load; nothing here builds a module name at run time.
125
122
  *
126
- * It is never resolved from process.cwd(): an MCP client starts the server in
127
- * whatever folder is open, which can be a cloned repository, and a
128
- * node_modules/puppeteer planted there would then run as this process. The one
129
- * other place looked in is a folder the user names in PINEPAPER_PUPPETEER_FROM
130
- * (for a strict layout — pnpm with hoist=false, Yarn PnP strict — where a
131
- * package cannot see its project's undeclared packages).
123
+ * `importHere` is an ordinary `import('puppeteer')`. Node resolves a bare specifier from the importing file's own
124
+ * location, walking up through the node_modules folders above dist/browser/, as it would for a declared dependency:
125
+ * `npx -p puppeteer -p @pinepaper.studio/mcp-server`, a global install of both, and a project install all put
126
+ * puppeteer where that finds it. It is NOT resolved from process.cwd() (ESM ignores the working directory and
127
+ * NODE_PATH): an MCP client starts the server in whatever folder is open, which can be a cloned repository, and a
128
+ * node_modules/puppeteer planted there must not run as this process.
129
+ *
130
+ * `requireFrom` serves the one other place looked in: a folder the user names in PINEPAPER_PUPPETEER_FROM (an
131
+ * absolute path), for a strict layout — pnpm with hoist=false, Yarn PnP strict — where a package cannot see its
132
+ * project's undeclared packages. It requires the same literal specifier from that folder (createRequire), so every
133
+ * module the package loads is named in its source; it is reached only when the user has set the variable.
132
134
  */
135
+ const DRIVERS = {
136
+ puppeteer: {
137
+ importHere: () => import('puppeteer'),
138
+ requireFrom: (req) => req('puppeteer'),
139
+ packageJson: (req) => req.resolve('puppeteer/package.json'),
140
+ },
141
+ 'puppeteer-core': {
142
+ importHere: () => import('puppeteer-core'),
143
+ requireFrom: (req) => req('puppeteer-core'),
144
+ packageJson: (req) => req.resolve('puppeteer-core/package.json'),
145
+ },
146
+ };
147
+ /** Load a driver the user installed beside this package (or in PINEPAPER_PUPPETEER_FROM); null when absent. */
133
148
  async function importOptional(name) {
149
+ const driver = DRIVERS[name];
134
150
  const versionFrom = (base) => {
135
151
  try {
136
- const pkgPath = createRequire(base).resolve(`${name}/package.json`);
152
+ const pkgPath = driver.packageJson(createRequire(base));
137
153
  return String(JSON.parse(readFileSync(pkgPath, 'utf8')).version ?? '') || null;
138
154
  }
139
155
  catch {
@@ -141,7 +157,7 @@ async function importOptional(name) {
141
157
  }
142
158
  };
143
159
  try {
144
- return { mod: await import(name), version: versionFrom(import.meta.url) };
160
+ return { mod: await driver.importHere(), version: versionFrom(import.meta.url) };
145
161
  }
146
162
  catch { /* not beside this package (or present and failing to load: treated as absent, as before) */ }
147
163
  const from = env('PINEPAPER_PUPPETEER_FROM')?.trim();
@@ -149,8 +165,9 @@ async function importOptional(name) {
149
165
  return null;
150
166
  const base = pathToFileURL(join(from, 'package.json')).href;
151
167
  try {
152
- const entry = createRequire(base).resolve(name);
153
- return { mod: await import(pathToFileURL(entry).href), version: versionFrom(base) };
168
+ // require() of an ES module (Node ≥ 22.12 unflagged; engines says ≥ 22.13): the literal name, resolved from
169
+ // the folder the user named, and no import() of a computed path anywhere in the package.
170
+ return { mod: driver.requireFrom(createRequire(base)), version: versionFrom(base) };
154
171
  }
155
172
  catch {
156
173
  return null;
@@ -163,16 +180,14 @@ function refuseOldPuppeteer(name, version) {
163
180
  }
164
181
  }
165
182
  async function loadPuppeteer() {
166
- const fullName = 'puppeteer'; // a variable: see importOptional
167
- const full = await importOptional(fullName);
183
+ const full = await importOptional('puppeteer');
168
184
  if (full) {
169
- refuseOldPuppeteer(fullName, full.version);
185
+ refuseOldPuppeteer('puppeteer', full.version);
170
186
  return { launch: (opts) => full.mod.default.launch(opts) };
171
187
  }
172
- const coreName = 'puppeteer-core';
173
- const coreLoaded = await importOptional(coreName);
188
+ const coreLoaded = await importOptional('puppeteer-core');
174
189
  if (coreLoaded)
175
- refuseOldPuppeteer(coreName, coreLoaded.version);
190
+ refuseOldPuppeteer('puppeteer-core', coreLoaded.version);
176
191
  const core = coreLoaded?.mod ?? null;
177
192
  if (core) {
178
193
  const executablePath = env('PINEPAPER_CHROME_PATH')?.trim();
@@ -880,30 +895,55 @@ export class PinePaperBrowserController {
880
895
  // Fourteen emitters spread raw engine results, so this is fixed once
881
896
  // here rather than fourteen times. The probe is the real predicate —
882
897
  // attempt the clone, and only walk the value when it refuses.
898
+ //
899
+ // THE DEPTH LIMIT IS FOR LIVE OBJECTS, NOT FOR DATA. A Paper item's graph
900
+ // is effectively unbounded, so a class instance stops at depth 6. A plain
901
+ // object or array is data the caller may send straight back, and cutting
902
+ // it replaced a value with a string in a reply that looked complete: one
903
+ // unclonable value anywhere turned a custom relation's
904
+ // edit.customRelations[].change.args.params.amp, depth 7, into "[deep]",
905
+ // which the tool then refused. Plain data is walked whole; the path set
906
+ // stops a cycle, and PLAIN_LIMIT stops a pathological chain.
907
+ const PLAIN_LIMIT = 64;
908
+ const onPath = new Set();
909
+ const isPlain = (v) => {
910
+ if (Array.isArray(v))
911
+ return true;
912
+ const proto = Object.getPrototypeOf(v);
913
+ return proto === null || proto === Object.prototype;
914
+ };
883
915
  const toBridgeSafe = (value, depth = 0) => {
884
916
  if (value === null || typeof value !== 'object') {
885
917
  return typeof value === 'function' ? undefined : value;
886
918
  }
887
- if (depth > 6)
919
+ if (onPath.has(value))
920
+ return '[circular]';
921
+ if (depth > (isPlain(value) ? PLAIN_LIMIT : 6))
888
922
  return '[deep]';
889
- if (Array.isArray(value))
890
- return value.map((v) => toBridgeSafe(v, depth + 1));
891
- const out = {};
892
- for (const key of Object.keys(value)) {
893
- let v;
894
- try {
895
- v = value[key];
896
- }
897
- catch {
898
- continue;
923
+ onPath.add(value);
924
+ try {
925
+ if (Array.isArray(value))
926
+ return value.map((v) => toBridgeSafe(v, depth + 1));
927
+ const out = {};
928
+ for (const key of Object.keys(value)) {
929
+ let v;
930
+ try {
931
+ v = value[key];
932
+ }
933
+ catch {
934
+ continue;
935
+ }
936
+ if (typeof v === 'function')
937
+ continue;
938
+ const safe = toBridgeSafe(v, depth + 1);
939
+ if (safe !== undefined)
940
+ out[key] = safe;
899
941
  }
900
- if (typeof v === 'function')
901
- continue;
902
- const safe = toBridgeSafe(v, depth + 1);
903
- if (safe !== undefined)
904
- out[key] = safe;
942
+ return out;
943
+ }
944
+ finally {
945
+ onPath.delete(value);
905
946
  }
906
- return out;
907
947
  };
908
948
  const bridgeSafe = (value) => {
909
949
  try {
@@ -974,8 +1014,8 @@ export class PinePaperBrowserController {
974
1014
  // bypass. The code is run from the Node side as a CDP Runtime.evaluate
975
1015
  // (below), which returns the script's trailing value exactly as eval did:
976
1016
  // both generated-code shapes are `(`-led expression statements. It used
977
- // to be evaluated here; the published package then carried an evaluating call
978
- // that supply-chain scanners flag, for what CDP already does.
1017
+ // to be evaluated inside this callback; CDP already does that job, so this
1018
+ // package contains no evaluating call of its own, in the page or in Node.
979
1019
  window.__ppBridgeSafe = bridgeSafe;
980
1020
  return { success: true, __ppRaw: true, executedVia: 'eval' };
981
1021
  }, code, runOptions);