@mcp-abap-adt/configurator 0.0.5 → 0.0.6

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/README.md CHANGED
@@ -11,17 +11,25 @@ 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
14
+ mcp-conf --client cline --env-path /path/to/.env --name abap
15
15
  mcp-conf --client cline --mcp TRIAL --name abap
16
16
  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=...
17
17
  mcp-conf --client cline --name local-mcp-sse --transport sse --url http://localhost:3001/sse
18
18
  mcp-conf --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http
19
19
  mcp-conf --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
20
20
  mcp-conf --client opencode --name abap --transport http --url http://localhost:3000/mcp/stream/http
21
+ mcp-conf --client kilo --name abap --transport http --url http://localhost:3000/mcp/stream/http
21
22
  mcp-conf --client copilot --name abap --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
23
+ mcp-conf tui
22
24
  ```
23
25
 
26
+ ## TUI
27
+
28
+ `mcp-conf tui` starts an interactive wizard.
29
+ - Step order: `operation` -> `client` -> `scope` (auto-skipped if only one scope is supported).
30
+ - For `add` + `sse/http`: prompts for URL, timeout, and repeatable headers.
31
+ - Keyboard: arrow keys + Enter, Ctrl+C to cancel.
32
+
24
33
  ## Docs
25
34
 
26
35
  - See `docs/CLIENT_INSTALLERS.md` for client-specific behavior, defaults, and config paths.
27
-
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Select, Input, Confirm } = require("enquirer");
4
+ const fs = require("node:fs");
5
+
6
+ const CLIENTS = [
7
+ { name: "cline", message: "Cline" },
8
+ { name: "codex", message: "Codex" },
9
+ { name: "claude", message: "Claude" },
10
+ { name: "goose", message: "Goose" },
11
+ { name: "cursor", message: "Cursor" },
12
+ { name: "windsurf", message: "Windsurf" },
13
+ { name: "opencode", message: "OpenCode (kilo)" },
14
+ { name: "copilot", message: "GitHub Copilot" },
15
+ { name: "antigravity", message: "Antigravity" },
16
+ ];
17
+
18
+ const HEADER_KEYS = [
19
+ "x-mcp-destination",
20
+ "x-sap-url",
21
+ "x-sap-client",
22
+ "x-sap-auth-type",
23
+ "x-sap-jwt-token",
24
+ "x-sap-user",
25
+ "x-sap-password",
26
+ ];
27
+
28
+ async function main() {
29
+ const result = {
30
+ headers: {},
31
+ timeout: 60,
32
+ };
33
+
34
+ result.tuiAction = await askSelect("Operation", ["ls", "add", "rm", "enable", "disable"]);
35
+ const client = await askSelect(
36
+ "Client",
37
+ CLIENTS.map((item) => item.name),
38
+ CLIENTS.map((item) => item.message),
39
+ );
40
+ result.clients = [client];
41
+
42
+ const scopes = getSupportedScopes(client);
43
+ result.scope = scopes.length === 1 ? scopes[0] : await askSelect("Scope", ["global", "local"]);
44
+
45
+ if (result.tuiAction !== "ls") {
46
+ result.name = await askInput("Server name", "abap");
47
+ } else {
48
+ result.name = null;
49
+ }
50
+
51
+ if (result.tuiAction !== "add") {
52
+ emitResult(result);
53
+ return;
54
+ }
55
+
56
+ const transports = getSupportedTransports(client);
57
+ result.transport =
58
+ transports.length === 1 ? transports[0] : await askSelect("Transport", transports);
59
+
60
+ if (result.transport === "stdio") {
61
+ const authSource = await askSelect("Auth source for stdio", [
62
+ "service key destination (--mcp)",
63
+ "session environment (--env)",
64
+ "specific env file (--env-path)",
65
+ ]);
66
+ if (authSource.startsWith("service key")) {
67
+ result.mcpDestination = await askInput("Destination name", "TRIAL");
68
+ result.useSessionEnv = false;
69
+ result.envPath = null;
70
+ result.url = null;
71
+ emitResult(result);
72
+ return;
73
+ }
74
+ if (authSource.startsWith("specific env file")) {
75
+ result.envPath = await askInput("Path to .env file");
76
+ result.useSessionEnv = false;
77
+ result.mcpDestination = null;
78
+ result.url = null;
79
+ emitResult(result);
80
+ return;
81
+ }
82
+ result.useSessionEnv = true;
83
+ result.envPath = null;
84
+ result.mcpDestination = null;
85
+ result.url = null;
86
+ emitResult(result);
87
+ return;
88
+ }
89
+
90
+ result.url = await askInput("Server URL (http/https)");
91
+ result.timeout = await askPositiveNumber("Timeout seconds", 60);
92
+ result.headers = await askHeaders();
93
+ result.useSessionEnv = false;
94
+ result.envPath = null;
95
+ result.mcpDestination = null;
96
+
97
+ emitResult(result);
98
+ }
99
+
100
+ function emitResult(result) {
101
+ fs.writeFileSync(3, JSON.stringify(result), "utf8");
102
+ }
103
+
104
+ async function askSelect(message, choices, choiceLabels) {
105
+ const promptChoices = choices.map((value, index) => ({
106
+ name: value,
107
+ message: choiceLabels?.[index] || value,
108
+ }));
109
+ const select = new Select({
110
+ name: "value",
111
+ message,
112
+ choices: promptChoices,
113
+ footer: "Use arrow keys + Enter. Ctrl+C to cancel.",
114
+ });
115
+ return select.run();
116
+ }
117
+
118
+ async function askInput(message, initial) {
119
+ const input = new Input({
120
+ name: "value",
121
+ message,
122
+ initial,
123
+ });
124
+ const value = await input.run();
125
+ if (!String(value || "").trim()) {
126
+ return askInput(message, initial);
127
+ }
128
+ return String(value).trim();
129
+ }
130
+
131
+ async function askPositiveNumber(message, initialValue) {
132
+ while (true) {
133
+ const raw = await askInput(message, String(initialValue));
134
+ const parsed = Number(raw);
135
+ if (Number.isFinite(parsed) && parsed > 0) {
136
+ return parsed;
137
+ }
138
+ }
139
+ }
140
+
141
+ async function askHeaders() {
142
+ const headers = {};
143
+ while (true) {
144
+ const key = await askSelect("Header key", [...HEADER_KEYS, "done"]);
145
+ if (key === "done") {
146
+ return headers;
147
+ }
148
+ headers[key] = await askInput(`Value for ${key}`);
149
+ const addMore = await new Confirm({
150
+ name: "value",
151
+ message: "Add another header?",
152
+ initial: true,
153
+ }).run();
154
+ if (!addMore) {
155
+ return headers;
156
+ }
157
+ }
158
+ }
159
+
160
+ function getSupportedScopes(clientName) {
161
+ if (clientName === "copilot") {
162
+ return ["local"];
163
+ }
164
+ if (["cline", "goose", "windsurf", "antigravity"].includes(clientName)) {
165
+ return ["global"];
166
+ }
167
+ return ["global", "local"];
168
+ }
169
+
170
+ function getSupportedTransports(clientName) {
171
+ if (clientName === "codex") {
172
+ return ["stdio", "http"];
173
+ }
174
+ return ["stdio", "sse", "http"];
175
+ }
176
+
177
+ main().catch((error) => {
178
+ if (error === "") {
179
+ process.exit(0);
180
+ }
181
+ process.stderr.write(`${error?.message || String(error)}\n`);
182
+ process.exit(1);
183
+ });
package/bin/mcp-conf.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const fs = require("node:fs");
4
4
  const path = require("node:path");
5
5
  const os = require("node:os");
6
+ const { spawnSync } = require("node:child_process");
6
7
 
7
8
  let yaml;
8
9
  try {
@@ -23,12 +24,13 @@ try {
23
24
 
24
25
  const args = process.argv.slice(2);
25
26
  const action = args[0] && !args[0].startsWith("-") ? args[0] : null;
26
- if (action && ["add", "rm", "ls", "enable", "disable", "where", "help"].includes(action)) {
27
+ if (action && ["add", "rm", "ls", "enable", "disable", "where", "tui", "help"].includes(action)) {
27
28
  args.shift();
28
29
  }
29
30
  const options = {
30
31
  clients: [],
31
32
  envPath: null,
33
+ useSessionEnv: false,
32
34
  mcpDestination: null,
33
35
  name: null,
34
36
  transport: "stdio",
@@ -52,7 +54,7 @@ if (args.includes("--help") || args.includes("-h") || action === "help") {
52
54
  const helpAction =
53
55
  action === "help"
54
56
  ? args[0]
55
- : action && ["add", "rm", "ls", "enable", "disable", "where"].includes(action)
57
+ : action && ["add", "rm", "ls", "enable", "disable", "where", "tui"].includes(action)
56
58
  ? action
57
59
  : null;
58
60
  printHelp(helpAction);
@@ -62,13 +64,34 @@ if (args.includes("--help") || args.includes("-h") || action === "help") {
62
64
  for (let i = 0; i < args.length; i += 1) {
63
65
  const arg = args[i];
64
66
  if (arg === "--client") {
65
- options.clients.push(args[i + 1]);
67
+ options.clients.push(normalizeClientName(args[i + 1]));
66
68
  i += 1;
67
69
  } else if (arg === "--env") {
70
+ const maybePath = args[i + 1];
71
+ if (maybePath && !maybePath.startsWith("-")) {
72
+ // Backward-compatible form: --env /path/to/.env
73
+ options.envPath = maybePath;
74
+ options.useSessionEnv = false;
75
+ options.mcpDestination = null;
76
+ i += 1;
77
+ } else {
78
+ options.useSessionEnv = true;
79
+ options.envPath = null;
80
+ options.mcpDestination = null;
81
+ }
82
+ } else if (arg === "--env-path") {
68
83
  options.envPath = args[i + 1];
84
+ options.useSessionEnv = false;
85
+ options.mcpDestination = null;
69
86
  i += 1;
87
+ } else if (arg === "--session-env") {
88
+ options.useSessionEnv = true;
89
+ options.envPath = null;
90
+ options.mcpDestination = null;
70
91
  } else if (arg === "--mcp") {
71
92
  options.mcpDestination = args[i + 1];
93
+ options.useSessionEnv = false;
94
+ options.envPath = null;
72
95
  i += 1;
73
96
  } else if (arg === "--name") {
74
97
  options.name = args[i + 1];
@@ -122,40 +145,46 @@ for (let i = 0; i < args.length; i += 1) {
122
145
  }
123
146
  }
124
147
 
125
- if (!action || !["add", "rm", "ls", "enable", "disable", "where"].includes(action)) {
126
- fail("Provide a command: add | rm | ls | enable | disable | where.");
148
+ if (!action || !["add", "rm", "ls", "enable", "disable", "where", "tui"].includes(action)) {
149
+ fail("Provide a command: add | rm | ls | enable | disable | where | tui.");
150
+ }
151
+
152
+ let effectiveAction = action;
153
+ if (action === "tui") {
154
+ runTuiWizard(options);
155
+ effectiveAction = options.tuiAction || "add";
127
156
  }
128
157
 
129
158
  if (options.clients.length === 0) {
130
159
  fail("Provide at least one --client.");
131
160
  }
132
161
 
133
- if (!["ls"].includes(action) && !options.name) {
162
+ if (!["ls"].includes(effectiveAction) && !options.name) {
134
163
  fail("Provide --name <serverName> (required).");
135
164
  }
136
165
 
137
166
  const transportNormalized = options.transport === "http" ? "streamableHttp" : options.transport;
138
167
  options.transport = transportNormalized;
139
168
 
140
- if (action === "rm") {
169
+ if (effectiveAction === "rm") {
141
170
  options.remove = true;
142
171
  }
143
- if (action === "ls") {
172
+ if (effectiveAction === "ls") {
144
173
  options.list = true;
145
174
  }
146
- if (action === "enable") {
175
+ if (effectiveAction === "enable") {
147
176
  options.toggle = true;
148
177
  options.disabled = false;
149
178
  }
150
- if (action === "disable") {
179
+ if (effectiveAction === "disable") {
151
180
  options.toggle = true;
152
181
  options.disabled = true;
153
182
  }
154
- if (action === "where") {
183
+ if (effectiveAction === "where") {
155
184
  options.where = true;
156
185
  }
157
186
 
158
- if (options.remove && action !== "rm") {
187
+ if (options.remove && effectiveAction !== "rm") {
159
188
  fail("Use the rm command instead of --remove.");
160
189
  }
161
190
  if (options.list && options.toggle) {
@@ -173,15 +202,16 @@ if (options.projectPath && options.allProjects) {
173
202
  if (options.where && (options.list || options.remove || options.toggle)) {
174
203
  fail("The where command does not support ls/rm/enable/disable flags.");
175
204
  }
176
- if (options.projectPath && action === "add" && options.scope !== "global") {
205
+ if (options.projectPath && effectiveAction === "add" && options.scope !== "global") {
177
206
  fail("--project is only supported for Claude global config.");
178
207
  }
179
208
 
180
- const requiresConnectionParams = !options.remove && !options.toggle && !options.list && !options.where;
209
+ const requiresConnectionParams =
210
+ !options.remove && !options.toggle && !options.list && !options.where;
181
211
 
182
212
  if (requiresConnectionParams && options.transport === "stdio") {
183
- if (!options.envPath && !options.mcpDestination) {
184
- fail("Provide either --env <path> or --mcp <destination>.");
213
+ if (!options.envPath && !options.mcpDestination && !options.useSessionEnv) {
214
+ fail("Provide --env, --env-path <path>, or --mcp <destination>.");
185
215
  }
186
216
  }
187
217
 
@@ -189,8 +219,8 @@ if (requiresConnectionParams && options.transport !== "stdio") {
189
219
  if (!options.url) {
190
220
  fail("Provide --url <http(s)://...> for sse/http transports.");
191
221
  }
192
- if (options.envPath || options.mcpDestination) {
193
- fail("--env/--mcp are only valid for stdio transport.");
222
+ if (options.envPath || options.mcpDestination || options.useSessionEnv) {
223
+ fail("--env/--env-path/--mcp are only valid for stdio transport.");
194
224
  }
195
225
  }
196
226
 
@@ -201,20 +231,22 @@ const userProfile = process.env.USERPROFILE || home;
201
231
 
202
232
  const serverArgsRaw = [
203
233
  `--transport=${options.transport}`,
204
- options.envPath
205
- ? `--env=${options.envPath}`
206
- : options.mcpDestination
207
- ? `--mcp=${options.mcpDestination.toLowerCase()}`
208
- : undefined,
234
+ options.useSessionEnv
235
+ ? "--env"
236
+ : options.envPath
237
+ ? `--env-path=${options.envPath}`
238
+ : options.mcpDestination
239
+ ? `--mcp=${options.mcpDestination.toLowerCase()}`
240
+ : undefined,
209
241
  ];
210
242
  const serverArgs = serverArgsRaw.filter(Boolean);
211
243
 
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) {
244
+ for (const client of options.clients) {
245
+ const scope = options.scope || getDefaultScope(client);
246
+ if (options.projectPath && client !== "claude") {
247
+ fail("--project is only supported for Claude.");
248
+ }
249
+ switch (client) {
218
250
  case "cline":
219
251
  requireScope("Cline", ["global"], scope);
220
252
  if (options.list) {
@@ -235,10 +267,14 @@ const serverArgs = serverArgsRaw.filter(Boolean);
235
267
  } else if (options.where) {
236
268
  whereCodexConfig(getCodexPath(platform, home, userProfile, scope), options.name);
237
269
  } else {
238
- writeCodexConfig(getCodexPath(platform, home, userProfile, scope), options.name, serverArgs);
270
+ writeCodexConfig(
271
+ getCodexPath(platform, home, userProfile, scope),
272
+ options.name,
273
+ serverArgs,
274
+ );
239
275
  }
240
276
  break;
241
- case "claude":
277
+ case "claude": {
242
278
  requireScope("Claude", ["global", "local"], scope);
243
279
  const claudeToggleScope = options.toggle ? "global" : scope;
244
280
  if (options.allProjects && claudeToggleScope !== "global") {
@@ -274,6 +310,7 @@ const serverArgs = serverArgsRaw.filter(Boolean);
274
310
  );
275
311
  }
276
312
  break;
313
+ }
277
314
  case "goose":
278
315
  requireScope("Goose", ["global"], scope);
279
316
  if (options.list) {
@@ -310,12 +347,7 @@ const serverArgs = serverArgsRaw.filter(Boolean);
310
347
  } else if (options.where) {
311
348
  whereJsonConfig(getAntigravityPath(home, scope), "antigravity", options.name);
312
349
  } else {
313
- writeJsonConfig(
314
- getAntigravityPath(home, scope),
315
- options.name,
316
- serverArgs,
317
- "antigravity",
318
- );
350
+ writeJsonConfig(getAntigravityPath(home, scope), options.name, serverArgs, "antigravity");
319
351
  }
320
352
  break;
321
353
  case "copilot":
@@ -363,6 +395,43 @@ const serverArgs = serverArgsRaw.filter(Boolean);
363
395
  }
364
396
  }
365
397
 
398
+ function normalizeClientName(clientName) {
399
+ if (!clientName) {
400
+ return clientName;
401
+ }
402
+ const normalized = clientName.toLowerCase();
403
+ return normalized === "kilo" ? "opencode" : normalized;
404
+ }
405
+
406
+ function runTuiWizard(opts) {
407
+ if (!process.stdin.isTTY) {
408
+ fail("TUI mode requires an interactive terminal.");
409
+ }
410
+ const helperPath = path.join(__dirname, "mcp-conf-tui.js");
411
+ const run = spawnSync(process.execPath, [helperPath], {
412
+ stdio: ["inherit", "inherit", "inherit", "pipe"],
413
+ encoding: "utf8",
414
+ });
415
+ if (run.error) {
416
+ fail(`Failed to start TUI helper: ${run.error.message}`);
417
+ }
418
+ if (run.status !== 0) {
419
+ process.exit(run.status || 1);
420
+ }
421
+ const rawPayload = run.output?.[3] || "";
422
+ const payload = String(rawPayload).trim();
423
+ if (!payload) {
424
+ fail("TUI did not return configuration.");
425
+ }
426
+ let selected;
427
+ try {
428
+ selected = JSON.parse(payload);
429
+ } catch {
430
+ fail("Invalid TUI output.");
431
+ }
432
+ Object.assign(opts, selected);
433
+ }
434
+
366
435
  function getClinePath(platformValue, homeDir, appDataDir) {
367
436
  if (platformValue === "win32") {
368
437
  return path.join(
@@ -1215,6 +1284,7 @@ function printHelp(command) {
1215
1284
 
1216
1285
  Usage:
1217
1286
  mcp-conf <add|rm|ls|enable|disable|where> --client <name> [options]
1287
+ mcp-conf tui
1218
1288
  mcp-conf help <command>
1219
1289
 
1220
1290
  Commands:
@@ -1224,6 +1294,7 @@ Commands:
1224
1294
  enable enable an existing entry
1225
1295
  disable disable an existing entry
1226
1296
  where show where a server name is defined
1297
+ tui interactive setup wizard
1227
1298
 
1228
1299
  Run:
1229
1300
  mcp-conf <command> --help
@@ -1241,12 +1312,13 @@ Notes:
1241
1312
  process.stdout.write(`${header} add
