@genart-dev/mcp-server 0.4.2 → 0.4.4
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 +72 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -27
- package/dist/index.js.map +1 -1
- package/dist/lib.cjs +73 -41
- 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 +58 -26
- package/dist/lib.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2744,6 +2744,7 @@ function isDirectComponent(name, components) {
|
|
|
2744
2744
|
|
|
2745
2745
|
// src/tools/capture.ts
|
|
2746
2746
|
var import_promises8 = require("fs/promises");
|
|
2747
|
+
var import_path9 = require("path");
|
|
2747
2748
|
var import_core9 = require("@genart-dev/core");
|
|
2748
2749
|
|
|
2749
2750
|
// src/capture/headless.ts
|
|
@@ -2846,8 +2847,9 @@ function generateSketchHtml(sketch, opts) {
|
|
|
2846
2847
|
}
|
|
2847
2848
|
return adapter.generateStandaloneHTML(effective);
|
|
2848
2849
|
}
|
|
2849
|
-
function
|
|
2850
|
-
|
|
2850
|
+
function deriveSnapshotPath(sketchPath, sketchId, seed) {
|
|
2851
|
+
const wsDir = (0, import_path9.dirname)(sketchPath);
|
|
2852
|
+
return (0, import_path9.join)(wsDir, "snapshots", `${sketchId}-${seed}-preview.png`);
|
|
2851
2853
|
}
|
|
2852
2854
|
async function captureScreenshot(state, input) {
|
|
2853
2855
|
state.requireWorkspace();
|
|
@@ -2880,11 +2882,12 @@ async function captureScreenshot(state, input) {
|
|
|
2880
2882
|
height,
|
|
2881
2883
|
inlineSize
|
|
2882
2884
|
});
|
|
2883
|
-
const
|
|
2885
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2886
|
+
const previewPath = deriveSnapshotPath(loaded.path, sketchId, effectiveSeed);
|
|
2884
2887
|
const metadata = await buildScreenshotMetadata(state, multi, {
|
|
2885
2888
|
target,
|
|
2886
2889
|
sketchId,
|
|
2887
|
-
seed:
|
|
2890
|
+
seed: effectiveSeed,
|
|
2888
2891
|
previewPath
|
|
2889
2892
|
});
|
|
2890
2893
|
const previewJpegBase64 = Buffer.from(multi.inlineJpeg).toString("base64");
|
|
@@ -2905,8 +2908,10 @@ async function buildScreenshotMetadata(state, multi, info) {
|
|
|
2905
2908
|
previewPath: info.previewPath
|
|
2906
2909
|
};
|
|
2907
2910
|
if (!state.remoteMode) {
|
|
2911
|
+
await (0, import_promises8.mkdir)((0, import_path9.dirname)(info.previewPath), { recursive: true });
|
|
2908
2912
|
await (0, import_promises8.writeFile)(info.previewPath, multi.previewPng);
|
|
2909
2913
|
metadata.savedPreviewTo = info.previewPath;
|
|
2914
|
+
metadata.previewWritten = true;
|
|
2910
2915
|
}
|
|
2911
2916
|
return metadata;
|
|
2912
2917
|
}
|
|
@@ -2935,11 +2940,12 @@ async function captureBatch(state, input) {
|
|
|
2935
2940
|
height,
|
|
2936
2941
|
inlineSize
|
|
2937
2942
|
});
|
|
2938
|
-
const
|
|
2943
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2944
|
+
const previewPath = deriveSnapshotPath(loaded.path, id, effectiveSeed);
|
|
2939
2945
|
const itemMetadata = await buildScreenshotMetadata(state, multi, {
|
|
2940
2946
|
target: "sketch",
|
|
2941
2947
|
sketchId: id,
|
|
2942
|
-
seed:
|
|
2948
|
+
seed: effectiveSeed,
|
|
2943
2949
|
previewPath
|
|
2944
2950
|
});
|
|
2945
2951
|
items.push({
|
|
@@ -3299,7 +3305,7 @@ function gatherRelevantSkills(aspects) {
|
|
|
3299
3305
|
|
|
3300
3306
|
// src/tools/series.ts
|
|
3301
3307
|
var import_promises9 = require("fs/promises");
|
|
3302
|
-
var
|
|
3308
|
+
var import_path10 = require("path");
|
|
3303
3309
|
var import_core11 = require("@genart-dev/core");
|
|
3304
3310
|
function now6() {
|
|
3305
3311
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -3462,7 +3468,7 @@ async function seriesSummary(state, input) {
|
|
|
3462
3468
|
for (const file of series.sketchFiles) {
|
|
3463
3469
|
let found = false;
|
|
3464
3470
|
for (const [id, loaded] of state.sketches) {
|
|
3465
|
-
if ((0,
|
|
3471
|
+
if ((0, import_path10.basename)(loaded.path) === file) {
|
|
3466
3472
|
const def = loaded.definition;
|
|
3467
3473
|
sketchInfos.push({
|
|
3468
3474
|
id,
|
|
@@ -3576,18 +3582,18 @@ async function promoteSketch(state, input) {
|
|
|
3576
3582
|
...input.agent ? { agent: input.agent } : {},
|
|
3577
3583
|
...input.model ? { model: input.model } : {}
|
|
3578
3584
|
};
|
|
3579
|
-
const sourceDir = (0,
|
|
3580
|
-
const newPath = (0,
|
|
3585
|
+
const sourceDir = (0, import_path10.dirname)(source.path);
|
|
3586
|
+
const newPath = (0, import_path10.resolve)(sourceDir, `${newId}.genart`);
|
|
3581
3587
|
const json = (0, import_core11.serializeGenart)(promotedDef);
|
|
3582
3588
|
if (!state.remoteMode) {
|
|
3583
3589
|
await (0, import_promises9.writeFile)(newPath, json, "utf-8");
|
|
3584
3590
|
}
|
|
3585
3591
|
state.sketches.set(newId, { definition: promotedDef, path: newPath });
|
|
3586
3592
|
const sourceRef = ws.sketches.find(
|
|
3587
|
-
(s) => s.file === (0,
|
|
3593
|
+
(s) => s.file === (0, import_path10.basename)(source.path)
|
|
3588
3594
|
);
|
|
3589
3595
|
const position = sourceRef ? { x: sourceRef.position.x, y: sourceRef.position.y + sourceDef.canvas.height + 200 } : { x: 0, y: 0 };
|
|
3590
|
-
const file = (0,
|
|
3596
|
+
const file = (0, import_path10.basename)(newPath);
|
|
3591
3597
|
state.workspace = {
|
|
3592
3598
|
...ws,
|
|
3593
3599
|
modified: ts,
|
|
@@ -3647,7 +3653,7 @@ function countBy(items) {
|
|
|
3647
3653
|
|
|
3648
3654
|
// src/tools/reference.ts
|
|
3649
3655
|
var import_promises10 = require("fs/promises");
|
|
3650
|
-
var
|
|
3656
|
+
var import_path11 = require("path");
|
|
3651
3657
|
var import_core12 = require("@genart-dev/core");
|
|
3652
3658
|
var import_promises11 = require("fs/promises");
|
|
3653
3659
|
function now7() {
|
|
@@ -3672,7 +3678,7 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
3672
3678
|
".svg"
|
|
3673
3679
|
]);
|
|
3674
3680
|
function isImageFile(path) {
|
|
3675
|
-
return IMAGE_EXTENSIONS.has((0,
|
|
3681
|
+
return IMAGE_EXTENSIONS.has((0, import_path11.extname)(path).toLowerCase());
|
|
3676
3682
|
}
|
|
3677
3683
|
var VALID_REFERENCE_TYPES = [
|
|
3678
3684
|
"image",
|
|
@@ -3688,7 +3694,7 @@ async function addReference(state, input) {
|
|
|
3688
3694
|
`Not a recognized image file: ${input.image}. Supported: ${[...IMAGE_EXTENSIONS].join(", ")}`
|
|
3689
3695
|
);
|
|
3690
3696
|
}
|
|
3691
|
-
const id = input.id ?? (0,
|
|
3697
|
+
const id = input.id ?? (0, import_path11.basename)(input.image, (0, import_path11.extname)(input.image)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
3692
3698
|
if (!id) {
|
|
3693
3699
|
throw new Error("Could not derive a valid ID from the image filename");
|
|
3694
3700
|
}
|
|
@@ -3699,15 +3705,15 @@ async function addReference(state, input) {
|
|
|
3699
3705
|
`Invalid reference type: '${refType}'. Valid types: ${VALID_REFERENCE_TYPES.join(", ")}`
|
|
3700
3706
|
);
|
|
3701
3707
|
}
|
|
3702
|
-
const workspaceDir = (0,
|
|
3703
|
-
const refsDir = (0,
|
|
3708
|
+
const workspaceDir = (0, import_path11.dirname)(state.workspacePath);
|
|
3709
|
+
const refsDir = (0, import_path11.resolve)(workspaceDir, "references");
|
|
3704
3710
|
await (0, import_promises10.mkdir)(refsDir, { recursive: true });
|
|
3705
|
-
const ext = (0,
|
|
3711
|
+
const ext = (0, import_path11.extname)(input.image);
|
|
3706
3712
|
const destFilename = `${id}${ext}`;
|
|
3707
|
-
const destPath = (0,
|
|
3713
|
+
const destPath = (0, import_path11.resolve)(refsDir, destFilename);
|
|
3708
3714
|
const relativePath = `references/${destFilename}`;
|
|
3709
3715
|
if (!state.remoteMode) {
|
|
3710
|
-
await (0, import_promises10.copyFile)((0,
|
|
3716
|
+
await (0, import_promises10.copyFile)((0, import_path11.resolve)(input.image), destPath);
|
|
3711
3717
|
}
|
|
3712
3718
|
const ref = {
|
|
3713
3719
|
id,
|
|
@@ -3789,12 +3795,12 @@ async function addReference(state, input) {
|
|
|
3789
3795
|
async function analyzeReference(state, input) {
|
|
3790
3796
|
state.requireWorkspace();
|
|
3791
3797
|
const { ref, location } = findReference(state, input.referenceId, input.seriesId, input.sketchId);
|
|
3792
|
-
const workspaceDir = (0,
|
|
3793
|
-
const imagePath = (0,
|
|
3798
|
+
const workspaceDir = (0, import_path11.dirname)(state.workspacePath);
|
|
3799
|
+
const imagePath = (0, import_path11.resolve)(workspaceDir, ref.path);
|
|
3794
3800
|
let previewJpegBase64;
|
|
3795
3801
|
try {
|
|
3796
3802
|
const imageBuffer = await (0, import_promises10.readFile)(imagePath);
|
|
3797
|
-
const ext = (0,
|
|
3803
|
+
const ext = (0, import_path11.extname)(ref.path).toLowerCase();
|
|
3798
3804
|
const mimeMap = {
|
|
3799
3805
|
".png": "image/png",
|
|
3800
3806
|
".jpg": "image/jpeg",
|
|
@@ -3949,8 +3955,8 @@ async function extractPalette(state, input) {
|
|
|
3949
3955
|
input.sketchId
|
|
3950
3956
|
);
|
|
3951
3957
|
const count = input.count ?? 6;
|
|
3952
|
-
const workspaceDir = (0,
|
|
3953
|
-
const imagePath = (0,
|
|
3958
|
+
const workspaceDir = (0, import_path11.dirname)(state.workspacePath);
|
|
3959
|
+
const imagePath = (0, import_path11.resolve)(workspaceDir, ref.path);
|
|
3954
3960
|
let previewJpegBase64;
|
|
3955
3961
|
try {
|
|
3956
3962
|
const imageBuffer = await (0, import_promises10.readFile)(imagePath);
|
|
@@ -4026,12 +4032,12 @@ function findReference(state, referenceId, seriesId, sketchId) {
|
|
|
4026
4032
|
// src/tools/export.ts
|
|
4027
4033
|
var import_fs = require("fs");
|
|
4028
4034
|
var import_promises12 = require("fs/promises");
|
|
4029
|
-
var
|
|
4035
|
+
var import_path12 = require("path");
|
|
4030
4036
|
var import_archiver = __toESM(require("archiver"), 1);
|
|
4031
4037
|
var import_core13 = require("@genart-dev/core");
|
|
4032
4038
|
var registry4 = (0, import_core13.createDefaultRegistry)();
|
|
4033
4039
|
async function validateOutputPath(outputPath) {
|
|
4034
|
-
const parentDir = (0,
|
|
4040
|
+
const parentDir = (0, import_path12.dirname)(outputPath);
|
|
4035
4041
|
try {
|
|
4036
4042
|
const s = await (0, import_promises12.stat)(parentDir);
|
|
4037
4043
|
if (!s.isDirectory()) {
|
|
@@ -5297,20 +5303,24 @@ async function initializePluginRegistry() {
|
|
|
5297
5303
|
await registry5.register(import_plugin_trace.default);
|
|
5298
5304
|
return registry5;
|
|
5299
5305
|
}
|
|
5300
|
-
function createServer(state) {
|
|
5306
|
+
function createServer(state, options) {
|
|
5307
|
+
const captureOnly = options?.captureOnly ?? false;
|
|
5301
5308
|
const server = new import_mcp.McpServer(
|
|
5302
5309
|
{
|
|
5303
|
-
name: "@genart/mcp-server",
|
|
5310
|
+
name: captureOnly ? "@genart/mcp-capture" : "@genart/mcp-server",
|
|
5304
5311
|
version: "0.4.0"
|
|
5305
5312
|
},
|
|
5306
5313
|
{
|
|
5307
5314
|
capabilities: {
|
|
5308
5315
|
tools: {},
|
|
5309
|
-
resources: {},
|
|
5310
|
-
prompts: {}
|
|
5316
|
+
...!captureOnly && { resources: {}, prompts: {} }
|
|
5311
5317
|
}
|
|
5312
5318
|
}
|
|
5313
5319
|
);
|
|
5320
|
+
if (captureOnly) {
|
|
5321
|
+
registerCaptureTools(server, state);
|
|
5322
|
+
return server;
|
|
5323
|
+
}
|
|
5314
5324
|
const registryReady = initializePluginRegistry().then((registry5) => {
|
|
5315
5325
|
state.pluginRegistry = registry5;
|
|
5316
5326
|
registerPluginMcpTools(server, registry5, state);
|
|
@@ -5327,7 +5337,9 @@ function createServer(state) {
|
|
|
5327
5337
|
registerSnapshotTools(server, state);
|
|
5328
5338
|
registerKnowledgeTools(server, state);
|
|
5329
5339
|
registerDesignTools(server, state);
|
|
5330
|
-
|
|
5340
|
+
if (!state.remoteMode) {
|
|
5341
|
+
registerCaptureTools(server, state);
|
|
5342
|
+
}
|
|
5331
5343
|
registerCritiqueTools(server, state);
|
|
5332
5344
|
registerSeriesTools(server, state);
|
|
5333
5345
|
registerReferenceTools(server, state);
|
|
@@ -5476,11 +5488,31 @@ function registerSketchTools(server, state) {
|
|
|
5476
5488
|
).optional().describe('Component dependencies. Use list_components to see available. Keys are component names, values are semver ranges (e.g. "^1.0.0") or objects with version/code/exports.'),
|
|
5477
5489
|
addToWorkspace: import_zod2.z.string().optional().describe("Path to workspace to add sketch to after creation"),
|
|
5478
5490
|
agent: import_zod2.z.string().optional().describe("Your CLI agent name (e.g. 'claude-code', 'codex-cli', 'gemini-cli', 'opencode', 'kiro')"),
|
|
5479
|
-
model: import_zod2.z.string().optional().describe("Your AI model identifier (e.g. 'claude-opus-4-6', 'gpt-4o', 'gemini-2.5-pro')")
|
|
5491
|
+
model: import_zod2.z.string().optional().describe("Your AI model identifier (e.g. 'claude-opus-4-6', 'gpt-4o', 'gemini-2.5-pro')"),
|
|
5492
|
+
capture: import_zod2.z.boolean().optional().describe("When true, automatically capture a screenshot after creation and return it inline (avoids a separate capture_screenshot call)")
|
|
5480
5493
|
},
|
|
5481
5494
|
async (args) => {
|
|
5482
5495
|
try {
|
|
5483
5496
|
const result = await createSketch(state, args);
|
|
5497
|
+
if (args.capture && !state.remoteMode) {
|
|
5498
|
+
try {
|
|
5499
|
+
const captureResult = await captureScreenshot(state, {
|
|
5500
|
+
target: "sketch",
|
|
5501
|
+
sketchId: args.id
|
|
5502
|
+
});
|
|
5503
|
+
return {
|
|
5504
|
+
content: [
|
|
5505
|
+
{ type: "text", text: JSON.stringify({ ...result, capture: captureResult.metadata }, null, 2) },
|
|
5506
|
+
{ type: "image", data: captureResult.previewJpegBase64, mimeType: "image/jpeg" }
|
|
5507
|
+
]
|
|
5508
|
+
};
|
|
5509
|
+
} catch (captureErr) {
|
|
5510
|
+
return jsonResult({
|
|
5511
|
+
...result,
|
|
5512
|
+
captureError: captureErr instanceof Error ? captureErr.message : String(captureErr)
|
|
5513
|
+
});
|
|
5514
|
+
}
|
|
5515
|
+
}
|
|
5484
5516
|
return jsonResult(result);
|
|
5485
5517
|
} catch (e) {
|
|
5486
5518
|
return toolError(e instanceof Error ? e.message : String(e));
|
|
@@ -6037,7 +6069,7 @@ function registerSnapshotTools(server, state) {
|
|
|
6037
6069
|
function registerCaptureTools(server, state) {
|
|
6038
6070
|
server.tool(
|
|
6039
6071
|
"capture_screenshot",
|
|
6040
|
-
"Capture a screenshot of a sketch. Returns metadata as text + a small inline JPEG image for visual review. In
|
|
6072
|
+
"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.",
|
|
6041
6073
|
{
|
|
6042
6074
|
target: import_zod2.z.enum(["selected", "sketch"]).optional().describe("What to capture (default: selected)"),
|
|
6043
6075
|
sketchId: import_zod2.z.string().optional().describe("Required when target is 'sketch'"),
|
|
@@ -6699,14 +6731,17 @@ function registerKnowledgeTools(server, state) {
|
|
|
6699
6731
|
|
|
6700
6732
|
// src/index.ts
|
|
6701
6733
|
async function main() {
|
|
6702
|
-
const
|
|
6703
|
-
|
|
6734
|
+
const captureOnly = process.argv.includes("--capture-only");
|
|
6735
|
+
const sidecar = !captureOnly && isSidecarMode();
|
|
6736
|
+
if (captureOnly) {
|
|
6737
|
+
console.error("[genart-mcp] Starting in capture-only mode");
|
|
6738
|
+
} else if (sidecar) {
|
|
6704
6739
|
console.error("[genart-mcp] Starting in sidecar mode");
|
|
6705
6740
|
} else {
|
|
6706
6741
|
console.error("[genart-mcp] Starting in stdio mode");
|
|
6707
6742
|
}
|
|
6708
6743
|
const state = new EditorState();
|
|
6709
|
-
const server = createServer(state);
|
|
6744
|
+
const server = createServer(state, { captureOnly });
|
|
6710
6745
|
const transport = new import_stdio.StdioServerTransport();
|
|
6711
6746
|
await server.connect(transport);
|
|
6712
6747
|
console.error("[genart-mcp] Server connected and ready");
|