@vizejs/musea-mcp-server 0.13.0 → 0.14.0
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/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-DNZL-15O.js → src-BY8aIu75.js} +251 -231
- package/package.json +2 -2
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -244,6 +244,135 @@ const toolDefinitions = [
|
|
|
244
244
|
}
|
|
245
245
|
];
|
|
246
246
|
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/tools/handler/analysis.ts
|
|
249
|
+
async function handleAnalyzeComponent(ctx, binding, args) {
|
|
250
|
+
const vuePath = args?.path;
|
|
251
|
+
if (!vuePath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
252
|
+
if (!binding.analyzeSfc) throw new McpError(ErrorCode.InternalError, "analyzeSfc not available in native binding");
|
|
253
|
+
const absolutePath = path.resolve(ctx.projectRoot, vuePath);
|
|
254
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
255
|
+
const analysis = binding.analyzeSfc(source, { filename: absolutePath });
|
|
256
|
+
return { content: [{
|
|
257
|
+
type: "text",
|
|
258
|
+
text: JSON.stringify({
|
|
259
|
+
props: analysis.props.map((p) => ({
|
|
260
|
+
name: p.name,
|
|
261
|
+
type: p.type,
|
|
262
|
+
required: p.required,
|
|
263
|
+
defaultValue: p.default_value
|
|
264
|
+
})),
|
|
265
|
+
emits: analysis.emits
|
|
266
|
+
}, null, 2)
|
|
267
|
+
}] };
|
|
268
|
+
}
|
|
269
|
+
async function handleGetPalette(ctx, binding, args) {
|
|
270
|
+
const artPath = args?.path;
|
|
271
|
+
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
272
|
+
if (!binding.generateArtPalette) throw new McpError(ErrorCode.InternalError, "generateArtPalette not available in native binding");
|
|
273
|
+
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
274
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
275
|
+
const palette = binding.generateArtPalette(source, { filename: absolutePath });
|
|
276
|
+
return { content: [{
|
|
277
|
+
type: "text",
|
|
278
|
+
text: JSON.stringify({
|
|
279
|
+
title: palette.title,
|
|
280
|
+
controls: palette.controls.map((c) => ({
|
|
281
|
+
name: c.name,
|
|
282
|
+
control: c.control,
|
|
283
|
+
defaultValue: c.default_value,
|
|
284
|
+
description: c.description,
|
|
285
|
+
required: c.required,
|
|
286
|
+
options: c.options,
|
|
287
|
+
range: c.range,
|
|
288
|
+
group: c.group
|
|
289
|
+
})),
|
|
290
|
+
groups: palette.groups,
|
|
291
|
+
json: palette.json,
|
|
292
|
+
typescript: palette.typescript
|
|
293
|
+
}, null, 2)
|
|
294
|
+
}] };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/tools/handler/registry.ts
|
|
299
|
+
async function handleListComponents(ctx, args) {
|
|
300
|
+
const arts = await ctx.scanArtFiles();
|
|
301
|
+
let results = Array.from(arts.values());
|
|
302
|
+
if (args?.category) results = results.filter((a) => a.category?.toLowerCase() === args.category.toLowerCase());
|
|
303
|
+
if (args?.tag) results = results.filter((a) => a.tags.some((t) => t.toLowerCase() === args.tag.toLowerCase()));
|
|
304
|
+
return { content: [{
|
|
305
|
+
type: "text",
|
|
306
|
+
text: JSON.stringify(results.map((r) => ({
|
|
307
|
+
path: path.relative(ctx.projectRoot, r.path),
|
|
308
|
+
title: r.title,
|
|
309
|
+
description: r.description,
|
|
310
|
+
component: r.component,
|
|
311
|
+
category: r.category,
|
|
312
|
+
tags: r.tags,
|
|
313
|
+
variantCount: r.variantCount
|
|
314
|
+
})), null, 2)
|
|
315
|
+
}] };
|
|
316
|
+
}
|
|
317
|
+
async function handleGetComponent(ctx, binding, args) {
|
|
318
|
+
const artPath = args?.path;
|
|
319
|
+
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
320
|
+
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
321
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
322
|
+
const parsed = binding.parseArt(source, { filename: absolutePath });
|
|
323
|
+
return { content: [{
|
|
324
|
+
type: "text",
|
|
325
|
+
text: JSON.stringify({
|
|
326
|
+
metadata: parsed.metadata,
|
|
327
|
+
variants: parsed.variants.map((v) => ({
|
|
328
|
+
name: v.name,
|
|
329
|
+
template: v.template,
|
|
330
|
+
isDefault: v.is_default,
|
|
331
|
+
skipVrt: v.skip_vrt
|
|
332
|
+
})),
|
|
333
|
+
hasScriptSetup: parsed.has_script_setup,
|
|
334
|
+
hasScript: parsed.has_script,
|
|
335
|
+
styleCount: parsed.style_count
|
|
336
|
+
}, null, 2)
|
|
337
|
+
}] };
|
|
338
|
+
}
|
|
339
|
+
async function handleGetVariant(ctx, binding, args) {
|
|
340
|
+
const artPath = args?.path;
|
|
341
|
+
const variantName = args?.variant;
|
|
342
|
+
if (!artPath || !variantName) throw new McpError(ErrorCode.InvalidParams, "path and variant are required");
|
|
343
|
+
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
344
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
345
|
+
const parsed = binding.parseArt(source, { filename: absolutePath });
|
|
346
|
+
const variant = parsed.variants.find((v) => v.name.toLowerCase() === variantName.toLowerCase());
|
|
347
|
+
if (!variant) throw new McpError(ErrorCode.InvalidParams, `Variant "${variantName}" not found`);
|
|
348
|
+
return { content: [{
|
|
349
|
+
type: "text",
|
|
350
|
+
text: JSON.stringify({
|
|
351
|
+
name: variant.name,
|
|
352
|
+
template: variant.template,
|
|
353
|
+
isDefault: variant.is_default,
|
|
354
|
+
skipVrt: variant.skip_vrt
|
|
355
|
+
}, null, 2)
|
|
356
|
+
}] };
|
|
357
|
+
}
|
|
358
|
+
async function handleSearchComponents(ctx, args) {
|
|
359
|
+
const query = (args?.query)?.toLowerCase();
|
|
360
|
+
if (!query) throw new McpError(ErrorCode.InvalidParams, "query is required");
|
|
361
|
+
const arts = await ctx.scanArtFiles();
|
|
362
|
+
const results = Array.from(arts.values()).filter((a) => a.title.toLowerCase().includes(query) || a.description?.toLowerCase().includes(query) || a.tags.some((t) => t.toLowerCase().includes(query)));
|
|
363
|
+
return { content: [{
|
|
364
|
+
type: "text",
|
|
365
|
+
text: JSON.stringify(results.map((r) => ({
|
|
366
|
+
path: path.relative(ctx.projectRoot, r.path),
|
|
367
|
+
title: r.title,
|
|
368
|
+
description: r.description,
|
|
369
|
+
component: r.component,
|
|
370
|
+
category: r.category,
|
|
371
|
+
tags: r.tags
|
|
372
|
+
})), null, 2)
|
|
373
|
+
}] };
|
|
374
|
+
}
|
|
375
|
+
|
|
247
376
|
//#endregion
|
|
248
377
|
//#region src/tokens.ts
|
|
249
378
|
async function parseTokensFromPath(tokensPath) {
|
|
@@ -336,240 +465,131 @@ function formatCategoryName(name) {
|
|
|
336
465
|
}
|
|
337
466
|
|
|
338
467
|
//#endregion
|
|
339
|
-
//#region src/tools/handler.ts
|
|
468
|
+
//#region src/tools/handler/generation.ts
|
|
469
|
+
async function handleGenerateVariants(ctx, binding, args) {
|
|
470
|
+
const componentRelPath = args?.componentPath;
|
|
471
|
+
if (!componentRelPath) throw new McpError(ErrorCode.InvalidParams, "componentPath is required");
|
|
472
|
+
if (!binding.analyzeSfc) throw new McpError(ErrorCode.InternalError, "analyzeSfc not available in native binding");
|
|
473
|
+
if (!binding.generateVariants) throw new McpError(ErrorCode.InternalError, "generateVariants not available in native binding");
|
|
474
|
+
const absolutePath = path.resolve(ctx.projectRoot, componentRelPath);
|
|
475
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
476
|
+
const analysis = binding.analyzeSfc(source, { filename: absolutePath });
|
|
477
|
+
const props = analysis.props.map((p) => ({
|
|
478
|
+
name: p.name,
|
|
479
|
+
prop_type: p.type,
|
|
480
|
+
required: p.required,
|
|
481
|
+
default_value: p.default_value
|
|
482
|
+
}));
|
|
483
|
+
const relPath = `./${path.basename(absolutePath)}`;
|
|
484
|
+
const result = binding.generateVariants(relPath, props, {
|
|
485
|
+
max_variants: args?.maxVariants,
|
|
486
|
+
include_default: args?.includeDefault,
|
|
487
|
+
include_boolean_toggles: args?.includeBooleanToggles,
|
|
488
|
+
include_enum_variants: args?.includeEnumVariants
|
|
489
|
+
});
|
|
490
|
+
return { content: [{
|
|
491
|
+
type: "text",
|
|
492
|
+
text: JSON.stringify({
|
|
493
|
+
componentName: result.component_name,
|
|
494
|
+
artFileContent: result.art_file_content,
|
|
495
|
+
variants: result.variants.map((v) => ({
|
|
496
|
+
name: v.name,
|
|
497
|
+
isDefault: v.is_default,
|
|
498
|
+
props: v.props,
|
|
499
|
+
description: v.description
|
|
500
|
+
}))
|
|
501
|
+
}, null, 2)
|
|
502
|
+
}] };
|
|
503
|
+
}
|
|
504
|
+
async function handleGenerateCsf(ctx, binding, args) {
|
|
505
|
+
const artPath = args?.path;
|
|
506
|
+
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
507
|
+
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
508
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
509
|
+
const csf = binding.artToCsf(source, { filename: absolutePath });
|
|
510
|
+
return { content: [{
|
|
511
|
+
type: "text",
|
|
512
|
+
text: csf.code
|
|
513
|
+
}] };
|
|
514
|
+
}
|
|
515
|
+
async function handleGenerateDocs(ctx, binding, args) {
|
|
516
|
+
const artPath = args?.path;
|
|
517
|
+
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
518
|
+
if (!binding.generateArtDoc) throw new McpError(ErrorCode.InternalError, "generateArtDoc not available in native binding");
|
|
519
|
+
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
520
|
+
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
521
|
+
const doc = binding.generateArtDoc(source, { filename: absolutePath }, {
|
|
522
|
+
include_source: args?.includeSource,
|
|
523
|
+
include_templates: args?.includeTemplates,
|
|
524
|
+
include_metadata: true
|
|
525
|
+
});
|
|
526
|
+
return { content: [{
|
|
527
|
+
type: "text",
|
|
528
|
+
text: JSON.stringify({
|
|
529
|
+
markdown: doc.markdown,
|
|
530
|
+
title: doc.title,
|
|
531
|
+
category: doc.category,
|
|
532
|
+
variantCount: doc.variant_count
|
|
533
|
+
}, null, 2)
|
|
534
|
+
}] };
|
|
535
|
+
}
|
|
536
|
+
async function handleGenerateCatalog(ctx, binding, args) {
|
|
537
|
+
if (!binding.generateArtCatalog) throw new McpError(ErrorCode.InternalError, "generateArtCatalog not available in native binding");
|
|
538
|
+
const arts = await ctx.scanArtFiles();
|
|
539
|
+
const sources = [];
|
|
540
|
+
for (const [filePath] of arts) {
|
|
541
|
+
const source = await fs.promises.readFile(filePath, "utf-8");
|
|
542
|
+
sources.push(source);
|
|
543
|
+
}
|
|
544
|
+
const catalog = binding.generateArtCatalog(sources, {
|
|
545
|
+
include_source: args?.includeSource,
|
|
546
|
+
include_templates: args?.includeTemplates,
|
|
547
|
+
include_metadata: true
|
|
548
|
+
});
|
|
549
|
+
return { content: [{
|
|
550
|
+
type: "text",
|
|
551
|
+
text: JSON.stringify({
|
|
552
|
+
markdown: catalog.markdown,
|
|
553
|
+
componentCount: catalog.component_count,
|
|
554
|
+
categories: catalog.categories,
|
|
555
|
+
tags: catalog.tags
|
|
556
|
+
}, null, 2)
|
|
557
|
+
}] };
|
|
558
|
+
}
|
|
559
|
+
async function handleGetTokens(ctx, args) {
|
|
560
|
+
const inputPath = args?.tokensPath;
|
|
561
|
+
const format = args?.format ?? "json";
|
|
562
|
+
let resolvedPath;
|
|
563
|
+
if (inputPath) resolvedPath = path.resolve(ctx.projectRoot, inputPath);
|
|
564
|
+
else resolvedPath = await ctx.resolveTokensPath();
|
|
565
|
+
if (!resolvedPath) throw new McpError(ErrorCode.InvalidParams, "No tokens path provided and none auto-detected. Looked for: tokens/, design-tokens/, style-dictionary/ directories.");
|
|
566
|
+
const categories = await parseTokensFromPath(resolvedPath);
|
|
567
|
+
if (format === "markdown") return { content: [{
|
|
568
|
+
type: "text",
|
|
569
|
+
text: generateTokensMarkdown(categories)
|
|
570
|
+
}] };
|
|
571
|
+
return { content: [{
|
|
572
|
+
type: "text",
|
|
573
|
+
text: JSON.stringify({ categories }, null, 2)
|
|
574
|
+
}] };
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region src/tools/handler/index.ts
|
|
340
579
|
async function handleToolCall(ctx, name, args) {
|
|
341
580
|
const binding = ctx.loadNative();
|
|
342
581
|
switch (name) {
|
|
343
|
-
case "analyze_component":
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
name: p.name,
|
|
355
|
-
type: p.type,
|
|
356
|
-
required: p.required,
|
|
357
|
-
defaultValue: p.default_value
|
|
358
|
-
})),
|
|
359
|
-
emits: analysis.emits
|
|
360
|
-
}, null, 2)
|
|
361
|
-
}] };
|
|
362
|
-
}
|
|
363
|
-
case "get_palette": {
|
|
364
|
-
const artPath = args?.path;
|
|
365
|
-
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
366
|
-
if (!binding.generateArtPalette) throw new McpError(ErrorCode.InternalError, "generateArtPalette not available in native binding");
|
|
367
|
-
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
368
|
-
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
369
|
-
const palette = binding.generateArtPalette(source, { filename: absolutePath });
|
|
370
|
-
return { content: [{
|
|
371
|
-
type: "text",
|
|
372
|
-
text: JSON.stringify({
|
|
373
|
-
title: palette.title,
|
|
374
|
-
controls: palette.controls.map((c) => ({
|
|
375
|
-
name: c.name,
|
|
376
|
-
control: c.control,
|
|
377
|
-
defaultValue: c.default_value,
|
|
378
|
-
description: c.description,
|
|
379
|
-
required: c.required,
|
|
380
|
-
options: c.options,
|
|
381
|
-
range: c.range,
|
|
382
|
-
group: c.group
|
|
383
|
-
})),
|
|
384
|
-
groups: palette.groups,
|
|
385
|
-
json: palette.json,
|
|
386
|
-
typescript: palette.typescript
|
|
387
|
-
}, null, 2)
|
|
388
|
-
}] };
|
|
389
|
-
}
|
|
390
|
-
case "list_components": {
|
|
391
|
-
const arts = await ctx.scanArtFiles();
|
|
392
|
-
let results = Array.from(arts.values());
|
|
393
|
-
if (args?.category) results = results.filter((a) => a.category?.toLowerCase() === args.category.toLowerCase());
|
|
394
|
-
if (args?.tag) results = results.filter((a) => a.tags.some((t) => t.toLowerCase() === args.tag.toLowerCase()));
|
|
395
|
-
return { content: [{
|
|
396
|
-
type: "text",
|
|
397
|
-
text: JSON.stringify(results.map((r) => ({
|
|
398
|
-
path: path.relative(ctx.projectRoot, r.path),
|
|
399
|
-
title: r.title,
|
|
400
|
-
description: r.description,
|
|
401
|
-
component: r.component,
|
|
402
|
-
category: r.category,
|
|
403
|
-
tags: r.tags,
|
|
404
|
-
variantCount: r.variantCount
|
|
405
|
-
})), null, 2)
|
|
406
|
-
}] };
|
|
407
|
-
}
|
|
408
|
-
case "get_component": {
|
|
409
|
-
const artPath = args?.path;
|
|
410
|
-
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
411
|
-
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
412
|
-
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
413
|
-
const parsed = binding.parseArt(source, { filename: absolutePath });
|
|
414
|
-
return { content: [{
|
|
415
|
-
type: "text",
|
|
416
|
-
text: JSON.stringify({
|
|
417
|
-
metadata: parsed.metadata,
|
|
418
|
-
variants: parsed.variants.map((v) => ({
|
|
419
|
-
name: v.name,
|
|
420
|
-
template: v.template,
|
|
421
|
-
isDefault: v.is_default,
|
|
422
|
-
skipVrt: v.skip_vrt
|
|
423
|
-
})),
|
|
424
|
-
hasScriptSetup: parsed.has_script_setup,
|
|
425
|
-
hasScript: parsed.has_script,
|
|
426
|
-
styleCount: parsed.style_count
|
|
427
|
-
}, null, 2)
|
|
428
|
-
}] };
|
|
429
|
-
}
|
|
430
|
-
case "get_variant": {
|
|
431
|
-
const artPath = args?.path;
|
|
432
|
-
const variantName = args?.variant;
|
|
433
|
-
if (!artPath || !variantName) throw new McpError(ErrorCode.InvalidParams, "path and variant are required");
|
|
434
|
-
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
435
|
-
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
436
|
-
const parsed = binding.parseArt(source, { filename: absolutePath });
|
|
437
|
-
const variant = parsed.variants.find((v) => v.name.toLowerCase() === variantName.toLowerCase());
|
|
438
|
-
if (!variant) throw new McpError(ErrorCode.InvalidParams, `Variant "${variantName}" not found`);
|
|
439
|
-
return { content: [{
|
|
440
|
-
type: "text",
|
|
441
|
-
text: JSON.stringify({
|
|
442
|
-
name: variant.name,
|
|
443
|
-
template: variant.template,
|
|
444
|
-
isDefault: variant.is_default,
|
|
445
|
-
skipVrt: variant.skip_vrt
|
|
446
|
-
}, null, 2)
|
|
447
|
-
}] };
|
|
448
|
-
}
|
|
449
|
-
case "search_components": {
|
|
450
|
-
const query = (args?.query)?.toLowerCase();
|
|
451
|
-
if (!query) throw new McpError(ErrorCode.InvalidParams, "query is required");
|
|
452
|
-
const arts = await ctx.scanArtFiles();
|
|
453
|
-
const results = Array.from(arts.values()).filter((a) => a.title.toLowerCase().includes(query) || a.description?.toLowerCase().includes(query) || a.tags.some((t) => t.toLowerCase().includes(query)));
|
|
454
|
-
return { content: [{
|
|
455
|
-
type: "text",
|
|
456
|
-
text: JSON.stringify(results.map((r) => ({
|
|
457
|
-
path: path.relative(ctx.projectRoot, r.path),
|
|
458
|
-
title: r.title,
|
|
459
|
-
description: r.description,
|
|
460
|
-
component: r.component,
|
|
461
|
-
category: r.category,
|
|
462
|
-
tags: r.tags
|
|
463
|
-
})), null, 2)
|
|
464
|
-
}] };
|
|
465
|
-
}
|
|
466
|
-
case "generate_variants": {
|
|
467
|
-
const componentRelPath = args?.componentPath;
|
|
468
|
-
if (!componentRelPath) throw new McpError(ErrorCode.InvalidParams, "componentPath is required");
|
|
469
|
-
if (!binding.analyzeSfc) throw new McpError(ErrorCode.InternalError, "analyzeSfc not available in native binding");
|
|
470
|
-
if (!binding.generateVariants) throw new McpError(ErrorCode.InternalError, "generateVariants not available in native binding");
|
|
471
|
-
const absolutePath = path.resolve(ctx.projectRoot, componentRelPath);
|
|
472
|
-
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
473
|
-
const analysis = binding.analyzeSfc(source, { filename: absolutePath });
|
|
474
|
-
const props = analysis.props.map((p) => ({
|
|
475
|
-
name: p.name,
|
|
476
|
-
prop_type: p.type,
|
|
477
|
-
required: p.required,
|
|
478
|
-
default_value: p.default_value
|
|
479
|
-
}));
|
|
480
|
-
const relPath = `./${path.basename(absolutePath)}`;
|
|
481
|
-
const result = binding.generateVariants(relPath, props, {
|
|
482
|
-
max_variants: args?.maxVariants,
|
|
483
|
-
include_default: args?.includeDefault,
|
|
484
|
-
include_boolean_toggles: args?.includeBooleanToggles,
|
|
485
|
-
include_enum_variants: args?.includeEnumVariants
|
|
486
|
-
});
|
|
487
|
-
return { content: [{
|
|
488
|
-
type: "text",
|
|
489
|
-
text: JSON.stringify({
|
|
490
|
-
componentName: result.component_name,
|
|
491
|
-
artFileContent: result.art_file_content,
|
|
492
|
-
variants: result.variants.map((v) => ({
|
|
493
|
-
name: v.name,
|
|
494
|
-
isDefault: v.is_default,
|
|
495
|
-
props: v.props,
|
|
496
|
-
description: v.description
|
|
497
|
-
}))
|
|
498
|
-
}, null, 2)
|
|
499
|
-
}] };
|
|
500
|
-
}
|
|
501
|
-
case "generate_csf": {
|
|
502
|
-
const artPath = args?.path;
|
|
503
|
-
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
504
|
-
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
505
|
-
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
506
|
-
const csf = binding.artToCsf(source, { filename: absolutePath });
|
|
507
|
-
return { content: [{
|
|
508
|
-
type: "text",
|
|
509
|
-
text: csf.code
|
|
510
|
-
}] };
|
|
511
|
-
}
|
|
512
|
-
case "generate_docs": {
|
|
513
|
-
const artPath = args?.path;
|
|
514
|
-
if (!artPath) throw new McpError(ErrorCode.InvalidParams, "path is required");
|
|
515
|
-
if (!binding.generateArtDoc) throw new McpError(ErrorCode.InternalError, "generateArtDoc not available in native binding");
|
|
516
|
-
const absolutePath = path.resolve(ctx.projectRoot, artPath);
|
|
517
|
-
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
518
|
-
const doc = binding.generateArtDoc(source, { filename: absolutePath }, {
|
|
519
|
-
include_source: args?.includeSource,
|
|
520
|
-
include_templates: args?.includeTemplates,
|
|
521
|
-
include_metadata: true
|
|
522
|
-
});
|
|
523
|
-
return { content: [{
|
|
524
|
-
type: "text",
|
|
525
|
-
text: JSON.stringify({
|
|
526
|
-
markdown: doc.markdown,
|
|
527
|
-
title: doc.title,
|
|
528
|
-
category: doc.category,
|
|
529
|
-
variantCount: doc.variant_count
|
|
530
|
-
}, null, 2)
|
|
531
|
-
}] };
|
|
532
|
-
}
|
|
533
|
-
case "generate_catalog": {
|
|
534
|
-
if (!binding.generateArtCatalog) throw new McpError(ErrorCode.InternalError, "generateArtCatalog not available in native binding");
|
|
535
|
-
const arts = await ctx.scanArtFiles();
|
|
536
|
-
const sources = [];
|
|
537
|
-
for (const [filePath] of arts) {
|
|
538
|
-
const source = await fs.promises.readFile(filePath, "utf-8");
|
|
539
|
-
sources.push(source);
|
|
540
|
-
}
|
|
541
|
-
const catalog = binding.generateArtCatalog(sources, {
|
|
542
|
-
include_source: args?.includeSource,
|
|
543
|
-
include_templates: args?.includeTemplates,
|
|
544
|
-
include_metadata: true
|
|
545
|
-
});
|
|
546
|
-
return { content: [{
|
|
547
|
-
type: "text",
|
|
548
|
-
text: JSON.stringify({
|
|
549
|
-
markdown: catalog.markdown,
|
|
550
|
-
componentCount: catalog.component_count,
|
|
551
|
-
categories: catalog.categories,
|
|
552
|
-
tags: catalog.tags
|
|
553
|
-
}, null, 2)
|
|
554
|
-
}] };
|
|
555
|
-
}
|
|
556
|
-
case "get_tokens": {
|
|
557
|
-
const inputPath = args?.tokensPath;
|
|
558
|
-
const format = args?.format ?? "json";
|
|
559
|
-
let resolvedPath;
|
|
560
|
-
if (inputPath) resolvedPath = path.resolve(ctx.projectRoot, inputPath);
|
|
561
|
-
else resolvedPath = await ctx.resolveTokensPath();
|
|
562
|
-
if (!resolvedPath) throw new McpError(ErrorCode.InvalidParams, "No tokens path provided and none auto-detected. Looked for: tokens/, design-tokens/, style-dictionary/ directories.");
|
|
563
|
-
const categories = await parseTokensFromPath(resolvedPath);
|
|
564
|
-
if (format === "markdown") return { content: [{
|
|
565
|
-
type: "text",
|
|
566
|
-
text: generateTokensMarkdown(categories)
|
|
567
|
-
}] };
|
|
568
|
-
return { content: [{
|
|
569
|
-
type: "text",
|
|
570
|
-
text: JSON.stringify({ categories }, null, 2)
|
|
571
|
-
}] };
|
|
572
|
-
}
|
|
582
|
+
case "analyze_component": return handleAnalyzeComponent(ctx, binding, args);
|
|
583
|
+
case "get_palette": return handleGetPalette(ctx, binding, args);
|
|
584
|
+
case "list_components": return handleListComponents(ctx, args);
|
|
585
|
+
case "get_component": return handleGetComponent(ctx, binding, args);
|
|
586
|
+
case "get_variant": return handleGetVariant(ctx, binding, args);
|
|
587
|
+
case "search_components": return handleSearchComponents(ctx, args);
|
|
588
|
+
case "generate_variants": return handleGenerateVariants(ctx, binding, args);
|
|
589
|
+
case "generate_csf": return handleGenerateCsf(ctx, binding, args);
|
|
590
|
+
case "generate_docs": return handleGenerateDocs(ctx, binding, args);
|
|
591
|
+
case "generate_catalog": return handleGenerateCatalog(ctx, binding, args);
|
|
592
|
+
case "get_tokens": return handleGetTokens(ctx, args);
|
|
573
593
|
default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
574
594
|
}
|
|
575
595
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/musea-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "MCP server for building Vue.js design systems - component analysis, documentation, variant generation, and design tokens",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
38
|
-
"@vizejs/native": "0.
|
|
38
|
+
"@vizejs/native": "0.14.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^22.14.0",
|