1242
1313
 
1243
1314
  Usage:
1244
- mcp-conf add --client <name> --name <serverName> [--env <path> | --mcp <dest>] [options]
1315
+ mcp-conf add --client <name> --name <serverName> [--env | --env-path <path> | --mcp <dest>] [options]
1245
1316
 
1246
1317
  Options:
1247
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1318
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | kilo | copilot | antigravity (repeatable)
1248
1319
  --name <serverName> required MCP server name key
1249
- --env <path> .env path (stdio only)
1320
+ --env use current shell/session env vars (stdio only)
1321
+ --env-path <path> .env path (stdio only)
1250
1322
  --mcp <dest> destination name (stdio only)
1251
1323
  --transport <type> stdio | sse | http (http => streamableHttp)
1252
1324
  --command <bin> command to run (default: mcp-abap-adt)
@@ -1270,7 +1342,7 @@ Usage:
1270
1342
  mcp-conf rm --client <name> --name <serverName> [options]
1271
1343
 
1272
1344
  Options:
1273
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1345
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | kilo | copilot | antigravity (repeatable)
1274
1346
  --name <serverName> required MCP server name key
1275
1347
  --global write to global user config (default)
1276
1348
  --local write to project config (where supported)
@@ -1289,7 +1361,7 @@ Usage:
1289
1361
  mcp-conf ls --client <name> [options]
