@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/lib.d.cts
CHANGED
|
@@ -116,7 +116,11 @@ declare class EditorState extends EventEmitter {
|
|
|
116
116
|
* Creates a McpServer instance with all tools, resources, and prompts.
|
|
117
117
|
*/
|
|
118
118
|
|
|
119
|
+
interface CreateServerOptions {
|
|
120
|
+
/** Only register capture tools (for local-only capture companion server). */
|
|
121
|
+
captureOnly?: boolean;
|
|
122
|
+
}
|
|
119
123
|
/** Create and configure the MCP server with all tools. */
|
|
120
|
-
declare function createServer(state: EditorState): McpServer;
|
|
124
|
+
declare function createServer(state: EditorState, options?: CreateServerOptions): McpServer;
|
|
121
125
|
|
|
122
|
-
export { type EditorMutationEvent, type EditorMutationType, EditorState, type EditorStateSnapshot, type LoadedSketch, createServer };
|
|
126
|
+
export { type CreateServerOptions, type EditorMutationEvent, type EditorMutationType, EditorState, type EditorStateSnapshot, type LoadedSketch, createServer };
|
package/dist/lib.d.ts
CHANGED
|
@@ -116,7 +116,11 @@ declare class EditorState extends EventEmitter {
|
|
|
116
116
|
* Creates a McpServer instance with all tools, resources, and prompts.
|
|
117
117
|
*/
|
|
118
118
|
|
|
119
|
+
interface CreateServerOptions {
|
|
120
|
+
/** Only register capture tools (for local-only capture companion server). */
|
|
121
|
+
captureOnly?: boolean;
|
|
122
|
+
}
|
|
119
123
|
/** Create and configure the MCP server with all tools. */
|
|
120
|
-
declare function createServer(state: EditorState): McpServer;
|
|
124
|
+
declare function createServer(state: EditorState, options?: CreateServerOptions): McpServer;
|
|
121
125
|
|
|
122
|
-
export { type EditorMutationEvent, type EditorMutationType, EditorState, type EditorStateSnapshot, type LoadedSketch, createServer };
|
|
126
|
+
export { type CreateServerOptions, type EditorMutationEvent, type EditorMutationType, EditorState, type EditorStateSnapshot, type LoadedSketch, createServer };
|
package/dist/lib.js
CHANGED
|
@@ -2424,7 +2424,8 @@ function isDirectComponent(name, components) {
|
|
|
2424
2424
|
}
|
|
2425
2425
|
|
|
2426
2426
|
// src/tools/capture.ts
|
|
2427
|
-
import { writeFile as writeFile5 } from "fs/promises";
|
|
2427
|
+
import { mkdir, writeFile as writeFile5 } from "fs/promises";
|
|
2428
|
+
import { dirname as dirname5, join as join3 } from "path";
|
|
2428
2429
|
import {
|
|
2429
2430
|
createDefaultRegistry as createDefaultRegistry2
|
|
2430
2431
|
} from "@genart-dev/core";
|
|
@@ -2529,8 +2530,9 @@ function generateSketchHtml(sketch, opts) {
|
|
|
2529
2530
|
}
|
|
2530
2531
|
return adapter.generateStandaloneHTML(effective);
|
|
2531
2532
|
}
|
|
2532
|
-
function
|
|
2533
|
-
|
|
2533
|
+
function deriveSnapshotPath(sketchPath, sketchId, seed) {
|
|
2534
|
+
const wsDir = dirname5(sketchPath);
|
|
2535
|
+
return join3(wsDir, "snapshots", `${sketchId}-${seed}-preview.png`);
|
|
2534
2536
|
}
|
|
2535
2537
|
async function captureScreenshot(state, input) {
|
|
2536
2538
|
state.requireWorkspace();
|
|
@@ -2563,11 +2565,12 @@ async function captureScreenshot(state, input) {
|
|
|
2563
2565
|
height,
|
|
2564
2566
|
inlineSize
|
|
2565
2567
|
});
|
|
2566
|
-
const
|
|
2568
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2569
|
+
const previewPath = deriveSnapshotPath(loaded.path, sketchId, effectiveSeed);
|
|
2567
2570
|
const metadata = await buildScreenshotMetadata(state, multi, {
|
|
2568
2571
|
target,
|
|
2569
2572
|
sketchId,
|
|
2570
|
-
seed:
|
|
2573
|
+
seed: effectiveSeed,
|
|
2571
2574
|
previewPath
|
|
2572
2575
|
});
|
|
2573
2576
|
const previewJpegBase64 = Buffer.from(multi.inlineJpeg).toString("base64");
|
|
@@ -2588,8 +2591,10 @@ async function buildScreenshotMetadata(state, multi, info) {
|
|
|
2588
2591
|
previewPath: info.previewPath
|
|
2589
2592
|
};
|
|
2590
2593
|
if (!state.remoteMode) {
|
|
2594
|
+
await mkdir(dirname5(info.previewPath), { recursive: true });
|
|
2591
2595
|
await writeFile5(info.previewPath, multi.previewPng);
|
|
2592
2596
|
metadata.savedPreviewTo = info.previewPath;
|
|
2597
|
+
metadata.previewWritten = true;
|
|
2593
2598
|
}
|
|
2594
2599
|
return metadata;
|
|
2595
2600
|
}
|
|
@@ -2618,11 +2623,12 @@ async function captureBatch(state, input) {
|
|
|
2618
2623
|
height,
|
|
2619
2624
|
inlineSize
|
|
2620
2625
|
});
|
|
2621
|
-
const
|
|
2626
|
+
const effectiveSeed = input.seed ?? sketch.state.seed;
|
|
2627
|
+
const previewPath = deriveSnapshotPath(loaded.path, id, effectiveSeed);
|
|
2622
2628
|
const itemMetadata = await buildScreenshotMetadata(state, multi, {
|
|
2623
2629
|
target: "sketch",
|
|
2624
2630
|
sketchId: id,
|
|
2625
|
-
seed:
|
|
2631
|
+
seed: effectiveSeed,
|
|
2626
2632
|
previewPath
|
|
2627
2633
|
});
|
|
2628
2634
|
items.push({
|
|
@@ -2982,7 +2988,7 @@ function gatherRelevantSkills(aspects) {
|
|
|
2982
2988
|
|
|
2983
2989
|
// src/tools/series.ts
|
|
2984
2990
|
import { writeFile as writeFile6 } from "fs/promises";
|
|
2985
|
-
import { basename as basename8, dirname as
|
|
2991
|
+
import { basename as basename8, dirname as dirname6, resolve as resolve2 } from "path";
|
|
2986
2992
|
import {
|
|
2987
2993
|
serializeGenart as serializeGenart4,
|
|
2988
2994
|
serializeWorkspace as serializeWorkspace3
|
|
@@ -3262,7 +3268,7 @@ async function promoteSketch(state, input) {
|
|
|
3262
3268
|
...input.agent ? { agent: input.agent } : {},
|
|
3263
3269
|
...input.model ? { model: input.model } : {}
|
|
3264
3270
|
};
|
|
3265
|
-
const sourceDir =
|
|
3271
|
+
const sourceDir = dirname6(source.path);
|
|
3266
3272
|
const newPath = resolve2(sourceDir, `${newId}.genart`);
|
|
3267
3273
|
const json = serializeGenart4(promotedDef);
|
|
3268
3274
|
if (!state.remoteMode) {
|
|
@@ -3332,8 +3338,8 @@ function countBy(items) {
|
|
|
3332
3338
|
}
|
|
3333
3339
|
|
|
3334
3340
|
// src/tools/reference.ts
|
|
3335
|
-
import { copyFile, mkdir, readFile as readFile4 } from "fs/promises";
|
|
3336
|
-
import { basename as basename9, dirname as
|
|
3341
|
+
import { copyFile, mkdir as mkdir2, readFile as readFile4 } from "fs/promises";
|
|
3342
|
+
import { basename as basename9, dirname as dirname7, extname, resolve as resolve3 } from "path";
|
|
3337
3343
|
import {
|
|
3338
3344
|
serializeGenart as serializeGenart5,
|
|
3339
3345
|
serializeWorkspace as serializeWorkspace4
|
|
@@ -3388,9 +3394,9 @@ async function addReference(state, input) {
|
|
|
3388
3394
|
`Invalid reference type: '${refType}'. Valid types: ${VALID_REFERENCE_TYPES.join(", ")}`
|
|
3389
3395
|
);
|
|
3390
3396
|
}
|
|
3391
|
-
const workspaceDir =
|
|
3397
|
+
const workspaceDir = dirname7(state.workspacePath);
|
|
3392
3398
|
const refsDir = resolve3(workspaceDir, "references");
|
|
3393
|
-
await
|
|
3399
|
+
await mkdir2(refsDir, { recursive: true });
|
|
3394
3400
|
const ext = extname(input.image);
|
|
3395
3401
|
const destFilename = `${id}${ext}`;
|
|
3396
3402
|
const destPath = resolve3(refsDir, destFilename);
|
|
@@ -3478,7 +3484,7 @@ async function addReference(state, input) {
|
|
|
3478
3484
|
async function analyzeReference(state, input) {
|
|
3479
3485
|
state.requireWorkspace();
|
|
3480
3486
|
const { ref, location } = findReference(state, input.referenceId, input.seriesId, input.sketchId);
|
|
3481
|
-
const workspaceDir =
|
|
3487
|
+
const workspaceDir = dirname7(state.workspacePath);
|
|
3482
3488
|
const imagePath = resolve3(workspaceDir, ref.path);
|
|
3483
3489
|
let previewJpegBase64;
|
|
3484
3490
|
try {
|
|
@@ -3638,7 +3644,7 @@ async function extractPalette(state, input) {
|
|
|
3638
3644
|
input.sketchId
|
|
3639
3645
|
);
|
|
3640
3646
|
const count = input.count ?? 6;
|
|
3641
|
-
const workspaceDir =
|
|
3647
|
+
const workspaceDir = dirname7(state.workspacePath);
|
|
3642
3648
|
const imagePath = resolve3(workspaceDir, ref.path);
|
|
3643
3649
|
let previewJpegBase64;
|
|
3644
3650
|
try {
|
|
@@ -3715,7 +3721,7 @@ function findReference(state, referenceId, seriesId, sketchId) {
|
|
|
3715
3721
|
// src/tools/export.ts
|
|
3716
3722
|
import { createWriteStream } from "fs";
|
|
3717
3723
|
import { stat as stat4, writeFile as writeFile8 } from "fs/promises";
|
|
3718
|
-
import { dirname as
|
|
3724
|
+
import { dirname as dirname8 } from "path";
|
|
3719
3725
|
import archiver from "archiver";
|
|
3720
3726
|
import {
|
|
3721
3727
|
createDefaultRegistry as createDefaultRegistry3,
|
|
@@ -3723,7 +3729,7 @@ import {
|
|
|
3723
3729
|
} from "@genart-dev/core";
|
|
3724
3730
|
var registry4 = createDefaultRegistry3();
|
|
3725
3731
|
async function validateOutputPath(outputPath) {
|
|
3726
|
-
const parentDir =
|
|
3732
|
+
const parentDir = dirname8(outputPath);
|
|
3727
3733
|
try {
|
|
3728
3734
|
const s = await stat4(parentDir);
|
|
3729
3735
|
if (!s.isDirectory()) {
|
|
@@ -4993,20 +4999,24 @@ async function initializePluginRegistry() {
|
|
|
4993
4999
|
await registry5.register(tracePlugin);
|
|
4994
5000
|
return registry5;
|
|
4995
5001
|
}
|
|
4996
|
-
function createServer(state) {
|
|
5002
|
+
function createServer(state, options) {
|
|
5003
|
+
const captureOnly = options?.captureOnly ?? false;
|
|
4997
5004
|
const server = new McpServer(
|
|
4998
5005
|
{
|
|
4999
|
-
name: "@genart/mcp-server",
|
|
5006
|
+
name: captureOnly ? "@genart/mcp-capture" : "@genart/mcp-server",
|
|
5000
5007
|
version: "0.4.0"
|
|
5001
5008
|
},
|
|
5002
5009
|
{
|
|
5003
5010
|
capabilities: {
|
|
5004
5011
|
tools: {},
|
|
5005
|
-
resources: {},
|
|
5006
|
-
prompts: {}
|
|
5012
|
+
...!captureOnly && { resources: {}, prompts: {} }
|
|
5007
5013
|
}
|
|
5008
5014
|
}
|
|
5009
5015
|
);
|
|
5016
|
+
if (captureOnly) {
|
|
5017
|
+
registerCaptureTools(server, state);
|
|
5018
|
+
return server;
|
|
5019
|
+
}
|
|
5010
5020
|
const registryReady = initializePluginRegistry().then((registry5) => {
|
|
5011
5021
|
state.pluginRegistry = registry5;
|
|
5012
5022
|
registerPluginMcpTools(server, registry5, state);
|
|
@@ -5023,7 +5033,9 @@ function createServer(state) {
|
|
|
5023
5033
|
registerSnapshotTools(server, state);
|
|
5024
5034
|
registerKnowledgeTools(server, state);
|
|
5025
5035
|
registerDesignTools(server, state);
|
|
5026
|
-
|
|
5036
|
+
if (!state.remoteMode) {
|
|
5037
|
+
registerCaptureTools(server, state);
|
|
5038
|
+
}
|
|
5027
5039
|
registerCritiqueTools(server, state);
|
|
5028
5040
|
registerSeriesTools(server, state);
|
|
5029
5041
|
registerReferenceTools(server, state);
|
|
@@ -5172,11 +5184,31 @@ function registerSketchTools(server, state) {
|
|
|
5172
5184
|
).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.'),
|
|
5173
5185
|
addToWorkspace: z2.string().optional().describe("Path to workspace to add sketch to after creation"),
|
|
5174
5186
|
agent: z2.string().optional().describe("Your CLI agent name (e.g. 'claude-code', 'codex-cli', 'gemini-cli', 'opencode', 'kiro')"),
|
|
5175
|
-
model: z2.string().optional().describe("Your AI model identifier (e.g. 'claude-opus-4-6', 'gpt-4o', 'gemini-2.5-pro')")
|
|
5187
|
+
model: z2.string().optional().describe("Your AI model identifier (e.g. 'claude-opus-4-6', 'gpt-4o', 'gemini-2.5-pro')"),
|
|
5188
|
+
capture: z2.boolean().optional().describe("When true, automatically capture a screenshot after creation and return it inline (avoids a separate capture_screenshot call)")
|
|
5176
5189
|
},
|
|
5177
5190
|
async (args) => {
|
|
5178
5191
|
try {
|
|
5179
5192
|
const result = await createSketch(state, args);
|
|
5193
|
+
if (args.capture && !state.remoteMode) {
|
|
5194
|
+
try {
|
|
5195
|
+
const captureResult = await captureScreenshot(state, {
|
|
5196
|
+
target: "sketch",
|
|
5197
|
+
sketchId: args.id
|
|
5198
|
+
});
|
|
5199
|
+
return {
|
|
5200
|
+
content: [
|
|
5201
|
+
{ type: "text", text: JSON.stringify({ ...result, capture: captureResult.metadata }, null, 2) },
|
|
5202
|
+
{ type: "image", data: captureResult.previewJpegBase64, mimeType: "image/jpeg" }
|
|
5203
|
+
]
|
|
5204
|
+
};
|
|
5205
|
+
} catch (captureErr) {
|
|
5206
|
+
return jsonResult({
|
|
5207
|
+
...result,
|
|
5208
|
+
captureError: captureErr instanceof Error ? captureErr.message : String(captureErr)
|
|
5209
|
+
});
|
|
5210
|
+
}
|
|
5211
|
+
}
|
|
5180
5212
|
return jsonResult(result);
|
|
5181
5213
|
} catch (e) {
|
|
5182
5214
|
return toolError(e instanceof Error ? e.message : String(e));
|
|
@@ -5733,7 +5765,7 @@ function registerSnapshotTools(server, state) {
|
|
|
5733
5765
|
function registerCaptureTools(server, state) {
|
|
5734
5766
|
server.tool(
|
|
5735
5767
|
"capture_screenshot",
|
|
5736
|
-
"Capture a screenshot of a sketch. Returns metadata as text + a small inline JPEG image for visual review. In
|
|
5768
|
+
"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.",
|
|
5737
5769
|
{
|
|
5738
5770
|
target: z2.enum(["selected", "sketch"]).optional().describe("What to capture (default: selected)"),
|
|
5739
5771
|
sketchId: z2.string().optional().describe("Required when target is 'sketch'"),
|
|
@@ -6396,7 +6428,7 @@ function registerKnowledgeTools(server, state) {
|
|
|
6396
6428
|
// src/state.ts
|
|
6397
6429
|
import { EventEmitter } from "events";
|
|
6398
6430
|
import { readFile as readFile5 } from "fs/promises";
|
|
6399
|
-
import { dirname as
|
|
6431
|
+
import { dirname as dirname9, isAbsolute, resolve as resolve4 } from "path";
|
|
6400
6432
|
|
|
6401
6433
|
// src/sidecar.ts
|
|
6402
6434
|
function isSidecarMode() {
|
|
@@ -6490,7 +6522,7 @@ var EditorState = class extends EventEmitter {
|
|
|
6490
6522
|
}
|
|
6491
6523
|
throw new Error("No workspace is currently open");
|
|
6492
6524
|
}
|
|
6493
|
-
const resolved = resolve4(
|
|
6525
|
+
const resolved = resolve4(dirname9(this.workspacePath), file);
|
|
6494
6526
|
if (this.basePath && !resolved.startsWith(this.basePath)) {
|
|
6495
6527
|
throw new Error(`Path escapes sandbox: ${resolved}`);
|
|
6496
6528
|
}
|