aidex-mcp 1.5.0 → 1.5.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to AiDex will be documented in this file.
4
4
 
5
+ ## [1.5.2] - 2026-02-01
6
+
7
+ ### Fixed
8
+ - **`aidex setup` for Claude Code**: Uses `claude mcp add --scope user` instead of editing settings.json directly
9
+ - Claude Desktop, Cursor, Windsurf still use JSON config editing
10
+
11
+ ## [1.5.1] - 2026-01-31
12
+
13
+ ### Fixed
14
+ - **`aidex setup`**: Now creates config file if client directory exists but config is missing (e.g. fresh Claude Code install)
15
+
5
16
  ## [1.5.0] - 2026-01-31
6
17
 
7
18
  ### Added
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AiDex Setup - Auto-register as MCP server in AI clients
3
3
  *
4
- * Supports: Claude Code, Claude Desktop, Cursor, Windsurf
4
+ * Supports: Claude Code (via CLI), Claude Desktop, Cursor, Windsurf
5
5
  */
6
6
  export declare function setupMcpClients(): void;
7
7
  export declare function unsetupMcpClients(): void;
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * AiDex Setup - Auto-register as MCP server in AI clients
3
3
  *
4
- * Supports: Claude Code, Claude Desktop, Cursor, Windsurf
4
+ * Supports: Claude Code (via CLI), Claude Desktop, Cursor, Windsurf
5
5
  */
6
6
  import { existsSync, readFileSync, writeFileSync } from 'fs';
7
7
  import { join } from 'path';
8
8
  import { homedir, platform } from 'os';
9
+ import { execSync } from 'child_process';
9
10
  // ============================================================
10
- // MCP Server Entry
11
+ // MCP Server Entry (for JSON-based clients)
11
12
  // ============================================================