1290
1362
 
1291
1363
  Options:
1292
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1364
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | kilo | copilot | antigravity (repeatable)
1293
1365
  --global write to global user config (default)
1294
1366
  --local write to project config (where supported)
1295
1367
  --all-projects Claude global: list across all projects
@@ -1306,7 +1378,7 @@ Usage:
1306
1378
  mcp-conf enable --client <name> --name <serverName> [options]
1307
1379
 
1308
1380
  Options:
1309
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1381
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | kilo | copilot | antigravity (repeatable)
1310
1382
  --name <serverName> required MCP server name key
1311
1383
  --global write to global user config (default)
1312
1384
  --local write to project config (where supported)
@@ -1325,7 +1397,7 @@ Usage:
1325
1397
  mcp-conf disable --client <name> --name <serverName> [options]
1326
1398
 
1327
1399
  Options:
1328
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1400
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | kilo | copilot | antigravity (repeatable)
1329
1401
  --name <serverName> required MCP server name key
1330
1402
  --global write to global user config (default)
1331
1403
  --local write to project config (where supported)
@@ -1344,7 +1416,7 @@ Usage:
1344
1416
  mcp-conf where --client <name> --name <serverName> [options]
1345
1417
 
1346
1418
  Options:
1347
- --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | copilot | antigravity (repeatable)
1419
+ --client <name> cline | codex | claude | goose | cursor | windsurf | opencode | kilo | copilot | antigravity (repeatable)
1348
1420
  --name <serverName> required MCP server name key
