frameshot-mcp 0.10.0 → 0.11.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.
@@ -10,7 +10,7 @@ import {
10
10
  SnapshotStore,
11
11
  SnapshotUseCase,
12
12
  ViteBundler
13
- } from "./chunk-WACVDBUF.js";
13
+ } from "./chunk-FQ3BVCX7.js";
14
14
 
15
15
  // src/use-cases/watch.ts
16
16
  import { watch } from "chokidar";
@@ -1476,6 +1476,7 @@ var RenderUseCase = class {
1476
1476
  const opts = this.resolveOptions(options);
1477
1477
  const ext = extname2(filePath).toLowerCase();
1478
1478
  const framework = EXT_TO_FRAMEWORK[ext] ?? "react";
1479
+ let fallbackReason;
1479
1480
  if (this.viteBundler) {
1480
1481
  try {
1481
1482
  const { url } = await this.viteBundler.getUrl(filePath, {
@@ -1488,16 +1489,18 @@ var RenderUseCase = class {
1488
1489
  );
1489
1490
  return { results: results2, mode: "vite" };
1490
1491
  } catch (err) {
1491
- const msg = err instanceof Error ? err.message : String(err);
1492
+ fallbackReason = err instanceof Error ? err.message : String(err);
1492
1493
  process.stderr.write(
1493
- `[frameshot] Vite pipeline failed (${msg}), falling back to CDN
1494
+ `[frameshot] Vite pipeline failed (${fallbackReason}), falling back to CDN
1494
1495
  `
1495
1496
  );
1496
1497
  }
1498
+ } else {
1499
+ fallbackReason = "Vite bundler not available";
1497
1500
  }
1498
1501
  const code = readFileSync3(filePath, "utf-8");
1499
1502
  const results = await this.render(code, framework, options);
1500
- return { results, mode: "cdn" };
1503
+ return { results, mode: "cdn", fallbackReason };
1501
1504
  }
1502
1505
  async renderInteraction(code, framework, interactions, options = {}) {
1503
1506
  const opts = this.resolveOptions(options);
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createContainer
4
- } from "./chunk-6OTGZDUU.js";
4
+ } from "./chunk-AF64XFKX.js";
5
5
  import {
6
6
  EXT_TO_FRAMEWORK
7
- } from "./chunk-WACVDBUF.js";
7
+ } from "./chunk-FQ3BVCX7.js";
8
8
 
9
9
  // src/cli.ts
10
10
  import { mkdirSync } from "fs";
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createContainer
4
- } from "./chunk-6OTGZDUU.js";
4
+ } from "./chunk-AF64XFKX.js";
5
5
  import {
6
6
  DEVICE_PRESETS,
7
7
  EXT_TO_FRAMEWORK,
8
8
  __export
9
- } from "./chunk-WACVDBUF.js";
9
+ } from "./chunk-FQ3BVCX7.js";
10
10
 
11
11
  // src/index.ts
12
12
  import { execSync } from "child_process";
@@ -14907,19 +14907,25 @@ function registerRenderFileTools(server2, useCase) {
14907
14907
  mock
14908
14908
  }) => {
14909
14909
  const start = performance.now();
14910
- const { results, mode } = await useCase.renderFile(path, {
14911
- props,
14912
- viewport: { width, height },
14913
- fullPage: true,
14914
- engines: ["chromium"],
14915
- darkMode,
14916
- tailwindVersion,
14917
- projectRoot,
14918
- mock
14919
- });
14910
+ const { results, mode, fallbackReason } = await useCase.renderFile(
14911
+ path,
14912
+ {
14913
+ props,
14914
+ viewport: { width, height },
14915
+ fullPage: true,
14916
+ engines: ["chromium"],
14917
+ darkMode,
14918
+ tailwindVersion,
14919
+ projectRoot,
14920
+ mock
14921
+ }
14922
+ );
14920
14923
  const elapsed = Math.round(performance.now() - start);
14921
14924
  const ext = extname(path).toLowerCase();
14922
14925
  const framework = EXT_TO_FRAMEWORK[ext] ?? "react";
14926
+ const fallbackNote = mode === "cdn" && fallbackReason ? `
14927
+ \u2139\uFE0F Fell back to CDN pipeline: ${fallbackReason}
14928
+ Imports from node_modules may not resolve. To fix: install vite as a devDep and add a minimal vite.config.` : "";
14923
14929
  const content = results.flatMap((r) => [
14924
14930
  {
14925
14931
  type: "image",
@@ -14930,7 +14936,7 @@ function registerRenderFileTools(server2, useCase) {
14930
14936
  type: "text",
14931
14937
  text: `[${mode}/${framework}] ${r.width}x${r.height} (${elapsed}ms)${r.consoleErrors.length ? `
14932
14938
  \u26A0\uFE0F Console errors:
14933
- ${r.consoleErrors.join("\n")}` : ""}`
14939
+ ${r.consoleErrors.join("\n")}` : ""}${fallbackNote}`
14934
14940
  }
14935
14941
  ]);
14936
14942
  return { content };
@@ -15569,21 +15575,9 @@ function registerAllTools(server2, useCases) {
15569
15575
 
15570
15576
  // src/index.ts
15571
15577
  var container = createContainer();
15572
- async function ensureBrowser() {
15573
- try {
15574
- await container.pool.warmup(["chromium"]);
15575
- } catch {
15576
- try {
15577
- execSync("npx playwright install chromium", { stdio: "pipe" });
15578
- await container.pool.warmup(["chromium"]);
15579
- } catch {
15580
- }
15581
- }
15582
- }
15583
- await ensureBrowser();
15584
15578
  var server = new McpServer({
15585
15579
  name: "frameshot",
15586
- version: "0.8.0"
15580
+ version: "0.10.0"
15587
15581
  });
15588
15582
  registerAllTools(server, {
15589
15583
  render: container.renderUseCase,
@@ -15596,6 +15590,18 @@ registerAllTools(server, {
15596
15590
  });
15597
15591
  var transport = new StdioServerTransport();
15598
15592
  await server.connect(transport);
15593
+ void (async () => {
15594
+ try {
15595
+ await container.pool.warmup(["chromium"]);
15596
+ } catch {
15597
+ try {
15598
+ execSync("npx playwright install chromium", { stdio: "pipe" });
15599
+ await container.pool.warmup(["chromium"]).catch(() => {
15600
+ });
15601
+ } catch {
15602
+ }
15603
+ }
15604
+ })();
15599
15605
  process.on("SIGINT", async () => {
15600
15606
  await container.shutdown();
15601
15607
  process.exit(0);
@@ -218,6 +218,8 @@ declare class RenderUseCase {
218
218
  renderFile(filePath: string, options?: Partial<FileRenderOptions>): Promise<{
219
219
  results: ScreenshotResult[];
220
220
  mode: "vite" | "cdn";
221
+ /** If we fell back to CDN, the reason the Vite pipeline was skipped. */
222
+ fallbackReason?: string;
221
223
  }>;
222
224
  renderInteraction(code: string, framework: Framework, interactions: Interaction[], options?: Partial<RenderOptions>): Promise<{
223
225
  image: string;
package/dist/renderer.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  SnapshotStore,
14
14
  SnapshotUseCase,
15
15
  ViteBundler
16
- } from "./chunk-WACVDBUF.js";
16
+ } from "./chunk-FQ3BVCX7.js";
17
17
  export {
18
18
  AuditUseCase,
19
19
  BrowserPool,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frameshot-mcp",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Zero-config visual testing for AI agents. Render project components with full Vite dependency resolution — no stories, no config.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -259,12 +259,17 @@ async function main() {
259
259
  try {
260
260
  // Render current (after) version
261
261
  console.log(` Rendering (after): ${filePath}`);
262
- const { results: afterResults, mode } = await renderUseCase.renderFile(
263
- filePath,
264
- renderOpts,
265
- );
262
+ const {
263
+ results: afterResults,
264
+ mode,
265
+ fallbackReason,
266
+ } = await renderUseCase.renderFile(filePath, renderOpts);
266
267
  const afterResult = afterResults[0];
267
268
 
269
+ if (mode === "cdn" && fallbackReason) {
270
+ console.log(` ℹ️ CDN fallback: ${fallbackReason}`);
271
+ }
272
+
268
273
  const afterPath = join(outputDir, `${safeName}_after.png`);
269
274
  writeFileSync(afterPath, Buffer.from(afterResult.image, "base64"));
270
275