@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.cjs +55 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -41
- package/dist/index.js.map +1 -1
- package/dist/lib.cjs +56 -56
- package/dist/lib.cjs.map +1 -1
- package/dist/lib.d.cts +6 -2
- package/dist/lib.d.ts +6 -2
- package/dist/lib.js +40 -40
- package/dist/lib.js.map +1 -1
- package/package.json +2 -10
package/dist/lib.cjs
CHANGED
|
@@ -2445,30 +2445,17 @@ 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
|
|
2451
|
-
var
|
|
2452
|
-
async function loadPuppeteer() {
|
|
2453
|
-
if (!cachedModule) {
|
|
2454
|
-
try {
|
|
2455
|
-
const mod = await import("puppeteer");
|
|
2456
|
-
cachedModule = mod.default ?? mod;
|
|
2457
|
-
} catch {
|
|
2458
|
-
throw new Error(
|
|
2459
|
-
"Puppeteer is required for screenshot capture. Install it with: npm install puppeteer"
|
|
2460
|
-
);
|
|
2461
|
-
}
|
|
2462
|
-
}
|
|
2463
|
-
return cachedModule;
|
|
2464
|
-
}
|
|
2452
|
+
var import_puppeteer = __toESM(require("puppeteer"), 1);
|
|
2465
2453
|
var browserInstance = null;
|
|
2466
2454
|
async function getBrowser() {
|
|
2467
2455
|
if (browserInstance && browserInstance.connected) {
|
|
2468
2456
|
return browserInstance;
|
|
2469
2457
|
}
|
|
2470
|
-
|
|
2471
|
-
browserInstance = await puppeteer.launch({
|
|
2458
|
+
browserInstance = await import_puppeteer.default.launch({
|
|
2472
2459
|
headless: true,
|
|
2473
2460
|
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || void 0,
|
|
2474
2461
|
args: [
|
|
@@ -2561,8 +2548,9 @@ function generateSketchHtml(sketch, opts) {
|
|
|
2561
2548
|
}
|
|
2562
2549
|
return adapter.generateStandaloneHTML(effective);
|
|
2563
2550
|
}
|
|
2564
|
-
function
|
|
2565
|
-
|
|
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`);
|
|
2566
2554
|
}
|
|
2567
2555
|
async function captureScreenshot(state, input) {
|
|
2568
2556
|
state.requireWorkspace();
|
|
@@ -2595,11 +2583,12 @@ async function captureScreenshot(state, input) {
|
|
|
2595
2583
|
height,
|
|
2596
2584
|
inlineSize
|
|
2597
2585
|
});
|
|
2598
|
-
const
|
|
2586
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2587
|
+
const previewPath = deriveSnapshotPath(loaded.path, sketchId, effectiveSeed);
|
|
2599
2588
|
const metadata = await buildScreenshotMetadata(state, multi, {
|
|
2600
2589
|
target,
|
|
2601
2590
|
sketchId,
|
|
2602
|
-
seed:
|
|
2591
|
+
seed: effectiveSeed,
|
|
2603
2592
|
previewPath
|
|
2604
2593
|
});
|
|
2605
2594
|
const previewJpegBase64 = Buffer.from(multi.inlineJpeg).toString("base64");
|
|
@@ -2620,8 +2609,10 @@ async function buildScreenshotMetadata(state, multi, info) {
|
|
|
2620
2609
|
previewPath: info.previewPath
|
|
2621
2610
|
};
|
|
2622
2611
|
if (!state.remoteMode) {
|
|
2612
|
+
await (0, import_promises6.mkdir)((0, import_path8.dirname)(info.previewPath), { recursive: true });
|
|
2623
2613
|
await (0, import_promises6.writeFile)(info.previewPath, multi.previewPng);
|
|
2624
2614
|
metadata.savedPreviewTo = info.previewPath;
|
|
2615
|
+
metadata.previewWritten = true;
|
|
2625
2616
|
}
|
|
2626
2617
|
return metadata;
|
|
2627
2618
|
}
|
|
@@ -2650,11 +2641,12 @@ async function captureBatch(state, input) {
|
|
|
2650
2641
|
height,
|
|
2651
2642
|
inlineSize
|
|
2652
2643
|
});
|
|
2653
|
-
const
|
|
2644
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2645
|
+
const previewPath = deriveSnapshotPath(loaded.path, id, effectiveSeed);
|
|
2654
2646
|
const itemMetadata = await buildScreenshotMetadata(state, multi, {
|
|
2655
2647
|
target: "sketch",
|
|
2656
2648
|
sketchId: id,
|
|
2657
|
-
seed:
|
|
2649
|
+
seed: effectiveSeed,
|
|
2658
2650
|
previewPath
|
|
2659
2651
|
});
|
|
2660
2652
|
items.push({
|
|
@@ -3014,7 +3006,7 @@ function gatherRelevantSkills(aspects) {
|
|
|
3014
3006
|
|
|
3015
3007
|
// src/tools/series.ts
|
|
3016
3008
|
var import_promises7 = require("fs/promises");
|
|
3017
|
-
var
|
|
3009
|
+
var import_path9 = require("path");
|
|
3018
3010
|
var import_core10 = require("@genart-dev/core");
|
|
3019
3011
|
function now6() {
|
|
3020
3012
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -3177,7 +3169,7 @@ async function seriesSummary(state, input) {
|
|
|
3177
3169
|
for (const file of series.sketchFiles) {
|
|
3178
3170
|
let found = false;
|
|
3179
3171
|
for (const [id, loaded] of state.sketches) {
|
|
3180
|
-
if ((0,
|
|
3172
|
+
if ((0, import_path9.basename)(loaded.path) === file) {
|
|
3181
3173
|
const def = loaded.definition;
|
|
3182
3174
|
sketchInfos.push({
|
|
3183
3175
|
id,
|
|
@@ -3291,18 +3283,18 @@ async function promoteSketch(state, input) {
|
|
|
3291
3283
|
...input.agent ? { agent: input.agent } : {},
|
|
3292
3284
|
...input.model ? { model: input.model } : {}
|
|
3293
3285
|
};
|
|
3294
|
-
const sourceDir = (0,
|
|
3295
|
-
const newPath = (0,
|
|
3286
|
+
const sourceDir = (0, import_path9.dirname)(source.path);
|
|
3287
|
+
const newPath = (0, import_path9.resolve)(sourceDir, `${newId}.genart`);
|
|
3296
3288
|
const json = (0, import_core10.serializeGenart)(promotedDef);
|
|
3297
3289
|
if (!state.remoteMode) {
|
|
3298
3290
|
await (0, import_promises7.writeFile)(newPath, json, "utf-8");
|
|
3299
3291
|
}
|
|
3300
3292
|
state.sketches.set(newId, { definition: promotedDef, path: newPath });
|
|
3301
3293
|
const sourceRef = ws.sketches.find(
|
|
3302
|
-
(s) => s.file === (0,
|
|
3294
|
+
(s) => s.file === (0, import_path9.basename)(source.path)
|
|
3303
3295
|
);
|
|
3304
3296
|
const position = sourceRef ? { x: sourceRef.position.x, y: sourceRef.position.y + sourceDef.canvas.height + 200 } : { x: 0, y: 0 };
|
|
3305
|
-
const file = (0,
|
|
3297
|
+
const file = (0, import_path9.basename)(newPath);
|
|
3306
3298
|
state.workspace = {
|
|
3307
3299
|
...ws,
|
|
3308
3300
|
modified: ts,
|
|
@@ -3362,7 +3354,7 @@ function countBy(items) {
|
|
|
3362
3354
|
|
|
3363
3355
|
// src/tools/reference.ts
|
|
3364
3356
|
var import_promises8 = require("fs/promises");
|
|
3365
|
-
var
|
|
3357
|
+
var import_path10 = require("path");
|
|
3366
3358
|
var import_core11 = require("@genart-dev/core");
|
|
3367
3359
|
var import_promises9 = require("fs/promises");
|
|
3368
3360
|
function now7() {
|
|
@@ -3387,7 +3379,7 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
3387
3379
|
".svg"
|
|
3388
3380
|
]);
|
|
3389
3381
|
function isImageFile(path) {
|
|
3390
|
-
return IMAGE_EXTENSIONS.has((0,
|
|
3382
|
+
return IMAGE_EXTENSIONS.has((0, import_path10.extname)(path).toLowerCase());
|
|
3391
3383
|
}
|
|
3392
3384
|
var VALID_REFERENCE_TYPES = [
|
|
3393
3385
|
"image",
|
|
@@ -3403,7 +3395,7 @@ async function addReference(state, input) {
|
|
|
3403
3395
|
`Not a recognized image file: ${input.image}. Supported: ${[...IMAGE_EXTENSIONS].join(", ")}`
|
|
3404
3396
|
);
|
|
3405
3397
|
}
|
|
3406
|
-
const id = input.id ?? (0,
|
|
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, "");
|
|
3407
3399
|
if (!id) {
|
|
3408
3400
|
throw new Error("Could not derive a valid ID from the image filename");
|
|
3409
3401
|
}
|
|
@@ -3414,15 +3406,15 @@ async function addReference(state, input) {
|
|
|
3414
3406
|
`Invalid reference type: '${refType}'. Valid types: ${VALID_REFERENCE_TYPES.join(", ")}`
|
|
3415
3407
|
);
|
|
3416
3408
|
}
|
|
3417
|
-
const workspaceDir = (0,
|
|
3418
|
-
const refsDir = (0,
|
|
3409
|
+
const workspaceDir = (0, import_path10.dirname)(state.workspacePath);
|
|
3410
|
+
const refsDir = (0, import_path10.resolve)(workspaceDir, "references");
|
|
3419
3411
|
await (0, import_promises8.mkdir)(refsDir, { recursive: true });
|
|
3420
|
-
const ext = (0,
|
|
3412
|
+
const ext = (0, import_path10.extname)(input.image);
|
|
3421
3413
|
const destFilename = `${id}${ext}`;
|
|
3422
|
-
const destPath = (0,
|
|
3414
|
+
const destPath = (0, import_path10.resolve)(refsDir, destFilename);
|
|
3423
3415
|
const relativePath = `references/${destFilename}`;
|
|
3424
3416
|
if (!state.remoteMode) {
|
|
3425
|
-
await (0, import_promises8.copyFile)((0,
|
|
3417
|
+
await (0, import_promises8.copyFile)((0, import_path10.resolve)(input.image), destPath);
|
|
3426
3418
|
}
|
|
3427
3419
|
const ref = {
|
|
3428
3420
|
id,
|
|
@@ -3504,12 +3496,12 @@ async function addReference(state, input) {
|
|
|
3504
3496
|
async function analyzeReference(state, input) {
|
|
3505
3497
|
state.requireWorkspace();
|
|
3506
3498
|
const { ref, location } = findReference(state, input.referenceId, input.seriesId, input.sketchId);
|
|
3507
|
-
const workspaceDir = (0,
|
|
3508
|
-
const imagePath = (0,
|
|
3499
|
+
const workspaceDir = (0, import_path10.dirname)(state.workspacePath);
|
|
3500
|
+
const imagePath = (0, import_path10.resolve)(workspaceDir, ref.path);
|
|
3509
3501
|
let previewJpegBase64;
|
|
3510
3502
|
try {
|
|
3511
3503
|
const imageBuffer = await (0, import_promises8.readFile)(imagePath);
|
|
3512
|
-
const ext = (0,
|
|
3504
|
+
const ext = (0, import_path10.extname)(ref.path).toLowerCase();
|
|
3513
3505
|
const mimeMap = {
|
|
3514
3506
|
".png": "image/png",
|
|
3515
3507
|
".jpg": "image/jpeg",
|
|
@@ -3664,8 +3656,8 @@ async function extractPalette(state, input) {
|
|
|
3664
3656
|
input.sketchId
|
|
3665
3657
|
);
|
|
3666
3658
|
const count = input.count ?? 6;
|
|
3667
|
-
const workspaceDir = (0,
|
|
3668
|
-
const imagePath = (0,
|
|
3659
|
+
const workspaceDir = (0, import_path10.dirname)(state.workspacePath);
|
|
3660
|
+
const imagePath = (0, import_path10.resolve)(workspaceDir, ref.path);
|
|
3669
3661
|
let previewJpegBase64;
|
|
3670
3662
|
try {
|
|
3671
3663
|
const imageBuffer = await (0, import_promises8.readFile)(imagePath);
|
|
@@ -3741,12 +3733,12 @@ function findReference(state, referenceId, seriesId, sketchId) {
|
|
|
3741
3733
|
// src/tools/export.ts
|
|
3742
3734
|
var import_fs = require("fs");
|
|
3743
3735
|
var import_promises10 = require("fs/promises");
|
|
3744
|
-
var
|
|
3736
|
+
var import_path11 = require("path");
|
|
3745
3737
|
var import_archiver = __toESM(require("archiver"), 1);
|
|
3746
3738
|
var import_core12 = require("@genart-dev/core");
|
|
3747
3739
|
var registry4 = (0, import_core12.createDefaultRegistry)();
|
|
3748
3740
|
async function validateOutputPath(outputPath) {
|
|
3749
|
-
const parentDir = (0,
|
|
3741
|
+
const parentDir = (0, import_path11.dirname)(outputPath);
|
|
3750
3742
|
try {
|
|
3751
3743
|
const s = await (0, import_promises10.stat)(parentDir);
|
|
3752
3744
|
if (!s.isDirectory()) {
|
|
@@ -5012,20 +5004,24 @@ async function initializePluginRegistry() {
|
|
|
5012
5004
|
await registry5.register(import_plugin_trace.default);
|
|
5013
5005
|
return registry5;
|
|
5014
5006
|
}
|
|
5015
|
-
function createServer(state) {
|
|
5007
|
+
function createServer(state, options) {
|
|
5008
|
+
const captureOnly = options?.captureOnly ?? false;
|
|
5016
5009
|
const server = new import_mcp.McpServer(
|
|
5017
5010
|
{
|
|
5018
|
-
name: "@genart/mcp-server",
|
|
5011
|
+
name: captureOnly ? "@genart/mcp-capture" : "@genart/mcp-server",
|
|
5019
5012
|
version: "0.4.0"
|
|
5020
5013
|
},
|
|
5021
5014
|
{
|
|
5022
5015
|
capabilities: {
|
|
5023
5016
|
tools: {},
|
|
5024
|
-
resources: {},
|
|
5025
|
-
prompts: {}
|
|
5017
|
+
...!captureOnly && { resources: {}, prompts: {} }
|
|
5026
5018
|
}
|
|
5027
5019
|
}
|
|
5028
5020
|
);
|
|
5021
|
+
if (captureOnly) {
|
|
5022
|
+
registerCaptureTools(server, state);
|
|
5023
|
+
return server;
|
|
5024
|
+
}
|
|
5029
5025
|
const registryReady = initializePluginRegistry().then((registry5) => {
|
|
5030
5026
|
state.pluginRegistry = registry5;
|
|
5031
5027
|
registerPluginMcpTools(server, registry5, state);
|
|
@@ -5042,7 +5038,9 @@ function createServer(state) {
|
|
|
5042
5038
|
registerSnapshotTools(server, state);
|
|
5043
5039
|
registerKnowledgeTools(server, state);
|
|
5044
5040
|
registerDesignTools(server, state);
|
|
5045
|
-
|
|
5041
|
+
if (!state.remoteMode) {
|
|
5042
|
+
registerCaptureTools(server, state);
|
|
5043
|
+
}
|
|
5046
5044
|
registerCritiqueTools(server, state);
|
|
5047
5045
|
registerSeriesTools(server, state);
|
|
5048
5046
|
registerReferenceTools(server, state);
|
|
@@ -5752,7 +5750,7 @@ function registerSnapshotTools(server, state) {
|
|
|
5752
5750
|
function registerCaptureTools(server, state) {
|
|
5753
5751
|
server.tool(
|
|
5754
5752
|
"capture_screenshot",
|
|
5755
|
-
"Capture a screenshot of a sketch. Returns metadata as text + a small inline JPEG image for visual review. In
|
|
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.",
|
|
5756
5754
|
{
|
|
5757
5755
|
target: import_zod2.z.enum(["selected", "sketch"]).optional().describe("What to capture (default: selected)"),
|
|
5758
5756
|
sketchId: import_zod2.z.string().optional().describe("Required when target is 'sketch'"),
|
|
@@ -5765,6 +5763,7 @@ function registerCaptureTools(server, state) {
|
|
|
5765
5763
|
async (args) => {
|
|
5766
5764
|
try {
|
|
5767
5765
|
const result = await captureScreenshot(state, args);
|
|
5766
|
+
console.error(`[capture_screenshot] jpeg base64 length: ${result.previewJpegBase64.length}, metadata: ${JSON.stringify(result.metadata)}`);
|
|
5768
5767
|
return {
|
|
5769
5768
|
content: [
|
|
5770
5769
|
{ type: "text", text: JSON.stringify(result.metadata, null, 2) },
|
|
@@ -5772,6 +5771,7 @@ function registerCaptureTools(server, state) {
|
|
|
5772
5771
|
]
|
|
5773
5772
|
};
|
|
5774
5773
|
} catch (e) {
|
|
5774
|
+
console.error(`[capture_screenshot] error: ${e instanceof Error ? e.message : String(e)}`);
|
|
5775
5775
|
return toolError(e instanceof Error ? e.message : String(e));
|
|
5776
5776
|
}
|
|
5777
5777
|
}
|
|
@@ -6413,7 +6413,7 @@ function registerKnowledgeTools(server, state) {
|
|
|
6413
6413
|
// src/state.ts
|
|
6414
6414
|
var import_events = require("events");
|
|
6415
6415
|
var import_promises11 = require("fs/promises");
|
|
6416
|
-
var
|
|
6416
|
+
var import_path12 = require("path");
|
|
6417
6417
|
|
|
6418
6418
|
// src/sidecar.ts
|
|
6419
6419
|
function isSidecarMode() {
|
|
@@ -6470,7 +6470,7 @@ var EditorState = class extends import_events.EventEmitter {
|
|
|
6470
6470
|
}
|
|
6471
6471
|
/** Resolve a file path, respecting the sandbox basePath when set. */
|
|
6472
6472
|
resolvePath(file) {
|
|
6473
|
-
if ((0,
|
|
6473
|
+
if ((0, import_path12.isAbsolute)(file)) {
|
|
6474
6474
|
if (this.basePath && !file.startsWith(this.basePath)) {
|
|
6475
6475
|
throw new Error(`Path escapes sandbox: ${file}`);
|
|
6476
6476
|
}
|
|
@@ -6478,10 +6478,10 @@ var EditorState = class extends import_events.EventEmitter {
|
|
|
6478
6478
|
}
|
|
6479
6479
|
if ((file.startsWith("~/") || file === "~") && !this.basePath) {
|
|
6480
6480
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
6481
|
-
return (0,
|
|
6481
|
+
return (0, import_path12.resolve)(home, file.slice(2));
|
|
6482
6482
|
}
|
|
6483
6483
|
const base = this.basePath ?? process.cwd();
|
|
6484
|
-
const resolved = (0,
|
|
6484
|
+
const resolved = (0, import_path12.resolve)(base, file);
|
|
6485
6485
|
if (this.basePath && !resolved.startsWith(this.basePath)) {
|
|
6486
6486
|
throw new Error(`Path escapes sandbox: ${resolved}`);
|
|
6487
6487
|
}
|
|
@@ -6489,7 +6489,7 @@ var EditorState = class extends import_events.EventEmitter {
|
|
|
6489
6489
|
}
|
|
6490
6490
|
/** Resolve a sketch file reference (relative to workspace dir) to an absolute path. */
|
|
6491
6491
|
resolveSketchPath(file) {
|
|
6492
|
-
if ((0,
|
|
6492
|
+
if ((0, import_path12.isAbsolute)(file)) {
|
|
6493
6493
|
if (this.basePath && !file.startsWith(this.basePath)) {
|
|
6494
6494
|
throw new Error(`Path escapes sandbox: ${file}`);
|
|
6495
6495
|
}
|
|
@@ -6497,11 +6497,11 @@ var EditorState = class extends import_events.EventEmitter {
|
|
|
6497
6497
|
}
|
|
6498
6498
|
if (!this.workspacePath) {
|
|
6499
6499
|
if (this.basePath) {
|
|
6500
|
-
return (0,
|
|
6500
|
+
return (0, import_path12.resolve)(this.basePath, file);
|
|
6501
6501
|
}
|
|
6502
6502
|
throw new Error("No workspace is currently open");
|
|
6503
6503
|
}
|
|
6504
|
-
const resolved = (0,
|
|
6504
|
+
const resolved = (0, import_path12.resolve)((0, import_path12.dirname)(this.workspacePath), file);
|
|
6505
6505
|
if (this.basePath && !resolved.startsWith(this.basePath)) {
|
|
6506
6506
|
throw new Error(`Path escapes sandbox: ${resolved}`);
|
|
6507
6507
|
}
|