1349
1421
  --global write to global user config (default)
1350
1422
  --local write to project config (where supported)
@@ -1353,6 +1425,18 @@ Options:
1353
1425
 
1354
1426
  Notes:
1355
1427
  Antigravity local scope is not supported yet; use --global.
1428
+ `);
1429
+ break;
1430
+ case "tui":
1431
+ process.stdout.write(`${header} tui
1432
+
1433
+ Usage:
1434
+ mcp-conf tui
1435
+
1436
+ Description:
1437
+ Start interactive setup wizard for add/ls/rm/enable/disable.
1438
+ Flow: operation -> client -> scope (skips scope when only one is supported).
1439
+ For add + sse/http, wizard also asks timeout and repeatable headers.
1356
1440
  `);
1357
1441
  break;
1358
1442
  default:
@@ -11,9 +11,9 @@ npm install -g @mcp-abap-adt/configurator
11
11
  ## Usage
12
12
 
13
13
  ```bash
14
- mcp-conf add --client cline --env /path/to/.env --name abap
14
+ mcp-conf add --client cline --env-path /path/to/.env --name abap
15
15
  mcp-conf add --client cline --mcp TRIAL --name abap
16
- mcp-conf add --client cline --env /path/to/.env --name abap --transport stdio
16
+ mcp-conf add --client cline --env-path /path/to/.env --name abap --transport stdio
17
17
  mcp-conf add --client claude --mcp TRIAL --name abap
