@axis-ds/mcp 1.4.1 → 1.4.2

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +153 -86
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -41,7 +41,7 @@ Claude Desktop 또는 기타 MCP 호환 클라이언트에서 설정:
41
41
  - 이름은 레지스트리 이름 그대로입니다. Agentic UI 는 `agentic-` 접두를 붙입니다(예: `agentic-run-progress`). 의존 항목(`utils` · `agentic-a11y-labels`)은 함께 설치됩니다.
42
42
  - `targetDir` 는 이미 있는 프로젝트 루트입니다(상대 경로는 서버의 현재 디렉터리 기준). `axis.config.json` 이 있으면 그 `componentsDir` · `agenticDir` 에, 없으면 `components/ui` · `components/agentic` 에 설치하고 그 사실을 알립니다. 프로젝트 밖으로 나가는 경로는 아무것도 쓰지 않고 실패합니다.
43
43
  - 내용이 다른 기존 파일은 덮어쓰지 않고 건너뛰며 응답 첫머리에 건너뛴 수를 적습니다. `overwrite: true` 일 때만 덮어씁니다.
44
- - 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다.
44
+ - 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다. lockfile 이 없으면 `package.json` 의 `packageManager` 를 봅니다(1.4.2 부터). `axis.apply_template` 의 「필요한 의존성」 · `axis.list_brands` · `axis.get_brand` 의 설치 안내도 1.4.2 부터 같은 방식으로 `targetDir` 의 매니저를 따릅니다(1.4.1 까지는 `pnpm` 고정).
45
45
 
46
46
  ## 토큰 도구
47
47
 
