a11y-devkit-deploy 0.9.6 → 0.9.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.
@@ -51,13 +51,15 @@
51
51
  "id": "claude",
52
52
  "displayName": "Claude Code",
53
53
  "mcpServerKey": "servers",
54
+ "globalMcpServerKey": "mcpServers",
54
55
  "skillsFolder": ".claude/skills",
55
- "mcpConfigFile": ".claude/mcp.json"
56
+ "mcpConfigFile": ".claude.json"
56
57
  },
57
58
  {
58
59
  "id": "cursor",
59
60
  "displayName": "Cursor",
60
61
  "mcpServerKey": "mcpServers",
62
+ "globalMcpServerKey": "mcpServers",
61
63
  "skillsFolder": ".cursor/skills",
62
64
  "mcpConfigFile": ".cursor/mcp.json"
63
65
  },
@@ -65,6 +67,7 @@
65
67
  "id": "codex",
66
68
  "displayName": "Codex",
67
69
  "mcpServerKey": "mcp_servers",
70
+ "globalMcpServerKey": "mcp_servers",
68
71
  "skillsFolder": ".codex/skills",
69
72
  "mcpConfigFile": ".codex/config.toml"
70
73
  },
@@ -72,6 +75,7 @@
72
75
  "id": "vscode",
73
76
  "displayName": "VSCode",
74
77
  "mcpServerKey": "servers",
78
+ "globalMcpServerKey": "servers",
75
79
  "skillsFolder": ".github/skills",
76
80
  "mcpConfigFile": ".github/mcp.json",
77
81
  "globalMcpConfigFile": "Code/User/mcp.json"
@@ -80,6 +84,7 @@
80
84
  "id": "windsurf",
81
85
  "displayName": "Windsurf",
82
86
  "mcpServerKey": "servers",
87
+ "globalMcpServerKey": "servers",
83
88
  "skillsFolder": ".codeium/windsurf/skills",
84
89
  "mcpConfigFile": ".codeium/windsurf/mcp_config.json"
85
90
  },
@@ -87,6 +92,7 @@
87
92
  "id": "factory",
88
93
  "displayName": "Factory",
89
94
  "mcpServerKey": "mcpServers",
95
+ "globalMcpServerKey": "mcpServers",
90
96
  "skillsFolder": ".factory/skills",
91
97
  "mcpConfigFile": ".factory/mcp.json"
92
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "a11y-devkit-deploy",
3
- "version": "0.9.6",
3
+ "version": "0.9.8",
4
4
  "description": "CLI to deploy a11y skills and MCP servers across IDEs",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -8,7 +8,7 @@ import kleur from "kleur";
8
8
  // Use gray with italics (ANSI 90 for gray, 3 for italic, 23 to reset italic)
9
9
  // This matches the subtitle color but with italic styling