18
18
  mcp-conf rm --client codex --name abap
19
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=...
@@ -21,8 +21,10 @@ mcp-conf add --client cline --name local-mcp-sse --transport sse --url http://lo
21
21
  mcp-conf add --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http
22
22
  mcp-conf add --client codex --name abap-http --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
23
23
  mcp-conf add --client opencode --name abap --transport http --url http://localhost:3000/mcp/stream/http
24
+ mcp-conf add --client kilo --name abap --transport http --url http://localhost:3000/mcp/stream/http
24
25
  mcp-conf add --client copilot --name abap --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
25
26
  mcp-conf add --client antigravity --name abap --transport http --url http://localhost:3000/mcp/stream/http
27
+ mcp-conf tui
26
28
  ```
27
29
 
28
30
  ## Common Tasks
@@ -30,7 +32,7 @@ mcp-conf add --client antigravity --name abap --transport http --url http://loca
30
32
  Add MCP:
31
33
  ```bash
32
34
  mcp-conf add --client codex --mcp TRIAL --name abap
33
- mcp-conf add --client cline --env /path/to/.env --name abap
35
+ mcp-conf add --client cline --env-path /path/to/.env --name abap
34
36
  mcp-conf add --client claude --mcp TRIAL --name abap
35
37
  mcp-conf add --client claude --name abap-http --transport http --url http://localhost:3000/mcp/stream/http --header x-mcp-destination=trial