package/dist/index.js CHANGED
@@ -603,7 +603,7 @@ function createPinnedFetch(options = {}) {
603
603
  const judge = options.judge ?? blockedAddressReason;
604
604
  const send = options.request ?? httpsRequest;
605
605
  const maxBytes = options.maxBytes ?? PINNED_FETCH_MAX_BYTES;
606
- return (input, init) => new Promise((resolve5, reject) => {
606
+ return (input, init) => new Promise((resolve4, reject) => {
607
607
  let url;
608
608
  try {
609
609
  url = new URL(input);
@@ -644,7 +644,7 @@ function createPinnedFetch(options = {}) {
644
644
  if (failed) return;
645
645
  const body = Buffer.concat(chunks).toString("utf8");
646
646
  const status = res.statusCode ?? 0;
647
- resolve5({ ok: status >= 200 && status < 300, status, text: async () => body });
647
+ resolve4({ ok: status >= 200 && status < 300, status, text: async () => body });
648
648
  });
649
649
  }
650
650
  );
@@ -871,8 +871,16 @@ var RegistryClient = class {
871
871
  };
872
872
 
873
873
  // ../axis-registry-core/src/project.ts
874
- import { existsSync as existsSync2, readFileSync as readFileSync3, statSync } from "fs";
874
+ import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync, statSync } from "fs";
875
875
  import path3 from "path";
876
+ function resolveBaseDir(baseDirInput) {
877
+ const resolved = path3.resolve(baseDirInput);
878
+ try {
879
+ return realpathSync(resolved);
880
+ } catch {
881
+ return resolved;
882
+ }
883
+ }
876
884
  var LOCKFILE_COMMANDS = [
877
885
  ["pnpm-lock.yaml", "pnpm install"],
878
886
  ["yarn.lock", "yarn install"],
@@ -894,7 +902,7 @@ function isWorkspaceRootDir(dir) {
894
902
  return Array.isArray(ws) || isPlainObject(ws) && Array.isArray(ws.packages);
895
903
  }
896
904
  function findWorkspaceRoot(baseDirInput) {
897
- let dir = path3.resolve(baseDirInput);
905
+ let dir = resolveBaseDir(baseDirInput);
898
906
  for (; ; ) {
899
907
  if (isWorkspaceRootDir(dir)) return dir;
900
908
  if (existsSync2(path3.join(dir, ".git"))) return void 0;
@@ -903,17 +911,45 @@ function findWorkspaceRoot(baseDirInput) {
903
911
  dir = parent;
904
912
  }
905
913
  }
914
+ var PACKAGE_MANAGER_COMMANDS = {
915
+ pnpm: "pnpm install",
916
+ yarn: "yarn install",
917
+ npm: "npm install"
918
+ };
919
+ function packageManagerCommandAt(dir) {
920
+ let parsed;
921
+ try {
922
+ parsed = JSON.parse(readFileSync3(path3.join(dir, "package.json"), "utf8"));
923
+ } catch {
924
+ return void 0;
925
+ }
926
+ if (!isPlainObject(parsed) || typeof parsed.packageManager !== "string") return void 0;
927
+ const name = /^(pnpm|yarn|npm)@/.exec(parsed.packageManager.trim())?.[1];
928
+ return name !== void 0 ? PACKAGE_MANAGER_COMMANDS[name] : void 0;
929
+ }
906
930
  function detectInstallCommand(baseDirInput) {
907
- const baseDir = path3.resolve(baseDirInput);
931
+ const baseDir = resolveBaseDir(baseDirInput);
908
932
  const own = lockfileCommandAt(baseDir);
909
933
  if (own !== void 0) return own;
910
- const root = findWorkspaceRoot(baseDir);
911
- if (root !== void 0 && root !== baseDir) {
934
+ const found = findWorkspaceRoot(baseDir);
935
+ const root = found !== void 0 && found !== baseDir ? found : void 0;
936
+ if (root !== void 0) {
912
937
  const fromRoot = lockfileCommandAt(root);
913
938
  if (fromRoot !== void 0) return fromRoot;
914
939
  }
940
+ const ownManager = packageManagerCommandAt(baseDir);
941
+ if (ownManager !== void 0) return ownManager;
942
+ if (root !== void 0) {
943
+ const rootManager = packageManagerCommandAt(root);
944
+ if (rootManager !== void 0) return rootManager;
945
+ }
915
946
  return "pnpm install";
916
947
  }
948
+ function packageManagerOf(command) {
949
+ if (command.startsWith("yarn")) return "yarn";
950
+ if (command.startsWith("npm")) return "npm";
951
+ return "pnpm";
952
+ }
917
953
  function hasDependency(pkg, name) {
918
954
  for (const field of ["dependencies", "devDependencies"]) {
919
955
  const deps = pkg[field];
@@ -923,14 +959,52 @@ function hasDependency(pkg, name) {
923
959
  }
924
960
  return void 0;
925
961
  }
962
+ function workspaceRootPackage(baseDirInput) {
963
+ const baseDir = resolveBaseDir(baseDirInput);
964
+ const root = findWorkspaceRoot(baseDir);
965
+ if (root === void 0 || root === baseDir) return void 0;
966
+ try {
967
+ const parsed = JSON.parse(readFileSync3(path3.join(root, "package.json"), "utf8"));
968
+ return isPlainObject(parsed) ? parsed : void 0;
969
+ } catch {
970
+ return void 0;
971
+ }
972
+ }
973
+ function declaredDependency(baseDir, pkg, name, rootPkg) {
974
+ if (pkg === void 0) return void 0;
975
+ const own = hasDependency(pkg, name);
976
+ if (own !== void 0) return { range: own, source: "app" };
977
+ const root = rootPkg === void 0 ? workspaceRootPackage(baseDir) : rootPkg ?? void 0;
978
+ const fromRoot = root !== void 0 ? hasDependency(root, name) : void 0;
979
+ return fromRoot !== void 0 ? { range: fromRoot, source: "root" } : void 0;
980
+ }
926
981
  function isPlainObject(value) {
927
982
  return typeof value === "object" && value !== null && !Array.isArray(value);
928
983
  }
929
- function addCommandFor(installCommand, deps) {
984
+ function addCommandPrefix(installCommand, options = {}) {
985
+ const dev = options.dev ? " -D" : "";
986
+ switch (packageManagerOf(installCommand)) {
987
+ case "yarn":
988
+ return `yarn add${dev}`;
989
+ case "npm":
990
+ return `npm install${dev}`;
991
+ default:
992
+ return `pnpm add${dev}`;
993
+ }
994
+ }
995
+ function addCommandFor(installCommand, deps, options = {}) {
930
996
  const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
931
- if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
932
- if (installCommand.startsWith("npm")) return `npm install ${specs}`;
933
- return `pnpm add ${specs}`;
997
+ return `${addCommandPrefix(installCommand, options)} ${specs}`;
998
+ }
999
+ function workspaceRunCommand(installCommand, pkg, script) {
1000
+ switch (packageManagerOf(installCommand)) {
1001
+ case "yarn":
1002
+ return `yarn workspace ${pkg} ${script}`;
1003
+ case "npm":
1004
+ return `npm run ${script} -w ${pkg}`;
1005
+ default:
1006
+ return `pnpm --filter ${pkg} ${script}`;
1007
+ }
934
1008
  }
935
1009
  var GLOBAL_CSS_CANDIDATES = [
936
1010
  "app/globals.css",
@@ -969,7 +1043,7 @@ function exactVersionOf(version) {
969
1043
  return v;
970
1044
  }
971
1045
  function findInstalledPackage(baseDirInput, name) {
972
- let dir = path3.resolve(baseDirInput);
1046
+ let dir = resolveBaseDir(baseDirInput);
973
1047
  for (; ; ) {
974
1048
  const pkgDir = path3.join(dir, "node_modules", ...name.split("/"));
975
1049
  const file = path3.join(pkgDir, "package.json");
@@ -989,7 +1063,7 @@ function findInstalledPackage(baseDirInput, name) {
989
1063
  }
990
1064
  }
991
1065
  function isPnpProject(baseDirInput) {
992
- let dir = path3.resolve(baseDirInput);
1066
+ let dir = resolveBaseDir(baseDirInput);
993
1067
  for (; ; ) {
994
1068
  if (isFile(path3.join(dir, ".pnp.cjs")) || isFile(path3.join(dir, ".pnp.js"))) return true;
995
1069
  const parent = path3.dirname(dir);
@@ -1010,16 +1084,10 @@ function compareExactVersions(a, b) {
1010
1084
  }
1011
1085
 
1012
1086
  // ../axis-registry-core/src/template/tailwind-core.ts
1013
- import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync4, realpathSync } from "fs";
1087
+ import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync4, realpathSync as realpathSync2 } from "fs";
1014
1088
  import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "path";
1015
- function hasDependency2(pkg, name) {
1016
- for (const field of ["dependencies", "devDependencies"]) {
1017
- const deps = pkg[field];
1018
- if (typeof deps === "object" && deps !== null && name in deps) {
1019
- return String(deps[name]);
1020
- }
1021
- }
1022
- return void 0;
1089
+ function declaredRange(baseDir, pkg, name) {
1090
+ return declaredDependency(baseDir, pkg, name)?.range;
1023
1091
  }
1024
1092
  function isPlainObject2(value) {
1025
1093
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1092,8 +1160,8 @@ function majorFromVersion(version) {
1092
1160
  return Number(m[1]);
1093
1161
  }
1094
1162
  function detectTailwind(baseDirInput, pkg) {
1095
- const baseDir = resolve(baseDirInput);
1096
- const declared = pkg ? hasDependency2(pkg, "tailwindcss") : void 0;
1163
+ const baseDir = resolveBaseDir(baseDirInput);
1164
+ const declared = pkg ? declaredRange(baseDir, pkg, "tailwindcss") : void 0;
1097
1165
  const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
1098
1166
  const declaredMajor = bounds?.lower;
1099
1167
  const version = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, "tailwindcss")?.version;
@@ -1144,7 +1212,7 @@ function findTokensCssImport(css) {
1144
1212
  var TOKENS_CSS_JS_IMPORT = /(?:\bimport\s+|\bfrom\s+|\brequire\s*\(\s*)(["'])(@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)\1/;
1145
1213
  var AXIS_VARIABLE_DEFINITION = /(?<![\w-])--axis-[\w-]+\s*:/;
1146
1214
  function findLayoutTokensCssImport(baseDirInput) {
1147
- const baseDir = resolve(baseDirInput);
1215
+ const baseDir = resolveBaseDir(baseDirInput);
1148
1216
  for (const candidate of ROOT_LAYOUT_FILES) {
1149
1217
  const file = join2(baseDir, candidate);
1150
1218
  if (!existsSync3(file)) continue;
@@ -1160,7 +1228,7 @@ function findLayoutTokensCssImport(baseDirInput) {
1160
1228
  return void 0;
1161
1229
  }
1162
1230
  function checkGlobalsCss(baseDirInput) {
1163
- const baseDir = resolve(baseDirInput);
1231
+ const baseDir = resolveBaseDir(baseDirInput);
1164
1232
  for (const candidate of TAILWIND_CSS_CANDIDATES) {
1165
1233
  const file = join2(baseDir, candidate);
1166
1234
  if (!existsSync3(file)) continue;
@@ -1252,11 +1320,11 @@ function installedAxisVersion(baseDir, name) {
1252
1320
  }
1253
1321
  function axisPackagesBelowTailwind4(pkg, baseDirInput) {
1254
1322
  if (!pkg) return [];
1255
- const baseDir = baseDirInput !== void 0 ? resolve(baseDirInput) : void 0;
1323
+ const baseDir = baseDirInput !== void 0 ? resolveBaseDir(baseDirInput) : void 0;
1256
1324
  const out = [];
1257
1325
  const min = lowerOf(TAILWIND4_MIN_AXIS_VERSION);
1258
1326
  for (const name of TAILWIND4_AXIS_PACKAGES) {
1259
- const range = hasDependency2(pkg, name);
1327
+ const range = baseDir !== void 0 ? declaredRange(baseDir, pkg, name) : hasDependency(pkg, name);
1260
1328
  if (range === void 0 || range.trim().startsWith("workspace:")) continue;
1261
1329
  const installed = baseDir !== void 0 ? installedAxisVersion(baseDir, name) : void 0;
1262
1330
  const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
@@ -1396,7 +1464,7 @@ function isCommonJsConfig(file, source) {
1396
1464
  return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
1397
1465
  }
1398
1466
  function packageVersionGate(baseDirInput, pkg, name, min) {
1399
- const baseDir = resolve(baseDirInput);
1467
+ const baseDir = resolveBaseDir(baseDirInput);
1400
1468
  if (!isPnpProject(baseDir)) {
1401
1469
  const installed = findInstalledPackage(baseDir, name)?.version;
1402
1470
  if (installed !== void 0) {
@@ -1404,7 +1472,7 @@ function packageVersionGate(baseDirInput, pkg, name, min) {
1404
1472
  if (cmp !== void 0) return { status: cmp >= 0 ? "ok" : "below", source: "installed", value: installed };
1405
1473
  }
1406
1474
  }
1407
- const declared = pkg ? hasDependency2(pkg, name) : void 0;
1475
+ const declared = pkg ? declaredRange(baseDir, pkg, name) : void 0;
1408
1476
  if (declared !== void 0) {
1409
1477
  const atLeast = rangeLowerAtLeast(declared, min);
1410
1478
  if (atLeast !== void 0) return { status: atLeast ? "ok" : "below", source: "declared", value: declared };
@@ -1425,12 +1493,12 @@ function readPackageJson(baseDir) {
1425
1493
  return void 0;
1426
1494
  }
1427
1495
  }
1428
- function tailwind4Issues(css, pkg, versions) {
1496
+ function tailwind4Issues(css, pkg, versions, baseDir) {
1429
1497
  const issues = [];
1430
1498
  const hasEntry = hasTokensTailwind4Import(css);
1431
1499
  if (!hasEntry) issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${TOKENS_TAILWIND4_IMPORT_LINE}`);
1432
1500
  const missing = TAILWIND4_COMPONENT_PACKAGES.filter(
1433
- (name) => pkg !== void 0 && hasDependency2(pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
1501
+ (name) => declaredRange(baseDir, pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
1434
1502
  );
1435
1503
  if (missing.length > 0) {
1436
1504
  issues.push(`\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C(tailwind.css)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${missing.map(componentTailwindImportLine).join(" ")}`);
@@ -1450,7 +1518,7 @@ function tailwind4Issues(css, pkg, versions) {
1450
1518
  return issues;
1451
1519
  }
1452
1520
  function checkTailwindSetup(baseDirInput) {
1453
- const baseDir = resolve(baseDirInput);
1521
+ const baseDir = resolveBaseDir(baseDirInput);
1454
1522
  const pkg = readPackageJson(baseDir);
1455
1523
  const tailwind = detectTailwind(baseDir, pkg);
1456
1524
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
@@ -1467,7 +1535,7 @@ function checkTailwindSetup(baseDirInput) {
1467
1535
  };
1468
1536
  }
1469
1537
  const versions = axisPackagesBelowTailwind4(pkg, baseDir);
1470
- const issues = tailwind4Issues(css, pkg, versions);
1538
+ const issues = tailwind4Issues(css, pkg, versions, baseDir);
1471
1539
  if (issues.length > 0) {
1472
1540
  return {
1473
1541
  name: "tailwind.config",
@@ -1606,7 +1674,7 @@ function realpathPosix(p) {
1606
1674
  const tail = [];
1607
1675
  for (let i = 0; i < 64; i++) {
1608
1676
  try {
1609
- return [realpathSync(cur), ...tail].join(sep).split(sep).join("/");
1677
+ return [realpathSync2(cur), ...tail].join(sep).split(sep).join("/");
1610
1678
  } catch {
1611
1679
  const parent = dirname2(cur);
1612
1680
  if (parent === cur) return void 0;
@@ -1626,7 +1694,8 @@ function contentGlobBranchCovers(glob, sample, baseDir) {
1626
1694
  }
1627
1695
  return leadingParentSegments(glob) === leadingParentSegments(sample) && contentGlobToRegExp(glob).test(sample);
1628
1696
  }
1629
- function contentGlobCovers(glob, sample, baseDir) {
1697
+ function contentGlobCovers(glob, sample, baseDirInput) {
1698
+ const baseDir = resolveBaseDir(baseDirInput);
1630
1699
  const branches = expandBraces(glob.trim()) ?? [glob];
1631
1700
  return branches.some((b) => contentGlobBranchCovers(b, sample, baseDir));
1632
1701
  }
@@ -1687,7 +1756,7 @@ function normalizeRel(p) {
1687
1756
  return s;
1688
1757
  }
1689
1758
  function inspectTailwindContent(baseDirInput) {
1690
- const baseDir = resolve(baseDirInput);
1759
+ const baseDir = resolveBaseDir(baseDirInput);
1691
1760
  const pkg = readPackageJson(baseDir);
1692
1761
  const tailwind = detectTailwind(baseDir, pkg);
1693
1762
  if (tailwind.major !== void 0 && tailwind.major >= 4) return null;
@@ -1700,7 +1769,7 @@ function inspectTailwindContent(baseDirInput) {
1700
1769
  targets.push({ label: `componentsDir(${componentsDir})`, sample: `${rel2}/button.tsx`, suggest: `./${rel2}/**/*.{ts,tsx}` });
1701
1770
  }
1702
1771
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
1703
- if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) {
1772
+ if (declaredRange(baseDir, pkg, name) !== void 0) {
1704
1773
  targets.push({ label: name, ...packageContentTarget(baseDir, name) });
1705
1774
  }
1706
1775
  }
@@ -1778,10 +1847,10 @@ function componentsUseAnimation(baseDir, componentsDir) {
1778
1847
  return false;
1779
1848
  }
1780
1849
  function checkAnimationPlugin(baseDirInput) {
1781
- const baseDir = resolve(baseDirInput);
1850
+ const baseDir = resolveBaseDir(baseDirInput);
1782
1851
  const pkg = readPackageJson(baseDir);
1783
1852
  const config = readAxisConfigLike(baseDir);
1784
- const declared = pkg !== void 0 && hasDependency2(pkg, "@axis-ds/ui-react") !== void 0;
1853
+ const declared = declaredRange(baseDir, pkg, "@axis-ds/ui-react") !== void 0;
1785
1854
  const copied = typeof config?.componentsDir === "string" && componentsUseAnimation(baseDir, config.componentsDir);
1786
1855
  if (!declared && !copied) return null;
1787
1856
  const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
@@ -1799,7 +1868,7 @@ function checkAnimationPlugin(baseDirInput) {
1799
1868
  const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
1800
1869
  const source = configFile !== void 0 ? stripJsComments(readFileSync4(join2(baseDir, configFile), "utf8")) : "";
1801
1870
  const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
1802
- const pluginDeclared = pkg !== void 0 && hasDependency2(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
1871
+ const pluginDeclared = declaredRange(baseDir, pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
1803
1872
  const pluginInstalled = pluginDeclared && (isPnpProject(baseDir) || findInstalledPackage(baseDir, ANIMATION_PLUGIN_TAILWIND3) !== void 0);
1804
1873
  if (plugins === "found" && pluginDeclared && pluginInstalled) {
1805
1874
  return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
@@ -1891,7 +1960,7 @@ function selectUtilsDependencies(tailwind) {
1891
1960
  }
1892
1961
 
1893
1962
  // ../axis-registry-core/src/add/safe-write.ts
1894
- import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
1963
+ import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
1895
1964
  import path4 from "path";
1896
1965
  import fs2 from "fs-extra";
1897
1966
  var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
@@ -1918,12 +1987,12 @@ function nearestExisting(p) {
1918
1987
  return cur;
1919
1988
  }
1920
1989
  function escapeReason(root, target, options = {}) {
1921
- const realRoot = realpathSync2(root);
1990
+ const realRoot = realpathSync3(root);
1922
1991
  if (!isSameOrInside(path4.resolve(root), path4.resolve(target)) || path4.resolve(target) === path4.resolve(root)) {
1923
1992
  return `\uACBD\uB85C\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4(${target})`;
1924
1993
  }
1925
1994
  const anchor = nearestExisting(path4.dirname(target));
1926
- const realAnchor = realpathSync2(anchor);
1995
+ const realAnchor = realpathSync3(anchor);
1927
1996
  if (!isSameOrInside(realRoot, realAnchor)) {
1928
1997
  return `\uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realAnchor})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
1929
1998
  }
@@ -1938,7 +2007,7 @@ function escapeReason(root, target, options = {}) {
1938
2007
  const shown = path4.relative(path4.resolve(root), path4.resolve(target)).split(path4.sep).join("/");
1939
2008
  let realTarget;
1940
2009
  try {
1941
- realTarget = realpathSync2(target);
2010
+ realTarget = realpathSync3(target);
1942
2011
  } catch {
1943
2012
  return `\uAE30\uC874 \uD30C\uC77C ${shown} \uC774 \uAE68\uC9C4 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C \uB530\uB77C\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uACE0\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694)`;
1944
2013
  }
@@ -1971,8 +2040,8 @@ function isSymlink(p) {
1971
2040
  function outsideLinkTarget(root, target) {
1972
2041
  if (!isSymlink(target)) return null;
1973
2042
  try {
1974
- const realTarget = realpathSync2(target);
1975
- return isSameOrInside(realpathSync2(root), realTarget) ? null : realTarget;
2043
+ const realTarget = realpathSync3(target);
2044
+ return isSameOrInside(realpathSync3(root), realTarget) ? null : realTarget;
1976
2045
  } catch {
1977
2046
  return null;
1978
2047
  }
@@ -1989,10 +2058,10 @@ function hardLinkMessage(shownPath, nlink) {
1989
2058
  return `\uAE30\uC874 \uD30C\uC77C ${shownPath} \uC774 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC9C4 \uD30C\uC77C\uC774\uB77C(\uB9C1\uD06C \uC218 ${nlink}) \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uBA74 \uC774\uC5B4\uC9C4 \uB2E4\uB978 \uACBD\uB85C\uC758 \uB0B4\uC6A9\uB3C4 \uBC14\uB01D\uB2C8\uB2E4. \uD558\uB4DC\uB9C1\uD06C\uB97C \uB04A\uC740(\uD30C\uC77C\uC744 \uBCF5\uC0AC\uD574 \uBC14\uAFBC) \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694`;
1990
2059
  }
1991
2060
  function writtenOutside(root, target) {
1992
- const realRoot = realpathSync2(root);
2061
+ const realRoot = realpathSync3(root);
1993
2062
  let realTarget;
1994
2063
  try {
1995
- realTarget = realpathSync2(target);
2064
+ realTarget = realpathSync3(target);
1996
2065
  } catch {
1997
2066
  return target;
1998
2067
  }
@@ -2026,8 +2095,8 @@ async function writeNoFollow(target, content, mode) {
2026
2095
  return actual;
2027
2096
  }
2028
2097
  function checkParentInside(root, target) {
2029
- const realRoot = realpathSync2(root);
2030
- const realParent = realpathSync2(path4.dirname(target));
2098
+ const realRoot = realpathSync3(root);
2099
+ const realParent = realpathSync3(path4.dirname(target));
2031
2100
  if (!isSameOrInside(realRoot, realParent)) {
2032
2101
  return `\uBD80\uBAA8 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realParent})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
2033
2102
  }
@@ -2301,11 +2370,12 @@ function missingDependencies(root, items) {
2301
2370
  pkg = void 0;
2302
2371
  }
2303
2372
  const ranges = selectUtilsDependencies(detectTailwind(root, pkg));
2373
+ const rootPkg = pkg !== void 0 ? workspaceRootPackage(root) ?? null : null;
2304
2374
  const specs = {};
2305
2375
  for (const item of items) {
2306
2376
  for (const dep of item.dependencies) {
2307
2377
  const name = dependencyName(dep);
2308
- if (pkg !== void 0 && hasDependency(pkg, name) !== void 0) continue;
2378
+ if (declaredDependency(root, pkg, name, rootPkg) !== void 0) continue;
2309
2379
  if (name in specs) continue;
2310
2380
  const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
2311
2381
  specs[name] = explicit ?? ranges[name];
@@ -2321,9 +2391,7 @@ function dependencyName(spec) {
2321
2391
  }
2322
2392
  function addCommandForSpecs(installCommand, specs) {
2323
2393
  const args = Object.entries(specs).map(([name, range]) => range ? `"${name}@${range}"` : name).join(" ");
2324
- if (installCommand.startsWith("yarn")) return `yarn add ${args}`;
2325
- if (installCommand.startsWith("npm")) return `npm install ${args}`;
2326
- return `pnpm add ${args}`;
2394
+ return `${addCommandPrefix(installCommand)} ${args}`;
2327
2395
  }
2328
2396
  function rel(root, p) {
2329
2397
  return toPosix(path5.relative(root, p));
@@ -4850,7 +4918,7 @@ function getBrand(baseDir, name) {
4850
4918
 
4851
4919
  // ../axis-registry-core/src/template/dependencies-core.ts
4852
4920
  import { readFileSync as readFileSync9 } from "fs";
4853
- import { join as join5, resolve as resolve4 } from "path";
4921
+ import { join as join5 } from "path";
4854
4922
  var REQUIRED_DEPENDENCIES = ["tailwindcss"];
4855
4923
  var RECOMMENDED_DEPENDENCIES = ["clsx", "tailwind-merge"];
4856
4924
  function declaredAxisPackages(pkg) {
@@ -4862,18 +4930,8 @@ function declaredAxisPackages(pkg) {
4862
4930
  }
4863
4931
  return out;
4864
4932
  }
4865
- function workspaceRootPackage(baseDir) {
4866
- const root = findWorkspaceRoot(baseDir);
4867
- if (root === void 0 || root === baseDir) return void 0;
4868
- try {
4869
- const parsed = JSON.parse(readFileSync9(join5(root, "package.json"), "utf8"));
4870
- return isPlainObject(parsed) ? parsed : void 0;
4871
- } catch {
4872
- return void 0;
4873
- }
4874
- }
4875
4933
  function checkDependencies(baseDirInput) {
4876
- const baseDir = resolve4(baseDirInput);
4934
+ const baseDir = resolveBaseDir(baseDirInput);
4877
4935
  let pkg;
4878
4936
  try {
4879
4937
  const parsed = JSON.parse(readFileSync9(join5(baseDir, "package.json"), "utf8"));
@@ -4885,17 +4943,18 @@ function checkDependencies(baseDirInput) {
4885
4943
  }
4886
4944
  return { name: "dependencies", severity: "fail", message: "package.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(JSON \uD655\uC778)" };
4887
4945
  }
4888
- const rootPkg = workspaceRootPackage(baseDir);
4889
- const fromRoot = (d) => !hasDependency(pkg, d) && rootPkg !== void 0 && Boolean(hasDependency(rootPkg, d));
4890
- const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d) && !fromRoot(d));
4946
+ const rootPkg = workspaceRootPackage(baseDir) ?? null;
4947
+ const declared = (d) => declaredDependency(baseDir, pkg, d, rootPkg);
4948
+ const fromRoot = (d) => declared(d)?.source === "root";
4949
+ const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => declared(d) === void 0);
4891
4950
  if (missingRequired.length > 0) {
4892
4951
  return { name: "dependencies", severity: "fail", message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}` };
4893
4952
  }
4894
- const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d) && !fromRoot(d));
4953
+ const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => declared(d) === void 0);
4895
4954
  const rootDeclared = [...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => fromRoot(d));
4896
4955
  const rootNote = rootDeclared.length > 0 ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8: ${rootDeclared.join(", ")}` : void 0;
4897
4956
  const targets = [
4898
- ...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0 || fromRoot(d)),
4957
+ ...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => declared(d) !== void 0),
4899
4958
  ...declaredAxisPackages(pkg)
4900
4959
  ];
4901
4960
  const pnp = isPnpProject(baseDir);
@@ -4970,6 +5029,7 @@ async function handleGetTemplate(params) {
4970
5029
  async function handleApplyTemplate(params) {
4971
5030
  const detail = await fetchTemplateDetail(params.name);
4972
5031
  const baseDir = path9.resolve(params.targetDir);
5032
+ const installCommand = detectInstallCommand(baseDir);
4973
5033
  const files = [];
4974
5034
  for (const file of detail.files) {
4975
5035
  const dest = path9.join(baseDir, file.path);
@@ -5007,7 +5067,8 @@ async function handleApplyTemplate(params) {
5007
5067
  files,
5008
5068
  dependencies: detail.dependencies || {},
5009
5069
  devDependencies: detail.devDependencies || {},
5010
- dryRun: !!params.dryRun
5070
+ dryRun: !!params.dryRun,
5071
+ installCommand
5011
5072
  };
5012
5073
  }
5013
5074
  async function handleDiffTemplate(params) {
@@ -5214,11 +5275,12 @@ function formatApplyTemplateResult(result) {
5214
5275
  const devDeps = Object.entries(result.devDependencies);
5215
5276
  if (deps.length > 0 || devDeps.length > 0) {
5216
5277
  lines.push("", "### \uD544\uC694\uD55C \uC758\uC874\uC131", "");
5278
+ const installCommand = result.installCommand ?? "pnpm install";
5217
5279
  if (deps.length > 0) {
5218
- lines.push(`\`pnpm add ${deps.map(([k, v]) => `${k}@${v}`).join(" ")}\``);
5280
+ lines.push(`\`${addCommandFor(installCommand, result.dependencies)}\``);
5219
5281
  }
5220
5282
  if (devDeps.length > 0) {
5221
- lines.push(`\`pnpm add -D ${devDeps.map(([k, v]) => `${k}@${v}`).join(" ")}\``);
5283
+ lines.push(`\`${addCommandFor(installCommand, result.devDependencies, { dev: true })}\``);
5222
5284
  }
5223
5285
  }
5224
5286
  return lines.join("\n");
@@ -5263,6 +5325,11 @@ var TOKENS_INSTALL_COMMAND = addCommandFor("pnpm install", { [TOKENS_PACKAGE]: `
5263
5325
  function baseDirOf(targetDir) {
5264
5326
  return path10.resolve(targetDir || process.cwd());
5265
5327
  }
5328
+ function tokensInstallCommandFor(targetDir) {
5329
+ return addCommandFor(detectInstallCommand(baseDirOf(targetDir)), {
5330
+ [TOKENS_PACKAGE]: `^${TOKENS_DEPENDENCY_MIN_VERSION}`
5331
+ });
5332
+ }
5266
5333
  async function handleListBrands(params) {
5267
5334
  return listBrands(baseDirOf(params.targetDir));
5268
5335
  }
@@ -5273,32 +5340,32 @@ async function handleGetBrand(params) {
5273
5340
  }
5274
5341
  return getBrand(baseDirOf(params.targetDir), name);
5275
5342
  }
5276
- function formatTokensStatusGuide(status, version) {
5343
+ function formatTokensStatusGuide(status, version, installCommand = TOKENS_INSTALL_COMMAND) {
5277
5344
  switch (status) {
5278
5345
  case "not-installed":
5279
5346
  return [
5280
5347
  `${TOKENS_PACKAGE} \uAC00 \uC124\uCE58\uB3FC \uC788\uC9C0 \uC54A\uC544 \uBE0C\uB79C\uB4DC\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`,
5281
5348
  "",
5282
- `- \uC124\uCE58: \`${TOKENS_INSTALL_COMMAND}\``
5349
+ `- \uC124\uCE58: \`${installCommand}\``
5283
5350
  ].join("\n");
5284
5351
  case "unsupported":
5285
5352
  return [
5286
5353
  `${TOKENS_PACKAGE} ${version ?? "(\uBC84\uC804 \uBAA8\uB984)"} \uC740 \uBE0C\uB79C\uB4DC\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${MIN_BRAND_TOKENS_VERSION} \uC774\uC0C1 \uD544\uC694).`,
5287
5354
  "",
5288
- `- \uC5C5\uADF8\uB808\uC774\uB4DC: \`${TOKENS_INSTALL_COMMAND}\``
5355
+ `- \uC5C5\uADF8\uB808\uC774\uB4DC: \`${installCommand}\``
5289
5356
  ].join("\n");
5290
5357
  case "not-built":
5291
5358
  return [
5292
5359
  `${TOKENS_PACKAGE}${version ? ` ${version}` : ""} \uB294 \uC788\uC9C0\uB9CC \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C\uC774 \uC5C6\uC5B4 \uBE0C\uB79C\uB4DC\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`,
5293
5360
  "",
5294
- `- \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uBA74 \`pnpm --filter ${TOKENS_PACKAGE} build\`, \uC544\uB2C8\uBA74 \uC7AC\uC124\uCE58: \`${TOKENS_INSTALL_COMMAND}\``
5361
+ `- \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uBA74 \`${workspaceRunCommand(installCommand, TOKENS_PACKAGE, "build")}\`, \uC544\uB2C8\uBA74 \uC7AC\uC124\uCE58: \`${installCommand}\``
5295
5362
  ].join("\n");
5296
5363
  }
5297
5364
  }
5298
- function formatListBrandsResult(result) {
5365
+ function formatListBrandsResult(result, installCommand) {
5299
5366
  const lines = ["## AXIS \uBE0C\uB79C\uB4DC\n"];
5300
5367
  if (result.status !== "ok") {
5301
- lines.push(formatTokensStatusGuide(result.status, result.version));
5368
+ lines.push(formatTokensStatusGuide(result.status, result.version, installCommand));
5302
5369
  return lines.join("\n");
5303
5370
  }
5304
5371
  if (result.brands.length === 0) {
@@ -5332,10 +5399,10 @@ function tokenTable(brand) {
5332
5399
  }
5333
5400
  return lines;
5334
5401
  }
5335
- function formatGetBrandResult(result, name) {
5402
+ function formatGetBrandResult(result, name, installCommand) {
5336
5403
  if (result.status !== "ok") {
5337
5404
  return [`## \uBE0C\uB79C\uB4DC: ${name}
5338
- `, formatTokensStatusGuide(result.status, result.version)].join("\n");
5405
+ `, formatTokensStatusGuide(result.status, result.version, installCommand)].join("\n");
5339
5406
  }
5340
5407
  const brand = result.brand;
5341
5408
  if (!brand) {
@@ -5949,7 +6016,7 @@ server.tool(
5949
6016
  async ({ targetDir }) => {
5950
6017
  try {
5951
6018
  const result = await handleListBrands({ targetDir });
5952
- const formatted = formatListBrandsResult(result);
6019
+ const formatted = formatListBrandsResult(result, tokensInstallCommandFor(targetDir));
5953
6020
  return {
5954
6021
  content: [
5955
6022
  {
@@ -5974,7 +6041,7 @@ server.tool(
5974
6041
  );
5975
6042
  server.tool(
5976
6043
  "axis.get_brand",
5977
- "\uBE0C\uB79C\uB4DC \uD558\uB098\uC758 import \uACBD\uB85C \xB7 Provider \uC124\uC815 \uC608\uC2DC(defaultBrand) \xB7 \uC8FC\uC694 \uD1A0\uD070 \xB7 \uBCF4\uC815 \uB0B4\uC5ED\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
6044
+ "\uBE0C\uB79C\uB4DC \uD558\uB098\uC758 import \uACBD\uB85C \xB7 \uBE0C\uB79C\uB4DC \uCF1C\uAE30 \uC608\uC2DC(<html data-brand> \xB7 ThemeProvider setBrand) \xB7 \uC8FC\uC694 \uD1A0\uD070 \xB7 \uBCF4\uC815 \uB0B4\uC5ED\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
5978
6045
  {
5979
6046
  name: z.string().describe("\uBE0C\uB79C\uB4DC \uC774\uB984 (\uC608: ontology)"),
5980
6047
  targetDir: z.string().optional().describe("\uB300\uC0C1 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC (\uAE30\uBCF8: \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC)")
@@ -5982,7 +6049,7 @@ server.tool(
5982
6049
  async ({ name, targetDir }) => {
5983
6050
  try {
5984
6051
  const result = await handleGetBrand({ name, targetDir });
5985
- const formatted = formatGetBrandResult(result, name);
6052
+ const formatted = formatGetBrandResult(result, name, tokensInstallCommandFor(targetDir));
5986
6053
  return {
5987
6054
  content: [
5988
6055
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/mcp",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - MCP Server for AI-assisted component discovery",
6
6
  "bin": {