12
13
  const AIDEX_MCP_ENTRY = {
13
14
  command: 'aidex',
@@ -20,45 +21,80 @@ function getClients() {
20
21
  const home = homedir();
21
22
  const plat = platform();
22
23
  const clients = [];
23
- // Claude Code
24
+ // Claude Code - uses its own CLI for MCP management
24
25
  clients.push({
26
+ type: 'cli',
25
27
  name: 'Claude Code',
26
- configPath: join(home, '.claude', 'settings.json')
28
+ detectCmd: 'claude --version',
29
+ addCmd: ['claude', 'mcp', 'add', '--scope', 'user', 'aidex', '--', 'aidex'],
30
+ removeCmd: ['claude', 'mcp', 'remove', '--scope', 'user', 'aidex']
27
31
  });
28
- // Claude Desktop
32
+ // Claude Desktop - JSON config
29
33
  if (plat === 'win32') {
30
34
  const appData = process.env.APPDATA || join(home, 'AppData', 'Roaming');
31
35
  clients.push({
36
+ type: 'json',
32
37
  name: 'Claude Desktop',
33
- configPath: join(appData, 'Claude', 'claude_desktop_config.json')
38
+ configPath: join(appData, 'Claude', 'claude_desktop_config.json'),
39
+ detectDir: join(appData, 'Claude')
34
40
  });
35
41
  }
36
42
  else if (plat === 'darwin') {
37
43
  clients.push({
44
+ type: 'json',
38
45
  name: 'Claude Desktop',
39
- configPath: join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
46
+ configPath: join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
47
+ detectDir: join(home, 'Library', 'Application Support', 'Claude')
40
48
  });
41
49
  }
42
50
  else {
43
51
  clients.push({
52
+ type: 'json',
44
53
  name: 'Claude Desktop',
45
- configPath: join(home, '.config', 'Claude', 'claude_desktop_config.json')
54
+ configPath: join(home, '.config', 'Claude', 'claude_desktop_config.json'),
55
+ detectDir: join(home, '.config', 'Claude')
46
56
  });
47
57
  }
48
- // Cursor
58
+ // Cursor - JSON config
49
59
  clients.push({
60
+ type: 'json',
50
61
  name: 'Cursor',
51
- configPath: join(home, '.cursor', 'mcp.json')
62
+ configPath: join(home, '.cursor', 'mcp.json'),
63
+ detectDir: join(home, '.cursor')
52
64
  });
53
- // Windsurf
65
+ // Windsurf - JSON config
54
66
  clients.push({
67
+ type: 'json',
55
68
  name: 'Windsurf',
56
- configPath: join(home, '.codeium', 'windsurf', 'mcp_config.json')
69
+ configPath: join(home, '.codeium', 'windsurf', 'mcp_config.json'),
70
+ detectDir: join(home, '.codeium', 'windsurf')
57
71
  });
58
72
  return clients;
59
73
  }
60
74
  // ============================================================
61
- // Config Read/Write
75
+ // CLI helpers
76
+ // ============================================================
77
+ function isCmdAvailable(cmd) {
78
+ try {
79
+ execSync(cmd, { stdio: 'pipe', timeout: 5000 });
80
+ return true;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ function runCmd(args) {
87
+ try {
88
+ const output = execSync(args.join(' '), { stdio: 'pipe', timeout: 10000 }).toString().trim();
89
+ return { success: true, output };
90
+ }
91
+ catch (err) {
92
+ const msg = err instanceof Error ? err.message : String(err);
93
+ return { success: false, error: msg };
94
+ }
95
+ }
96
+ // ============================================================
97
+ // JSON Config Read/Write
62
98
  // ============================================================
63
99
  function readJsonConfig(filePath) {
64
100
  try {
@@ -86,75 +122,113 @@ function writeJsonConfig(filePath, data) {
86
122
  }
87
123
  }
88
124
  // ============================================================
89
- // Setup / Unsetup
125
+ // Setup
90
126
  // ============================================================
127
+ function setupCliClient(client) {
128
+ if (!isCmdAvailable(client.detectCmd)) {
129
+ return { status: ` - ${client.name} (not installed)`, registered: false };
130
+ }
131
+ const result = runCmd(client.addCmd);
132
+ if (result.success) {
133
+ return { status: ` ✓ ${client.name}`, registered: true };
134
+ }
135
+ else {
136
+ return { status: ` ✗ ${client.name} (${result.error})`, registered: false };
137
+ }
138
+ }
139
+ function setupJsonClient(client) {
140
+ if (!existsSync(client.detectDir)) {
141
+ return { status: ` - ${client.name} (not installed)`, registered: false };
142
+ }
143
+ let data;
144
+ if (existsSync(client.configPath)) {
145
+ const config = readJsonConfig(client.configPath);
146
+ if (!config.success || !config.data) {
147
+ return { status: ` ✗ ${client.name} (${config.error})`, registered: false };
148
+ }
149
+ data = config.data;
150
+ }
151
+ else {
152
+ data = {};
153
+ }
154
+ if (!data.mcpServers || typeof data.mcpServers !== 'object') {
155
+ data.mcpServers = {};
156
+ }
157
+ data.mcpServers.aidex = { ...AIDEX_MCP_ENTRY };
158
+ const writeResult = writeJsonConfig(client.configPath, data);
159
+ if (!writeResult.success) {
160
+ return { status: ` ✗ ${client.name} (${writeResult.error})`, registered: false };
161
+ }
162
+ return { status: ` ✓ ${client.name} (${client.configPath})`, registered: true };
163
+ }
91
164
  export function setupMcpClients() {
92
165
  const clients = getClients();
93
- const results = [];
94
166
  let registered = 0;
95
167
  console.log('\nAiDex MCP Server Registration');
96
168
  console.log('==============================\n');
97
169
  for (const client of clients) {
98
- if (!existsSync(client.configPath)) {
99
- results.push({ client: client.name, status: 'skipped', configPath: client.configPath });
100
- console.log(` - ${client.name} (not installed)`);
101
- continue;
102
- }
103
- const config = readJsonConfig(client.configPath);
104
- if (!config.success || !config.data) {
105
- results.push({ client: client.name, status: 'error', configPath: client.configPath, message: config.error });
106
- console.log(` ✗ ${client.name} (${config.error})`);
107
- continue;
108
- }
109
- const data = config.data;
110
- if (!data.mcpServers || typeof data.mcpServers !== 'object') {
111
- data.mcpServers = {};
112
- }
113
- data.mcpServers.aidex = { ...AIDEX_MCP_ENTRY };
114
- const writeResult = writeJsonConfig(client.configPath, data);
115
- if (!writeResult.success) {
116
- results.push({ client: client.name, status: 'error', configPath: client.configPath, message: writeResult.error });
117
- console.log(` ✗ ${client.name} (${writeResult.error})`);
118
- continue;
119
- }
120
- registered++;
121
- results.push({ client: client.name, status: 'registered', configPath: client.configPath });
122
- console.log(` ✓ ${client.name} (${client.configPath})`);
170
+ const result = client.type === 'cli'
171
+ ? setupCliClient(client)
172
+ : setupJsonClient(client);
173
+ console.log(result.status);
174
+ if (result.registered)
175
+ registered++;
123
176
  }
124
177
  console.log(`\nRegistered AiDex with ${registered} client(s).\n`);
125
178
  if (registered > 0) {
126
179
  console.log('Restart your AI client(s) to activate AiDex.\n');
127
180
  }
128
181
  }
182
+ // ============================================================
183
+ // Unsetup
184
+ // ============================================================
185
+ function unsetupCliClient(client) {
186
+ if (!isCmdAvailable(client.detectCmd)) {
187
+ return { status: ` - ${client.name} (not installed)`, removed: false };
188
+ }
189
+ const result = runCmd(client.removeCmd);
190
+ if (result.success) {
191
+ return { status: ` ✓ Removed from ${client.name}`, removed: true };
192
+ }
193
+ else {
194
+ return { status: ` - ${client.name} (not registered)`, removed: false };
195
+ }
196
+ }
197
+ function unsetupJsonClient(client) {
198
+ if (!existsSync(client.detectDir)) {
199
+ return { status: ` - ${client.name} (not installed)`, removed: false };
200
+ }
201
+ if (!existsSync(client.configPath)) {
202
+ return { status: ` - ${client.name} (not registered)`, removed: false };
203
+ }
204
+ const config = readJsonConfig(client.configPath);
205
+ if (!config.success || !config.data) {
206
+ return { status: ` ✗ ${client.name} (${config.error})`, removed: false };
207
+ }
208
+ const data = config.data;
209
+ const servers = data.mcpServers;
210
+ if (!servers || !servers.aidex) {
211
+ return { status: ` - ${client.name} (not registered)`, removed: false };
212
+ }
213
+ delete servers.aidex;
214
+ const writeResult = writeJsonConfig(client.configPath, data);
215
+ if (!writeResult.success) {
216
+ return { status: ` ✗ ${client.name} (${writeResult.error})`, removed: false };
217
+ }
218
+ return { status: ` ✓ Removed from ${client.name}`, removed: true };
219
+ }
129
220
  export function unsetupMcpClients() {
130
221
  const clients = getClients();
131
222
  let removed = 0;
132
223
  console.log('\nAiDex MCP Server Unregistration');
133
224
  console.log('================================\n');
134
225
  for (const client of clients) {
135
- if (!existsSync(client.configPath)) {
136
- console.log(` - ${client.name} (not installed)`);
137
- continue;
138
- }
139
- const config = readJsonConfig(client.configPath);
140
- if (!config.success || !config.data) {
141
- console.log(` ✗ ${client.name} (${config.error})`);
142
- continue;
143
- }
144
- const data = config.data;
145
- const servers = data.mcpServers;
146
- if (!servers || !servers.aidex) {
147
- console.log(` - ${client.name} (not registered)`);
148
- continue;
149
- }
150
- delete servers.aidex;
151
- const writeResult = writeJsonConfig(client.configPath, data);
152
- if (!writeResult.success) {
153
- console.log(` ✗ ${client.name} (${writeResult.error})`);
154
- continue;
155
- }
156
- removed++;
157
- console.log(` ✓ Removed from ${client.name}`);
226
+ const result = client.type === 'cli'
227
+ ? unsetupCliClient(client)
228
+ : unsetupJsonClient(client);
229
+ console.log(result.status);
230
+ if (result.removed)
231
+ removed++;
158
232
  }
159
233
  console.log(`\nUnregistered AiDex from ${removed} client(s).\n`);
160
234
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidex-mcp",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "MCP Server providing persistent code indexing for Claude Code",
5
5
  "main": "build/index.js",
6
6
  "bin": {