@mcp-abap-adt/configurator 0.0.2 → 0.0.4

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/bin/mcp-conf.js CHANGED
@@ -22,6 +22,10 @@ try {
22
22
  }
23
23
 
24
24
  const args = process.argv.slice(2);
25
+ const action = args[0] && !args[0].startsWith("-") ? args[0] : null;
26
+ if (action && ["add", "rm", "ls", "enable", "disable", "where", "help"].includes(action)) {
27
+ args.shift();
28
+ }
25
29
  const options = {
26
30
  clients: [],
27
31
  envPath: null,
@@ -29,18 +33,29 @@ const options = {
29
33
  name: null,
30
34
  transport: "stdio",
31
35
  command: "mcp-abap-adt",
36
+ scope: null,
32
37
  dryRun: false,
33
38
  force: false,
34
39
  disabled: false,
35
40
  toggle: false,
36
41
  remove: false,
42
+ list: false,
43
+ allProjects: false,
44
+ projectPath: null,
45
+ where: false,
37
46
  url: null,
38
47
  headers: {},
39
48
  timeout: 60,
40
49
  };
41
50
 
42
- if (args.includes("--help") || args.includes("-h")) {
43
- printHelp();
51
+ if (args.includes("--help") || args.includes("-h") || action === "help") {
52
+ const helpAction =
53
+ action === "help"
54
+ ? args[0]
55
+ : action && ["add", "rm", "ls", "enable", "disable", "where"].includes(action)
56
+ ? action
57
+ : null;
58
+ printHelp(helpAction);
44
59
  process.exit(0);
45
60
  }
46
61
 
@@ -64,6 +79,21 @@ for (let i = 0; i < args.length; i += 1) {
64
79
  } else if (arg === "--command") {
65
80
  options.command = args[i + 1];
66
81
  i += 1;
82
+ } else if (arg === "--global") {
83
+ if (options.scope && options.scope !== "global") {
84
+ fail("Choose either --global or --local (not both).");
85
+ }
86
+ options.scope = "global";
87
+ } else if (arg === "--local") {
88
+ if (options.scope && options.scope !== "local") {
89
+ fail("Choose either --global or --local (not both).");
90
+ }
91
+ options.scope = "local";
92
+ } else if (arg === "--all-projects") {
93
+ options.allProjects = true;
94
+ } else if (arg === "--project") {
95
+ options.projectPath = args[i + 1];
96
+ i += 1;
67
97
  } else if (arg === "--url") {
68
98
  options.url = args[i + 1];
69
99
  i += 1;
@@ -92,18 +122,62 @@ for (let i = 0; i < args.length; i += 1) {
92
122
  }
93
123
  }
94
124
 
125
+ if (!action || !["add", "rm", "ls", "enable", "disable", "where"].includes(action)) {
126
+ fail("Provide a command: add | rm | ls | enable | disable | where.");
127
+ }
128
+
95
129
  if (options.clients.length === 0) {
96
130
  fail("Provide at least one --client.");
97
131
  }
98
132
 
99
- if (!options.name) {
133
+ if (!["ls"].includes(action) && !options.name) {
100
134
  fail("Provide --name <serverName> (required).");
101
135
  }
102
136
 
103
137
  const transportNormalized = options.transport === "http" ? "streamableHttp" : options.transport;
104
138
  options.transport = transportNormalized;
105
139
 
106
- const requiresConnectionParams = !options.remove && !options.toggle;
140
+ if (action === "rm") {
141
+ options.remove = true;
142
+ }
143
+ if (action === "ls") {
144
+ options.list = true;
145
+ }
146
+ if (action === "enable") {
147
+ options.toggle = true;
148
+ options.disabled = false;
149
+ }
150
+ if (action === "disable") {
151
+ options.toggle = true;
152
+ options.disabled = true;
153
+ }
154
+ if (action === "where") {
155
+ options.where = true;
156
+ }
157
+
158
+ if (options.remove && action !== "rm") {
159
+ fail("Use the rm command instead of --remove.");
160
+ }
161
+ if (options.list && options.toggle) {
162
+ fail("The ls command does not support --enable/--disable.");
163
+ }
164
+ if (options.remove && options.toggle) {
165
+ fail("The rm command does not support --enable/--disable.");
166
+ }
167
+ if (options.allProjects && !options.list && !options.toggle && !options.remove && !options.where) {
168
+ fail("--all-projects is only supported for rm/enable/disable/ls/where.");
169
+ }
170
+ if (options.projectPath && options.allProjects) {
171
+ fail("Use either --project or --all-projects (not both).");
172
+ }
173
+ if (options.where && (options.list || options.remove || options.toggle)) {
174
+ fail("The where command does not support ls/rm/enable/disable flags.");
175
+ }
176
+ if (options.projectPath && action === "add" && options.scope !== "global") {
177
+ fail("--project is only supported for Claude global config.");
178
+ }
179
+
180
+ const requiresConnectionParams = !options.remove && !options.toggle && !options.list && !options.where;
107
181
 
108
182
  if (requiresConnectionParams && options.transport === "stdio") {
109
183
  if (!options.envPath && !options.mcpDestination) {
@@ -135,44 +209,154 @@ const serverArgsRaw = [
135
209
  ];
136
210
  const serverArgs = serverArgsRaw.filter(Boolean);
137
211
 
138
- for (const client of options.clients) {
139
- switch (client) {
212
+ for (const client of options.clients) {
213
+ const scope = options.scope || getDefaultScope(client);
214
+ if (options.projectPath && client !== "claude") {
215
+ fail("--project is only supported for Claude.");
216
+ }
217
+ switch (client) {
140
218
  case "cline":
141
- writeJsonConfig(getClinePath(platform, home, appData), options.name, serverArgs, "cline");
219
+ requireScope("Cline", ["global"], scope);
220
+ if (options.list) {
221
+ listJsonConfig(getClinePath(platform, home, appData), "cline");
222
+ } else if (options.where) {
223
+ whereJsonConfig(getClinePath(platform, home, appData), "cline", options.name);
224
+ } else {
225
+ writeJsonConfig(getClinePath(platform, home, appData), options.name, serverArgs, "cline");
226
+ }
142
227
  break;
143
228
  case "codex":
144
229
  if (options.transport === "sse") {
145
230
  fail("Codex does not support SSE transport.");
146
231
  }
147
- writeCodexConfig(getCodexPath(platform, home, userProfile), options.name, serverArgs);
232
+ requireScope("Codex", ["global"], scope);
233
+ if (options.list) {
234
+ listCodexConfig(getCodexPath(platform, home, userProfile));
235
+ } else if (options.where) {
236
+ whereCodexConfig(getCodexPath(platform, home, userProfile), options.name);
237
+ } else {
238
+ writeCodexConfig(getCodexPath(platform, home, userProfile), options.name, serverArgs);
239
+ }
148
240
  break;
149
241
  case "claude":
150
- writeClaudeConfig(getClaudePath(platform, home, appData), options.name, serverArgs);
242
+ requireScope("Claude", ["global", "local"], scope);
243
+ const claudeToggleScope = options.toggle ? "global" : scope;
244
+ if (options.allProjects && claudeToggleScope !== "global") {
245
+ fail("--all-projects is only supported for Claude global config.");
246
+ }
247
+ if (options.projectPath && claudeToggleScope !== "global") {
248
+ fail("--project is only supported for Claude global config.");
249
+ }
250
+ if (options.toggle && scope === "local") {
251
+ const localPath = getClaudePath(platform, home, appData, "local");
252
+ if (!claudeLocalHasServer(localPath, options.name)) {
253
+ fail(`Server "${options.name}" not found in ${localPath}.`);
254
+ }
255
+ }
256
+ if (options.list) {
257
+ listClaudeConfig(
258
+ getClaudePath(platform, home, appData, claudeToggleScope),
259
+ options.allProjects,
260
+ options.projectPath,
261
+ );
262
+ } else if (options.where) {
263
+ whereClaudeConfig(
264
+ getClaudePath(platform, home, appData, claudeToggleScope),
265
+ options.name,
266
+ options.allProjects,
267
+ options.projectPath,
268
+ );
269
+ } else {
270
+ writeClaudeConfig(
271
+ getClaudePath(platform, home, appData, claudeToggleScope),
272
+ options.name,
273
+ serverArgs,
274
+ );
275
+ }
151
276
  break;
152
277
  case "goose":
153
- writeGooseConfig(getGoosePath(platform, home, appData), options.name, serverArgs);
278
+ requireScope("Goose", ["global"], scope);
279
+ if (options.list) {
280
+ listGooseConfig(getGoosePath(platform, home, appData));
281
+ } else if (options.where) {
282
+ whereGooseConfig(getGoosePath(platform, home, appData), options.name);
283
+ } else {
284
+ writeGooseConfig(getGoosePath(platform, home, appData), options.name, serverArgs);
285
+ }
154
286
  break;
155
287
  case "opencode":
156
- writeJsonConfig(getOpenCodePath(), options.name, serverArgs, "opencode");
288
+ requireScope("OpenCode", ["global", "local"], scope);
289
+ if (options.list) {
290
+ listJsonConfig(getOpenCodePath(platform, home, appData, scope), "opencode");
291
+ } else if (options.where) {
292
+ whereJsonConfig(getOpenCodePath(platform, home, appData, scope), "opencode", options.name);
293
+ } else {
294
+ writeJsonConfig(
295
+ getOpenCodePath(platform, home, appData, scope),
296
+ options.name,
297
+ serverArgs,
298
+ "opencode",
299
+ );
300
+ }
301
+ break;
302
+ case "antigravity":
303
+ requireScope("Antigravity", ["global", "local"], scope);
304
+ if (scope === "local") {
305
+ process.stdout.write("Antigravity local scope is not supported yet.\n");
306
+ break;
307
+ }
308
+ if (options.list) {
309
+ listJsonConfig(getAntigravityPath(home, scope), "antigravity");
310
+ } else if (options.where) {
311
+ whereJsonConfig(getAntigravityPath(home, scope), "antigravity", options.name);
312
+ } else {
313
+ writeJsonConfig(
314
+ getAntigravityPath(home, scope),
315
+ options.name,
316
+ serverArgs,
317
+ "antigravity",
318
+ );
319
+ }
157
320
  break;
158
321
  case "copilot":
159
- writeJsonConfig(getCopilotPath(), options.name, serverArgs, "copilot");
322
+ requireScope("GitHub Copilot", ["local"], scope);
323
+ if (options.list) {
324
+ listJsonConfig(getCopilotPath(), "copilot");
325
+ } else if (options.where) {
326
+ whereJsonConfig(getCopilotPath(), "copilot", options.name);
327
+ } else {
328
+ writeJsonConfig(getCopilotPath(), options.name, serverArgs, "copilot");
329
+ }
160
330
  break;
161
331
  case "cursor":
162
- writeJsonConfig(
163
- getCursorPath(platform, home, userProfile),
164
- options.name,
165
- serverArgs,
166
- "cursor",
167
- );
332
+ requireScope("Cursor", ["global", "local"], scope);
333
+ if (options.list) {
334
+ listJsonConfig(getCursorPath(platform, home, userProfile, scope), "cursor");
335
+ } else if (options.where) {
336
+ whereJsonConfig(getCursorPath(platform, home, userProfile, scope), "cursor", options.name);
337
+ } else {
338
+ writeJsonConfig(
339
+ getCursorPath(platform, home, userProfile, scope),
340
+ options.name,
341
+ serverArgs,
342
+ "cursor",
343
+ );
344
+ }
168
345
  break;
169
346
  case "windsurf":
170
- writeJsonConfig(
171
- getWindsurfPath(platform, home, userProfile),
172
- options.name,
173
- serverArgs,
174
- "windsurf",
175
- );
347
+ requireScope("Windsurf", ["global"], scope);
348
+ if (options.list) {
349
+ listJsonConfig(getWindsurfPath(platform, home, userProfile), "windsurf");
350
+ } else if (options.where) {
351
+ whereJsonConfig(getWindsurfPath(platform, home, userProfile), "windsurf", options.name);
352
+ } else {
353
+ writeJsonConfig(
354
+ getWindsurfPath(platform, home, userProfile),
355
+ options.name,
356
+ serverArgs,
357
+ "windsurf",
358
+ );
359
+ }
176
360
  break;
177
361
  default:
178
362
  fail(`Unknown client: ${client}`);
@@ -210,7 +394,10 @@ function getCodexPath(platformValue, homeDir, userProfileDir) {
210
394
  return path.join(homeDir, ".codex", "config.toml");
211
395
  }
212
396
 
213
- function getClaudePath(platformValue, homeDir, appDataDir) {
397
+ function getClaudePath(platformValue, homeDir, appDataDir, scopeValue) {
398
+ if (scopeValue === "local") {
399
+ return path.join(process.cwd(), ".mcp.json");
400
+ }
214
401
  if (platformValue === "darwin") {
215
402
  return path.join(
216
403
  homeDir,
@@ -233,7 +420,10 @@ function getGoosePath(platformValue, homeDir, appDataDir) {
233
420
  return path.join(homeDir, ".config", "goose", "config.yaml");
234
421
  }
235
422
 
236
- function getCursorPath(platformValue, homeDir, userProfileDir) {
423
+ function getCursorPath(platformValue, homeDir, userProfileDir, scopeValue) {
424
+ if (scopeValue === "local") {
425
+ return path.join(process.cwd(), ".cursor", "mcp.json");
426
+ }
237
427
  const base = platformValue === "win32" ? userProfileDir : homeDir;
238
428
  return path.join(base, ".cursor", "mcp.json");
239
429
  }
@@ -242,8 +432,21 @@ function getCopilotPath() {
242
432
  return path.join(process.cwd(), ".vscode", "mcp.json");
243
433
  }
244
434
 
245
- function getOpenCodePath() {
246
- return path.join(process.cwd(), "opencode.json");
435
+ function getOpenCodePath(platformValue, homeDir, appDataDir, scopeValue) {
436
+ if (scopeValue === "local") {
437
+ return path.join(process.cwd(), "opencode.json");
438
+ }
439
+ if (platformValue === "win32") {
440
+ return path.join(appDataDir, "opencode", "opencode.json");
441
+ }
442
+ return path.join(homeDir, ".config", "opencode", "opencode.json");
443
+ }
444
+
445
+ function getAntigravityPath(homeDir, scopeValue) {
446
+ if (scopeValue === "local") {
447
+ return path.join(process.cwd(), ".antigravity", "mcp.json");
448
+ }
449
+ return path.join(homeDir, ".gemini", "antigravity", "mcp_config.json");
247
450
  }
248
451
 
249
452
  function getWindsurfPath(platformValue, homeDir, userProfileDir) {
@@ -253,6 +456,50 @@ function getWindsurfPath(platformValue, homeDir, userProfileDir) {
253
456
  return path.join(homeDir, ".codeium", "windsurf", "mcp_config.json");
254
457
  }
255
458
 
459
+ function requireScope(clientLabel, allowedScopes, requestedScope) {
460
+ if (!allowedScopes.includes(requestedScope)) {
461
+ fail(
462
+ `${clientLabel} supports ${allowedScopes.join("/")} configuration only. ` +
463
+ `Use --${allowedScopes[0]}.`,
464
+ );
465
+ }
466
+ }
467
+
468
+ function getDefaultScope(clientType) {
469
+ if (clientType === "copilot") {
470
+ return "local";
471
+ }
472
+ return "global";
473
+ }
474
+
475
+ function resolveProjectSelector(data, projectPath) {
476
+ if (!projectPath) {
477
+ return resolveClaudeProjectKey(data);
478
+ }
479
+ if (!data.projects) {
480
+ return projectPath;
481
+ }
482
+ if (data.projects[projectPath]) {
483
+ return projectPath;
484
+ }
485
+ let desiredReal;
486
+ try {
487
+ desiredReal = fs.realpathSync(projectPath);
488
+ } catch {
489
+ return projectPath;
490
+ }
491
+ for (const key of Object.keys(data.projects)) {
492
+ try {
493
+ if (fs.realpathSync(key) === desiredReal) {
494
+ return key;
495
+ }
496
+ } catch {
497
+ // ignore invalid paths
498
+ }
499
+ }
500
+ return projectPath;
501
+ }
502
+
256
503
  function getDefaultDisabled(clientType) {
257
504
  return ["cline", "codex", "windsurf", "goose", "claude", "opencode"].includes(clientType);
258
505
  }
@@ -262,6 +509,8 @@ function writeJsonConfig(filePath, serverName, argsArray, clientType) {
262
509
  const data = readJson(filePath);
263
510
  if (clientType === "opencode") {
264
511
  data.mcp = data.mcp || {};
512
+ } else if (clientType === "antigravity") {
513
+ data.mcpServers = data.mcpServers || {};
265
514
  } else if (clientType === "copilot") {
266
515
  data.servers = data.servers || {};
267
516
  data.inputs = data.inputs || [];
@@ -288,6 +537,8 @@ function writeJsonConfig(filePath, serverName, argsArray, clientType) {
288
537
  };
289
538
  if (clientType === "opencode") {
290
539
  store[serverName].enabled = !options.disabled;
540
+ } else if (clientType === "antigravity") {
541
+ store[serverName].disabled = !!options.disabled;
291
542
  } else {
292
543
  store[serverName].disabled = !!options.disabled;
293
544
  }
@@ -356,6 +607,29 @@ function writeJsonConfig(filePath, serverName, argsArray, clientType) {
356
607
  writeFile(filePath, JSON.stringify(data, null, 2));
357
608
  return;
358
609
  }
610
+ if (clientType === "antigravity") {
611
+ if (options.transport === "stdio") {
612
+ store[serverName] = {
613
+ command: options.command,
614
+ args: argsArray,
615
+ timeout: options.timeout,
616
+ disabled: !!options.disabled,
617
+ };
618
+ } else {
619
+ const entry = {
620
+ type: "http",
621
+ serverUrl: options.url,
622
+ timeout: options.timeout,
623
+ disabled: !!options.disabled,
624
+ };
625
+ if (Object.keys(options.headers).length > 0) {
626
+ entry.headers = options.headers;
627
+ }
628
+ store[serverName] = entry;
629
+ }
630
+ writeFile(filePath, JSON.stringify(data, null, 2));
631
+ return;
632
+ }
359
633
  if (options.transport === "stdio") {
360
634
  data.mcpServers[serverName] = {
361
635
  command: options.command,
@@ -384,30 +658,7 @@ function writeClaudeConfig(filePath, serverName, argsArray) {
384
658
  const data = readJson(filePath);
385
659
  const isDesktopConfig =
386
660
  filePath.endsWith(".claude.json") || filePath.endsWith("claude_desktop_config.json");
387
- const projectPath = process.cwd();
388
- const resolveProjectKey = () => {
389
- const desired = projectPath;
390
- if (!data.projects || data.projects[desired]) {
391
- return desired;
392
- }
393
- let desiredReal;
394
- try {
395
- desiredReal = fs.realpathSync(desired);
396
- } catch {
397
- return desired;
398
- }
399
- const keys = Object.keys(data.projects || {});
400
- for (const key of keys) {
401
- try {
402
- if (fs.realpathSync(key) === desiredReal) {
403
- return key;
404
- }
405
- } catch {
406
- // ignore invalid paths
407
- }
408
- }
409
- return desired;
410
- };
661
+ const resolveProjectKey = () => resolveProjectSelector(data, options.projectPath);
411
662
  const updateClaudeMcpLists = (projectNode) => {
412
663
  projectNode.enabledMcpServers = projectNode.enabledMcpServers || [];
413
664
  projectNode.disabledMcpServers = projectNode.disabledMcpServers || [];
@@ -450,15 +701,35 @@ function writeClaudeConfig(filePath, serverName, argsArray) {
450
701
  };
451
702
  if (options.remove) {
452
703
  if (isDesktopConfig) {
453
- if (!data.projects?.[projectPath]?.mcpServers?.[serverName]) {
454
- fail(`Server "${serverName}" not found for ${projectPath}.`);
455
- }
456
- delete data.projects[projectPath].mcpServers[serverName];
457
- const projectNode = data.projects[projectPath];
458
- projectNode.enabledMcpServers =
459
- projectNode.enabledMcpServers?.filter((name) => name !== serverName) || [];
460
- projectNode.disabledMcpServers =
461
- projectNode.disabledMcpServers?.filter((name) => name !== serverName) || [];
704
+ if (options.allProjects) {
705
+ const projects = Object.keys(data.projects || {});
706
+ let removed = false;
707
+ for (const key of projects) {
708
+ if (data.projects?.[key]?.mcpServers?.[serverName]) {
709
+ delete data.projects[key].mcpServers[serverName];
710
+ const projectNode = data.projects[key];
711
+ projectNode.enabledMcpServers =
712
+ projectNode.enabledMcpServers?.filter((name) => name !== serverName) || [];
713
+ projectNode.disabledMcpServers =
714
+ projectNode.disabledMcpServers?.filter((name) => name !== serverName) || [];
715
+ removed = true;
716
+ }
717
+ }
718
+ if (!removed) {
719
+ fail(`Server "${serverName}" not found in any Claude projects.`);
720
+ }
721
+ } else {
722
+ const projectKey = resolveProjectKey();
723
+ if (!data.projects?.[projectKey]?.mcpServers?.[serverName]) {
724
+ fail(`Server "${serverName}" not found for ${projectKey}.`);
725
+ }
726
+ delete data.projects[projectKey].mcpServers[serverName];
727
+ const projectNode = data.projects[projectKey];
728
+ projectNode.enabledMcpServers =
729
+ projectNode.enabledMcpServers?.filter((name) => name !== serverName) || [];
730
+ projectNode.disabledMcpServers =
731
+ projectNode.disabledMcpServers?.filter((name) => name !== serverName) || [];
732
+ }
462
733
  } else {
463
734
  data.mcpServers = data.mcpServers || {};
464
735
  if (!data.mcpServers[serverName]) {
@@ -474,6 +745,42 @@ function writeClaudeConfig(filePath, serverName, argsArray) {
474
745
  }
475
746
  if (isDesktopConfig) {
476
747
  data.projects = data.projects || {};
748
+ if (options.toggle) {
749
+ if (options.allProjects) {
750
+ const projects = Object.keys(data.projects || {});
751
+ let toggled = false;
752
+ for (const key of projects) {
753
+ if (!data.projects[key]) {
754
+ continue;
755
+ }
756
+ data.projects[key].mcpServers = data.projects[key].mcpServers || {};
757
+ if (!data.projects[key].mcpServers[serverName]) {
758
+ continue;
759
+ }
760
+ updateClaudeMcpLists(data.projects[key]);
761
+ toggled = true;
762
+ }
763
+ if (!toggled) {
764
+ fail(`Server "${serverName}" not found in any Claude projects.`);
765
+ }
766
+ writeFile(filePath, JSON.stringify(data, null, 2));
767
+ return;
768
+ }
769
+ const projectKey = resolveProjectKey();
770
+ if (!data.projects[projectKey]) {
771
+ data.projects[projectKey] = {
772
+ allowedTools: [],
773
+ mcpContextUris: [],
774
+ mcpServers: {},
775
+ enabledMcpServers: [],
776
+ disabledMcpServers: [],
777
+ };
778
+ }
779
+ data.projects[projectKey].mcpServers = data.projects[projectKey].mcpServers || {};
780
+ updateClaudeMcpLists(data.projects[projectKey]);
781
+ writeFile(filePath, JSON.stringify(data, null, 2));
782
+ return;
783
+ }
477
784
  const projectKey = resolveProjectKey();
478
785
  if (!data.projects[projectKey]) {
479
786
  data.projects[projectKey] = {
@@ -488,14 +795,6 @@ function writeClaudeConfig(filePath, serverName, argsArray) {
488
795
  data.projects[projectKey].disabledMcpServers =
489
796
  data.projects[projectKey].disabledMcpServers || [];
490
797
  data.projects[projectKey].mcpServers = data.projects[projectKey].mcpServers || {};
491
- if (options.toggle) {
492
- if (!data.projects[projectKey].mcpServers[serverName]) {
493
- fail(`Server "${serverName}" not found for ${projectKey}.`);
494
- }
495
- updateClaudeMcpLists(data.projects[projectKey]);
496
- writeFile(filePath, JSON.stringify(data, null, 2));
497
- return;
498
- }
499
798
  if (data.projects[projectKey].mcpServers[serverName] && !options.force) {
500
799
  fail(`Server "${serverName}" already exists for ${projectKey}. Use --force to overwrite.`);
501
800
  }
@@ -532,7 +831,7 @@ function writeClaudeConfig(filePath, serverName, argsArray) {
532
831
  };
533
832
  } else {
534
833
  const entry = {
535
- type: options.transport,
834
+ type: options.transport === "streamableHttp" ? "http" : options.transport,
536
835
  url: options.url,
537
836
  timeout: options.timeout,
538
837
  };
@@ -545,6 +844,30 @@ function writeClaudeConfig(filePath, serverName, argsArray) {
545
844
  writeFile(filePath, JSON.stringify(data, null, 2));
546
845
  }
547
846
 
847
+ function resolveClaudeProjectKey(data, projectPath = process.cwd()) {
848
+ const desired = projectPath;
849
+ if (!data.projects || data.projects[desired]) {
850
+ return desired;
851
+ }
852
+ let desiredReal;
853
+ try {
854
+ desiredReal = fs.realpathSync(desired);
855
+ } catch {
856
+ return desired;
857
+ }
858
+ const keys = Object.keys(data.projects || {});
859
+ for (const key of keys) {
860
+ try {
861
+ if (fs.realpathSync(key) === desiredReal) {
862
+ return key;
863
+ }
864
+ } catch {
865
+ // ignore invalid paths
866
+ }
867
+ }
868
+ return desired;
869
+ }
870
+
548
871
  function writeCodexConfig(filePath, serverName, argsArray) {
549
872
  ensureDir(filePath);
550
873
  if (!toml) {
@@ -663,6 +986,141 @@ function writeGooseConfig(filePath, serverName, argsArray) {
663
986
  writeFile(filePath, yaml.stringify(data));
664
987
  }
665
988
 
989
+ function listJsonConfig(filePath, clientType) {
990
+ const data = readJson(filePath);
991
+ let store;
992
+ if (clientType === "opencode") {
993
+ store = data.mcp || {};
994
+ } else if (clientType === "antigravity") {
995
+ store = data.mcpServers || {};
996
+ } else if (clientType === "copilot") {
997
+ store = data.servers || {};
998
+ } else {
999
+ store = data.mcpServers || {};
1000
+ }
1001
+ outputList(filePath, Object.keys(store));
1002
+ }
1003
+
1004
+ function listCodexConfig(filePath) {
1005
+ if (!toml) {
1006
+ fail("TOML dependency not available. Install dependencies and retry.");
1007
+ }
1008
+ const data = readToml(filePath);
1009
+ const store = data.mcp_servers || {};
1010
+ outputList(filePath, Object.keys(store));
1011
+ }
1012
+
1013
+ function listGooseConfig(filePath) {
1014
+ if (!yaml) {
1015
+ fail("YAML dependency not available. Install dependencies and retry.");
1016
+ }
1017
+ const data = readYaml(filePath);
1018
+ const store = data.extensions || {};
1019
+ outputList(filePath, Object.keys(store));
1020
+ }
1021
+
1022
+ function listClaudeConfig(filePath, allProjects, projectPath) {
1023
+ const data = readJson(filePath);
1024
+ const isDesktopConfig =
1025
+ filePath.endsWith(".claude.json") || filePath.endsWith("claude_desktop_config.json");
1026
+ if (isDesktopConfig) {
1027
+ const projects = Object.keys(data.projects || {});
1028
+ if (allProjects) {
1029
+ if (!projects.length) {
1030
+ outputList(filePath, [], "no-projects");
1031
+ return;
1032
+ }
1033
+ for (const key of projects.sort()) {
1034
+ const projectNode = data.projects?.[key];
1035
+ const store = projectNode?.mcpServers || {};
1036
+ outputList(filePath, Object.keys(store), key);
1037
+ }
1038
+ return;
1039
+ }
1040
+ const projectKey = resolveProjectSelector(data, projectPath);
1041
+ const projectNode = data.projects?.[projectKey];
1042
+ const store = projectNode?.mcpServers || {};
1043
+ outputList(filePath, Object.keys(store), projectKey);
1044
+ return;
1045
+ }
1046
+ const store = data.mcpServers || {};
1047
+ outputList(filePath, Object.keys(store));
1048
+ }
1049
+
1050
+ function claudeLocalHasServer(filePath, serverName) {
1051
+ const data = readJson(filePath);
1052
+ const store = data.mcpServers || {};
1053
+ return Boolean(store[serverName]);
1054
+ }
1055
+
1056
+ function whereJsonConfig(filePath, clientType, serverName) {
1057
+ const data = readJson(filePath);
1058
+ let store;
1059
+ if (clientType === "opencode") {
1060
+ store = data.mcp || {};
1061
+ } else if (clientType === "antigravity") {
1062
+ store = data.mcpServers || {};
1063
+ } else if (clientType === "copilot") {
1064
+ store = data.servers || {};
1065
+ } else {
1066
+ store = data.mcpServers || {};
1067
+ }
1068
+ outputWhere(filePath, serverName, Boolean(store[serverName]));
1069
+ }
1070
+
1071
+ function whereCodexConfig(filePath, serverName) {
1072
+ if (!toml) {
1073
+ fail("TOML dependency not available. Install dependencies and retry.");
1074
+ }
1075
+ const data = readToml(filePath);
1076
+ const store = data.mcp_servers || {};
1077
+ outputWhere(filePath, serverName, Boolean(store[serverName]));
1078
+ }
1079
+
1080
+ function whereGooseConfig(filePath, serverName) {
1081
+ if (!yaml) {
1082
+ fail("YAML dependency not available. Install dependencies and retry.");
1083
+ }
1084
+ const data = readYaml(filePath);
1085
+ const store = data.extensions || {};
1086
+ outputWhere(filePath, serverName, Boolean(store[serverName]));
1087
+ }
1088
+
1089
+ function whereClaudeConfig(filePath, serverName, allProjects, projectPath) {
1090
+ const data = readJson(filePath);
1091
+ const isDesktopConfig =
1092
+ filePath.endsWith(".claude.json") || filePath.endsWith("claude_desktop_config.json");
1093
+ if (isDesktopConfig) {
1094
+ const projects = Object.keys(data.projects || {});
1095
+ if (allProjects) {
1096
+ if (!projects.length) {
1097
+ outputWhere(filePath, serverName, false, "no-projects");
1098
+ return;
1099
+ }
1100
+ let found = false;
1101
+ for (const key of projects.sort()) {
1102
+ const projectNode = data.projects?.[key];
1103
+ const store = projectNode?.mcpServers || {};
1104
+ if (store[serverName]) {
1105
+ outputWhere(filePath, serverName, true, key);
1106
+ found = true;
1107
+ }
1108
+ }
1109
+ if (!found) {
1110
+ outputWhere(filePath, serverName, false, "all-projects");
1111
+ }
1112
+ return;
1113
+ }
1114
+ const projectKey = resolveProjectSelector(data, projectPath);
1115
+ const projectNode = data.projects?.[projectKey];
1116
+ const store = projectNode?.mcpServers || {};
1117
+ outputWhere(filePath, serverName, Boolean(store[serverName]), projectKey);
1118
+ return;
1119
+ }
1120
+ const store = data.mcpServers || {};
1121
+ outputWhere(filePath, serverName, Boolean(store[serverName]));
1122
+ }
1123
+
666
1124
  function readJson(filePath) {
667
1125
  if (!fs.existsSync(filePath)) {
668
1126
  return {};
@@ -708,6 +1166,24 @@ function readToml(filePath) {
708
1166
  }
709
1167
  }
710
1168
 
1169
+ function outputList(filePath, keys, projectKey) {
1170
+ const header = projectKey ? `# ${filePath} (${projectKey})` : `# ${filePath}`;
1171
+ process.stdout.write(`${header}\n`);
1172
+ if (!keys.length) {
1173
+ process.stdout.write("- (none)\n");
1174
+ return;
1175
+ }
1176
+ for (const name of keys.sort()) {
1177
+ process.stdout.write(`- ${name}\n`);
1178
+ }
1179
+ }
1180
+
1181
+ function outputWhere(filePath, serverName, found, projectKey) {
1182
+ const header = projectKey ? `# ${filePath} (${projectKey})` : `# ${filePath}`;
1183
+ process.stdout.write(`${header}\n`);
1184
+ process.stdout.write(`- ${serverName}: ${found ? "found" : "not found"}\n`);
1185
+ }
1186
+
711
1187
  function ensureDir(filePath) {
712
1188
  const dir = path.dirname(filePath);
713
1189
  if (!fs.existsSync(dir)) {
@@ -729,30 +1205,158 @@ function fail(message) {
729
1205
  process.exit(1);
730
1206
  }
731
1207
 
732
- function printHelp() {
733
- process.stdout.write(`mcp-conf
1208
+ function printHelp(command) {
1209
+ const header = "mcp-conf";
1210
+ if (!command) {
1211
+ process.stdout.write(`${header}
734
1212
 
735
1213
  Usage:
736
- mcp-conf --client <name> --name <serverName> [--env <path> | --mcp <dest>] [options]
1214
+ mcp-conf <add|rm|ls|enable|disable|where> --client <name> [options]
1215
+ mcp-conf help <command>
1216
+
1217
+ Commands:
1218
+ add add or update an MCP server entry
1219
+ rm remove an MCP server entry
1220
+ ls list MCP server entries
1221
+ enable enable an existing entry
1222
+ disable disable an existing entry
1223
+ where show where a server name is defined
1224
+
1225
+ Run:
1226
+ mcp-conf <command> --help
1227
+ mcp-conf help <command>
1228
+
1229
+ Notes:
1230
+ Scope defaults to --global (Copilot uses --local only).
1231
+ For Claude, --local maps to the project scope file ./.mcp.json.
1232
+ `);
1233
+ return;
1234
+ }
1235
+ switch (command) {
1236
+ case "add":
1237
+ process.stdout.write(`${header} add
1238
+
1239
+ Usage:
1240
+ mcp-conf add --client <name> --name <serverName> [--env <path> | --mcp <dest>] [options]
737
1241
 
738
1242
  Options:
739
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot (repeatable)
1243
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
740
1244
  --name <serverName> required MCP server name key
741
- --env <path> .env path (add/update only)
742
- --mcp <dest> destination name (add/update only)
1245
+ --env <path> .env path (stdio only)
1246
+ --mcp <dest> destination name (stdio only)
743
1247
  --transport <type> stdio | sse | http (http => streamableHttp)
744
1248
  --command <bin> command to run (default: mcp-abap-adt)
1249
+ --global write to global user config (default)
1250
+ --local write to project config (where supported)
1251
+ --project <path> Claude global: target a specific project path
745
1252
  --url <http(s)://...> required for sse/http
746
1253
  --header key=value add request header (repeatable)
747
1254
  --timeout <seconds> entry timeout (default: 60)
748
- --disable disable entry (Codex/OpenCode/Cline/Windsurf/Goose/Claude; not Cursor/Copilot)
749
- --enable enable entry (Codex/OpenCode/Cline/Windsurf/Goose/Claude; not Cursor/Copilot)
750
- --remove remove entry
751
- --force overwrite existing entry (add/update)
1255
+ --force overwrite existing entry
1256
+ --dry-run print changes without writing files
1257
+
1258
+ Notes:
1259
+ Antigravity local scope is not supported yet; use --global.
1260
+ `);
1261
+ break;
1262
+ case "rm":
1263
+ process.stdout.write(`${header} rm
1264
+
1265
+ Usage:
1266
+ mcp-conf rm --client <name> --name <serverName> [options]
1267
+
1268
+ Options:
1269
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1270
+ --name <serverName> required MCP server name key
1271
+ --global write to global user config (default)
1272
+ --local write to project config (where supported)
1273
+ --all-projects Claude global: remove across all projects
1274
+ --project <path> Claude global: target a specific project path
1275
+ --dry-run print changes without writing files
1276
+
1277
+ Notes:
1278
+ Antigravity local scope is not supported yet; use --global.
1279
+ `);
1280
+ break;
1281
+ case "ls":
1282
+ process.stdout.write(`${header} ls
1283
+
1284
+ Usage:
1285
+ mcp-conf ls --client <name> [options]
1286
+
1287
+ Options:
1288
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1289
+ --global write to global user config (default)
1290
+ --local write to project config (where supported)
1291
+ --all-projects Claude global: list across all projects
1292
+ --project <path> Claude global: target a specific project path
1293
+
1294
+ Notes:
1295
+ Antigravity local scope is not supported yet; use --global.
1296
+ `);
1297
+ break;
1298
+ case "enable":
1299
+ process.stdout.write(`${header} enable
1300
+
1301
+ Usage:
1302
+ mcp-conf enable --client <name> --name <serverName> [options]
1303
+
1304
+ Options:
1305
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1306
+ --name <serverName> required MCP server name key
1307
+ --global write to global user config (default)
1308
+ --local write to project config (where supported)
1309
+ --all-projects Claude global: enable across all projects
1310
+ --project <path> Claude global: target a specific project path
752
1311
  --dry-run print changes without writing files
753
- -h, --help show this help
754
1312
 
755
1313
  Notes:
756
- New entries for Cline/Codex/Windsurf/Goose/Claude/OpenCode are added disabled by default.
1314
+ Antigravity local scope is not supported yet; use --global.
757
1315
  `);
1316
+ break;
1317
+ case "disable":
1318
+ process.stdout.write(`${header} disable
1319
+
1320
+ Usage:
1321
+ mcp-conf disable --client <name> --name <serverName> [options]
1322
+
1323
+ Options:
1324
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1325
+ --name <serverName> required MCP server name key
1326
+ --global write to global user config (default)
1327
+ --local write to project config (where supported)
1328
+ --all-projects Claude global: disable across all projects
1329
+ --project <path> Claude global: target a specific project path
1330
+ --dry-run print changes without writing files
1331
+
1332
+ Notes:
1333
+ Antigravity local scope is not supported yet; use --global.
1334
+ `);
1335
+ break;
1336
+ case "where":
1337
+ process.stdout.write(`${header} where
1338
+
1339
+ Usage:
1340
+ mcp-conf where --client <name> --name <serverName> [options]
1341
+
1342
+ Options:
1343
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1344
+ --name <serverName> required MCP server name key
1345
+ --global write to global user config (default)
1346
+ --local write to project config (where supported)
1347
+ --all-projects Claude global: search across all projects
1348
+ --project <path> Claude global: target a specific project path
1349
+
1350
+ Notes:
1351
+ Antigravity local scope is not supported yet; use --global.
1352
+ `);
1353
+ break;
1354
+ default:
1355
+ process.stdout.write(`${header}
1356
+
1357
+ Unknown command "${command}".
1358
+ Run:
1359
+ mcp-conf help
1360
+ `);
1361
+ }
758
1362
  }
@@ -11,79 +11,109 @@ npm install -g @mcp-abap-adt/configurator
11
11
  ## Usage
12
12
 
13
13
  ```bash
14
- mcp-conf --client cline --env /path/to/.env --name abap
15
- mcp-conf --client cline --mcp TRIAL --name abap
16
- mcp-conf --client cline --env /path/to/.env --name abap --transport stdio
17
- mcp-conf --client claude --mcp TRIAL --name abap
18
- mcp-conf --client codex --name abap --remove
19
- mcp-conf --client cline --name direct-jwt-test-001 --transport http --url http://localhost:4004/mcp/stream/http --header x-sap-url=https://... --header x-sap-client=210 --header x-sap-auth-type=jwt --header x-sap-jwt-token=...
20
- mcp-conf --client cline --name local-mcp-sse --transport sse --url http://localhost:3001/sse
21
- mcp-conf --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http
22
- mcp-conf --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
23
- mcp-conf --client opencode --name abap --transport http --url http://localhost:3000/mcp/stream/http
24
- mcp-conf --client copilot --name abap --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
14
+ mcp-conf add --client cline --env /path/to/.env --name abap
15
+ mcp-conf add --client cline --mcp TRIAL --name abap
16
+ mcp-conf add --client cline --env /path/to/.env --name abap --transport stdio
17
+ mcp-conf add --client claude --mcp TRIAL --name abap
18
+ mcp-conf rm --client codex --name abap
19
+ mcp-conf add --client cline --name direct-jwt-test-001 --transport http --url http://localhost:4004/mcp/stream/http --header x-sap-url=https://... --header x-sap-client=210 --header x-sap-auth-type=jwt --header x-sap-jwt-token=...
20
+ mcp-conf add --client cline --name local-mcp-sse --transport sse --url http://localhost:3001/sse
21
+ mcp-conf add --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http
22
+ mcp-conf add --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
23
+ mcp-conf add --client opencode --name abap --transport http --url http://localhost:3000/mcp/stream/http
24
+ mcp-conf add --client copilot --name abap --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
25
+ mcp-conf add --client antigravity --name abap --transport http --url http://localhost:3000/mcp/stream/http
25
26
  ```
26
27
 
27
28
  ## Common Tasks
28
29
 
29
30
  Add MCP:
30
31
  ```bash
31
- mcp-conf --client codex --mcp TRIAL --name abap
32
- mcp-conf --client cline --env /path/to/.env --name abap
33
- mcp-conf --client claude --mcp TRIAL --name abap
32
+ mcp-conf add --client codex --mcp TRIAL --name abap
33
+ mcp-conf add --client cline --env /path/to/.env --name abap
34
+ mcp-conf add --client claude --mcp TRIAL --name abap
35
+ mcp-conf add --client claude --name abap-http --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
36
+ mcp-conf add --client claude --name abap --project /path/to/project --mcp TRIAL
34
37
  ```
35
38
 
36
39
  Disable MCP:
37
40
  ```bash
38
- mcp-conf --client codex --name abap --disable
39
- mcp-conf --client cline --name abap --disable
41
+ mcp-conf disable --client codex --name abap
42
+ mcp-conf disable --client cline --name abap
40
43
  ```
41
44
 
42
45
  Enable MCP:
43
46
  ```bash
44
- mcp-conf --client codex --name abap --enable
45
- mcp-conf --client cline --name abap --enable
47
+ mcp-conf enable --client codex --name abap
48
+ mcp-conf enable --client cline --name abap
49
+ mcp-conf enable --client antigravity --name abap
46
50
  ```
47
51
 
48
52
  Remove MCP:
49
53
  ```bash
50
- mcp-conf --client codex --name abap --remove
51
- mcp-conf --client cline --name abap --remove
52
- mcp-conf --client claude --name abap --remove
54
+ mcp-conf rm --client codex --name abap
55
+ mcp-conf rm --client cline --name abap
56
+ mcp-conf rm --client claude --name abap
57
+ mcp-conf rm --client antigravity --name abap
58
+ ```
59
+
60
+ List MCP servers:
61
+ ```bash
62
+ mcp-conf ls --client codex
63
+ mcp-conf ls --client cline
64
+ mcp-conf ls --client claude --local
65
+ mcp-conf ls --client claude --all-projects
66
+ mcp-conf ls --client antigravity --global
67
+ ```
68
+
69
+ Find where a server is defined:
70
+ ```bash
71
+ mcp-conf where --client codex --name abap
72
+ mcp-conf where --client claude --name goose --project /path/to/project
73
+ mcp-conf where --client claude --name goose --all-projects
53
74
  ```
54
75
 
55
76
  Options:
56
- - `--client <name>` (repeatable): `cline`, `codex`, `claude`, `goose`, `cursor`, `windsurf`, `opencode`, `copilot`
77
+ - Commands: `add`, `rm`, `ls`, `enable`, `disable`, `where` (first argument)
78
+ - `--client <name>` (repeatable): `cline`, `codex`, `claude`, `goose`, `cursor`, `windsurf`, `opencode`, `copilot`, `antigravity`
57
79
  - `--env <path>`: use a specific `.env` file
58
80
  - `--mcp <destination>`: use service key destination
59
81
  - `--name <serverName>`: MCP server name (required)
60
82
  - `--transport <type>`: `stdio`, `sse`, or `http` (`http` maps to `streamableHttp`)
61
83
  - `--command <bin>`: command to run (default: `mcp-abap-adt`)
84
+ - `--global`: write to the global user config (default)
85
+ - `--local`: write to the project config (supported by `cursor`, `opencode`, `copilot`, `claude`)
86
+ - `--all-projects`: for Claude (global scope), apply `rm/enable/disable/ls/where` across all projects
87
+ - `--project <path>`: for Claude (global scope), target a specific project path
62
88
  - `--url <http(s)://...>`: required for `sse` and `http`
63
89
  - `--header key=value`: add request header (repeatable)
64
90
  - `--timeout <seconds>`: timeout value for client entries (default: 60)
65
- - `--disable`: disable server entry (Codex/OpenCode: `enabled = false`, Cline/Windsurf: `disabled = true`, Claude: moves name to `disabledMcpServers`; not Cursor/Copilot)
66
- - `--enable`: enable server entry (Codex/OpenCode: `enabled = true`, Cline/Windsurf: `disabled = false`, Claude: moves name to `enabledMcpServers`; not Cursor/Copilot)
67
- - `--remove`: remove server entry from client config
68
91
 
69
92
  Notes:
70
- - `--disable` and `--remove` do not require `--env` or `--mcp`.
93
+ - `disable` and `rm` do not require `--env` or `--mcp`.
71
94
  - `--env`/`--mcp` are only valid for `stdio` transport. For `sse/http`, use `--url` and optional `--header`.
72
95
  - Cursor/Copilot enable/disable are not implemented yet.
96
+ - Antigravity enable/disable uses `disabled: true|false` on the entry.
97
+ - Antigravity local scope is not supported yet; use `--global`.
73
98
  - Claude stores enable/disable state under `enabledMcpServers` and `disabledMcpServers` for each project.
74
- - New entries for Cline, Codex, Windsurf, Goose, Claude, and OpenCode are added **disabled by default**. Use `--enable` to turn them on.
99
+ - Claude enable/disable always updates `~/.claude.json` (global scope), even if you pass `--local`.
100
+ - Antigravity HTTP entries use `serverUrl` instead of `url`.
101
+ - New entries for Cline, Codex, Windsurf, Goose, Claude, and OpenCode are added **disabled by default**. Use `enable` to turn them on.
75
102
  - Windsurf follows `disabled` like Cline. The configurator sets `disabled = true` for default-disabled entries.
76
- - `--enable`/`--disable` only work if the server entry already exists. Use add commands with `--env` or `--mcp` first.
103
+ - `enable`/`disable` only work if the server entry already exists. Use add commands with `--env` or `--mcp` first.
77
104
  - Non-stdio transports are supported for Cline/Cursor/Windsurf/Claude/Goose. Codex supports `http` (streamable HTTP) but not `sse`.
78
105
  - Codex writes custom headers under `http_headers` in `~/.codex/config.toml`.
79
106
  - Codex HTTP entries include `startup_timeout_sec` (default: 60).
80
107
  - `--dry-run`: print changes without writing files
81
108
  - `--force`: overwrite existing server entry if it exists
109
+ - Scope defaults to `--global` (GitHub Copilot is `--local` only).
110
+ - For Claude, `--local` maps to the documented project scope file `./.mcp.json`.
82
111
 
83
112
  ## Config Locations
84
113
 
85
114
  Paths are client-specific and OS-dependent. The installer writes config files in:
86
115
 
116
+ Global (default) locations:
87
117
  - **Cline**:
88
118
  - Linux/macOS: `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
89
119
  - Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json`
@@ -104,8 +134,20 @@ Paths are client-specific and OS-dependent. The installer writes config files in
104
134
  - **Windsurf**:
105
135
  - Linux/macOS: `~/.codeium/windsurf/mcp_config.json`
106
136
  - Windows: `%USERPROFILE%\.codeium\windsurf\mcp_config.json`
137
+ - **OpenCode**:
138
+ - Linux/macOS: `~/.config/opencode/opencode.json`
139
+ - Windows: `%APPDATA%\opencode\opencode.json`
140
+ - **Antigravity**:
141
+ - Linux/macOS: `~/.gemini/antigravity/mcp_config.json`
142
+
143
+ Local (project) locations:
144
+ - **Claude Code**:
145
+ - Project: `./.mcp.json`
146
+ - **Cursor**:
147
+ - Project: `./.cursor/mcp.json`
107
148
  - **OpenCode**:
108
149
  - Project: `./opencode.json` (uses `mcp.<name>` entries with `enabled: true|false`)
109
150
  - **GitHub Copilot**:
110
151
  - Project: `./.vscode/mcp.json` (uses `servers.<name>` entries)
111
-
152
+ - **Antigravity**:
153
+ - Project: `./.antigravity/mcp.json` (community-reported; not supported yet)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/configurator",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "MCP client configurator for mcp-abap-adt and mcp-abap-adt-proxy",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,7 +27,7 @@
27
27
  "npm": ">=9.0.0"
28
28
  },
29
29
  "dependencies": {
30
- "@iarna/toml": "^2.2.5",
30
+ "@iarna/toml": "^3.0.0",
31
31
  "yaml": "^2.8.1"
32
32
  },
33
33
  "devDependencies": {