10
10
  const grayItalic = (text) => {
11
- if (typeof text === 'string') {
11
+ if (typeof text === "string") {
12
12
  return `\x1b[3m\x1b[90m${text}\x1b[39m\x1b[23m`;
13
13
  }
14
14
  // Return a function that applies both italic and gray
@@ -16,16 +16,27 @@ const grayItalic = (text) => {
16
16
  };
17
17
 
18
18
  // Replace gray with italic gray for helper text
19
- Object.defineProperty(kleur, 'gray', {
20
- get() { return grayItalic; },
21
- configurable: true
19
+ Object.defineProperty(kleur, "gray", {
20
+ get() {
21
+ return grayItalic;
22
+ },
23
+ configurable: true,
22
24
  });
23
25
 
24
26
  import prompts from "prompts";
25
27
 
26
28
  import { header, info, warn, success, startSpinner, formatPath } from "./ui.js";
27
- import { getPlatform, getHostApplicationPaths, getTempDir, getMcpRepoDir } from "./paths.js";
28
- import { installSkillsFromNpm, uninstallSkillsFromTargets, cleanupTemp } from "./installers/skills.js";
29
+ import {
30
+ getPlatform,
31
+ getHostApplicationPaths,
32
+ getTempDir,
33
+ getMcpRepoDir,
34
+ } from "./paths.js";
35
+ import {
36
+ installSkillsFromNpm,
37
+ uninstallSkillsFromTargets,
38
+ cleanupTemp,
39
+ } from "./installers/skills.js";
29
40
  import { installMcpConfig, removeMcpConfig } from "./installers/mcp.js";
30
41
  import { getGitMcpPrompts, parseArgsString } from "./prompts/git-mcp.js";
31
42
  import { installGitMcp } from "./installers/git-mcp.js";
@@ -74,7 +85,11 @@ async function run() {
74
85
  const platformInfo = getPlatform();
75
86
  const config = await loadConfig();
76
87
  const pkg = await loadPackageJson();
77
- const hostPaths = getHostApplicationPaths(projectRoot, platformInfo, config.hostApplications);
88
+ const hostPaths = getHostApplicationPaths(
89
+ projectRoot,
90
+ platformInfo,
91
+ config.hostApplications,
92
+ );
78
93
  const args = parseArgs(process.argv);
79
94
 
80
95
  header(
@@ -99,7 +114,13 @@ async function run() {
99
114
 
100
115
  // Branch to Git MCP installation flow
101
116
  if (args.gitMcp) {
102
- await runGitMcpInstallation(projectRoot, platformInfo, config, hostPaths, args);
117
+ await runGitMcpInstallation(
118
+ projectRoot,
119
+ platformInfo,
120
+ config,
121
+ hostPaths,
122
+ args,
123
+ );
103
124
  return;
104
125
  }
105
126
 
@@ -132,12 +153,15 @@ async function run() {
132
153
  },
133
154
  );
134
155
 
135
- selectedProfile = config.profiles.find((p) => p.id === profileResponse.profile);
156
+ selectedProfile = config.profiles.find(
157
+ (p) => p.id === profileResponse.profile,
158
+ );
136
159
 
137
160
  if (selectedProfile) {
138
161
  // Filter skills based on profile
139
162
  skillsToInstall = config.skills.filter((skill) => {
140
- const skillNpmName = typeof skill === "string" ? skill : skill.npmName;
163
+ const skillNpmName =
164
+ typeof skill === "string" ? skill : skill.npmName;
141
165
  return selectedProfile.skills.includes(skillNpmName);
142
166
  });
143
167
 
@@ -168,7 +192,7 @@ async function run() {
168
192
  console.log(` ${description}`);
169
193
  });
170
194
 
171
- console.log("\nMCP Servers to install:");
195
+ console.log("\nMCP Servers to install: [will install globally]");
172
196
  mcpServersToInstall.forEach((server) => {
173
197
  const description = server.description || "No description";
174
198
  console.log(` • ${server.name}`);
@@ -240,7 +264,8 @@ async function run() {
240
264
  {
241
265
  title: "Global for this user",
242
266
  value: "global",
243
- description: "Write to user-level host application config folders",
267
+ description:
268
+ "Write to user-level host application config folders",
244
269
  },
245
270
  ],
246
271
  initial: 0,
@@ -262,7 +287,9 @@ async function run() {
262
287
  );
263
288
 
264
289
  scope = scope || response.scope;
265
- mcpScope = response.mcpScope || (config.supportLocalMcpInstallation ? "local" : "global");
290
+ mcpScope =
291
+ response.mcpScope ||
292
+ (config.supportLocalMcpInstallation ? "local" : "global");
266
293
  hostSelection = response.hosts || hostSelection;
267
294
  }
268
295
 
@@ -274,7 +301,9 @@ async function run() {
274
301
  }
275
302
 
276
303
  if (!hostSelection.length) {
277
- warn("No host applications selected. MCP installation requires at least one host application.");
304
+ warn(
305
+ "No host applications selected. MCP installation requires at least one host application.",
306
+ );
278
307
  process.exit(1);
279
308
  }
280
309
 
@@ -318,10 +347,14 @@ async function run() {
318
347
 
319
348
  for (let i = 0; i < hostSelection.length; i++) {
320
349
  const host = hostSelection[i];
350
+ const serverKey = mcpScope === "global"
351
+ ? hostPaths[host].globalMcpServerKey
352
+ : hostPaths[host].mcpServerKey;
321
353
  await installMcpConfig(
322
354
  mcpConfigPaths[i],
323
355
  mcpServersToInstall,
324
- hostPaths[host].mcpServerKey,
356
+ serverKey,
357
+ platformInfo,
325
358
  );
326
359
  }
327
360
  mcpSpinner.succeed(
@@ -353,7 +386,13 @@ async function run() {
353
386
  info("Documentation: https://github.com/joe-watkins/a11y-devkit#readme");
354
387
  }
355
388
 
356
- async function runUninstall(projectRoot, platformInfo, config, hostPaths, args) {
389
+ async function runUninstall(
390
+ projectRoot,
391
+ platformInfo,
392
+ config,
393
+ hostPaths,
394
+ args,
395
+ ) {
357
396
  console.log("\n");
358
397
  info("Removing skills and MCP servers installed by this tool");
359
398
  console.log("");
@@ -433,7 +472,8 @@ async function runUninstall(projectRoot, platformInfo, config, hostPaths, args)
433
472
  {
434
473
  title: "Global for this user",
435
474
  value: "global",
436
- description: "Remove from user-level host application config folders",
475
+ description:
476
+ "Remove from user-level host application config folders",
437
477
  },
438
478
  ],
439
479
  initial: 0,
@@ -469,7 +509,9 @@ async function runUninstall(projectRoot, platformInfo, config, hostPaths, args)
469
509
  }
470
510
 
471
511
  if (!hostSelection.length) {
472
- warn("No host applications selected. Uninstall requires at least one host application.");
512
+ warn(
513
+ "No host applications selected. Uninstall requires at least one host application.",
514
+ );
473
515
  process.exit(1);
474
516
  }
475
517
 
@@ -518,10 +560,13 @@ async function runUninstall(projectRoot, platformInfo, config, hostPaths, args)
518
560
 
519
561
  for (let i = 0; i < hostSelection.length; i++) {
520
562
  const host = hostSelection[i];
563
+ const serverKey = mcpScope === "global"
564
+ ? hostPaths[host].globalMcpServerKey
565
+ : hostPaths[host].mcpServerKey;
521
566
  const result = await removeMcpConfig(
522
567
  mcpConfigPaths[i],
523
568
  serverNames,
524
- hostPaths[host].mcpServerKey,
569
+ serverKey,
525
570
  );
526
571
  removedCount += result.removed;
527
572
  }
@@ -538,7 +583,13 @@ async function runUninstall(projectRoot, platformInfo, config, hostPaths, args)
538
583
  success("Uninstall complete.");
539
584
  }
540
585
 
541
- async function runGitMcpInstallation(projectRoot, platformInfo, config, hostPaths, args) {
586
+ async function runGitMcpInstallation(
587
+ projectRoot,
588
+ platformInfo,
589
+ config,
590
+ hostPaths,
591
+ args,
592
+ ) {
542
593
  // Check if --yes flag is used with --git-mcp
543
594
  if (args.autoYes) {
544
595
  warn("--yes flag not supported for Git MCP installation");
@@ -592,7 +643,9 @@ async function runGitMcpInstallation(projectRoot, platformInfo, config, hostPath
592
643
 
593
644
  // Prompt for MCP Config Scope (where to write MCP configurations)
594
645
  // Skip if local MCP installation is not supported
595
- let mcpScopeResponse = { mcpScope: config.supportLocalMcpInstallation ? null : "global" };
646
+ let mcpScopeResponse = {
647
+ mcpScope: config.supportLocalMcpInstallation ? null : "global",
648
+ };
596
649
 
597
650
  if (config.supportLocalMcpInstallation) {
598
651
  mcpScopeResponse = await prompts(
@@ -648,7 +701,9 @@ async function runGitMcpInstallation(projectRoot, platformInfo, config, hostPath
648
701
  const hostSelection = hostResponse.hosts || [];
649
702
 
650
703
  if (!hostSelection.length) {
651
- warn("No host applications selected. MCP installation requires at least one host application.");
704
+ warn(
705
+ "No host applications selected. MCP installation requires at least one host application.",
706
+ );
652
707
  process.exit(1);
653
708
  }
654
709
 
@@ -715,10 +770,14 @@ async function runGitMcpInstallation(projectRoot, platformInfo, config, hostPath
715
770
 
716
771
  for (let i = 0; i < hostSelection.length; i++) {
717
772
  const host = hostSelection[i];
773
+ const serverKey = mcpScope === "global"
774
+ ? hostPaths[host].globalMcpServerKey
775
+ : hostPaths[host].mcpServerKey;
718
776
  await installMcpConfig(
719
777
  mcpConfigPaths[i],
720
778
  [mcpServerConfig],
721
- hostPaths[host].mcpServerKey,
779
+ serverKey,
780
+ platformInfo,
722
781
  );
723
782
  }
724
783
 
@@ -729,7 +788,9 @@ async function runGitMcpInstallation(projectRoot, platformInfo, config, hostPath
729
788
  // Display success message
730
789
  success("Git MCP installation complete!");
731
790
  info(`Repository location: ${mcpServer.repoPath}`);
732
- info(`MCP server '${mcpServer.name}' configured in ${hostSelection.length} host application(s)`);
791
+ info(
792
+ `MCP server '${mcpServer.name}' configured in ${hostSelection.length} host application(s)`,
793
+ );
733
794
  console.log("");
734
795
  success("Next Steps:");
735
796
  info("Restart your host application to load the new MCP server");
@@ -738,4 +799,3 @@ async function runGitMcpInstallation(projectRoot, platformInfo, config, hostPath
738
799
  }
739
800
 
740
801
  export { run };
741
-
@@ -143,7 +143,7 @@ async function loadConfig(filePath) {
143
143
  return isTomlFile(filePath) ? loadToml(filePath) : loadJson(filePath);
144
144
  }
145
145
 
146
- function mergeServers(existing, incoming, serverKey = "servers") {
146
+ function mergeServers(existing, incoming, serverKey = "servers", platformInfo = null) {
147
147
  const existingServers = existing[serverKey] && typeof existing[serverKey] === "object"
148
148
  ? existing[serverKey]
149
149
  : {};
@@ -151,9 +151,18 @@ function mergeServers(existing, incoming, serverKey = "servers") {
151
151
  const merged = { ...existing, [serverKey]: { ...existingServers } };
152
152
 
153
153
  for (const server of incoming) {
154
+ let command = server.command;
155
+ let args = server.args || [];
156
+
157
+ // On Windows, wrap npx commands with cmd /c
158
+ if (platformInfo?.isWindows && command === "npx") {
159
+ command = "cmd";
160
+ args = ["/c", "npx", ...args];
161
+ }
162
+
154
163
  const serverConfig = {
155
- command: server.command,
156
- args: server.args || [],
164
+ command,
165
+ args,
157
166
  startup_timeout_sec: 30
158
167
  };
159
168
 
@@ -201,10 +210,10 @@ function removeServers(existing, removeNames, serverKey = "servers") {
201
210
  return { updated, removed };
202
211
  }
203
212
 
204
- async function installMcpConfig(configPath, servers, serverKey = "servers") {
213
+ async function installMcpConfig(configPath, servers, serverKey = "servers", platformInfo = null) {
205
214
  await fs.mkdir(path.dirname(configPath), { recursive: true });
206
215
  const existing = await loadConfig(configPath);
207
- const updated = mergeServers(existing, servers, serverKey);
216
+ const updated = mergeServers(existing, servers, serverKey, platformInfo);
208
217
 
209
218
  if (isTomlFile(configPath)) {
210
219
  await fs.writeFile(configPath, stringifySimpleToml(updated), "utf8");
package/src/paths.js CHANGED
@@ -57,6 +57,7 @@ function getHostApplicationPaths(projectRoot, platformInfo = getPlatform(), host
57
57
  mcpConfig: globalMcpConfig,
58
58
  localMcpConfig: path.join(projectRoot, mcpConfigFile),
59
59
  mcpServerKey: host.mcpServerKey,
60
+ globalMcpServerKey: host.globalMcpServerKey || host.mcpServerKey,
60
61
  skillsDir: globalSkillsDir,
61
62
  localSkillsDir: path.join(projectRoot, skillsFolder)
62
63
  };