@phidiassj/aiyoperps-mcp-installer 0.6.7 → 0.6.9

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.
@@ -147,13 +147,11 @@ async function detectClaudeCode(url) {
147
147
 
148
148
  async function detectClaudeDesktop(url) {
149
149
  const candidates = getClaudeDesktopCandidates();
150
- const configPath = candidates.find(fileExists) ??
151
- candidates.find(candidate => fs.existsSync(path.dirname(candidate))) ??
152
- candidates[0];
153
- const exists = fileExists(configPath);
154
- const parentExists = fs.existsSync(path.dirname(configPath));
155
- const baseConfigRoot = path.dirname(path.dirname(configPath));
156
- const baseRootExists = fs.existsSync(baseConfigRoot);
150
+ const configPaths = selectClaudeDesktopConfigPaths(candidates);
151
+ const primaryPath = configPaths[0];
152
+ const exists = configPaths.some(fileExists);
153
+ const parentExists = configPaths.some(configPath => fs.existsSync(path.dirname(configPath)));
154
+ const baseRootExists = configPaths.some(configPath => fs.existsSync(path.dirname(path.dirname(configPath))));
157
155
  const detected = exists || parentExists || baseRootExists;
158
156
  let supported = baseRootExists;
159
157
  let installed = false;
@@ -167,8 +165,12 @@ async function detectClaudeDesktop(url) {
167
165
 
168
166
  if (exists) {
169
167
  try {
170
- const parsed = JSON.parse(fs.readFileSync(configPath, 'utf8'));
171
- installed = Boolean(parsed?.mcpServers?.[SERVER_NAME]);
168
+ installed = configPaths
169
+ .filter(fileExists)
170
+ .some(configPath => {
171
+ const parsed = JSON.parse(fs.readFileSync(configPath, 'utf8'));
172
+ return Boolean(parsed?.mcpServers?.[SERVER_NAME]);
173
+ });
172
174
  reason = installed ? 'installed' : 'config parsed successfully';
173
175
  } catch (error) {
174
176
  supported = false;
@@ -184,9 +186,10 @@ async function detectClaudeDesktop(url) {
184
186
  supported,
185
187
  installed,
186
188
  reason,
187
- path: configPath,
188
- install: () => installClaudeDesktop(configPath, url),
189
- uninstall: () => uninstallClaudeDesktop(configPath)
189
+ configPaths,
190
+ path: configPaths.join(' | '),
191
+ install: () => installClaudeDesktop(configPaths, url),
192
+ uninstall: () => uninstallClaudeDesktop(configPaths)
190
193
  };
191
194
  }
192
195
 
@@ -412,7 +415,7 @@ function createInstallAction(host, url) {
412
415
  case 'claude-code':
413
416
  return () => installClaudeCode(url);
414
417
  case 'claude-desktop':
415
- return () => installClaudeDesktop(host.path, url);
418
+ return () => installClaudeDesktop(host.configPaths, url);
416
419
  case 'openclaw':
417
420
  return () => installOpenClaw(url);
418
421
  default:
@@ -463,37 +466,46 @@ function uninstallCodex(configPath) {
463
466
  fs.writeFileSync(configPath, next.trim() ? `${next.replace(/\s*$/, '')}\n` : '', 'utf8');
464
467
  }
465
468
 
466
- function installClaudeDesktop(configPath, url) {
467
- ensureParentDir(configPath);
469
+ function installClaudeDesktop(configPaths, url) {
470
+ const targets = configPaths.filter(fileExists);
471
+ if (targets.length === 0) {
472
+ targets.push(configPaths[0]);
473
+ }
468
474
 
469
- const payload = fileExists(configPath)
470
- ? JSON.parse(fs.readFileSync(configPath, 'utf8'))
471
- : {};
475
+ for (const configPath of targets) {
476
+ ensureParentDir(configPath);
472
477
 
473
- payload.mcpServers ??= {};
474
- payload.mcpServers[SERVER_NAME] = buildJsonServerConfig(url);
478
+ const payload = fileExists(configPath)
479
+ ? JSON.parse(fs.readFileSync(configPath, 'utf8'))
480
+ : {};
475
481
 
476
- backupIfExists(configPath);
477
- fs.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
478
- }
482
+ payload.mcpServers ??= {};
483
+ payload.mcpServers[SERVER_NAME] = buildJsonServerConfig(url);
479
484
 
480
- function uninstallClaudeDesktop(configPath) {
481
- if (!fileExists(configPath)) {
482
- return;
485
+ backupIfExists(configPath);
486
+ fs.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
483
487
  }
488
+ }
484
489
 
485
- const payload = JSON.parse(fs.readFileSync(configPath, 'utf8'));
486
- if (!payload?.mcpServers?.[SERVER_NAME]) {
487
- return;
488
- }
490
+ function uninstallClaudeDesktop(configPaths) {
491
+ for (const configPath of configPaths) {
492
+ if (!fileExists(configPath)) {
493
+ continue;
494
+ }
489
495
 
490
- delete payload.mcpServers[SERVER_NAME];
491
- if (Object.keys(payload.mcpServers).length === 0) {
492
- delete payload.mcpServers;
493
- }
496
+ const payload = JSON.parse(fs.readFileSync(configPath, 'utf8'));
497
+ if (!payload?.mcpServers?.[SERVER_NAME]) {
498
+ continue;
499
+ }
494
500
 
495
- backupIfExists(configPath);
496
- fs.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
501
+ delete payload.mcpServers[SERVER_NAME];
502
+ if (Object.keys(payload.mcpServers).length === 0) {
503
+ delete payload.mcpServers;
504
+ }
505
+
506
+ backupIfExists(configPath);
507
+ fs.writeFileSync(configPath, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
508
+ }
497
509
  }
498
510
 
499
511
  function installClaudeCode(url) {
@@ -1003,10 +1015,32 @@ function getClaudeDesktopCandidates() {
1003
1015
 
1004
1016
  if (process.platform === 'win32') {
1005
1017
  const appData = env.APPDATA || path.join(env.USERPROFILE || os.homedir(), 'AppData', 'Roaming');
1006
- return [
1018
+ const localAppData = env.LOCALAPPDATA || path.join(env.USERPROFILE || os.homedir(), 'AppData', 'Local');
1019
+ const storeCandidates = [];
1020
+ const roamingCandidates = [
1007
1021
  path.join(appData, 'Claude', 'claude_desktop_config.json'),
1008
1022
  path.join(appData, 'Claude', 'config.json')
1009
1023
  ];
1024
+
1025
+ const packagesRoot = path.join(localAppData, 'Packages');
1026
+ if (fs.existsSync(packagesRoot)) {
1027
+ try {
1028
+ const packageDirs = fs.readdirSync(packagesRoot, { withFileTypes: true })
1029
+ .filter(entry => entry.isDirectory())
1030
+ .map(entry => entry.name)
1031
+ .filter(name => name.toLowerCase().startsWith('claude_'));
1032
+
1033
+ for (const packageDir of packageDirs) {
1034
+ storeCandidates.push(
1035
+ path.join(packagesRoot, packageDir, 'LocalCache', 'Roaming', 'Claude', 'claude_desktop_config.json'),
1036
+ path.join(packagesRoot, packageDir, 'LocalCache', 'Roaming', 'Claude', 'config.json'));
1037
+ }
1038
+ } catch {
1039
+ // Ignore directory enumeration failures and keep default candidates.
1040
+ }
1041
+ }
1042
+
1043
+ return [...new Set([...storeCandidates, ...roamingCandidates])];
1010
1044
  }
1011
1045
 
1012
1046
  if (process.platform === 'darwin') {
@@ -1022,6 +1056,34 @@ function getClaudeDesktopCandidates() {
1022
1056
  ];
1023
1057
  }
1024
1058
 
1059
+ function selectClaudeDesktopConfigPaths(candidates) {
1060
+ const existingPrimary = candidates.filter(candidate =>
1061
+ fileExists(candidate) &&
1062
+ path.basename(candidate).toLowerCase() === 'claude_desktop_config.json');
1063
+ if (existingPrimary.length > 0) {
1064
+ return existingPrimary;
1065
+ }
1066
+
1067
+ const existingAny = candidates.filter(fileExists);
1068
+ if (existingAny.length > 0) {
1069
+ return existingAny;
1070
+ }
1071
+
1072
+ const creatablePrimary = candidates.find(candidate =>
1073
+ path.basename(candidate).toLowerCase() === 'claude_desktop_config.json' &&
1074
+ fs.existsSync(path.dirname(candidate)));
1075
+ if (creatablePrimary) {
1076
+ return [creatablePrimary];
1077
+ }
1078
+
1079
+ const creatableAny = candidates.find(candidate => fs.existsSync(path.dirname(candidate)));
1080
+ if (creatableAny) {
1081
+ return [creatableAny];
1082
+ }
1083
+
1084
+ return [candidates[0]];
1085
+ }
1086
+
1025
1087
  function resolveOpenClawConfigPath() {
1026
1088
  const explicit = env.OPENCLAW_CONFIG_PATH;
1027
1089
  if (explicit) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phidiassj/aiyoperps-mcp-installer",
3
- "version": "0.6.7",
3
+ "version": "0.6.9",
4
4
  "description": "Interactive installer for registering AiyoPerps MCP with supported AI agent hosts.",
5
5
  "license": "MIT",
6
6
  "type": "module",