@vizejs/musea-mcp-server 0.390.0 → 0.404.8
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.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-BrLbwFKO.mjs → src-BB93rq2Q.mjs} +98 -37
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as startServer, t as createMuseaServer } from "./src-
|
|
1
|
+
import { n as startServer, t as createMuseaServer } from "./src-BB93rq2Q.mjs";
|
|
2
2
|
export { createMuseaServer, createMuseaServer as default, startServer };
|
|
@@ -19,6 +19,101 @@ function loadNative() {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
//#endregion
|
|
22
|
+
//#region src/vue-source-path.ts
|
|
23
|
+
/**
|
|
24
|
+
* Confine MCP component reads to real `.vue` files.
|
|
25
|
+
*
|
|
26
|
+
* Request paths that merely *end with* `.vue` are not enough: a planted
|
|
27
|
+
* `Evil.vue` → `.env` symlink would otherwise be read by generate/analyze
|
|
28
|
+
* and by art-declared component sources.
|
|
29
|
+
*/
|
|
30
|
+
function realpathNearest$2(targetPath) {
|
|
31
|
+
let current = path.resolve(targetPath);
|
|
32
|
+
const missingParts = [];
|
|
33
|
+
while (true) try {
|
|
34
|
+
const real = fs.realpathSync.native(current);
|
|
35
|
+
return missingParts.length > 0 ? path.join(real, ...missingParts.reverse()) : real;
|
|
36
|
+
} catch {
|
|
37
|
+
const parent = path.dirname(current);
|
|
38
|
+
if (parent === current) return path.resolve(targetPath);
|
|
39
|
+
missingParts.push(path.basename(current));
|
|
40
|
+
current = parent;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function isVueSourcePath(candidatePath) {
|
|
44
|
+
return realpathNearest$2(candidatePath).toLowerCase().endsWith(".vue");
|
|
45
|
+
}
|
|
46
|
+
function assertVueSourcePath(candidatePath, label = "path") {
|
|
47
|
+
if (!isVueSourcePath(candidatePath)) throw new McpError(ErrorCode.InvalidParams, `${label} must be a .vue file`);
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/component-source-descriptor.ts
|
|
51
|
+
function realpathNearest$1(targetPath) {
|
|
52
|
+
let current = path.resolve(targetPath);
|
|
53
|
+
const missingParts = [];
|
|
54
|
+
while (true) try {
|
|
55
|
+
const real = fs.realpathSync.native(current);
|
|
56
|
+
return missingParts.length > 0 ? path.join(real, ...missingParts.reverse()) : real;
|
|
57
|
+
} catch {
|
|
58
|
+
const parent = path.dirname(current);
|
|
59
|
+
if (parent === current) return path.resolve(targetPath);
|
|
60
|
+
missingParts.push(path.basename(current));
|
|
61
|
+
current = parent;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function isProjectPath$1(projectRoot, candidatePath) {
|
|
65
|
+
const root = realpathNearest$1(projectRoot);
|
|
66
|
+
const candidate = realpathNearest$1(candidatePath);
|
|
67
|
+
const relativePath = path.relative(root, candidate);
|
|
68
|
+
return relativePath === "" || !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
|
|
69
|
+
}
|
|
70
|
+
function toProjectPath$1(projectRoot, absolutePath) {
|
|
71
|
+
const root = realpathNearest$1(projectRoot);
|
|
72
|
+
const resolved = realpathNearest$1(absolutePath);
|
|
73
|
+
const relativePath = path.relative(root, resolved);
|
|
74
|
+
return isProjectPath$1(root, resolved) ? relativePath || "." : resolved;
|
|
75
|
+
}
|
|
76
|
+
function resolveComponentSourcePath(artAbsolutePath, componentReference) {
|
|
77
|
+
if (!componentReference) return null;
|
|
78
|
+
if (path.isAbsolute(componentReference)) return componentReference;
|
|
79
|
+
return path.resolve(path.dirname(artAbsolutePath), componentReference);
|
|
80
|
+
}
|
|
81
|
+
async function getComponentSourceDescriptor(ctx, resolved) {
|
|
82
|
+
const componentPath = resolveComponentSourcePath(resolved.absolutePath, resolved.info.component);
|
|
83
|
+
if (!componentPath) return {
|
|
84
|
+
reference: resolved.info.component,
|
|
85
|
+
exists: false,
|
|
86
|
+
error: "This art file does not declare a component source."
|
|
87
|
+
};
|
|
88
|
+
if (!isProjectPath$1(ctx.projectRoot, componentPath)) return {
|
|
89
|
+
reference: resolved.info.component,
|
|
90
|
+
exists: false,
|
|
91
|
+
error: "Component source is outside the project root."
|
|
92
|
+
};
|
|
93
|
+
if (!isVueSourcePath(componentPath)) return {
|
|
94
|
+
reference: resolved.info.component,
|
|
95
|
+
exists: false,
|
|
96
|
+
error: "Component source must be a .vue file."
|
|
97
|
+
};
|
|
98
|
+
try {
|
|
99
|
+
await fs.promises.access(componentPath, fs.constants.R_OK);
|
|
100
|
+
return {
|
|
101
|
+
reference: resolved.info.component,
|
|
102
|
+
absolutePath: componentPath,
|
|
103
|
+
path: toProjectPath$1(ctx.projectRoot, componentPath),
|
|
104
|
+
exists: true
|
|
105
|
+
};
|
|
106
|
+
} catch {
|
|
107
|
+
return {
|
|
108
|
+
reference: resolved.info.component,
|
|
109
|
+
absolutePath: componentPath,
|
|
110
|
+
path: toProjectPath$1(ctx.projectRoot, componentPath),
|
|
111
|
+
exists: false,
|
|
112
|
+
error: `Component source not found: ${toProjectPath$1(ctx.projectRoot, componentPath)}`
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
22
117
|
//#region src/markdown-template.ts
|
|
23
118
|
const SELF_TAG_NAME = "Self";
|
|
24
119
|
const TEMPLATE_FENCE_LANGUAGES = new Set([
|
|
@@ -352,41 +447,6 @@ async function resolveArtReference(ctx, args) {
|
|
|
352
447
|
alternatives: buildAlternatives(results)
|
|
353
448
|
};
|
|
354
449
|
}
|
|
355
|
-
function resolveComponentSourcePath(artAbsolutePath, componentReference) {
|
|
356
|
-
if (!componentReference) return null;
|
|
357
|
-
if (path.isAbsolute(componentReference)) return componentReference;
|
|
358
|
-
return path.resolve(path.dirname(artAbsolutePath), componentReference);
|
|
359
|
-
}
|
|
360
|
-
async function getComponentSourceDescriptor(ctx, resolved) {
|
|
361
|
-
const componentPath = resolveComponentSourcePath(resolved.absolutePath, resolved.info.component);
|
|
362
|
-
if (!componentPath) return {
|
|
363
|
-
reference: resolved.info.component,
|
|
364
|
-
exists: false,
|
|
365
|
-
error: "This art file does not declare a component source."
|
|
366
|
-
};
|
|
367
|
-
if (!isProjectPath(ctx.projectRoot, componentPath)) return {
|
|
368
|
-
reference: resolved.info.component,
|
|
369
|
-
exists: false,
|
|
370
|
-
error: "Component source is outside the project root."
|
|
371
|
-
};
|
|
372
|
-
try {
|
|
373
|
-
await fs.promises.access(componentPath, fs.constants.R_OK);
|
|
374
|
-
return {
|
|
375
|
-
reference: resolved.info.component,
|
|
376
|
-
absolutePath: componentPath,
|
|
377
|
-
path: toProjectPath(ctx.projectRoot, componentPath),
|
|
378
|
-
exists: true
|
|
379
|
-
};
|
|
380
|
-
} catch {
|
|
381
|
-
return {
|
|
382
|
-
reference: resolved.info.component,
|
|
383
|
-
absolutePath: componentPath,
|
|
384
|
-
path: toProjectPath(ctx.projectRoot, componentPath),
|
|
385
|
-
exists: false,
|
|
386
|
-
error: `Component source not found: ${toProjectPath(ctx.projectRoot, componentPath)}`
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
450
|
function normalizeDefaultValue(value) {
|
|
391
451
|
if (value === "true") return true;
|
|
392
452
|
if (value === "false") return false;
|
|
@@ -1121,6 +1181,7 @@ async function handleAnalyzeComponent(ctx, binding, args) {
|
|
|
1121
1181
|
if (directPath?.endsWith(".vue") && !directPath.endsWith(".art.vue")) {
|
|
1122
1182
|
if (!binding.analyzeSfc) throw new McpError(ErrorCode.InternalError, "analyzeSfc not available in native binding");
|
|
1123
1183
|
const absolutePath = resolveProjectPath(ctx.projectRoot, directPath, "path");
|
|
1184
|
+
assertVueSourcePath(absolutePath, "path");
|
|
1124
1185
|
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
1125
1186
|
const analysis = binding.analyzeSfc(source, { filename: absolutePath });
|
|
1126
1187
|
return { content: [{
|
|
@@ -1400,10 +1461,10 @@ function normalizeCategories(categories) {
|
|
|
1400
1461
|
async function handleGenerateVariants(ctx, binding, args) {
|
|
1401
1462
|
const componentRelPath = args?.componentPath;
|
|
1402
1463
|
if (!componentRelPath) throw new McpError(ErrorCode.InvalidParams, "componentPath is required");
|
|
1403
|
-
|
|
1464
|
+
const absolutePath = resolveProjectPath(ctx.projectRoot, componentRelPath, "componentPath");
|
|
1465
|
+
assertVueSourcePath(absolutePath, "componentPath");
|
|
1404
1466
|
if (!binding.analyzeSfc) throw new McpError(ErrorCode.InternalError, "analyzeSfc not available in native binding");
|
|
1405
1467
|
if (!binding.generateVariants) throw new McpError(ErrorCode.InternalError, "generateVariants not available in native binding");
|
|
1406
|
-
const absolutePath = resolveProjectPath(ctx.projectRoot, componentRelPath, "componentPath");
|
|
1407
1468
|
const source = await fs.promises.readFile(absolutePath, "utf-8");
|
|
1408
1469
|
const props = binding.analyzeSfc(source, { filename: absolutePath }).props.map((prop) => ({
|
|
1409
1470
|
name: prop.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/musea-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.404.8",
|
|
4
4
|
"description": "MCP server for building Vue.js design systems - component analysis, documentation, variant generation, and design tokens",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
45
|
-
"@vizejs/native": "0.
|
|
45
|
+
"@vizejs/native": "0.404.8",
|
|
46
46
|
"@vue/compiler-dom": "3.5.35",
|
|
47
47
|
"typescript": "6.0.3"
|
|
48
48
|
},
|