@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as startServer } from "./src-BrLbwFKO.mjs";
2
+ import { n as startServer } from "./src-BB93rq2Q.mjs";
3
3
  //#region src/cli.ts
4
4
  /**
5
5
  * Musea MCP Server CLI.
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as startServer, t as createMuseaServer } from "./src-BrLbwFKO.mjs";
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
- if (!componentRelPath.endsWith(".vue")) throw new McpError(ErrorCode.InvalidParams, "componentPath must be a .vue file");
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.390.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.390.0",
45
+ "@vizejs/native": "0.404.8",
46
46
  "@vue/compiler-dom": "3.5.35",
47
47
  "typescript": "6.0.3"
48
48
  },