@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/index.cjs
CHANGED
|
@@ -2744,30 +2744,17 @@ 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
|
|
2750
|
-
var
|
|
2751
|
-
async function loadPuppeteer() {
|
|
2752
|
-
if (!cachedModule) {
|
|
2753
|
-
try {
|
|
2754
|
-
const mod = await import("puppeteer");
|
|
2755
|
-
cachedModule = mod.default ?? mod;
|
|
2756
|
-
} catch {
|
|
2757
|
-
throw new Error(
|
|
2758
|
-
"Puppeteer is required for screenshot capture. Install it with: npm install puppeteer"
|
|
2759
|
-
);
|
|
2760
|
-
}
|
|
2761
|
-
}
|
|
2762
|
-
return cachedModule;
|
|
2763
|
-
}
|
|
2751
|
+
var import_puppeteer = __toESM(require("puppeteer"), 1);
|
|
2764
2752
|
var browserInstance = null;
|
|
2765
2753
|
async function getBrowser() {
|
|
2766
2754
|
if (browserInstance && browserInstance.connected) {
|
|
2767
2755
|
return browserInstance;
|
|
2768
2756
|
}
|
|
2769
|
-
|
|
2770
|
-
browserInstance = await puppeteer.launch({
|
|
2757
|
+
browserInstance = await import_puppeteer.default.launch({
|
|
2771
2758
|
headless: true,
|
|
2772
2759
|
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || void 0,
|
|
2773
2760
|
args: [
|
|
@@ -2860,8 +2847,9 @@ function generateSketchHtml(sketch, opts) {
|
|
|
2860
2847
|
}
|
|
2861
2848
|
return adapter.generateStandaloneHTML(effective);
|
|
2862
2849
|
}
|
|
2863
|
-
function
|
|
2864
|
-
|
|
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`);
|
|
2865
2853
|
}
|
|
2866
2854
|
async function captureScreenshot(state, input) {
|
|
2867
2855
|
state.requireWorkspace();
|
|
@@ -2894,11 +2882,12 @@ async function captureScreenshot(state, input) {
|
|
|
2894
2882
|
height,
|
|
2895
2883
|
inlineSize
|
|
2896
2884
|
});
|
|
2897
|
-
const
|
|
2885
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2886
|
+
const previewPath = deriveSnapshotPath(loaded.path, sketchId, effectiveSeed);
|
|
2898
2887
|
const metadata = await buildScreenshotMetadata(state, multi, {
|
|
2899
2888
|
target,
|
|
2900
2889
|
sketchId,
|
|
2901
|
-
seed:
|
|
2890
|
+
seed: effectiveSeed,
|
|
2902
2891
|
previewPath
|
|
2903
2892
|
});
|
|
2904
2893
|
const previewJpegBase64 = Buffer.from(multi.inlineJpeg).toString("base64");
|
|
@@ -2919,8 +2908,10 @@ async function buildScreenshotMetadata(state, multi, info) {
|
|
|
2919
2908
|
previewPath: info.previewPath
|
|
2920
2909
|
};
|
|
2921
2910
|
if (!state.remoteMode) {
|
|
2911
|
+
await (0, import_promises8.mkdir)((0, import_path9.dirname)(info.previewPath), { recursive: true });
|
|
2922
2912
|
await (0, import_promises8.writeFile)(info.previewPath, multi.previewPng);
|
|
2923
2913
|
metadata.savedPreviewTo = info.previewPath;
|
|
2914
|
+
metadata.previewWritten = true;
|
|
2924
2915
|
}
|
|
2925
2916
|
return metadata;
|
|
2926
2917
|
}
|
|
@@ -2949,11 +2940,12 @@ async function captureBatch(state, input) {
|
|
|
2949
2940
|
height,
|
|
2950
2941
|
inlineSize
|
|
2951
2942
|
});
|
|
2952
|
-
const
|
|
2943
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2944
|
+
const previewPath = deriveSnapshotPath(loaded.path, id, effectiveSeed);
|
|
2953
2945
|
const itemMetadata = await buildScreenshotMetadata(state, multi, {
|
|
2954
2946
|
target: "sketch",
|
|
2955
2947
|
sketchId: id,
|
|
2956
|
-
seed:
|
|
2948
|
+
seed: effectiveSeed,
|
|
2957
2949
|
previewPath
|
|
2958
2950
|
});
|
|
2959
2951
|
items.push({
|
|
@@ -3313,7 +3305,7 @@ function gatherRelevantSkills(aspects) {
|
|
|
3313
3305
|
|
|
3314
3306
|
// src/tools/series.ts
|
|
3315
3307
|
var import_promises9 = require("fs/promises");
|
|
3316
|
-
var
|
|
3308
|
+
var import_path10 = require("path");
|
|
3317
3309
|
var import_core11 = require("@genart-dev/core");
|
|
3318
3310
|
function now6() {
|
|
3319
3311
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -3476,7 +3468,7 @@ async function seriesSummary(state, input) {
|
|
|
3476
3468
|
for (const file of series.sketchFiles) {
|
|
3477
3469
|
let found = false;
|
|
3478
3470
|
for (const [id, loaded] of state.sketches) {
|
|
3479
|
-
if ((0,
|
|
3471
|
+
if ((0, import_path10.basename)(loaded.path) === file) {
|
|
3480
3472
|
const def = loaded.definition;
|
|
3481
3473
|
sketchInfos.push({
|
|
3482
3474
|
id,
|
|
@@ -3590,18 +3582,18 @@ async function promoteSketch(state, input) {
|
|
|
3590
3582
|
...input.agent ? { agent: input.agent } : {},
|
|
3591
3583
|
...input.model ? { model: input.model } : {}
|
|
3592
3584
|
};
|
|
3593
|
-
const sourceDir = (0,
|
|
3594
|
-
const newPath = (0,
|
|
3585
|
+
const sourceDir = (0, import_path10.dirname)(source.path);
|
|
3586
|
+
const newPath = (0, import_path10.resolve)(sourceDir, `${newId}.genart`);
|
|
3595
3587
|
const json = (0, import_core11.serializeGenart)(promotedDef);
|
|
3596
3588
|
if (!state.remoteMode) {
|
|
3597
3589
|
await (0, import_promises9.writeFile)(newPath, json, "utf-8");
|
|
3598
3590
|
}
|
|
3599
3591
|
state.sketches.set(newId, { definition: promotedDef, path: newPath });
|
|
3600
3592
|
const sourceRef = ws.sketches.find(
|
|
3601
|
-
(s) => s.file === (0,
|
|
3593
|
+
(s) => s.file === (0, import_path10.basename)(source.path)
|
|
3602
3594
|
);
|
|
3603
3595
|
const position = sourceRef ? { x: sourceRef.position.x, y: sourceRef.position.y + sourceDef.canvas.height + 200 } : { x: 0, y: 0 };
|
|
3604
|
-
const file = (0,
|
|
3596
|
+
const file = (0, import_path10.basename)(newPath);
|
|
3605
3597
|
state.workspace = {
|
|
3606
3598
|
...ws,
|
|
3607
3599
|
modified: ts,
|
|
@@ -3661,7 +3653,7 @@ function countBy(items) {
|
|
|
3661
3653
|
|
|
3662
3654
|
// src/tools/reference.ts
|
|
3663
3655
|
var import_promises10 = require("fs/promises");
|
|
3664
|
-
var
|
|
3656
|
+
var import_path11 = require("path");
|
|
3665
3657
|
var import_core12 = require("@genart-dev/core");
|
|
3666
3658
|
var import_promises11 = require("fs/promises");
|
|
3667
3659
|
function now7() {
|
|
@@ -3686,7 +3678,7 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
3686
3678
|
".svg"
|
|
3687
3679
|
]);
|
|
3688
3680
|
function isImageFile(path) {
|
|
3689
|
-
return IMAGE_EXTENSIONS.has((0,
|
|
3681
|
+
return IMAGE_EXTENSIONS.has((0, import_path11.extname)(path).toLowerCase());
|
|
3690
3682
|
}
|
|
3691
3683
|
var VALID_REFERENCE_TYPES = [
|
|
3692
3684
|
"image",
|
|
@@ -3702,7 +3694,7 @@ async function addReference(state, input) {
|
|
|
3702
3694
|
`Not a recognized image file: ${input.image}. Supported: ${[...IMAGE_EXTENSIONS].join(", ")}`
|
|
3703
3695
|
);
|
|
3704
3696
|
}
|
|
3705
|
-
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, "");
|
|
3706
3698
|
if (!id) {
|
|
3707
3699
|
throw new Error("Could not derive a valid ID from the image filename");
|
|
3708
3700
|
}
|
|
@@ -3713,15 +3705,15 @@ async function addReference(state, input) {
|
|
|
3713
3705
|
`Invalid reference type: '${refType}'. Valid types: ${VALID_REFERENCE_TYPES.join(", ")}`
|
|
3714
3706
|
);
|
|
3715
3707
|
}
|
|
3716
|
-
const workspaceDir = (0,
|
|
3717
|
-
const refsDir = (0,
|
|
3708
|
+
const workspaceDir = (0, import_path11.dirname)(state.workspacePath);
|
|
3709
|
+
const refsDir = (0, import_path11.resolve)(workspaceDir, "references");
|
|
3718
3710
|
await (0, import_promises10.mkdir)(refsDir, { recursive: true });
|
|
3719
|
-
const ext = (0,
|
|
3711
|
+
const ext = (0, import_path11.extname)(input.image);
|
|
3720
3712
|
const destFilename = `${id}${ext}`;
|
|
3721
|
-
const destPath = (0,
|
|
3713
|
+
const destPath = (0, import_path11.resolve)(refsDir, destFilename);
|
|
3722
3714
|
const relativePath = `references/${destFilename}`;
|
|
3723
3715
|
if (!state.remoteMode) {
|
|
3724
|
-
await (0, import_promises10.copyFile)((0,
|
|
3716
|
+
await (0, import_promises10.copyFile)((0, import_path11.resolve)(input.image), destPath);
|
|
3725
3717
|
}
|
|
3726
3718
|
const ref = {
|
|
3727
3719
|
id,
|
|
@@ -3803,12 +3795,12 @@ async function addReference(state, input) {
|
|
|
3803
3795
|
async function analyzeReference(state, input) {
|
|
3804
3796
|
state.requireWorkspace();
|
|
3805
3797
|
const { ref, location } = findReference(state, input.referenceId, input.seriesId, input.sketchId);
|
|
3806
|
-
const workspaceDir = (0,
|
|
3807
|
-
const imagePath = (0,
|
|
3798
|
+
const workspaceDir = (0, import_path11.dirname)(state.workspacePath);
|
|
3799
|
+
const imagePath = (0, import_path11.resolve)(workspaceDir, ref.path);
|
|
3808
3800
|
let previewJpegBase64;
|
|
3809
3801
|
try {
|
|
3810
3802
|
const imageBuffer = await (0, import_promises10.readFile)(imagePath);
|
|
3811
|
-
const ext = (0,
|
|
3803
|
+
const ext = (0, import_path11.extname)(ref.path).toLowerCase();
|
|
3812
3804
|
const mimeMap = {
|
|
3813
3805
|
".png": "image/png",
|
|
3814
3806
|
".jpg": "image/jpeg",
|
|
@@ -3963,8 +3955,8 @@ async function extractPalette(state, input) {
|
|
|
3963
3955
|
input.sketchId
|
|
3964
3956
|
);
|
|
3965
3957
|
const count = input.count ?? 6;
|
|
3966
|
-
const workspaceDir = (0,
|
|
3967
|
-
const imagePath = (0,
|
|
3958
|
+
const workspaceDir = (0, import_path11.dirname)(state.workspacePath);
|
|
3959
|
+
const imagePath = (0, import_path11.resolve)(workspaceDir, ref.path);
|
|
3968
3960
|
let previewJpegBase64;
|
|
3969
3961
|
try {
|
|
3970
3962
|
const imageBuffer = await (0, import_promises10.readFile)(imagePath);
|
|
@@ -4040,12 +4032,12 @@ function findReference(state, referenceId, seriesId, sketchId) {
|
|
|
4040
4032
|
// src/tools/export.ts
|
|
4041
4033
|
var import_fs = require("fs");
|
|
4042
4034
|
var import_promises12 = require("fs/promises");
|
|
4043
|
-
var
|
|
4035
|
+
var import_path12 = require("path");
|
|
4044
4036
|
var import_archiver = __toESM(require("archiver"), 1);
|
|
4045
4037
|
var import_core13 = require("@genart-dev/core");
|
|
4046
4038
|
var registry4 = (0, import_core13.createDefaultRegistry)();
|
|
4047
4039
|
async function validateOutputPath(outputPath) {
|
|
4048
|
-
const parentDir = (0,
|
|
4040
|
+
const parentDir = (0, import_path12.dirname)(outputPath);
|
|
4049
4041
|
try {
|
|
4050
4042
|
const s = await (0, import_promises12.stat)(parentDir);
|
|
4051
4043
|
if (!s.isDirectory()) {
|
|
@@ -5311,20 +5303,24 @@ async function initializePluginRegistry() {
|
|
|
5311
5303
|
await registry5.register(import_plugin_trace.default);
|
|
5312
5304
|
return registry5;
|
|
5313
5305
|
}
|
|
5314
|
-
function createServer(state) {
|
|
5306
|
+
function createServer(state, options) {
|
|
5307
|
+
const captureOnly = options?.captureOnly ?? false;
|
|
5315
5308
|
const server = new import_mcp.McpServer(
|
|
5316
5309
|
{
|
|
5317
|
-
name: "@genart/mcp-server",
|
|
5310
|
+
name: captureOnly ? "@genart/mcp-capture" : "@genart/mcp-server",
|
|
5318
5311
|
version: "0.4.0"
|
|
5319
5312
|
},
|
|
5320
5313
|
{
|
|
5321
5314
|
capabilities: {
|
|
5322
5315
|
tools: {},
|
|
5323
|
-
resources: {},
|
|
5324
|
-
prompts: {}
|
|
5316
|
+
...!captureOnly && { resources: {}, prompts: {} }
|
|
5325
5317
|
}
|
|
5326
5318
|
}
|
|
5327
5319
|
);
|
|
5320
|
+
if (captureOnly) {
|
|
5321
|
+
registerCaptureTools(server, state);
|
|
5322
|
+
return server;
|
|
5323
|
+
}
|
|
5328
5324
|
const registryReady = initializePluginRegistry().then((registry5) => {
|
|
5329
5325
|
state.pluginRegistry = registry5;
|
|
5330
5326
|
registerPluginMcpTools(server, registry5, state);
|
|
@@ -5341,7 +5337,9 @@ function createServer(state) {
|
|
|
5341
5337
|
registerSnapshotTools(server, state);
|
|
5342
5338
|
registerKnowledgeTools(server, state);
|
|
5343
5339
|
registerDesignTools(server, state);
|
|
5344
|
-
|
|
5340
|
+
if (!state.remoteMode) {
|
|
5341
|
+
registerCaptureTools(server, state);
|
|
5342
|
+
}
|
|
5345
5343
|
registerCritiqueTools(server, state);
|
|
5346
5344
|
registerSeriesTools(server, state);
|
|
5347
5345
|
registerReferenceTools(server, state);
|
|
@@ -6051,7 +6049,7 @@ function registerSnapshotTools(server, state) {
|
|
|
6051
6049
|
function registerCaptureTools(server, state) {
|
|
6052
6050
|
server.tool(
|
|
6053
6051
|
"capture_screenshot",
|
|
6054
|
-
"Capture a screenshot of a sketch. Returns metadata as text + a small inline JPEG image for visual review. In
|
|
6052
|
+
"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.",
|
|
6055
6053
|
{
|
|
6056
6054
|
target: import_zod2.z.enum(["selected", "sketch"]).optional().describe("What to capture (default: selected)"),
|
|
6057
6055
|
sketchId: import_zod2.z.string().optional().describe("Required when target is 'sketch'"),
|
|
@@ -6064,6 +6062,7 @@ function registerCaptureTools(server, state) {
|
|
|
6064
6062
|
async (args) => {
|
|
6065
6063
|
try {
|
|
6066
6064
|
const result = await captureScreenshot(state, args);
|
|
6065
|
+
console.error(`[capture_screenshot] jpeg base64 length: ${result.previewJpegBase64.length}, metadata: ${JSON.stringify(result.metadata)}`);
|
|
6067
6066
|
return {
|
|
6068
6067
|
content: [
|
|
6069
6068
|
{ type: "text", text: JSON.stringify(result.metadata, null, 2) },
|
|
@@ -6071,6 +6070,7 @@ function registerCaptureTools(server, state) {
|
|
|
6071
6070
|
]
|
|
6072
6071
|
};
|
|
6073
6072
|
} catch (e) {
|
|
6073
|
+
console.error(`[capture_screenshot] error: ${e instanceof Error ? e.message : String(e)}`);
|
|
6074
6074
|
return toolError(e instanceof Error ? e.message : String(e));
|
|
6075
6075
|
}
|
|
6076
6076
|
}
|
|
@@ -6711,14 +6711,17 @@ function registerKnowledgeTools(server, state) {
|
|
|
6711
6711
|
|
|
6712
6712
|
// src/index.ts
|
|
6713
6713
|
async function main() {
|
|
6714
|
-
const
|
|
6715
|
-
|
|
6714
|
+
const captureOnly = process.argv.includes("--capture-only");
|
|
6715
|
+
const sidecar = !captureOnly && isSidecarMode();
|
|
6716
|
+
if (captureOnly) {
|
|
6717
|
+
console.error("[genart-mcp] Starting in capture-only mode");
|
|
6718
|
+
} else if (sidecar) {
|
|
6716
6719
|
console.error("[genart-mcp] Starting in sidecar mode");
|
|
6717
6720
|
} else {
|
|
6718
6721
|
console.error("[genart-mcp] Starting in stdio mode");
|
|
6719
6722
|
}
|
|
6720
6723
|
const state = new EditorState();
|
|
6721
|
-
const server = createServer(state);
|
|
6724
|
+
const server = createServer(state, { captureOnly });
|
|
6722
6725
|
const transport = new import_stdio.StdioServerTransport();
|
|
6723
6726
|
await server.connect(transport);
|
|
6724
6727
|
console.error("[genart-mcp] Server connected and ready");
|