36
38
  mcp-conf add --client claude --name abap --project /path/to/project --mcp TRIAL
@@ -73,16 +75,26 @@ mcp-conf where --client claude --name goose --project /path/to/project
73
75
  mcp-conf where --client claude --name goose --all-projects
74
76
  ```
75
77
 
78
+ TUI wizard:
79
+ ```bash
80
+ mcp-conf tui
81
+ ```
82
+ - Flow order: `operation` -> `client` -> `scope`.
83
+ - Scope step is skipped automatically for single-scope clients.
84
+ - For `add` with `sse/http`, the wizard asks URL, timeout, and repeatable headers.
85
+ - Controls: arrow keys + Enter, Ctrl+C to cancel.
86
+
76
87
  Options:
77
- - Commands: `add`, `rm`, `ls`, `enable`, `disable`, `where` (first argument)
78
- - `--client <name>` (repeatable): `cline`, `codex`, `claude`, `goose`, `cursor`, `windsurf`, `opencode`, `copilot`, `antigravity`
79
- - `--env <path>`: use a specific `.env` file
88
+ - Commands: `add`, `rm`, `ls`, `enable`, `disable`, `where`, `tui` (first argument)
89
+ - `--client <name>` (repeatable): `cline`, `codex`, `claude`, `goose`, `cursor`, `windsurf`, `opencode` (`kilo` alias), `copilot`, `antigravity`
90
+ - `--env`: use shell/session environment variables (stdio only)
91
+ - `--env-path <path>`: use a specific `.env` file (stdio only)
80
92
  - `--mcp <destination>`: use service key destination
81
93
  - `--name <serverName>`: MCP server name (required)
82
94
  - `--transport <type>`: `stdio`, `sse`, or `http` (`http` maps to `streamableHttp`)
83
95
  - `--command <bin>`: command to run (default: `mcp-abap-adt`)
84
96
  - `--global`: write to the global user config (default)
85
- - `--local`: write to the project config (supported by `cursor`, `opencode`, `copilot`, `claude`, `codex`)
97
+ - `--local`: write to the project config (supported by `cursor`, `opencode`/`kilo`, `copilot`, `claude`, `codex`)
86
98
  - `--all-projects`: for Claude (global scope), apply `rm/enable/disable/ls/where` across all projects
87
99
  - `--project <path>`: for Claude (global scope), target a specific project path
88
100
  - `--url <http(s)://...>`: required for `sse` and `http`
