@genart-dev/mcp-server 0.4.2 → 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/lib.cjs CHANGED
@@ -2445,6 +2445,7 @@ function isDirectComponent(name, components) {
2445
2445
 
2446
2446
  // src/tools/capture.ts
2447
2447
  var import_promises6 = require("fs/promises");
2448
+ var import_path8 = require("path");
2448
2449
  var import_core8 = require("@genart-dev/core");
2449
2450
 
2450
2451
  // src/capture/headless.ts
@@ -2547,8 +2548,9 @@ function generateSketchHtml(sketch, opts) {
2547
2548
  }
2548
2549
  return adapter.generateStandaloneHTML(effective);
2549
2550
  }
2550
- function derivePreviewPath(sketchPath) {
2551
- return sketchPath.replace(/\.genart$/, ".png");
2551
+ function deriveSnapshotPath(sketchPath, sketchId, seed) {
2552
+ const wsDir = (0, import_path8.dirname)(sketchPath);
2553
+ return (0, import_path8.join)(wsDir, "snapshots", `${sketchId}-${seed}-preview.png`);
2552
2554
  }
2553
2555
  async function captureScreenshot(state, input) {
2554
2556
  state.requireWorkspace();
@@ -2581,11 +2583,12 @@ async function captureScreenshot(state, input) {
2581
2583
  height,
2582
2584
  inlineSize
2583
2585
  });
2584
- const previewPath = derivePreviewPath(loaded.path);
2586
+ const effectiveSeed = input.seed ?? sketch.state.seed;
2587
+ const previewPath = deriveSnapshotPath(loaded.path, sketchId, effectiveSeed);
2585
2588
  const metadata = await buildScreenshotMetadata(state, multi, {
2586
2589
  target,
2587
2590
  sketchId,
2588
- seed: input.seed ?? sketch.state.seed,
2591
+ seed: effectiveSeed,
2589
2592
  previewPath
2590
2593
  });
2591
2594
  const previewJpegBase64 = Buffer.from(multi.inlineJpeg).toString("base64");
@@ -2606,8 +2609,10 @@ async function buildScreenshotMetadata(state, multi, info) {
2606
2609
  previewPath: info.previewPath
2607
2610
  };
2608
2611
  if (!state.remoteMode) {
2612
+ await (0, import_promises6.mkdir)((0, import_path8.dirname)(info.previewPath), { recursive: true });
2609
2613
  await (0, import_promises6.writeFile)(info.previewPath, multi.previewPng);
2610
2614
  metadata.savedPreviewTo = info.previewPath;
2615
+ metadata.previewWritten = true;
2611
2616
  }
2612
2617
  return metadata;
2613
2618
  }
@@ -2636,11 +2641,12 @@ async function captureBatch(state, input) {
2636
2641
  height,
2637
2642
  inlineSize
2638
2643
  });
2639
- const previewPath = derivePreviewPath(loaded.path);
2644
+ const effectiveSeed = input.seed ?? sketch.state.seed;
2645
+ const previewPath = deriveSnapshotPath(loaded.path, id, effectiveSeed);
2640
2646
  const itemMetadata = await buildScreenshotMetadata(state, multi, {
2641
2647
  target: "sketch",
2642
2648
  sketchId: id,
2643
- seed: input.seed ?? sketch.state.seed,
2649
+ seed: effectiveSeed,
2644
2650
  previewPath
2645
2651
  });
