@genart-dev/mcp-server 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2743,32 +2743,19 @@ function isDirectComponent(name, components) {
2743
2743
  }
2744
2744
 
2745
2745
  // src/tools/capture.ts
2746
- import { writeFile as writeFile6 } from "fs/promises";
2746
+ import { mkdir, writeFile as writeFile6 } from "fs/promises";
2747
+ import { dirname as dirname6, join as join3 } from "path";
2747
2748
  import {
2748
2749
  createDefaultRegistry as createDefaultRegistry2
2749
2750
  } from "@genart-dev/core";
2750
2751
 
2751
2752
  // src/capture/headless.ts
2752
- var cachedModule = null;
2753
- async function loadPuppeteer() {
2754
- if (!cachedModule) {
2755
- try {
2756
- const mod = await import("puppeteer");
2757
- cachedModule = mod.default ?? mod;
2758
- } catch {
2759
- throw new Error(
2760
- "Puppeteer is required for screenshot capture. Install it with: npm install puppeteer"
2761
- );
2762
- }
2763
- }
2764
- return cachedModule;
2765
- }
2753
+ import puppeteer from "puppeteer";
2766
2754
  var browserInstance = null;
2767
2755
  async function getBrowser() {
2768
2756
  if (browserInstance && browserInstance.connected) {
2769
2757
  return browserInstance;
2770
2758
  }
2771
- const puppeteer = await loadPuppeteer();
2772
2759
  browserInstance = await puppeteer.launch({
2773
2760
  headless: true,
2774
2761
  executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || void 0,
@@ -2862,8 +2849,9 @@ function generateSketchHtml(sketch, opts) {
2862
2849
  }
2863
2850
  return adapter.generateStandaloneHTML(effective);
2864
2851
  }
2865
- function derivePreviewPath(sketchPath) {
2866
- return sketchPath.replace(/\.genart$/, ".png");
2852
+ function deriveSnapshotPath(sketchPath, sketchId, seed) {
2853
+ const wsDir = dirname6(sketchPath);
2854
+ return join3(wsDir, "snapshots", `${sketchId}-${seed}-preview.png`);
2867
2855
  }
2868
2856
  async function captureScreenshot(state, input) {
2869
2857
  state.requireWorkspace();
@@ -2896,11 +2884,12 @@ async function captureScreenshot(state, input) {
2896
2884
  height,
2897
2885
  inlineSize
2898
2886
  });
2899
- const previewPath = derivePreviewPath(loaded.path);
2887
+ const effectiveSeed = input.seed ?? sketch.state.seed;
2888
+ const previewPath = deriveSnapshotPath(loaded.path, sketchId, effectiveSeed);
2900
2889
  const metadata = await buildScreenshotMetadata(state, multi, {
2901
2890
  target,
2902
2891
  sketchId,
2903
- seed: input.seed ?? sketch.state.seed,
2892
+ seed: effectiveSeed,
2904
2893
  previewPath
2905
2894
  });
2906
2895
  const previewJpegBase64 = Buffer.from(multi.inlineJpeg).toString("base64");
@@ -2921,8 +2910,10 @@ async function buildScreenshotMetadata(state, multi, info) {
2921
2910
  previewPath: info.previewPath
2922
2911
  };
2923
2912
  if (!state.remoteMode) {
2913
+ await mkdir(dirname6(info.previewPath), { recursive: true });
2924
2914
  await writeFile6(info.previewPath, multi.previewPng);
2925
2915
  metadata.savedPreviewTo = info.previewPath;
2916
+ metadata.previewWritten = true;
2926
2917
  }
2927
2918
  return metadata;
2928
2919
  }
@@ -2951,11 +2942,12 @@ async function captureBatch(state, input) {
2951
2942
  height,
2952
2943
  inlineSize
2953
2944
  });
2954
- const previewPath = derivePreviewPath(loaded.path);
2945
+ const effectiveSeed = input.seed ?? sketch.state.seed;
2946
+ const previewPath = deriveSnapshotPath(loaded.path, id, effectiveSeed);
2955
2947
  const itemMetadata = await buildScreenshotMetadata(state, multi, {
2956
2948
  target: "sketch",
2957
2949
  sketchId: id,
2958
- seed: input.seed ?? sketch.state.seed,
2950
+ seed: effectiveSeed,
2959
2951
  previewPath
2960
2952
  });
2961
2953
  items.push({
@@ -3315,7 +3307,7 @@ function gatherRelevantSkills(aspects) {
3315
3307
 
3316
3308
  // src/tools/series.ts
3317
3309
  import { writeFile as writeFile7 } from "fs/promises";
3318
- import { basename as basename8, dirname as dirname6, resolve as resolve3 } from "path";
3310
+ import { basename as basename8, dirname as dirname7, resolve as resolve3 } from "path";
3319
3311
  import {
3320
3312
  serializeGenart as serializeGenart5,
3321
3313
  serializeWorkspace as serializeWorkspace4
@@ -3595,7 +3587,7 @@ async function promoteSketch(state, input) {
3595
3587
  ...input.agent ? { agent: input.agent } : {},
3596
3588
  ...input.model ? { model: input.model } : {}
3597
3589
  };
3598
- const sourceDir = dirname6(source.path);
3590
+ const sourceDir = dirname7(source.path);
3599
3591
  const newPath = resolve3(sourceDir, `${newId}.genart`);
3600
3592
  const json = serializeGenart5(promotedDef);
3601
3593
  if (!state.remoteMode) {
@@ -3665,8 +3657,8 @@ function countBy(items) {
3665
3657
  }
3666
3658
 
3667
3659
  // src/tools/reference.ts
3668
- import { copyFile, mkdir, readFile as readFile5 } from "fs/promises";
3669
- import { basename as basename9, dirname as dirname7, extname, resolve as resolve4 } from "path";
3660
+ import { copyFile, mkdir as mkdir2, readFile as readFile5 } from "fs/promises";
3661
+ import { basename as basename9, dirname as dirname8, extname, resolve as resolve4 } from "path";
3670
3662
  import {
3671
3663
  serializeGenart as serializeGenart6,
3672
3664
  serializeWorkspace as serializeWorkspace5
@@ -3721,9 +3713,9 @@ async function addReference(state, input) {
3721
3713
  `Invalid reference type: '${refType}'. Valid types: ${VALID_REFERENCE_TYPES.join(", ")}`
3722
3714
  );
3723
3715
  }
3724
- const workspaceDir = dirname7(state.workspacePath);
3716
+ const workspaceDir = dirname8(state.workspacePath);
3725
3717
  const refsDir = resolve4(workspaceDir, "references");
3726
- await mkdir(refsDir, { recursive: true });
3718
+ await mkdir2(refsDir, { recursive: true });
3727
3719
  const ext = extname(input.image);
3728
3720
  const destFilename = `${id}${ext}`;
3729
3721
  const destPath = resolve4(refsDir, destFilename);
@@ -3811,7 +3803,7 @@ async function addReference(state, input) {
3811
3803
  async function analyzeReference(state, input) {
3812
3804
  state.requireWorkspace();
3813
3805
  const { ref, location } = findReference(state, input.referenceId, input.seriesId, input.sketchId);
3814
- const workspaceDir = dirname7(state.workspacePath);
3806
+ const workspaceDir = dirname8(state.workspacePath);
3815
3807
  const imagePath = resolve4(workspaceDir, ref.path);
3816
3808
  let previewJpegBase64;
3817
3809
  try {
@@ -3971,7 +3963,7 @@ async function extractPalette(state, input) {
3971
3963
  input.sketchId
3972
3964
  );
3973
3965
  const count = input.count ?? 6;
3974
- const workspaceDir = dirname7(state.workspacePath);
3966
+ const workspaceDir = dirname8(state.workspacePath);
3975
3967
  const imagePath = resolve4(workspaceDir, ref.path);
3976
3968
  let previewJpegBase64;
3977
3969
  try {
@@ -4048,7 +4040,7 @@ function findReference(state, referenceId, seriesId, sketchId) {
4048
4040
  // src/tools/export.ts
4049
4041
  import { createWriteStream } from "fs";
4050
4042
  import { stat as stat4, writeFile as writeFile9 } from "fs/promises";
4051
- import { dirname as dirname8 } from "path";
4043
+ import { dirname as dirname9 } from "path";
4052
4044
  import archiver from "archiver";
4053
4045
  import {
4054
4046
  createDefaultRegistry as createDefaultRegistry3,
@@ -4056,7 +4048,7 @@ import {
4056
4048
  } from "@genart-dev/core";
4057
4049
  var registry4 = createDefaultRegistry3();
4058
4050
  async function validateOutputPath(outputPath) {
4059
- const parentDir = dirname8(outputPath);
4051
+ const parentDir = dirname9(outputPath);
4060
4052
  try {
4061
4053
  const s = await stat4(parentDir);
4062
4054
  if (!s.isDirectory()) {
@@ -5326,20 +5318,24 @@ async function initializePluginRegistry() {
5326
5318
  await registry5.register(tracePlugin);
5327
5319
  return registry5;
5328
5320
  }
5329
- function createServer(state) {
5321
+ function createServer(state, options) {
5322
+ const captureOnly = options?.captureOnly ?? false;
5330
5323
  const server = new McpServer(
5331
5324
  {
5332
- name: "@genart/mcp-server",
5325
+ name: captureOnly ? "@genart/mcp-capture" : "@genart/mcp-server",
5333
5326
  version: "0.4.0"
5334
5327
  },
5335
5328
  {
5336
5329
  capabilities: {
5337
5330
  tools: {},
5338
- resources: {},
5339
- prompts: {}
5331
+ ...!captureOnly && { resources: {}, prompts: {} }
5340
5332
  }
5341
5333
  }
5342
5334
  );
5335
+ if (captureOnly) {
5336
+ registerCaptureTools(server, state);
5337
+ return server;
5338
+ }
5343
5339
  const registryReady = initializePluginRegistry().then((registry5) => {
5344
5340
  state.pluginRegistry = registry5;
5345
5341
  registerPluginMcpTools(server, registry5, state);
@@ -5356,7 +5352,9 @@ function createServer(state) {
5356
5352
  registerSnapshotTools(server, state);
5357
5353
  registerKnowledgeTools(server, state);
5358
5354
  registerDesignTools(server, state);
5359
- registerCaptureTools(server, state);
5355
+ if (!state.remoteMode) {
5356
+ registerCaptureTools(server, state);
5357
+ }
5360
5358
  registerCritiqueTools(server, state);
5361
5359
  registerSeriesTools(server, state);
5362
5360
  registerReferenceTools(server, state);
@@ -6066,7 +6064,7 @@ function registerSnapshotTools(server, state) {
6066
6064
  function registerCaptureTools(server, state) {
6067
6065
  server.tool(
6068
6066
  "capture_screenshot",
6069
- "Capture a screenshot of a sketch. Returns metadata as text + a small inline JPEG image for visual review. In remote mode, metadata includes previewFileContent (base64 PNG) to Write locally.",
6067
+ "Capture a screenshot of a sketch. Returns metadata as text + a small inline JPEG image for visual review. In local mode, writes a full-res PNG to snapshots/<sketchId>-<seed>-preview.png next to the workspace. The savedPreviewTo path in metadata points to the file on disk.",
6070
6068
  {
6071
6069
  target: z2.enum(["selected", "sketch"]).optional().describe("What to capture (default: selected)"),
6072
6070
  sketchId: z2.string().optional().describe("Required when target is 'sketch'"),
@@ -6079,6 +6077,7 @@ function registerCaptureTools(server, state) {
6079
6077
  async (args) => {
6080
6078
  try {
6081
6079
  const result = await captureScreenshot(state, args);
6080
+ console.error(`[capture_screenshot] jpeg base64 length: ${result.previewJpegBase64.length}, metadata: ${JSON.stringify(result.metadata)}`);
6082
6081
  return {
6083
6082
  content: [
6084
6083
  { type: "text", text: JSON.stringify(result.metadata, null, 2) },
@@ -6086,6 +6085,7 @@ function registerCaptureTools(server, state) {
6086
6085
  ]
6087
6086
  };
6088
6087
  } catch (e) {
6088
+ console.error(`[capture_screenshot] error: ${e instanceof Error ? e.message : String(e)}`);
6089
6089
  return toolError(e instanceof Error ? e.message : String(e));
6090
6090
  }
6091
6091
  }
@@ -6726,14 +6726,17 @@ function registerKnowledgeTools(server, state) {
6726
6726
 
6727
6727
  // src/index.ts
6728
6728
  async function main() {
6729
- const sidecar = isSidecarMode();
6730
- if (sidecar) {
6729
+ const captureOnly = process.argv.includes("--capture-only");
6730
+ const sidecar = !captureOnly && isSidecarMode();
6731
+ if (captureOnly) {
6732
+ console.error("[genart-mcp] Starting in capture-only mode");
6733
+ } else if (sidecar) {
6731
6734
  console.error("[genart-mcp] Starting in sidecar mode");
6732
6735
  } else {
6733
6736
  console.error("[genart-mcp] Starting in stdio mode");
6734
6737
  }
6735
6738
  const state = new EditorState();
6736
- const server = createServer(state);
6739
+ const server = createServer(state, { captureOnly });
6737
6740
  const transport = new StdioServerTransport();
6738
6741
  await server.connect(transport);
6739
6742
  console.error("[genart-mcp] Server connected and ready");