@@ -90,8 +102,9 @@ Options:
90
102
  - `--timeout <seconds>`: timeout value for client entries (default: 60)
91
103
 
92
104
  Notes:
93
- - `disable` and `rm` do not require `--env` or `--mcp`.
94
- - `--env`/`--mcp` are only valid for `stdio` transport. For `sse/http`, use `--url` and optional `--header`.
105
+ - `disable` and `rm` do not require `--env`, `--env-path`, or `--mcp`.
106
+ - `--env`/`--env-path`/`--mcp` are only valid for `stdio` transport. For `sse/http`, use `--url` and optional `--header`.
107
+ - `mcp-conf tui` starts an interactive wizard and writes the same config as `add`.
95
108
  - Cursor/Copilot enable/disable are not implemented yet.
96
109
  - Antigravity enable/disable uses `disabled: true|false` on the entry.
97
110
  - Antigravity local scope is not supported yet; use `--global`.
@@ -100,7 +113,7 @@ Notes:
100
113
  - Antigravity HTTP entries use `serverUrl` instead of `url`.
101
114
  - New entries for Cline, Codex, Windsurf, Goose, Claude, and OpenCode are added **disabled by default**. Use `enable` to turn them on.
102
115
  - Windsurf follows `disabled` like Cline. The configurator sets `disabled = true` for default-disabled entries.
103
- - `enable`/`disable` only work if the server entry already exists. Use add commands with `--env` or `--mcp` first.
116
+ - `enable`/`disable` only work if the server entry already exists. Use add commands with `--env`, `--env-path`, or `--mcp` first.
104
117
  - Non-stdio transports are supported for Cline/Cursor/Windsurf/Claude/Goose. Codex supports `http` (streamable HTTP) but not `sse`.
105
118
  - Codex writes custom headers under `http_headers` in `~/.codex/config.toml` (or `./.codex/config.toml` for `--local`).
106
119
  - Codex HTTP entries include `startup_timeout_sec` (default: 60).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/configurator",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "MCP client configurator for mcp-abap-adt and mcp-abap-adt-proxy",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,9 +28,10 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@iarna/toml": "^3.0.0",
31
+ "enquirer": "^2.4.1",
31
32
  "yaml": "^2.8.1"
32
33
  },
33
34
  "devDependencies": {
34
- "@biomejs/biome": "^2.3.14"
35
+ "@biomejs/biome": "^2.3.15"
35
36
  }
36
37
  }