2646
2652
  items.push({
@@ -3000,7 +3006,7 @@ function gatherRelevantSkills(aspects) {
3000
3006
 
3001
3007
  // src/tools/series.ts
3002
3008
  var import_promises7 = require("fs/promises");
3003
- var import_path8 = require("path");
3009
+ var import_path9 = require("path");
3004
3010
  var import_core10 = require("@genart-dev/core");
3005
3011
  function now6() {
3006
3012
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -3163,7 +3169,7 @@ async function seriesSummary(state, input) {
3163
3169
  for (const file of series.sketchFiles) {
3164
3170
  let found = false;
3165
3171
  for (const [id, loaded] of state.sketches) {
3166
- if ((0, import_path8.basename)(loaded.path) === file) {
3172
+ if ((0, import_path9.basename)(loaded.path) === file) {
3167
3173
  const def = loaded.definition;
3168
3174
  sketchInfos.push({
3169
3175
  id,
@@ -3277,18 +3283,18 @@ async function promoteSketch(state, input) {
3277
3283
  ...input.agent ? { agent: input.agent } : {},
3278
3284
  ...input.model ? { model: input.model } : {}
3279
3285
  };
3280
- const sourceDir = (0, import_path8.dirname)(source.path);
3281
- const newPath = (0, import_path8.resolve)(sourceDir, `${newId}.genart`);
3286
+ const sourceDir = (0, import_path9.dirname)(source.path);
3287
+ const newPath = (0, import_path9.resolve)(sourceDir, `${newId}.genart`);
3282
3288
  const json = (0, import_core10.serializeGenart)(promotedDef);
3283
3289
  if (!state.remoteMode) {
3284
3290
  await (0, import_promises7.writeFile)(newPath, json, "utf-8");
3285
3291
  }
3286
3292
  state.sketches.set(newId, { definition: promotedDef, path: newPath });
3287
3293
  const sourceRef = ws.sketches.find(
3288
- (s) => s.file === (0, import_path8.basename)(source.path)
3294
+ (s) => s.file === (0, import_path9.basename)(source.path)
3289
3295
  );
3290
3296
  const position = sourceRef ? { x: sourceRef.position.x, y: sourceRef.position.y + sourceDef.canvas.height + 200 } : { x: 0, y: 0 };
3291
- const file = (0, import_path8.basename)(newPath);
3297
+ const file = (0, import_path9.basename)(newPath);
3292
3298
  state.workspace = {
3293
3299
  ...ws,
3294
3300
  modified: ts,
@@ -3348,7 +3354,7 @@ function countBy(items) {
3348
3354
 
3349
3355
  // src/tools/reference.ts
3350
3356
  var import_promises8 = require("fs/promises");
3351
- var import_path9 = require("path");
3357
+ var import_path10 = require("path");
3352
3358
  var import_core11 = require("@genart-dev/core");
3353
3359
  var import_promises9 = require("fs/promises");
3354
3360
  function now7() {
@@ -3373,7 +3379,7 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
3373
3379
  ".svg"
3374
3380
  ]);
3375
3381
  function isImageFile(path) {
3376
- return IMAGE_EXTENSIONS.has((0, import_path9.extname)(path).toLowerCase());
3382
+ return IMAGE_EXTENSIONS.has((0, import_path10.extname)(path).toLowerCase());
3377
3383
  }
3378
3384
  var VALID_REFERENCE_TYPES = [
3379
3385
  "image",
@@ -3389,7 +3395,7 @@ async function addReference(state, input) {
3389
3395
  `Not a recognized image file: ${input.image}. Supported: ${[...IMAGE_EXTENSIONS].join(", ")}`
3390
3396
  );
3391
3397
  }
3392
- const id = input.id ?? (0, import_path9.basename)(input.image, (0, import_path9.extname)(input.image)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
3398
+ const id = input.id ?? (0, import_path10.basename)(input.image, (0, import_path10.extname)(input.image)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
3393
3399
  if (!id) {
3394
3400
  throw new Error("Could not derive a valid ID from the image filename");
3395
3401
  }
@@ -3400,15 +3406,15 @@ async function addReference(state, input) {
3400
3406
  `Invalid reference type: '${refType}'. Valid types: ${VALID_REFERENCE_TYPES.join(", ")}`
3401
3407
  );
3402
3408
  }
3403
- const workspaceDir = (0, import_path9.dirname)(state.workspacePath);
3404
- const refsDir = (0, import_path9.resolve)(workspaceDir, "references");
3409
+ const workspaceDir = (0, import_path10.dirname)(state.workspacePath);
3410
+ const refsDir = (0, import_path10.resolve)(workspaceDir, "references");
3405
3411
  await (0, import_promises8.mkdir)(refsDir, { recursive: true });
3406
- const ext = (0, import_path9.extname)(input.image);
3412
+ const ext = (0, import_path10.extname)(input.image);
3407
3413
  const destFilename = `${id}${ext}`;
3408
- const destPath = (0, import_path9.resolve)(refsDir, destFilename);
3414
+ const destPath = (0, import_path10.resolve)(refsDir, destFilename);
3409
3415
  const relativePath = `references/${destFilename}`;
3410
3416
  if (!state.remoteMode) {
3411
- await (0, import_promises8.copyFile)((0, import_path9.resolve)(input.image), destPath);
3417
+ await (0, import_promises8.copyFile)((0, import_path10.resolve)(input.image), destPath);
3412
3418
  }
3413
3419
  const ref = {
3414
3420
  id,
@@ -3490,12 +3496,12 @@ async function addReference(state, input) {
3490
3496
  async function analyzeReference(state, input) {
3491
3497
  state.requireWorkspace();
3492
3498
  const { ref, location } = findReference(state, input.referenceId, input.seriesId, input.sketchId);
3493
- const workspaceDir = (0, import_path9.dirname)(state.workspacePath);
3494
- const imagePath = (0, import_path9.resolve)(workspaceDir, ref.path);
3499
+ const workspaceDir = (0, import_path10.dirname)(state.workspacePath);
3500
+ const imagePath = (0, import_path10.resolve)(workspaceDir, ref.path);
3495
3501
  let previewJpegBase64;
3496
3502
  try {
3497
3503
  const imageBuffer = await (0, import_promises8.readFile)(imagePath);
3498
- const ext = (0, import_path9.extname)(ref.path).toLowerCase();
3504
+ const ext = (0, import_path10.extname)(ref.path).toLowerCase();
3499
3505
  const mimeMap = {
3500
3506
  ".png": "image/png",
3501
3507
  ".jpg": "image/jpeg",
@@ -3650,8 +3656,8 @@ async function extractPalette(state, input) {
3650
3656
  input.sketchId
3651
3657
  );
3652
3658
  const count = input.count ?? 6;
3653
- const workspaceDir = (0, import_path9.dirname)(state.workspacePath);
3654
- const imagePath = (0, import_path9.resolve)(workspaceDir, ref.path);
3659
+ const workspaceDir = (0, import_path10.dirname)(state.workspacePath);
3660
+ const imagePath = (0, import_path10.resolve)(workspaceDir, ref.path);
3655
3661
  let previewJpegBase64;
3656
3662
  try {
3657
3663
  const imageBuffer = await (0, import_promises8.readFile)(imagePath);
@@ -3727,12 +3733,12 @@ function findReference(state, referenceId, seriesId, sketchId) {
3727
3733
  // src/tools/export.ts
3728
3734
  var import_fs = require("fs");
3729
3735
  var import_promises10 = require("fs/promises");
3730
- var import_path10 = require("path");
3736
+ var import_path11 = require("path");
3731
3737
  var import_archiver = __toESM(require("archiver"), 1);
3732
3738
  var import_core12 = require("@genart-dev/core");
3733
3739
  var registry4 = (0, import_core12.createDefaultRegistry)();
3734
3740
  async function validateOutputPath(outputPath) {
3735
- const parentDir = (0, import_path10.dirname)(outputPath);
3741
+ const parentDir = (0, import_path11.dirname)(outputPath);
3736
3742
  try {
3737
3743
  const s = await (0, import_promises10.stat)(parentDir);
3738
3744
  if (!s.isDirectory()) {
@@ -4998,20 +5004,24 @@ async function initializePluginRegistry() {
4998
5004
  await registry5.register(import_plugin_trace.default);
4999
5005
  return registry5;
5000
5006
  }
5001
- function createServer(state) {
5007
+ function createServer(state, options) {
5008
+ const captureOnly = options?.captureOnly ?? false;
5002
5009
  const server = new import_mcp.McpServer(
5003
5010
  {
5004
- name: "@genart/mcp-server",
5011
+ name: captureOnly ? "@genart/mcp-capture" : "@genart/mcp-server",
5005
5012
  version: "0.4.0"
5006
5013
  },
5007
5014
  {
5008
5015
  capabilities: {
5009
5016
  tools: {},
5010
- resources: {},
5011
- prompts: {}
5017
+ ...!captureOnly && { resources: {}, prompts: {} }
5012
5018
  }
5013
5019
  }
5014
5020
  );
5021
+ if (captureOnly) {
5022
+ registerCaptureTools(server, state);
5023
+ return server;
5024
+ }
5015
5025
  const registryReady = initializePluginRegistry().then((registry5) => {
5016
5026
  state.pluginRegistry = registry5;
5017
5027
  registerPluginMcpTools(server, registry5, state);
@@ -5028,7 +5038,9 @@ function createServer(state) {
5028
5038
  registerSnapshotTools(server, state);
5029
5039
  registerKnowledgeTools(server, state);
5030
5040
  registerDesignTools(server, state);
5031
- registerCaptureTools(server, state);
5041
+ if (!state.remoteMode) {
5042
+ registerCaptureTools(server, state);
5043
+ }
5032
5044
  registerCritiqueTools(server, state);
5033
5045
  registerSeriesTools(server, state);
5034
5046
  registerReferenceTools(server, state);
@@ -5738,7 +5750,7 @@ function registerSnapshotTools(server, state) {
5738
5750
  function registerCaptureTools(server, state) {
5739
5751
  server.tool(
5740
5752
  "capture_screenshot",
5741
- "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.",
5753
+ "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.",
5742
5754
  {
5743
5755
  target: import_zod2.z.enum(["selected", "sketch"]).optional().describe("What to capture (default: selected)"),
5744
5756
  sketchId: import_zod2.z.string().optional().describe("Required when target is 'sketch'"),
@@ -6401,7 +6413,7 @@ function registerKnowledgeTools(server, state) {
6401
6413
  // src/state.ts
6402
6414
  var import_events = require("events");
6403
6415
  var import_promises11 = require("fs/promises");
6404
- var import_path11 = require("path");
6416
+ var import_path12 = require("path");
6405
6417
 
6406
6418
  // src/sidecar.ts
6407
6419
  function isSidecarMode() {
@@ -6458,7 +6470,7 @@ var EditorState = class extends import_events.EventEmitter {
6458
6470
  }
6459
6471
  /** Resolve a file path, respecting the sandbox basePath when set. */
6460
6472
  resolvePath(file) {
6461
- if ((0, import_path11.isAbsolute)(file)) {
6473
+ if ((0, import_path12.isAbsolute)(file)) {
6462
6474
  if (this.basePath && !file.startsWith(this.basePath)) {
6463
6475
  throw new Error(`Path escapes sandbox: ${file}`);
6464
6476
  }
@@ -6466,10 +6478,10 @@ var EditorState = class extends import_events.EventEmitter {
6466
6478
  }
6467
6479
  if ((file.startsWith("~/") || file === "~") && !this.basePath) {
6468
6480
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
6469
- return (0, import_path11.resolve)(home, file.slice(2));
6481
+ return (0, import_path12.resolve)(home, file.slice(2));
6470
6482
  }
6471
6483
  const base = this.basePath ?? process.cwd();
6472
- const resolved = (0, import_path11.resolve)(base, file);
6484
+ const resolved = (0, import_path12.resolve)(base, file);
6473
6485
  if (this.basePath && !resolved.startsWith(this.basePath)) {
6474
6486
  throw new Error(`Path escapes sandbox: ${resolved}`);
6475
6487
  }
@@ -6477,7 +6489,7 @@ var EditorState = class extends import_events.EventEmitter {
6477
6489
  }
6478
6490
  /** Resolve a sketch file reference (relative to workspace dir) to an absolute path. */
6479
6491
  resolveSketchPath(file) {
6480
- if ((0, import_path11.isAbsolute)(file)) {
6492
+ if ((0, import_path12.isAbsolute)(file)) {
6481
6493
  if (this.basePath && !file.startsWith(this.basePath)) {
6482
6494
  throw new Error(`Path escapes sandbox: ${file}`);
6483
6495
  }
@@ -6485,11 +6497,11 @@ var EditorState = class extends import_events.EventEmitter {
6485
6497
  }
6486
6498
  if (!this.workspacePath) {
6487
6499
  if (this.basePath) {
6488
- return (0, import_path11.resolve)(this.basePath, file);
6500
+ return (0, import_path12.resolve)(this.basePath, file);
6489
6501
  }
6490
6502
  throw new Error("No workspace is currently open");
6491
6503
  }
6492
- const resolved = (0, import_path11.resolve)((0, import_path11.dirname)(this.workspacePath), file);
6504
+ const resolved = (0, import_path12.resolve)((0, import_path12.dirname)(this.workspacePath), file);
6493
6505
  if (this.basePath && !resolved.startsWith(this.basePath)) {
6494
6506
  throw new Error(`Path escapes sandbox: ${resolved}`);
6495
6507
  }