@tronsfey/ucli 0.4.2 → 0.5.0

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/dist/index.js CHANGED
@@ -10,7 +10,61 @@ import { createRequire as createRequire2 } from "module";
10
10
  // src/config.ts
11
11
  import Conf from "conf";
12
12
  import { homedir } from "os";
13
- import { join } from "path";
13
+ import { join, dirname } from "path";
14
+ import { chmodSync, mkdirSync } from "fs";
15
+
16
+ // src/lib/config-encryption.ts
17
+ import {
18
+ createCipheriv,
19
+ createDecipheriv,
20
+ randomBytes,
21
+ pbkdf2Sync
22
+ } from "crypto";
23
+ import { hostname, userInfo } from "os";
24
+ var ENC_PREFIX = "enc:v1:";
25
+ var ALGORITHM = "aes-256-gcm";
26
+ var SALT_LEN = 32;
27
+ var IV_LEN = 12;
28
+ var TAG_LEN = 16;
29
+ var PBKDF2_ITERATIONS = 1e5;
30
+ function deriveKey(salt) {
31
+ let user = "default";
32
+ try {
33
+ user = userInfo().username;
34
+ } catch {
35
+ }
36
+ const material = `ucli:${user}@${hostname()}`;
37
+ return pbkdf2Sync(material, salt, PBKDF2_ITERATIONS, 32, "sha512");
38
+ }
39
+ function encryptValue(plaintext) {
40
+ const salt = randomBytes(SALT_LEN);
41
+ const key = deriveKey(salt);
42
+ const iv = randomBytes(IV_LEN);
43
+ const cipher = createCipheriv(ALGORITHM, key, iv);
44
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
45
+ const tag = cipher.getAuthTag();
46
+ const packed = Buffer.concat([salt, iv, tag, encrypted]);
47
+ return ENC_PREFIX + packed.toString("base64");
48
+ }
49
+ function decryptValue(stored) {
50
+ if (!stored.startsWith(ENC_PREFIX)) {
51
+ return stored;
52
+ }
53
+ const packed = Buffer.from(stored.slice(ENC_PREFIX.length), "base64");
54
+ const salt = packed.subarray(0, SALT_LEN);
55
+ const iv = packed.subarray(SALT_LEN, SALT_LEN + IV_LEN);
56
+ const tag = packed.subarray(SALT_LEN + IV_LEN, SALT_LEN + IV_LEN + TAG_LEN);
57
+ const encrypted = packed.subarray(SALT_LEN + IV_LEN + TAG_LEN);
58
+ const key = deriveKey(salt);
59
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
60
+ decipher.setAuthTag(tag);
61
+ return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString("utf8");
62
+ }
63
+ function isEncrypted(value) {
64
+ return value.startsWith(ENC_PREFIX);
65
+ }
66
+
67
+ // src/config.ts
14
68
  var conf = new Conf({
15
69
  projectName: "ucli",
16
70
  schema: {
@@ -19,18 +73,35 @@ var conf = new Conf({
19
73
  }
20
74
  });
21
75
  var cacheDir = join(homedir(), ".cache", "ucli");
76
+ function hardenConfigPermissions() {
77
+ try {
78
+ const configPath = conf.path;
79
+ const configDir = dirname(configPath);
80
+ mkdirSync(configDir, { recursive: true, mode: 448 });
81
+ chmodSync(configDir, 448);
82
+ chmodSync(configPath, 384);
83
+ } catch {
84
+ console.warn("Warning: Could not enforce restrictive file permissions on config. Token is encrypted but file permissions may be permissive.");
85
+ }
86
+ }
22
87
  function getConfig() {
23
88
  const serverUrl = conf.get("serverUrl");
24
- const token = conf.get("token");
25
- if (!serverUrl || !token) {
89
+ const rawToken = conf.get("token");
90
+ if (!serverUrl || !rawToken) {
26
91
  console.error("ucli is not configured. Run: ucli configure --server <url> --token <jwt>");
27
92
  process.exit(1);
28
93
  }
94
+ const token = decryptValue(rawToken);
95
+ if (!isEncrypted(rawToken)) {
96
+ conf.set("token", encryptValue(token));
97
+ hardenConfigPermissions();
98
+ }
29
99
  return { serverUrl, token };
30
100
  }
31
101
  function saveConfig(cfg) {
32
102
  conf.set("serverUrl", cfg.serverUrl);
33
- conf.set("token", cfg.token);
103
+ conf.set("token", encryptValue(cfg.token));
104
+ hardenConfigPermissions();
34
105
  }
35
106
  function isConfigured() {
36
107
  return Boolean(conf.get("serverUrl") && conf.get("token"));
@@ -83,6 +154,18 @@ var ServerClient = class {
83
154
  }
84
155
  };
85
156
 
157
+ // src/lib/exit-codes.ts
158
+ var ExitCode = {
159
+ SUCCESS: 0,
160
+ GENERAL_ERROR: 1,
161
+ USAGE_ERROR: 2,
162
+ CONFIG_ERROR: 3,
163
+ AUTH_ERROR: 4,
164
+ CONNECTIVITY_ERROR: 5,
165
+ NOT_FOUND: 6,
166
+ SERVER_ERROR: 7
167
+ };
168
+
86
169
  // src/commands/configure.ts
87
170
  function registerConfigure(program2) {
88
171
  program2.command("configure").description("Configure the OAS Gateway server URL and authentication token").requiredOption("--server <url>", "OAS Gateway server URL (e.g. https://oas.example.com)").requiredOption("--token <jwt>", "Group JWT token issued by the server admin").action(async (opts) => {
@@ -99,7 +182,7 @@ function registerConfigure(program2) {
99
182
  } catch (err) {
100
183
  console.error("Connection failed:", err.message);
101
184
  console.error("Please check the server URL and token.");
102
- process.exit(1);
185
+ process.exit(ExitCode.CONNECTIVITY_ERROR);
103
186
  }
104
187
  });
105
188
  }
@@ -163,12 +246,12 @@ async function clearOASCache(name) {
163
246
  // src/lib/oas-runner.ts
164
247
  import { spawn } from "child_process";
165
248
  import { createRequire } from "module";
166
- import { join as join3, dirname } from "path";
249
+ import { join as join3, dirname as dirname2 } from "path";
167
250
  var require2 = createRequire(import.meta.url);
168
251
  function resolveOpenapi2CliBin() {
169
252
  try {
170
253
  const pkgPath = require2.resolve("@tronsfey/openapi2cli/package.json");
171
- const pkgDir = dirname(pkgPath);
254
+ const pkgDir = dirname2(pkgPath);
172
255
  const pkg2 = require2("@tronsfey/openapi2cli/package.json");
173
256
  const binEntry = pkg2.bin?.["openapi2cli"] ?? "bin/openapi2cli.js";
174
257
  return join3(pkgDir, binEntry);
@@ -303,6 +386,68 @@ async function getServiceHelp(entry) {
303
386
  });
304
387
  }
305
388
 
389
+ // src/lib/yaml.ts
390
+ function toYaml(value, indent = 0) {
391
+ if (value === null || value === void 0) {
392
+ return "null";
393
+ }
394
+ if (typeof value === "boolean") {
395
+ return value ? "true" : "false";
396
+ }
397
+ if (typeof value === "number") {
398
+ return String(value);
399
+ }
400
+ if (typeof value === "string") {
401
+ if (needsQuoting(value)) {
402
+ return JSON.stringify(value);
403
+ }
404
+ return value;
405
+ }
406
+ if (Array.isArray(value)) {
407
+ if (value.length === 0) return "[]";
408
+ const prefix = " ".repeat(indent);
409
+ return value.map((item) => {
410
+ const serialised = toYaml(item, indent + 2);
411
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
412
+ const firstNewline = serialised.indexOf("\n");
413
+ if (firstNewline === -1) {
414
+ return `${prefix}- ${serialised.trimStart()}`;
415
+ }
416
+ const firstLine = serialised.slice(0, firstNewline);
417
+ const rest = serialised.slice(firstNewline + 1);
418
+ return `${prefix}- ${firstLine.trimStart()}
419
+ ${rest}`;
420
+ }
421
+ return `${prefix}- ${serialised}`;
422
+ }).join("\n");
423
+ }
424
+ if (typeof value === "object") {
425
+ const entries = Object.entries(value);
426
+ if (entries.length === 0) return "{}";
427
+ const prefix = " ".repeat(indent);
428
+ return entries.map(([key, val]) => {
429
+ if (val === null || val === void 0) {
430
+ return `${prefix}${key}: null`;
431
+ }
432
+ if (typeof val === "object") {
433
+ const nested = toYaml(val, indent + 2);
434
+ return `${prefix}${key}:
435
+ ${nested}`;
436
+ }
437
+ return `${prefix}${key}: ${toYaml(val, indent)}`;
438
+ }).join("\n");
439
+ }
440
+ return String(value);
441
+ }
442
+ function needsQuoting(s) {
443
+ if (s === "") return true;
444
+ if (s === "true" || s === "false" || s === "null") return true;
445
+ if (/^\d/.test(s)) return true;
446
+ if (/[:{}\[\],&*#?|<>=!%@`'"\\\n\r\t]/.test(s)) return true;
447
+ if (s.startsWith(" ") || s.endsWith(" ")) return true;
448
+ return false;
449
+ }
450
+
306
451
  // src/commands/services.ts
307
452
  function registerServices(program2) {
308
453
  const services = program2.command("services").description("Manage and inspect available OAS services");
@@ -334,6 +479,14 @@ function registerServices(program2) {
334
479
  console.log(JSON.stringify(safe, null, 2));
335
480
  return;
336
481
  }
482
+ if (format === "yaml") {
483
+ const safe = entries.map(({ authConfig, ...rest }) => ({
484
+ ...rest,
485
+ authConfig: { type: authConfig["type"] ?? rest.authType }
486
+ }));
487
+ console.log(toYaml(safe));
488
+ return;
489
+ }
337
490
  const nameWidth = Math.max(10, ...entries.map((e) => e.name.length));
338
491
  console.log(`
339
492
  ${"SERVICE".padEnd(nameWidth)} AUTH DESCRIPTION`);
@@ -354,7 +507,7 @@ ${"SERVICE".padEnd(nameWidth)} AUTH DESCRIPTION`);
354
507
  } catch (err) {
355
508
  console.error(`Service not found: ${name}`);
356
509
  console.error("Run `ucli services list` to see available services.");
357
- process.exit(1);
510
+ process.exit(ExitCode.NOT_FOUND);
358
511
  }
359
512
  const help = await getServiceHelp(entry);
360
513
  const format = (opts.format ?? "table").toLowerCase();
@@ -368,6 +521,16 @@ ${"SERVICE".padEnd(nameWidth)} AUTH DESCRIPTION`);
368
521
  console.log(JSON.stringify(safe, null, 2));
369
522
  return;
370
523
  }
524
+ if (format === "yaml") {
525
+ const { authConfig, ...rest } = entry;
526
+ const safe = {
527
+ ...rest,
528
+ authConfig: { type: authConfig["type"] ?? rest.authType },
529
+ operationsHelp: help
530
+ };
531
+ console.log(toYaml(safe));
532
+ return;
533
+ }
371
534
  console.log(`
372
535
  Service: ${entry.name}`);
373
536
  console.log(`Description: ${entry.description || "(none)"}`);
@@ -386,12 +549,12 @@ function registerRun(program2) {
386
549
  program2.command("run [service] [args...]").description("Execute an operation on a service").option("--service <name>", "Service name (from `services list`)").option("--operation <id>", "OperationId to execute").option("--params <json>", "JSON string of operation parameters").option("--format <fmt>", "Output format: json | table | yaml", "json").option("--query <jmespath>", "Filter response with JMESPath expression").option("--data <json>", "Request body (JSON string or @filename)").allowUnknownOption(true).action(async (serviceArg, args, opts) => {
387
550
  if (serviceArg && opts.service && serviceArg !== opts.service) {
388
551
  console.error(`Conflicting service values: positional "${serviceArg}" and --service "${opts.service}". Use either the positional argument or --service flag, not both.`);
389
- process.exit(1);
552
+ process.exit(ExitCode.USAGE_ERROR);
390
553
  }
391
554
  const service = opts.service ?? serviceArg;
392
555
  if (!service) {
393
556
  console.error("Missing service name. Use positional <service> or --service <name>.");
394
- process.exit(1);
557
+ process.exit(ExitCode.USAGE_ERROR);
395
558
  }
396
559
  const cfg = getConfig();
397
560
  const client = new ServerClient(cfg);
@@ -401,7 +564,7 @@ function registerRun(program2) {
401
564
  } catch {
402
565
  console.error(`Unknown service: ${service}`);
403
566
  console.error("Run `ucli services list` to see available services.");
404
- process.exit(1);
567
+ process.exit(ExitCode.NOT_FOUND);
405
568
  }
406
569
  const extraArgs = opts.args ?? [];
407
570
  const operationArgs = [...args, ...extraArgs];
@@ -414,7 +577,7 @@ function registerRun(program2) {
414
577
  parsed = JSON.parse(opts.params);
415
578
  } catch {
416
579
  console.error(`Invalid --params JSON. Example: --params '{"petId": 1}'`);
417
- process.exit(1);
580
+ process.exit(ExitCode.USAGE_ERROR);
418
581
  }
419
582
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
420
583
  for (const [k, v] of Object.entries(parsed)) {
@@ -438,7 +601,7 @@ function registerRun(program2) {
438
601
  });
439
602
  } catch (err) {
440
603
  console.error("Operation failed:", err.message);
441
- process.exit(1);
604
+ process.exit(ExitCode.GENERAL_ERROR);
442
605
  }
443
606
  });
444
607
  }
@@ -499,7 +662,7 @@ function registerHelp(program2) {
499
662
  } catch {
500
663
  console.error(`Unknown service: ${service}`);
501
664
  console.error("Run `ucli services list` to see available services.");
502
- process.exit(1);
665
+ process.exit(ExitCode.NOT_FOUND);
503
666
  }
504
667
  console.log(`
505
668
  === ${entry.name} ===`);
@@ -549,6 +712,18 @@ MAINTENANCE
549
712
  ucli refresh
550
713
  Force-refresh the local OAS cache from the server.
551
714
 
715
+ ucli doctor
716
+ Check configuration, server connectivity, and token validity.
717
+
718
+ SHELL COMPLETIONS
719
+ eval "$(ucli completions bash)"
720
+ eval "$(ucli completions zsh)"
721
+ ucli completions fish | source
722
+
723
+ GLOBAL FLAGS
724
+ --debug Enable verbose debug logging
725
+ -v, --version Show version number
726
+
552
727
  ERRORS
553
728
  401 Unauthorized \u2192 Run: ucli configure --server <url> --token <jwt>
554
729
  404 Not Found \u2192 Check service name: ucli services list
@@ -648,6 +823,14 @@ function registerMcp(program2) {
648
823
  console.log(JSON.stringify(safe, null, 2));
649
824
  return;
650
825
  }
826
+ if (format === "yaml") {
827
+ const safe = entries.map(({ authConfig, ...rest }) => ({
828
+ ...rest,
829
+ authConfig: { type: authConfig.type }
830
+ }));
831
+ console.log(toYaml(safe));
832
+ return;
833
+ }
651
834
  const nameWidth = Math.max(10, ...entries.map((e) => e.name.length));
652
835
  console.log(`
653
836
  ${"SERVER".padEnd(nameWidth)} TRANSPORT DESCRIPTION`);
@@ -658,7 +841,7 @@ ${"SERVER".padEnd(nameWidth)} TRANSPORT DESCRIPTION`);
658
841
  }
659
842
  console.log();
660
843
  });
661
- mcp.command("tools <server>").description("List tools available on a MCP server").option("--format <fmt>", "Output format: table | json", "table").action(async (serverName, opts) => {
844
+ mcp.command("tools <server>").description("List tools available on a MCP server").option("--format <fmt>", "Output format: table | json | yaml", "table").action(async (serverName, opts) => {
662
845
  const cfg = getConfig();
663
846
  const client = new ServerClient(cfg);
664
847
  let entry;
@@ -667,14 +850,14 @@ ${"SERVER".padEnd(nameWidth)} TRANSPORT DESCRIPTION`);
667
850
  } catch {
668
851
  console.error(`Unknown MCP server: ${serverName}`);
669
852
  console.error("Run `ucli mcp list` to see available servers.");
670
- process.exit(1);
853
+ process.exit(ExitCode.NOT_FOUND);
671
854
  }
672
855
  let tools;
673
856
  try {
674
857
  tools = await listMcpTools(entry);
675
858
  } catch (err) {
676
859
  console.error("Failed to fetch tools:", err.message);
677
- process.exit(1);
860
+ process.exit(ExitCode.GENERAL_ERROR);
678
861
  }
679
862
  if (tools.length === 0) {
680
863
  console.log(`No tools found on MCP server "${serverName}".`);
@@ -685,6 +868,10 @@ ${"SERVER".padEnd(nameWidth)} TRANSPORT DESCRIPTION`);
685
868
  console.log(JSON.stringify(tools, null, 2));
686
869
  return;
687
870
  }
871
+ if (format === "yaml") {
872
+ console.log(toYaml(tools));
873
+ return;
874
+ }
688
875
  console.log(`
689
876
  Tools on "${serverName}":`);
690
877
  console.log("\u2500".repeat(60));
@@ -703,27 +890,262 @@ Tools on "${serverName}":`);
703
890
  } catch {
704
891
  console.error(`Unknown MCP server: ${serverName}`);
705
892
  console.error("Run `ucli mcp list` to see available servers.");
706
- process.exit(1);
893
+ process.exit(ExitCode.NOT_FOUND);
707
894
  }
708
895
  try {
709
896
  await runMcpTool(entry, toolName, args);
710
897
  } catch (err) {
711
898
  console.error("Tool execution failed:", err.message);
712
- process.exit(1);
899
+ process.exit(ExitCode.GENERAL_ERROR);
900
+ }
901
+ });
902
+ }
903
+
904
+ // src/lib/errors.ts
905
+ var debugEnabled = false;
906
+ function setDebugMode(enabled) {
907
+ debugEnabled = enabled;
908
+ }
909
+ function debug(message) {
910
+ if (debugEnabled) {
911
+ console.error(`[DEBUG] ${message}`);
912
+ }
913
+ }
914
+ var HINT_MAP = {
915
+ [ExitCode.CONFIG_ERROR]: "Run: ucli configure --server <url> --token <jwt>",
916
+ [ExitCode.AUTH_ERROR]: "Your token may be expired or revoked. Run: ucli configure --server <url> --token <jwt>",
917
+ [ExitCode.CONNECTIVITY_ERROR]: "Check that the server URL is correct and the server is running. Run: ucli doctor",
918
+ [ExitCode.NOT_FOUND]: "Check the resource name. Run: ucli services list or ucli mcp list",
919
+ [ExitCode.SERVER_ERROR]: "The server returned an unexpected error. Try again or run: ucli doctor"
920
+ };
921
+
922
+ // src/commands/doctor.ts
923
+ import axios2 from "axios";
924
+ function registerDoctor(program2) {
925
+ program2.command("doctor").description("Check configuration, server connectivity, and token validity").action(async () => {
926
+ const results = [];
927
+ debug("Checking configuration...");
928
+ if (!isConfigured()) {
929
+ results.push({
930
+ name: "Configuration",
931
+ ok: false,
932
+ detail: "Not configured. Run: ucli configure --server <url> --token <jwt>"
933
+ });
934
+ printResults(results);
935
+ process.exit(ExitCode.CONFIG_ERROR);
936
+ }
937
+ let cfg;
938
+ try {
939
+ cfg = getConfig();
940
+ results.push({
941
+ name: "Configuration",
942
+ ok: true,
943
+ detail: `Server: ${cfg.serverUrl}`
944
+ });
945
+ } catch (err) {
946
+ results.push({
947
+ name: "Configuration",
948
+ ok: false,
949
+ detail: `Failed to read config: ${err.message}`
950
+ });
951
+ printResults(results);
952
+ process.exit(ExitCode.CONFIG_ERROR);
953
+ }
954
+ debug(`Checking connectivity to ${cfg.serverUrl}...`);
955
+ try {
956
+ const healthUrl = `${cfg.serverUrl}/api/v1/health`;
957
+ const resp = await axios2.get(healthUrl, { timeout: 1e4 });
958
+ results.push({
959
+ name: "Server connectivity",
960
+ ok: resp.status === 200,
961
+ detail: resp.status === 200 ? `Health endpoint OK (${cfg.serverUrl})` : `Unexpected status: ${resp.status}`
962
+ });
963
+ } catch (err) {
964
+ const msg = axios2.isAxiosError(err) ? err.code ?? err.message : err.message;
965
+ results.push({
966
+ name: "Server connectivity",
967
+ ok: false,
968
+ detail: `Cannot reach server: ${msg}`
969
+ });
970
+ }
971
+ debug("Validating JWT token...");
972
+ try {
973
+ const client = new ServerClient(cfg);
974
+ await client.listOAS();
975
+ results.push({
976
+ name: "Authentication",
977
+ ok: true,
978
+ detail: "Token accepted by server"
979
+ });
980
+ } catch (err) {
981
+ const msg = err.message;
982
+ results.push({
983
+ name: "Authentication",
984
+ ok: false,
985
+ detail: `Token rejected: ${msg}`
986
+ });
987
+ }
988
+ printResults(results);
989
+ const allOk = results.every((r) => r.ok);
990
+ process.exit(allOk ? ExitCode.SUCCESS : ExitCode.GENERAL_ERROR);
991
+ });
992
+ }
993
+ function printResults(results) {
994
+ console.log("\nucli doctor\n" + "\u2550".repeat(40));
995
+ for (const r of results) {
996
+ const icon = r.ok ? "\u2713" : "\u2716";
997
+ console.log(` ${icon} ${r.name}: ${r.detail}`);
998
+ }
999
+ console.log();
1000
+ }
1001
+
1002
+ // src/commands/completions.ts
1003
+ function registerCompletions(program2) {
1004
+ program2.command("completions <shell>").description("Generate shell completion script (bash | zsh | fish)").action((shell) => {
1005
+ const normalized = shell.toLowerCase().trim();
1006
+ switch (normalized) {
1007
+ case "bash":
1008
+ console.log(bashCompletions());
1009
+ break;
1010
+ case "zsh":
1011
+ console.log(zshCompletions());
1012
+ break;
1013
+ case "fish":
1014
+ console.log(fishCompletions());
1015
+ break;
1016
+ default:
1017
+ console.error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
1018
+ process.exit(ExitCode.USAGE_ERROR);
713
1019
  }
714
1020
  });
715
1021
  }
1022
+ function bashCompletions() {
1023
+ return `# ucli bash completions \u2014 eval "$(ucli completions bash)"
1024
+ _ucli_completions() {
1025
+ local cur prev commands
1026
+ COMPREPLY=()
1027
+ cur="\${COMP_WORDS[COMP_CWORD]}"
1028
+ prev="\${COMP_WORDS[COMP_CWORD-1]}"
1029
+ commands="configure services run refresh help mcp doctor completions"
1030
+
1031
+ case "\${COMP_WORDS[1]}" in
1032
+ services)
1033
+ COMPREPLY=( $(compgen -W "list info" -- "$cur") )
1034
+ return 0
1035
+ ;;
1036
+ mcp)
1037
+ COMPREPLY=( $(compgen -W "list tools run" -- "$cur") )
1038
+ return 0
1039
+ ;;
1040
+ completions)
1041
+ COMPREPLY=( $(compgen -W "bash zsh fish" -- "$cur") )
1042
+ return 0
1043
+ ;;
1044
+ run|help)
1045
+ # dynamic completions would require server calls; skip for now
1046
+ return 0
1047
+ ;;
1048
+ esac
1049
+
1050
+ if [ "$COMP_CWORD" -eq 1 ]; then
1051
+ COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
1052
+ fi
1053
+
1054
+ return 0
1055
+ }
1056
+ complete -F _ucli_completions ucli`;
1057
+ }
1058
+ function zshCompletions() {
1059
+ return `# ucli zsh completions \u2014 eval "$(ucli completions zsh)"
1060
+ #compdef ucli
1061
+
1062
+ _ucli() {
1063
+ local -a commands
1064
+ commands=(
1065
+ 'configure:Configure server URL and authentication token'
1066
+ 'services:Manage and inspect available OAS services'
1067
+ 'run:Execute an operation on a service'
1068
+ 'refresh:Force-refresh the local OAS cache'
1069
+ 'help:Show usage guide'
1070
+ 'mcp:Interact with MCP servers'
1071
+ 'doctor:Check configuration and connectivity'
1072
+ 'completions:Generate shell completion script'
1073
+ )
1074
+
1075
+ _arguments -C \\
1076
+ '1: :->command' \\
1077
+ '*::arg:->args'
1078
+
1079
+ case $state in
1080
+ command)
1081
+ _describe -t commands 'ucli commands' commands
1082
+ ;;
1083
+ args)
1084
+ case $words[1] in
1085
+ services)
1086
+ _values 'subcommand' 'list[List all OAS services]' 'info[Show service details]'
1087
+ ;;
1088
+ mcp)
1089
+ _values 'subcommand' 'list[List MCP servers]' 'tools[List tools]' 'run[Call a tool]'
1090
+ ;;
1091
+ completions)
1092
+ _values 'shell' bash zsh fish
1093
+ ;;
1094
+ esac
1095
+ ;;
1096
+ esac
1097
+ }
1098
+
1099
+ _ucli "$@"`;
1100
+ }
1101
+ function fishCompletions() {
1102
+ return `# ucli fish completions \u2014 ucli completions fish | source
1103
+ complete -c ucli -e
1104
+
1105
+ # Top-level commands
1106
+ complete -c ucli -n __fish_use_subcommand -a configure -d 'Configure server URL and token'
1107
+ complete -c ucli -n __fish_use_subcommand -a services -d 'Manage OAS services'
1108
+ complete -c ucli -n __fish_use_subcommand -a run -d 'Execute a service operation'
1109
+ complete -c ucli -n __fish_use_subcommand -a refresh -d 'Refresh local cache'
1110
+ complete -c ucli -n __fish_use_subcommand -a help -d 'Show usage guide'
1111
+ complete -c ucli -n __fish_use_subcommand -a mcp -d 'Interact with MCP servers'
1112
+ complete -c ucli -n __fish_use_subcommand -a doctor -d 'Check config and connectivity'
1113
+ complete -c ucli -n __fish_use_subcommand -a completions -d 'Generate shell completions'
1114
+
1115
+ # services subcommands
1116
+ complete -c ucli -n '__fish_seen_subcommand_from services' -a list -d 'List services'
1117
+ complete -c ucli -n '__fish_seen_subcommand_from services' -a info -d 'Show service details'
1118
+
1119
+ # mcp subcommands
1120
+ complete -c ucli -n '__fish_seen_subcommand_from mcp' -a list -d 'List MCP servers'
1121
+ complete -c ucli -n '__fish_seen_subcommand_from mcp' -a tools -d 'List tools'
1122
+ complete -c ucli -n '__fish_seen_subcommand_from mcp' -a run -d 'Call a tool'
1123
+
1124
+ # completions subcommands
1125
+ complete -c ucli -n '__fish_seen_subcommand_from completions' -a 'bash zsh fish' -d 'Shell type'`;
1126
+ }
716
1127
 
717
1128
  // src/index.ts
718
1129
  var require3 = createRequire2(import.meta.url);
719
1130
  var pkg = require3("../package.json");
720
1131
  var program = new Command();
721
- program.name("ucli").description(pkg.description).version(pkg.version, "-v, --version").addHelpCommand(false);
1132
+ program.name("ucli").description(pkg.description).version(pkg.version, "-v, --version").option("--debug", "Enable verbose debug logging").addHelpCommand(false).hook("preAction", (_thisCommand, actionCommand) => {
1133
+ let cmd = actionCommand;
1134
+ while (cmd) {
1135
+ if (cmd.opts().debug) {
1136
+ setDebugMode(true);
1137
+ break;
1138
+ }
1139
+ cmd = cmd.parent;
1140
+ }
1141
+ });
722
1142
  registerConfigure(program);
723
1143
  registerServices(program);
724
1144
  registerRun(program);
725
1145
  registerRefresh(program);
726
1146
  registerMcp(program);
1147
+ registerDoctor(program);
1148
+ registerCompletions(program);
727
1149
  registerHelp(program);
728
1150
  program.parse(process.argv);
729
1151
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/lib/server-client.ts","../src/commands/configure.ts","../src/lib/cache.ts","../src/lib/oas-runner.ts","../src/commands/services.ts","../src/commands/run.ts","../src/commands/refresh.ts","../src/commands/help-cmd.ts","../src/lib/mcp-runner.ts","../src/commands/mcp.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { createRequire } from 'node:module'\nimport { registerConfigure } from './commands/configure.js'\nimport { registerServices } from './commands/services.js'\nimport { registerRun } from './commands/run.js'\nimport { registerRefresh } from './commands/refresh.js'\nimport { registerHelp } from './commands/help-cmd.js'\nimport { registerMcp } from './commands/mcp.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('../package.json') as { version: string; description: string }\n\nconst program = new Command()\n\nprogram\n .name('ucli')\n .description(pkg.description)\n .version(pkg.version, '-v, --version')\n .addHelpCommand(false) // we provide our own help command\n\nregisterConfigure(program)\nregisterServices(program)\nregisterRun(program)\nregisterRefresh(program)\nregisterMcp(program)\nregisterHelp(program)\n\nprogram.parse(process.argv)\n","import Conf from 'conf'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface CLIConfig {\n serverUrl: string\n token: string\n}\n\nconst conf = new Conf<CLIConfig>({\n projectName: 'ucli',\n schema: {\n serverUrl: { type: 'string' },\n token: { type: 'string' },\n },\n})\n\nexport const cacheDir = join(homedir(), '.cache', 'ucli')\n\nexport function getConfig(): CLIConfig {\n const serverUrl = conf.get('serverUrl')\n const token = conf.get('token')\n\n if (!serverUrl || !token) {\n console.error('ucli is not configured. Run: ucli configure --server <url> --token <jwt>')\n process.exit(1)\n }\n\n return { serverUrl, token }\n}\n\nexport function saveConfig(cfg: CLIConfig): void {\n conf.set('serverUrl', cfg.serverUrl)\n conf.set('token', cfg.token)\n}\n\nexport function isConfigured(): boolean {\n return Boolean(conf.get('serverUrl') && conf.get('token'))\n}\n","/**\n * HTTP client for the ucli-server API.\n * Attaches group JWT and handles common error cases.\n */\nimport axios, { type AxiosInstance } from 'axios'\nimport type { CLIConfig } from '../config.js'\n\nexport interface OASEntryPublic {\n id: string\n name: string\n description: string\n remoteUrl: string\n baseEndpoint: string | null\n authType: 'bearer' | 'api_key' | 'basic' | 'oauth2_cc' | 'none'\n authConfig: Record<string, unknown>\n cacheTtl: number\n}\n\nexport type McpAuthConfig =\n | { type: 'none' }\n | { type: 'http_headers'; headers: Record<string, string> }\n | { type: 'env'; env: Record<string, string> }\n\nexport interface McpEntryPublic {\n id: string\n groupId: string\n name: string\n description: string\n transport: 'http' | 'stdio'\n serverUrl: string | null\n command: string | null\n authConfig: McpAuthConfig\n enabled: boolean\n}\n\nexport class ServerClient {\n private http: AxiosInstance\n\n constructor(cfg: CLIConfig) {\n this.http = axios.create({\n baseURL: cfg.serverUrl.replace(/\\/$/, ''),\n headers: {\n Authorization: `Bearer ${cfg.token}`,\n 'Content-Type': 'application/json',\n },\n timeout: 15_000,\n })\n\n this.http.interceptors.response.use(\n (r) => r,\n (err: unknown) => {\n if (axios.isAxiosError(err)) {\n const status = err.response?.status\n const message = (err.response?.data as { message?: string })?.message ?? err.message\n\n if (status === 401) {\n console.error('Authentication failed. Run: ucli configure --server <url> --token <jwt>')\n process.exit(1)\n }\n\n throw new Error(`Server error ${status ?? 'unknown'}: ${message}`)\n }\n throw err\n },\n )\n }\n\n async listOAS(): Promise<OASEntryPublic[]> {\n const { data } = await this.http.get<OASEntryPublic[]>('/api/v1/oas')\n return data\n }\n\n async getOAS(name: string): Promise<OASEntryPublic> {\n const { data } = await this.http.get<OASEntryPublic>(`/api/v1/oas/${encodeURIComponent(name)}`)\n return data\n }\n\n async listMCP(): Promise<McpEntryPublic[]> {\n const { data } = await this.http.get<McpEntryPublic[]>('/api/v1/mcp')\n return data\n }\n\n async getMCP(name: string): Promise<McpEntryPublic> {\n const { data } = await this.http.get<McpEntryPublic>(`/api/v1/mcp/${encodeURIComponent(name)}`)\n return data\n }\n}\n","import type { Command } from 'commander'\nimport { saveConfig, isConfigured } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\n\nexport function registerConfigure(program: Command): void {\n program\n .command('configure')\n .description('Configure the OAS Gateway server URL and authentication token')\n .requiredOption('--server <url>', 'OAS Gateway server URL (e.g. https://oas.example.com)')\n .requiredOption('--token <jwt>', 'Group JWT token issued by the server admin')\n .action(async (opts: { server: string; token: string }) => {\n const serverUrl = opts.server.replace(/\\/$/, '')\n const token = opts.token\n\n // Validate connectivity before saving\n console.log(`Connecting to ${serverUrl}...`)\n const client = new ServerClient({ serverUrl, token })\n\n try {\n await client.listOAS()\n saveConfig({ serverUrl, token })\n console.log('✓ Configuration saved successfully.')\n console.log(` Server: ${serverUrl}`)\n console.log(` Token: ${token.slice(0, 20)}...`)\n } catch (err) {\n console.error('Connection failed:', (err as Error).message)\n console.error('Please check the server URL and token.')\n process.exit(1)\n }\n })\n}\n","/**\n * Local file cache for OAS entries.\n * Stored at ~/.cache/oas-cli/<name>.json with TTL metadata.\n *\n * Security: authConfig credential values are stripped before writing.\n * Only { type } is persisted — full secrets are never written to disk.\n */\nimport { readFile, writeFile, mkdir, unlink, chmod } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { cacheDir } from '../config.js'\nimport type { OASEntryPublic } from './server-client.js'\n\ninterface CacheFile {\n entries: OASEntryPublic[]\n fetchedAt: number // ms timestamp\n ttlSec: number // cache duration\n}\n\nconst LIST_CACHE_FILE = join(cacheDir, 'oas-list.json')\n\nasync function ensureCacheDir(): Promise<void> {\n await mkdir(cacheDir, { recursive: true, mode: 0o700 })\n}\n\n/** Strip credential secrets from authConfig — only persist { type }. */\nfunction redactEntries(entries: OASEntryPublic[]): OASEntryPublic[] {\n return entries.map((e) => ({\n ...e,\n authConfig: { type: (e.authConfig as Record<string, unknown>)['type'] ?? e.authType },\n }))\n}\n\nexport async function readOASListCache(): Promise<OASEntryPublic[] | null> {\n try {\n const raw = await readFile(LIST_CACHE_FILE, 'utf8')\n const cached: CacheFile = JSON.parse(raw)\n const age = (Date.now() - cached.fetchedAt) / 1000\n if (cached.ttlSec === 0 || age > cached.ttlSec) return null // expired\n return cached.entries\n } catch {\n return null // not found or parse error\n }\n}\n\nexport async function writeOASListCache(entries: OASEntryPublic[], ttlSec: number): Promise<void> {\n await ensureCacheDir()\n const cached: CacheFile = { entries: redactEntries(entries), fetchedAt: Date.now(), ttlSec }\n await writeFile(LIST_CACHE_FILE, JSON.stringify(cached, null, 2), { encoding: 'utf8', mode: 0o600 })\n await chmod(LIST_CACHE_FILE, 0o600)\n}\n\nexport async function clearOASListCache(): Promise<void> {\n try {\n await unlink(LIST_CACHE_FILE)\n } catch {\n // ignore if not found\n }\n}\n\nexport async function clearOASCache(name: string): Promise<void> {\n try {\n const raw = await readFile(LIST_CACHE_FILE, 'utf8')\n const cached: CacheFile = JSON.parse(raw)\n const entries = Array.isArray(cached.entries) ? cached.entries.filter((e) => e.name !== name) : []\n if (entries.length === 0) {\n await clearOASListCache()\n return\n }\n const next: CacheFile = {\n entries,\n fetchedAt: cached.fetchedAt ?? Date.now(),\n ttlSec: cached.ttlSec ?? 0,\n }\n await writeFile(LIST_CACHE_FILE, JSON.stringify(next, null, 2), { encoding: 'utf8', mode: 0o600 })\n } catch {\n await clearOASListCache()\n }\n}\n","/**\n * Bridge between oas-cli and @tronsfey/openapi2cli run mode.\n *\n * Spawns openapi2cli as a child process, injecting auth config\n * as environment variables (never exposed to the agent's shell).\n */\nimport { spawn } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport { join, dirname } from 'node:path'\nimport type { OASEntryPublic } from './server-client.js'\n\nconst require = createRequire(import.meta.url)\n\nfunction resolveOpenapi2CliBin(): string {\n try {\n const pkgPath = require.resolve('@tronsfey/openapi2cli/package.json')\n const pkgDir = dirname(pkgPath)\n // @tronsfey/openapi2cli exposes its binary; find it\n const pkg = require('@tronsfey/openapi2cli/package.json') as { bin?: Record<string, string> }\n const binEntry = pkg.bin?.['openapi2cli'] ?? 'bin/openapi2cli.js'\n return join(pkgDir, binEntry)\n } catch {\n throw new Error(\n '@tronsfey/openapi2cli is not installed. Run: pnpm add @tronsfey/openapi2cli in packages/cli',\n )\n }\n}\n\nexport interface RunOptions {\n entry: OASEntryPublic\n /** Operation command args (e.g. ['listPets', '--limit', '10']) */\n operationArgs: string[]\n format?: 'json' | 'table' | 'yaml'\n query?: string\n}\n\n/**\n * Build auth environment variables for injection into child process.\n * The calling shell (and thus the AI agent) never sees these values.\n */\nfunction buildAuthEnv(entry: OASEntryPublic): Record<string, string> {\n const cfg = entry.authConfig\n const prefix = entry.name.toUpperCase().replace(/[^A-Z0-9]/g, '_')\n\n switch (cfg['type']) {\n case 'bearer':\n return { [`${prefix}_TOKEN`]: cfg['token'] as string }\n\n case 'api_key':\n return { [`${prefix}_API_KEY`]: cfg['key'] as string }\n\n case 'basic':\n return { [`${prefix}_CREDENTIALS`]: `${cfg['username']}:${cfg['password']}` }\n\n case 'oauth2_cc':\n return {\n [`${prefix}_CLIENT_ID`]: cfg['clientId'] as string,\n [`${prefix}_CLIENT_SECRET`]: cfg['clientSecret'] as string,\n [`${prefix}_SCOPES`]: (cfg['scopes'] as string[]).join(' '),\n }\n\n default:\n return {}\n }\n}\n\n/**\n * Environment variable allowlist for subprocess execution.\n * Only these variables (when present in the parent) are forwarded to the\n * child process. This prevents leakage of secrets such as cloud credentials,\n * encryption keys, or database passwords that may be in the parent env.\n */\nconst SAFE_ENV_KEYS: readonly string[] = [\n // System essentials\n 'PATH', 'HOME', 'USER', 'LOGNAME', 'SHELL', 'TMPDIR', 'TMP', 'TEMP',\n // Terminal / display\n 'TERM', 'COLORTERM', 'NO_COLOR', 'FORCE_COLOR', 'LANG', 'LC_ALL',\n 'LC_CTYPE', 'LC_MESSAGES', 'LC_COLLATE',\n // Node.js\n 'NODE_ENV', 'NODE_PATH', 'NODE_OPTIONS', 'NODE_EXTRA_CA_CERTS',\n // Network proxy (required for tools behind corporate proxies)\n 'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY',\n 'http_proxy', 'https_proxy', 'no_proxy',\n // OS-specific\n 'SYSTEMROOT', 'COMSPEC', 'APPDATA', 'LOCALAPPDATA', 'PROGRAMFILES',\n 'XDG_RUNTIME_DIR', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME',\n]\n\nfunction buildSafeEnv(authEnv: Record<string, string>): Record<string, string> {\n const safe: Record<string, string> = {}\n for (const key of SAFE_ENV_KEYS) {\n if (process.env[key] !== undefined) {\n safe[key] = process.env[key]!\n }\n }\n return { ...safe, ...authEnv }\n}\n\nexport async function runOperation(opts: RunOptions): Promise<void> {\n const bin = resolveOpenapi2CliBin()\n const { entry, operationArgs, format, query } = opts\n\n const args = [\n 'run',\n '--oas', entry.remoteUrl,\n '--cache-ttl', String(entry.cacheTtl),\n ...(entry.baseEndpoint ? ['--endpoint', entry.baseEndpoint] : []),\n ...(format ? ['--format', format] : []),\n ...(query ? ['--query', query] : []),\n ...operationArgs,\n ]\n\n const authEnv = buildAuthEnv(entry)\n\n await new Promise<void>((resolve, reject) => {\n const child = spawn(process.execPath, [bin, ...args], {\n stdio: 'inherit',\n env: buildSafeEnv(authEnv),\n })\n\n child.on('close', (code) => {\n if (code === 0) resolve()\n else reject(new Error(`openapi2cli exited with code ${code}`))\n })\n child.on('error', reject)\n })\n}\n\n/**\n * Get list of available operations for a service by running `--help`.\n * Returns the raw help text from openapi2cli.\n */\nexport async function getServiceHelp(entry: OASEntryPublic): Promise<string> {\n const bin = resolveOpenapi2CliBin()\n const args = [\n 'run',\n '--oas', entry.remoteUrl,\n '--cache-ttl', String(entry.cacheTtl),\n '--help',\n ]\n\n return new Promise<string>((resolve, reject) => {\n let output = ''\n const child = spawn(process.execPath, [bin, ...args], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n child.stdout?.on('data', (d: Buffer) => { output += d.toString() })\n child.stderr?.on('data', (d: Buffer) => { output += d.toString() })\n child.on('close', () => resolve(output))\n child.on('error', reject)\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { readOASListCache, writeOASListCache } from '../lib/cache.js'\nimport { getServiceHelp } from '../lib/oas-runner.js'\n\nexport function registerServices(program: Command): void {\n const services = program\n .command('services')\n .description('Manage and inspect available OAS services')\n\n // services list\n services\n .command('list')\n .description('List all OAS services available in the current group')\n .option('--refresh', 'Bypass local cache and fetch fresh from server')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .option('--no-cache', 'Bypass local cache and fetch fresh from server')\n .action(async (opts: { cache: boolean; refresh?: boolean; format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n if (!opts.cache) {\n process.emitWarning('The --no-cache flag is deprecated. Please use --refresh instead.')\n }\n\n const useCache = opts.cache && !opts.refresh\n let entries = useCache ? await readOASListCache() : null\n\n if (!entries) {\n entries = await client.listOAS()\n if (entries.length > 0) {\n const maxTtl = Math.min(...entries.map((e) => e.cacheTtl))\n await writeOASListCache(entries, maxTtl)\n }\n }\n\n const format = (opts.format ?? 'table').toLowerCase()\n\n if (entries.length === 0) {\n console.log('No services registered in this group.')\n return\n }\n\n if (format === 'json') {\n // Strip authConfig secrets from JSON output — only expose { type }\n const safe = entries.map(({ authConfig, ...rest }) => ({\n ...rest,\n authConfig: { type: (authConfig as Record<string, unknown>)['type'] ?? rest.authType },\n }))\n console.log(JSON.stringify(safe, null, 2))\n return\n }\n\n const nameWidth = Math.max(10, ...entries.map((e) => e.name.length))\n console.log(`\\n${'SERVICE'.padEnd(nameWidth)} AUTH DESCRIPTION`)\n console.log(`${'-'.repeat(nameWidth)} -------- ${'-'.repeat(40)}`)\n for (const e of entries) {\n const auth = e.authType.padEnd(8)\n const desc = e.description.length > 60 ? e.description.slice(0, 57) + '...' : e.description\n console.log(`${e.name.padEnd(nameWidth)} ${auth} ${desc}`)\n }\n console.log()\n })\n\n // services info <name>\n services\n .command('info <name>')\n .description('Show detailed information and available operations for a service')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .action(async (name: string, opts: { format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getOAS(name)\n } catch (err) {\n console.error(`Service not found: ${name}`)\n console.error('Run `ucli services list` to see available services.')\n process.exit(1)\n }\n\n const help = await getServiceHelp(entry)\n const format = (opts.format ?? 'table').toLowerCase()\n if (format === 'json') {\n // Strip authConfig secrets from JSON output\n const { authConfig, ...rest } = entry\n const safe = {\n ...rest,\n authConfig: { type: (authConfig as Record<string, unknown>)['type'] ?? rest.authType },\n operationsHelp: help,\n }\n console.log(JSON.stringify(safe, null, 2))\n return\n }\n\n console.log(`\\nService: ${entry.name}`)\n console.log(`Description: ${entry.description || '(none)'}`)\n console.log(`OAS URL: ${entry.remoteUrl}`)\n if (entry.baseEndpoint) console.log(`Base endpoint: ${entry.baseEndpoint}`)\n console.log(`Auth type: ${entry.authType}`)\n console.log(`Cache TTL: ${entry.cacheTtl}s`)\n console.log('\\nAvailable operations:')\n console.log('─'.repeat(60))\n console.log(help)\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { runOperation } from '../lib/oas-runner.js'\n\nexport function registerRun(program: Command): void {\n program\n .command('run [service] [args...]')\n .description('Execute an operation on a service')\n .option('--service <name>', 'Service name (from `services list`)')\n .option('--operation <id>', 'OperationId to execute')\n .option('--params <json>', 'JSON string of operation parameters')\n .option('--format <fmt>', 'Output format: json | table | yaml', 'json')\n .option('--query <jmespath>', 'Filter response with JMESPath expression')\n .option('--data <json>', 'Request body (JSON string or @filename)')\n .allowUnknownOption(true)\n .action(async (\n serviceArg: string | undefined,\n args: string[],\n opts: { service?: string; operation?: string; params?: string; format?: string; query?: string; data?: string; args?: string[] },\n ) => {\n if (serviceArg && opts.service && serviceArg !== opts.service) {\n console.error(`Conflicting service values: positional \"${serviceArg}\" and --service \"${opts.service}\". Use either the positional argument or --service flag, not both.`)\n process.exit(1)\n }\n\n const service = opts.service ?? serviceArg\n if (!service) {\n console.error('Missing service name. Use positional <service> or --service <name>.')\n process.exit(1)\n }\n\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getOAS(service)\n } catch {\n console.error(`Unknown service: ${service}`)\n console.error('Run `ucli services list` to see available services.')\n process.exit(1)\n }\n\n // Collect extra args (pass-through to openapi2cli)\n const extraArgs = opts.args ?? []\n const operationArgs = [...args, ...extraArgs]\n\n if (opts.operation) {\n operationArgs.unshift(opts.operation)\n }\n\n if (opts.params) {\n let parsed: unknown\n try {\n parsed = JSON.parse(opts.params)\n } catch {\n console.error('Invalid --params JSON. Example: --params \\'{\"petId\": 1}\\'')\n process.exit(1)\n }\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n for (const [k, v] of Object.entries(parsed as Record<string, unknown>)) {\n if (v === undefined || v === null) continue\n const strVal = typeof v === 'object' ? JSON.stringify(v) : String(v)\n operationArgs.push(`--${k}`, strVal)\n }\n }\n }\n\n if (opts.data) {\n operationArgs.push('--data', opts.data)\n }\n\n const format = opts.format as 'json' | 'table' | 'yaml' | undefined\n const query = opts.query as string | undefined\n\n try {\n await runOperation({\n entry,\n operationArgs,\n ...(format !== undefined ? { format } : {}),\n ...(query !== undefined ? { query } : {}),\n })\n } catch (err) {\n console.error('Operation failed:', (err as Error).message)\n process.exit(1)\n }\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { writeOASListCache, clearOASListCache, clearOASCache } from '../lib/cache.js'\n\nexport function registerRefresh(program: Command): void {\n program\n .command('refresh')\n .description('Force-refresh the local OAS cache from the server')\n .option('--service <name>', 'Refresh only a specific service')\n .action(async (opts: { service?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n console.log('Refreshing OAS list from server...')\n if (opts.service) {\n await clearOASCache(opts.service)\n } else {\n await clearOASListCache()\n }\n\n const entries = await client.listOAS()\n if (entries.length > 0) {\n const maxTtl = Math.min(...entries.map((e) => e.cacheTtl))\n await writeOASListCache(entries, maxTtl)\n }\n\n console.log(`✓ Refreshed ${entries.length} service(s).`)\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig, isConfigured } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { readOASListCache, writeOASListCache } from '../lib/cache.js'\nimport { getServiceHelp } from '../lib/oas-runner.js'\n\nexport function registerHelp(program: Command): void {\n program\n .command('help [service]')\n .description('Show usage guide. Pass a service name for service-specific operations.')\n .action(async (service?: string) => {\n if (!service) {\n printGeneralHelp()\n if (isConfigured()) {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n let entries = await readOASListCache()\n if (!entries) {\n entries = await client.listOAS()\n if (entries.length > 0) {\n const maxTtl = Math.min(...entries.map((e) => e.cacheTtl))\n await writeOASListCache(entries, maxTtl)\n }\n }\n if (entries.length > 0) {\n console.log('\\nAvailable services:')\n for (const e of entries) {\n console.log(` ${e.name.padEnd(20)} ${e.description}`)\n }\n console.log('\\nTip: Run `ucli help <service>` for service-specific operations.')\n }\n } else {\n console.log('\\nRun `ucli configure --server <url> --token <jwt>` to get started.')\n }\n return\n }\n\n // Service-specific help\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getOAS(service)\n } catch {\n console.error(`Unknown service: ${service}`)\n console.error('Run `ucli services list` to see available services.')\n process.exit(1)\n }\n\n console.log(`\\n=== ${entry.name} ===`)\n console.log(`${entry.description}`)\n console.log(`\\nOAS spec: ${entry.remoteUrl}`)\n console.log('\\nOperations:')\n console.log('─'.repeat(60))\n\n const help = await getServiceHelp(entry)\n console.log(help)\n\n console.log('\\nExamples:')\n console.log(` ucli run ${entry.name} <operation>`)\n console.log(` ucli run ${entry.name} <operation> --format table`)\n console.log(` ucli run ${entry.name} <operation> --query \"results[*].id\"`)\n console.log(` ucli run ${entry.name} <operation> --data '{\"key\":\"value\"}'`)\n })\n}\n\nfunction printGeneralHelp(): void {\n console.log(`\nucli — OpenAPI & MCP Gateway for AI Agents\n════════════════════════════════════════\n\nSETUP\n ucli configure --server <url> --token <jwt>\n Configure server connection and authentication.\n\nDISCOVERY\n ucli services list\n List all OAS services available in your group.\n\n ucli services info <service>\n Show detailed service info and all available operations.\n\n ucli help [service]\n Show this guide, or service-specific operations.\n\nEXECUTION\n ucli run <service> <operation> [options]\n Execute a service operation.\n\n Options:\n --format json|table|yaml Output format (default: json)\n --query <jmespath> Filter response with JMESPath\n --data <json|@file> Request body for POST/PUT/PATCH\n\nMAINTENANCE\n ucli refresh\n Force-refresh the local OAS cache from the server.\n\nERRORS\n 401 Unauthorized → Run: ucli configure --server <url> --token <jwt>\n 404 Not Found → Check service name: ucli services list\n 4xx Client Error → Check operation args: ucli services info <service>\n 5xx Server Error → Retry or run: ucli refresh\n`)\n}\n","/**\n * MCP tool runner using @tronsfey/mcp2cli programmatic API.\n *\n * Auth credentials are injected via McpServerConfig (headers or env) —\n * never passed as CLI arguments (which would be visible in `ps`).\n */\nimport type { McpEntryPublic } from './server-client.js'\n\n/**\n * Resolve a named export from a module that may be CJS-wrapped (exports live\n * under `module.default`) or a plain ESM module (named exports at top level).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction resolve(mod: any, name: string): unknown {\n if (typeof mod[name] === 'function') return mod[name]\n if (mod.default && typeof mod.default[name] === 'function') return mod.default[name]\n throw new Error(`Cannot resolve export \"${name}\" from module`)\n}\n\nasync function getMcp2cli() {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const clientMod = await import('@tronsfey/mcp2cli/dist/client/index.js') as any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const runnerMod = await import('@tronsfey/mcp2cli/dist/runner/index.js') as any\n return {\n createMcpClient: resolve(clientMod, 'createMcpClient') as (...args: unknown[]) => Promise<unknown>,\n getTools: resolve(runnerMod, 'getTools') as (...args: unknown[]) => Promise<{ name: string; description?: string }[]>,\n runTool: resolve(runnerMod, 'runTool') as (...args: unknown[]) => Promise<void>,\n }\n}\n\nasync function closeClient(client: unknown): Promise<void> {\n if (typeof (client as { close?: unknown }).close === 'function') {\n await (client as { close: () => Promise<void> }).close()\n }\n}\n\nfunction buildMcpConfig(entry: McpEntryPublic): Record<string, unknown> {\n const base: Record<string, unknown> = { type: entry.transport }\n if (entry.transport === 'http') {\n base.url = entry.serverUrl\n } else {\n base.command = entry.command\n }\n const auth = entry.authConfig\n if (auth.type === 'http_headers') {\n base.headers = auth.headers\n } else if (auth.type === 'env') {\n base.env = auth.env\n }\n return base\n}\n\nexport async function listMcpTools(entry: McpEntryPublic): Promise<{ name: string; description?: string }[]> {\n const { createMcpClient, getTools } = await getMcp2cli()\n const config = buildMcpConfig(entry)\n const client = await createMcpClient(config)\n try {\n const tools = await getTools(client, config, { noCache: true })\n return tools\n } finally {\n await closeClient(client)\n }\n}\n\nexport async function runMcpTool(entry: McpEntryPublic, toolName: string, rawArgs: string[]): Promise<void> {\n const { createMcpClient, getTools, runTool } = await getMcp2cli()\n const config = buildMcpConfig(entry)\n const client = await createMcpClient(config)\n try {\n const tools = await getTools(client, config, { noCache: false, cacheTtl: 3600 })\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const tool = tools.find((t: any) => t.name === toolName)\n if (!tool) throw new Error(`Tool \"${toolName}\" not found on MCP server \"${entry.name}\"`)\n const normalizedArgs: string[] = []\n for (const arg of rawArgs) {\n if (arg.includes('=') && !arg.startsWith('--')) {\n const idx = arg.indexOf('=')\n const key = arg.slice(0, idx)\n const value = arg.slice(idx + 1)\n normalizedArgs.push(`--${key}`, value)\n } else {\n normalizedArgs.push(arg)\n }\n }\n await runTool(client, tool, normalizedArgs, {})\n } finally {\n await closeClient(client)\n }\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { listMcpTools, runMcpTool } from '../lib/mcp-runner.js'\n\nexport function registerMcp(program: Command): void {\n const mcp = program\n .command('mcp')\n .description('Interact with MCP servers registered in your group')\n\n // mcp list\n mcp\n .command('list')\n .description('List all MCP servers available in the current group')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .action(async (opts: { format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n const entries = await client.listMCP()\n\n if (entries.length === 0) {\n console.log('No MCP servers registered in this group.')\n return\n }\n\n const format = (opts.format ?? 'table').toLowerCase()\n if (format === 'json') {\n // Strip authConfig secrets from JSON output — only expose { type }\n const safe = entries.map(({ authConfig, ...rest }) => ({\n ...rest,\n authConfig: { type: authConfig.type },\n }))\n console.log(JSON.stringify(safe, null, 2))\n return\n }\n\n const nameWidth = Math.max(10, ...entries.map(e => e.name.length))\n console.log(`\\n${'SERVER'.padEnd(nameWidth)} TRANSPORT DESCRIPTION`)\n console.log(`${'-'.repeat(nameWidth)} --------- ${'-'.repeat(40)}`)\n for (const e of entries) {\n const desc = e.description.length > 60 ? e.description.slice(0, 57) + '...' : e.description\n console.log(`${e.name.padEnd(nameWidth)} ${e.transport.padEnd(9)} ${desc}`)\n }\n console.log()\n })\n\n // mcp tools <server>\n mcp\n .command('tools <server>')\n .description('List tools available on a MCP server')\n .option('--format <fmt>', 'Output format: table | json', 'table')\n .action(async (serverName: string, opts: { format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getMCP(serverName)\n } catch {\n console.error(`Unknown MCP server: ${serverName}`)\n console.error('Run `ucli mcp list` to see available servers.')\n process.exit(1)\n }\n\n let tools\n try {\n tools = await listMcpTools(entry)\n } catch (err) {\n console.error('Failed to fetch tools:', (err as Error).message)\n process.exit(1)\n }\n\n if (tools.length === 0) {\n console.log(`No tools found on MCP server \"${serverName}\".`)\n return\n }\n\n const format = (opts.format ?? 'table').toLowerCase()\n if (format === 'json') {\n console.log(JSON.stringify(tools, null, 2))\n return\n }\n\n console.log(`\\nTools on \"${serverName}\":`)\n console.log('─'.repeat(60))\n for (const t of tools) {\n console.log(` ${t.name}`)\n if (t.description) console.log(` ${t.description}`)\n }\n console.log()\n })\n\n // mcp run <server> <tool> [args...]\n mcp\n .command('run <server> <tool> [args...]')\n .description('Call a tool on a MCP server')\n .action(async (serverName: string, toolName: string, args: string[]) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getMCP(serverName)\n } catch {\n console.error(`Unknown MCP server: ${serverName}`)\n console.error('Run `ucli mcp list` to see available servers.')\n process.exit(1)\n }\n\n try {\n await runMcpTool(entry, toolName, args)\n } catch (err) {\n console.error('Tool execution failed:', (err as Error).message)\n process.exit(1)\n }\n })\n}\n"],"mappings":"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","names":["createRequire","program","join","join","join","require","pkg","resolve","program","program","program","program","cfg","client","program","require","createRequire"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/lib/config-encryption.ts","../src/lib/server-client.ts","../src/lib/exit-codes.ts","../src/commands/configure.ts","../src/lib/cache.ts","../src/lib/oas-runner.ts","../src/lib/yaml.ts","../src/commands/services.ts","../src/commands/run.ts","../src/commands/refresh.ts","../src/commands/help-cmd.ts","../src/lib/mcp-runner.ts","../src/commands/mcp.ts","../src/lib/errors.ts","../src/commands/doctor.ts","../src/commands/completions.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { createRequire } from 'node:module'\nimport { registerConfigure } from './commands/configure.js'\nimport { registerServices } from './commands/services.js'\nimport { registerRun } from './commands/run.js'\nimport { registerRefresh } from './commands/refresh.js'\nimport { registerHelp } from './commands/help-cmd.js'\nimport { registerMcp } from './commands/mcp.js'\nimport { registerDoctor } from './commands/doctor.js'\nimport { registerCompletions } from './commands/completions.js'\nimport { setDebugMode } from './lib/errors.js'\n\nconst require = createRequire(import.meta.url)\nconst pkg = require('../package.json') as { version: string; description: string }\n\nconst program = new Command()\n\nprogram\n .name('ucli')\n .description(pkg.description)\n .version(pkg.version, '-v, --version')\n .option('--debug', 'Enable verbose debug logging')\n .addHelpCommand(false) // we provide our own help command\n .hook('preAction', (_thisCommand, actionCommand) => {\n // Walk up to root to find the --debug flag\n let cmd = actionCommand\n while (cmd) {\n if ((cmd.opts() as Record<string, unknown>).debug) {\n setDebugMode(true)\n break\n }\n cmd = cmd.parent as Command\n }\n })\n\nregisterConfigure(program)\nregisterServices(program)\nregisterRun(program)\nregisterRefresh(program)\nregisterMcp(program)\nregisterDoctor(program)\nregisterCompletions(program)\nregisterHelp(program)\n\nprogram.parse(process.argv)\n","import Conf from 'conf'\nimport { homedir } from 'node:os'\nimport { join, dirname } from 'node:path'\nimport { chmodSync, mkdirSync } from 'node:fs'\nimport { encryptValue, decryptValue, isEncrypted } from './lib/config-encryption.js'\n\nexport interface CLIConfig {\n serverUrl: string\n token: string\n}\n\nconst conf = new Conf<CLIConfig>({\n projectName: 'ucli',\n schema: {\n serverUrl: { type: 'string' },\n token: { type: 'string' },\n },\n})\n\nexport const cacheDir = join(homedir(), '.cache', 'ucli')\n\n/** Ensure the config file and its directory have restrictive permissions. */\nfunction hardenConfigPermissions(): void {\n try {\n const configPath = conf.path\n const configDir = dirname(configPath)\n mkdirSync(configDir, { recursive: true, mode: 0o700 })\n chmodSync(configDir, 0o700)\n chmodSync(configPath, 0o600)\n } catch {\n // Permission enforcement may fail on some platforms (e.g., Windows)\n console.warn('Warning: Could not enforce restrictive file permissions on config. Token is encrypted but file permissions may be permissive.')\n }\n}\n\nexport function getConfig(): CLIConfig {\n const serverUrl = conf.get('serverUrl')\n const rawToken = conf.get('token')\n\n if (!serverUrl || !rawToken) {\n console.error('ucli is not configured. Run: ucli configure --server <url> --token <jwt>')\n process.exit(1)\n }\n\n const token = decryptValue(rawToken)\n\n // Auto-migrate: re-encrypt legacy plaintext tokens on read\n if (!isEncrypted(rawToken)) {\n conf.set('token', encryptValue(token))\n hardenConfigPermissions()\n }\n\n return { serverUrl, token }\n}\n\nexport function saveConfig(cfg: CLIConfig): void {\n conf.set('serverUrl', cfg.serverUrl)\n conf.set('token', encryptValue(cfg.token))\n hardenConfigPermissions()\n}\n\nexport function isConfigured(): boolean {\n return Boolean(conf.get('serverUrl') && conf.get('token'))\n}\n","/**\n * Config value encryption utilities.\n *\n * Encrypts sensitive config values (e.g., JWT tokens) at rest using AES-256-GCM\n * with a machine-specific derived key. This ensures credentials are never stored\n * in plaintext on disk.\n *\n * Key derivation: PBKDF2(username + hostname, random-salt, 100k iterations, SHA-512)\n * Format: \"enc:v1:<base64(salt + iv + authTag + ciphertext)>\"\n */\nimport {\n createCipheriv,\n createDecipheriv,\n randomBytes,\n pbkdf2Sync,\n} from 'node:crypto'\nimport { hostname, userInfo } from 'node:os'\n\nconst ENC_PREFIX = 'enc:v1:'\nconst ALGORITHM = 'aes-256-gcm'\nconst SALT_LEN = 32\nconst IV_LEN = 12\nconst TAG_LEN = 16\nconst PBKDF2_ITERATIONS = 100_000\n\n/** Derive a 256-bit key from machine-specific identity + per-value random salt. */\nfunction deriveKey(salt: Buffer): Buffer {\n let user = 'default'\n try {\n user = userInfo().username\n } catch {\n // userInfo() may throw on some platforms (e.g., certain containers)\n }\n const material = `ucli:${user}@${hostname()}`\n return pbkdf2Sync(material, salt, PBKDF2_ITERATIONS, 32, 'sha512')\n}\n\n/** Encrypt a plaintext string. Returns prefixed ciphertext string. */\nexport function encryptValue(plaintext: string): string {\n const salt = randomBytes(SALT_LEN)\n const key = deriveKey(salt)\n const iv = randomBytes(IV_LEN)\n const cipher = createCipheriv(ALGORITHM, key, iv)\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])\n const tag = cipher.getAuthTag()\n const packed = Buffer.concat([salt, iv, tag, encrypted])\n return ENC_PREFIX + packed.toString('base64')\n}\n\n/**\n * Decrypt a stored value. If the value has the encryption prefix, it is\n * decrypted; otherwise it is returned as-is for backward compatibility\n * with legacy plaintext configs.\n */\nexport function decryptValue(stored: string): string {\n if (!stored.startsWith(ENC_PREFIX)) {\n return stored\n }\n const packed = Buffer.from(stored.slice(ENC_PREFIX.length), 'base64')\n const salt = packed.subarray(0, SALT_LEN)\n const iv = packed.subarray(SALT_LEN, SALT_LEN + IV_LEN)\n const tag = packed.subarray(SALT_LEN + IV_LEN, SALT_LEN + IV_LEN + TAG_LEN)\n const encrypted = packed.subarray(SALT_LEN + IV_LEN + TAG_LEN)\n const key = deriveKey(salt)\n const decipher = createDecipheriv(ALGORITHM, key, iv)\n decipher.setAuthTag(tag)\n return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf8')\n}\n\n/** Check whether a stored value is encrypted (has the encryption prefix). */\nexport function isEncrypted(value: string): boolean {\n return value.startsWith(ENC_PREFIX)\n}\n","/**\n * HTTP client for the ucli-server API.\n * Attaches group JWT and handles common error cases.\n */\nimport axios, { type AxiosInstance } from 'axios'\nimport type { CLIConfig } from '../config.js'\n\nexport interface OASEntryPublic {\n id: string\n name: string\n description: string\n remoteUrl: string\n baseEndpoint: string | null\n authType: 'bearer' | 'api_key' | 'basic' | 'oauth2_cc' | 'none'\n authConfig: Record<string, unknown>\n cacheTtl: number\n}\n\nexport type McpAuthConfig =\n | { type: 'none' }\n | { type: 'http_headers'; headers: Record<string, string> }\n | { type: 'env'; env: Record<string, string> }\n\nexport interface McpEntryPublic {\n id: string\n groupId: string\n name: string\n description: string\n transport: 'http' | 'stdio'\n serverUrl: string | null\n command: string | null\n authConfig: McpAuthConfig\n enabled: boolean\n}\n\nexport class ServerClient {\n private http: AxiosInstance\n\n constructor(cfg: CLIConfig) {\n this.http = axios.create({\n baseURL: cfg.serverUrl.replace(/\\/$/, ''),\n headers: {\n Authorization: `Bearer ${cfg.token}`,\n 'Content-Type': 'application/json',\n },\n timeout: 15_000,\n })\n\n this.http.interceptors.response.use(\n (r) => r,\n (err: unknown) => {\n if (axios.isAxiosError(err)) {\n const status = err.response?.status\n const message = (err.response?.data as { message?: string })?.message ?? err.message\n\n if (status === 401) {\n console.error('Authentication failed. Run: ucli configure --server <url> --token <jwt>')\n process.exit(1)\n }\n\n throw new Error(`Server error ${status ?? 'unknown'}: ${message}`)\n }\n throw err\n },\n )\n }\n\n async listOAS(): Promise<OASEntryPublic[]> {\n const { data } = await this.http.get<OASEntryPublic[]>('/api/v1/oas')\n return data\n }\n\n async getOAS(name: string): Promise<OASEntryPublic> {\n const { data } = await this.http.get<OASEntryPublic>(`/api/v1/oas/${encodeURIComponent(name)}`)\n return data\n }\n\n async listMCP(): Promise<McpEntryPublic[]> {\n const { data } = await this.http.get<McpEntryPublic[]>('/api/v1/mcp')\n return data\n }\n\n async getMCP(name: string): Promise<McpEntryPublic> {\n const { data } = await this.http.get<McpEntryPublic>(`/api/v1/mcp/${encodeURIComponent(name)}`)\n return data\n }\n}\n","/**\n * Structured exit codes for automation and scripting.\n *\n * Convention:\n * 0 — success\n * 1 — general / unknown error\n * 2 — usage / argument error\n * 3 — configuration error (missing or invalid config)\n * 4 — authentication error (invalid / expired token)\n * 5 — connectivity error (server unreachable)\n * 6 — not-found error (service / resource doesn't exist)\n * 7 — server error (5xx from upstream)\n */\n\nexport const ExitCode = {\n SUCCESS: 0,\n GENERAL_ERROR: 1,\n USAGE_ERROR: 2,\n CONFIG_ERROR: 3,\n AUTH_ERROR: 4,\n CONNECTIVITY_ERROR: 5,\n NOT_FOUND: 6,\n SERVER_ERROR: 7,\n} as const\n\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode]\n","import type { Command } from 'commander'\nimport { saveConfig, isConfigured } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { ExitCode } from '../lib/exit-codes.js'\n\nexport function registerConfigure(program: Command): void {\n program\n .command('configure')\n .description('Configure the OAS Gateway server URL and authentication token')\n .requiredOption('--server <url>', 'OAS Gateway server URL (e.g. https://oas.example.com)')\n .requiredOption('--token <jwt>', 'Group JWT token issued by the server admin')\n .action(async (opts: { server: string; token: string }) => {\n const serverUrl = opts.server.replace(/\\/$/, '')\n const token = opts.token\n\n // Validate connectivity before saving\n console.log(`Connecting to ${serverUrl}...`)\n const client = new ServerClient({ serverUrl, token })\n\n try {\n await client.listOAS()\n saveConfig({ serverUrl, token })\n console.log('✓ Configuration saved successfully.')\n console.log(` Server: ${serverUrl}`)\n console.log(` Token: ${token.slice(0, 20)}...`)\n } catch (err) {\n console.error('Connection failed:', (err as Error).message)\n console.error('Please check the server URL and token.')\n process.exit(ExitCode.CONNECTIVITY_ERROR)\n }\n })\n}\n","/**\n * Local file cache for OAS entries.\n * Stored at ~/.cache/oas-cli/<name>.json with TTL metadata.\n *\n * Security: authConfig credential values are stripped before writing.\n * Only { type } is persisted — full secrets are never written to disk.\n */\nimport { readFile, writeFile, mkdir, unlink, chmod } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { cacheDir } from '../config.js'\nimport type { OASEntryPublic } from './server-client.js'\n\ninterface CacheFile {\n entries: OASEntryPublic[]\n fetchedAt: number // ms timestamp\n ttlSec: number // cache duration\n}\n\nconst LIST_CACHE_FILE = join(cacheDir, 'oas-list.json')\n\nasync function ensureCacheDir(): Promise<void> {\n await mkdir(cacheDir, { recursive: true, mode: 0o700 })\n}\n\n/** Strip credential secrets from authConfig — only persist { type }. */\nfunction redactEntries(entries: OASEntryPublic[]): OASEntryPublic[] {\n return entries.map((e) => ({\n ...e,\n authConfig: { type: (e.authConfig as Record<string, unknown>)['type'] ?? e.authType },\n }))\n}\n\nexport async function readOASListCache(): Promise<OASEntryPublic[] | null> {\n try {\n const raw = await readFile(LIST_CACHE_FILE, 'utf8')\n const cached: CacheFile = JSON.parse(raw)\n const age = (Date.now() - cached.fetchedAt) / 1000\n if (cached.ttlSec === 0 || age > cached.ttlSec) return null // expired\n return cached.entries\n } catch {\n return null // not found or parse error\n }\n}\n\nexport async function writeOASListCache(entries: OASEntryPublic[], ttlSec: number): Promise<void> {\n await ensureCacheDir()\n const cached: CacheFile = { entries: redactEntries(entries), fetchedAt: Date.now(), ttlSec }\n await writeFile(LIST_CACHE_FILE, JSON.stringify(cached, null, 2), { encoding: 'utf8', mode: 0o600 })\n await chmod(LIST_CACHE_FILE, 0o600)\n}\n\nexport async function clearOASListCache(): Promise<void> {\n try {\n await unlink(LIST_CACHE_FILE)\n } catch {\n // ignore if not found\n }\n}\n\nexport async function clearOASCache(name: string): Promise<void> {\n try {\n const raw = await readFile(LIST_CACHE_FILE, 'utf8')\n const cached: CacheFile = JSON.parse(raw)\n const entries = Array.isArray(cached.entries) ? cached.entries.filter((e) => e.name !== name) : []\n if (entries.length === 0) {\n await clearOASListCache()\n return\n }\n const next: CacheFile = {\n entries,\n fetchedAt: cached.fetchedAt ?? Date.now(),\n ttlSec: cached.ttlSec ?? 0,\n }\n await writeFile(LIST_CACHE_FILE, JSON.stringify(next, null, 2), { encoding: 'utf8', mode: 0o600 })\n } catch {\n await clearOASListCache()\n }\n}\n","/**\n * Bridge between oas-cli and @tronsfey/openapi2cli run mode.\n *\n * Spawns openapi2cli as a child process, injecting auth config\n * as environment variables (never exposed to the agent's shell).\n */\nimport { spawn } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport { join, dirname } from 'node:path'\nimport type { OASEntryPublic } from './server-client.js'\n\nconst require = createRequire(import.meta.url)\n\nfunction resolveOpenapi2CliBin(): string {\n try {\n const pkgPath = require.resolve('@tronsfey/openapi2cli/package.json')\n const pkgDir = dirname(pkgPath)\n // @tronsfey/openapi2cli exposes its binary; find it\n const pkg = require('@tronsfey/openapi2cli/package.json') as { bin?: Record<string, string> }\n const binEntry = pkg.bin?.['openapi2cli'] ?? 'bin/openapi2cli.js'\n return join(pkgDir, binEntry)\n } catch {\n throw new Error(\n '@tronsfey/openapi2cli is not installed. Run: pnpm add @tronsfey/openapi2cli in packages/cli',\n )\n }\n}\n\nexport interface RunOptions {\n entry: OASEntryPublic\n /** Operation command args (e.g. ['listPets', '--limit', '10']) */\n operationArgs: string[]\n format?: 'json' | 'table' | 'yaml'\n query?: string\n}\n\n/**\n * Build auth environment variables for injection into child process.\n * The calling shell (and thus the AI agent) never sees these values.\n */\nfunction buildAuthEnv(entry: OASEntryPublic): Record<string, string> {\n const cfg = entry.authConfig\n const prefix = entry.name.toUpperCase().replace(/[^A-Z0-9]/g, '_')\n\n switch (cfg['type']) {\n case 'bearer':\n return { [`${prefix}_TOKEN`]: cfg['token'] as string }\n\n case 'api_key':\n return { [`${prefix}_API_KEY`]: cfg['key'] as string }\n\n case 'basic':\n return { [`${prefix}_CREDENTIALS`]: `${cfg['username']}:${cfg['password']}` }\n\n case 'oauth2_cc':\n return {\n [`${prefix}_CLIENT_ID`]: cfg['clientId'] as string,\n [`${prefix}_CLIENT_SECRET`]: cfg['clientSecret'] as string,\n [`${prefix}_SCOPES`]: (cfg['scopes'] as string[]).join(' '),\n }\n\n default:\n return {}\n }\n}\n\n/**\n * Environment variable allowlist for subprocess execution.\n * Only these variables (when present in the parent) are forwarded to the\n * child process. This prevents leakage of secrets such as cloud credentials,\n * encryption keys, or database passwords that may be in the parent env.\n */\nconst SAFE_ENV_KEYS: readonly string[] = [\n // System essentials\n 'PATH', 'HOME', 'USER', 'LOGNAME', 'SHELL', 'TMPDIR', 'TMP', 'TEMP',\n // Terminal / display\n 'TERM', 'COLORTERM', 'NO_COLOR', 'FORCE_COLOR', 'LANG', 'LC_ALL',\n 'LC_CTYPE', 'LC_MESSAGES', 'LC_COLLATE',\n // Node.js\n 'NODE_ENV', 'NODE_PATH', 'NODE_OPTIONS', 'NODE_EXTRA_CA_CERTS',\n // Network proxy (required for tools behind corporate proxies)\n 'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY',\n 'http_proxy', 'https_proxy', 'no_proxy',\n // OS-specific\n 'SYSTEMROOT', 'COMSPEC', 'APPDATA', 'LOCALAPPDATA', 'PROGRAMFILES',\n 'XDG_RUNTIME_DIR', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME',\n]\n\nfunction buildSafeEnv(authEnv: Record<string, string>): Record<string, string> {\n const safe: Record<string, string> = {}\n for (const key of SAFE_ENV_KEYS) {\n if (process.env[key] !== undefined) {\n safe[key] = process.env[key]!\n }\n }\n return { ...safe, ...authEnv }\n}\n\nexport async function runOperation(opts: RunOptions): Promise<void> {\n const bin = resolveOpenapi2CliBin()\n const { entry, operationArgs, format, query } = opts\n\n const args = [\n 'run',\n '--oas', entry.remoteUrl,\n '--cache-ttl', String(entry.cacheTtl),\n ...(entry.baseEndpoint ? ['--endpoint', entry.baseEndpoint] : []),\n ...(format ? ['--format', format] : []),\n ...(query ? ['--query', query] : []),\n ...operationArgs,\n ]\n\n const authEnv = buildAuthEnv(entry)\n\n await new Promise<void>((resolve, reject) => {\n const child = spawn(process.execPath, [bin, ...args], {\n stdio: 'inherit',\n env: buildSafeEnv(authEnv),\n })\n\n child.on('close', (code) => {\n if (code === 0) resolve()\n else reject(new Error(`openapi2cli exited with code ${code}`))\n })\n child.on('error', reject)\n })\n}\n\n/**\n * Get list of available operations for a service by running `--help`.\n * Returns the raw help text from openapi2cli.\n */\nexport async function getServiceHelp(entry: OASEntryPublic): Promise<string> {\n const bin = resolveOpenapi2CliBin()\n const args = [\n 'run',\n '--oas', entry.remoteUrl,\n '--cache-ttl', String(entry.cacheTtl),\n '--help',\n ]\n\n return new Promise<string>((resolve, reject) => {\n let output = ''\n const child = spawn(process.execPath, [bin, ...args], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n child.stdout?.on('data', (d: Buffer) => { output += d.toString() })\n child.stderr?.on('data', (d: Buffer) => { output += d.toString() })\n child.on('close', () => resolve(output))\n child.on('error', reject)\n })\n}\n","/**\n * YAML output format support.\n *\n * A lightweight YAML serialiser that covers the data shapes produced by\n * ucli commands (plain objects, arrays, strings, numbers, booleans, null).\n * No external dependencies — we don't need a full YAML parser, only output.\n */\n\n/** Convert a JSON-serialisable value to a YAML string. */\nexport function toYaml(value: unknown, indent = 0): string {\n if (value === null || value === undefined) {\n return 'null'\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false'\n }\n\n if (typeof value === 'number') {\n return String(value)\n }\n\n if (typeof value === 'string') {\n // Use quotes if the string contains special YAML characters\n if (needsQuoting(value)) {\n return JSON.stringify(value)\n }\n return value\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]'\n const prefix = ' '.repeat(indent)\n return value\n .map((item) => {\n const serialised = toYaml(item, indent + 2)\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n // Object items: put the first key on the same line as the dash\n const firstNewline = serialised.indexOf('\\n')\n if (firstNewline === -1) {\n return `${prefix}- ${serialised.trimStart()}`\n }\n const firstLine = serialised.slice(0, firstNewline)\n const rest = serialised.slice(firstNewline + 1)\n return `${prefix}- ${firstLine.trimStart()}\\n${rest}`\n }\n return `${prefix}- ${serialised}`\n })\n .join('\\n')\n }\n\n if (typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n if (entries.length === 0) return '{}'\n const prefix = ' '.repeat(indent)\n return entries\n .map(([key, val]) => {\n if (val === null || val === undefined) {\n return `${prefix}${key}: null`\n }\n if (typeof val === 'object') {\n const nested = toYaml(val, indent + 2)\n return `${prefix}${key}:\\n${nested}`\n }\n return `${prefix}${key}: ${toYaml(val, indent)}`\n })\n .join('\\n')\n }\n\n return String(value)\n}\n\nfunction needsQuoting(s: string): boolean {\n if (s === '') return true\n if (s === 'true' || s === 'false' || s === 'null') return true\n if (/^\\d/.test(s)) return true\n if (/[:{}\\[\\],&*#?|<>=!%@`'\"\\\\\\n\\r\\t]/.test(s)) return true\n if (s.startsWith(' ') || s.endsWith(' ')) return true\n return false\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { readOASListCache, writeOASListCache } from '../lib/cache.js'\nimport { getServiceHelp } from '../lib/oas-runner.js'\nimport { toYaml } from '../lib/yaml.js'\nimport { ExitCode } from '../lib/exit-codes.js'\n\nexport function registerServices(program: Command): void {\n const services = program\n .command('services')\n .description('Manage and inspect available OAS services')\n\n // services list\n services\n .command('list')\n .description('List all OAS services available in the current group')\n .option('--refresh', 'Bypass local cache and fetch fresh from server')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .option('--no-cache', 'Bypass local cache and fetch fresh from server')\n .action(async (opts: { cache: boolean; refresh?: boolean; format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n if (!opts.cache) {\n process.emitWarning('The --no-cache flag is deprecated. Please use --refresh instead.')\n }\n\n const useCache = opts.cache && !opts.refresh\n let entries = useCache ? await readOASListCache() : null\n\n if (!entries) {\n entries = await client.listOAS()\n if (entries.length > 0) {\n const maxTtl = Math.min(...entries.map((e) => e.cacheTtl))\n await writeOASListCache(entries, maxTtl)\n }\n }\n\n const format = (opts.format ?? 'table').toLowerCase()\n\n if (entries.length === 0) {\n console.log('No services registered in this group.')\n return\n }\n\n if (format === 'json') {\n // Strip authConfig secrets from JSON output — only expose { type }\n const safe = entries.map(({ authConfig, ...rest }) => ({\n ...rest,\n authConfig: { type: (authConfig as Record<string, unknown>)['type'] ?? rest.authType },\n }))\n console.log(JSON.stringify(safe, null, 2))\n return\n }\n\n if (format === 'yaml') {\n const safe = entries.map(({ authConfig, ...rest }) => ({\n ...rest,\n authConfig: { type: (authConfig as Record<string, unknown>)['type'] ?? rest.authType },\n }))\n console.log(toYaml(safe))\n return\n }\n\n const nameWidth = Math.max(10, ...entries.map((e) => e.name.length))\n console.log(`\\n${'SERVICE'.padEnd(nameWidth)} AUTH DESCRIPTION`)\n console.log(`${'-'.repeat(nameWidth)} -------- ${'-'.repeat(40)}`)\n for (const e of entries) {\n const auth = e.authType.padEnd(8)\n const desc = e.description.length > 60 ? e.description.slice(0, 57) + '...' : e.description\n console.log(`${e.name.padEnd(nameWidth)} ${auth} ${desc}`)\n }\n console.log()\n })\n\n // services info <name>\n services\n .command('info <name>')\n .description('Show detailed information and available operations for a service')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .action(async (name: string, opts: { format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getOAS(name)\n } catch (err) {\n console.error(`Service not found: ${name}`)\n console.error('Run `ucli services list` to see available services.')\n process.exit(ExitCode.NOT_FOUND)\n }\n\n const help = await getServiceHelp(entry)\n const format = (opts.format ?? 'table').toLowerCase()\n if (format === 'json') {\n // Strip authConfig secrets from JSON output\n const { authConfig, ...rest } = entry\n const safe = {\n ...rest,\n authConfig: { type: (authConfig as Record<string, unknown>)['type'] ?? rest.authType },\n operationsHelp: help,\n }\n console.log(JSON.stringify(safe, null, 2))\n return\n }\n\n if (format === 'yaml') {\n const { authConfig, ...rest } = entry\n const safe = {\n ...rest,\n authConfig: { type: (authConfig as Record<string, unknown>)['type'] ?? rest.authType },\n operationsHelp: help,\n }\n console.log(toYaml(safe))\n return\n }\n\n console.log(`\\nService: ${entry.name}`)\n console.log(`Description: ${entry.description || '(none)'}`)\n console.log(`OAS URL: ${entry.remoteUrl}`)\n if (entry.baseEndpoint) console.log(`Base endpoint: ${entry.baseEndpoint}`)\n console.log(`Auth type: ${entry.authType}`)\n console.log(`Cache TTL: ${entry.cacheTtl}s`)\n console.log('\\nAvailable operations:')\n console.log('─'.repeat(60))\n console.log(help)\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { runOperation } from '../lib/oas-runner.js'\nimport { ExitCode } from '../lib/exit-codes.js'\n\nexport function registerRun(program: Command): void {\n program\n .command('run [service] [args...]')\n .description('Execute an operation on a service')\n .option('--service <name>', 'Service name (from `services list`)')\n .option('--operation <id>', 'OperationId to execute')\n .option('--params <json>', 'JSON string of operation parameters')\n .option('--format <fmt>', 'Output format: json | table | yaml', 'json')\n .option('--query <jmespath>', 'Filter response with JMESPath expression')\n .option('--data <json>', 'Request body (JSON string or @filename)')\n .allowUnknownOption(true)\n .action(async (\n serviceArg: string | undefined,\n args: string[],\n opts: { service?: string; operation?: string; params?: string; format?: string; query?: string; data?: string; args?: string[] },\n ) => {\n if (serviceArg && opts.service && serviceArg !== opts.service) {\n console.error(`Conflicting service values: positional \"${serviceArg}\" and --service \"${opts.service}\". Use either the positional argument or --service flag, not both.`)\n process.exit(ExitCode.USAGE_ERROR)\n }\n\n const service = opts.service ?? serviceArg\n if (!service) {\n console.error('Missing service name. Use positional <service> or --service <name>.')\n process.exit(ExitCode.USAGE_ERROR)\n }\n\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getOAS(service)\n } catch {\n console.error(`Unknown service: ${service}`)\n console.error('Run `ucli services list` to see available services.')\n process.exit(ExitCode.NOT_FOUND)\n }\n\n // Collect extra args (pass-through to openapi2cli)\n const extraArgs = opts.args ?? []\n const operationArgs = [...args, ...extraArgs]\n\n if (opts.operation) {\n operationArgs.unshift(opts.operation)\n }\n\n if (opts.params) {\n let parsed: unknown\n try {\n parsed = JSON.parse(opts.params)\n } catch {\n console.error('Invalid --params JSON. Example: --params \\'{\"petId\": 1}\\'')\n process.exit(ExitCode.USAGE_ERROR)\n }\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n for (const [k, v] of Object.entries(parsed as Record<string, unknown>)) {\n if (v === undefined || v === null) continue\n const strVal = typeof v === 'object' ? JSON.stringify(v) : String(v)\n operationArgs.push(`--${k}`, strVal)\n }\n }\n }\n\n if (opts.data) {\n operationArgs.push('--data', opts.data)\n }\n\n const format = opts.format as 'json' | 'table' | 'yaml' | undefined\n const query = opts.query as string | undefined\n\n try {\n await runOperation({\n entry,\n operationArgs,\n ...(format !== undefined ? { format } : {}),\n ...(query !== undefined ? { query } : {}),\n })\n } catch (err) {\n console.error('Operation failed:', (err as Error).message)\n process.exit(ExitCode.GENERAL_ERROR)\n }\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { writeOASListCache, clearOASListCache, clearOASCache } from '../lib/cache.js'\n\nexport function registerRefresh(program: Command): void {\n program\n .command('refresh')\n .description('Force-refresh the local OAS cache from the server')\n .option('--service <name>', 'Refresh only a specific service')\n .action(async (opts: { service?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n console.log('Refreshing OAS list from server...')\n if (opts.service) {\n await clearOASCache(opts.service)\n } else {\n await clearOASListCache()\n }\n\n const entries = await client.listOAS()\n if (entries.length > 0) {\n const maxTtl = Math.min(...entries.map((e) => e.cacheTtl))\n await writeOASListCache(entries, maxTtl)\n }\n\n console.log(`✓ Refreshed ${entries.length} service(s).`)\n })\n}\n","import type { Command } from 'commander'\nimport { getConfig, isConfigured } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { readOASListCache, writeOASListCache } from '../lib/cache.js'\nimport { getServiceHelp } from '../lib/oas-runner.js'\nimport { ExitCode } from '../lib/exit-codes.js'\n\nexport function registerHelp(program: Command): void {\n program\n .command('help [service]')\n .description('Show usage guide. Pass a service name for service-specific operations.')\n .action(async (service?: string) => {\n if (!service) {\n printGeneralHelp()\n if (isConfigured()) {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n let entries = await readOASListCache()\n if (!entries) {\n entries = await client.listOAS()\n if (entries.length > 0) {\n const maxTtl = Math.min(...entries.map((e) => e.cacheTtl))\n await writeOASListCache(entries, maxTtl)\n }\n }\n if (entries.length > 0) {\n console.log('\\nAvailable services:')\n for (const e of entries) {\n console.log(` ${e.name.padEnd(20)} ${e.description}`)\n }\n console.log('\\nTip: Run `ucli help <service>` for service-specific operations.')\n }\n } else {\n console.log('\\nRun `ucli configure --server <url> --token <jwt>` to get started.')\n }\n return\n }\n\n // Service-specific help\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getOAS(service)\n } catch {\n console.error(`Unknown service: ${service}`)\n console.error('Run `ucli services list` to see available services.')\n process.exit(ExitCode.NOT_FOUND)\n }\n\n console.log(`\\n=== ${entry.name} ===`)\n console.log(`${entry.description}`)\n console.log(`\\nOAS spec: ${entry.remoteUrl}`)\n console.log('\\nOperations:')\n console.log('─'.repeat(60))\n\n const help = await getServiceHelp(entry)\n console.log(help)\n\n console.log('\\nExamples:')\n console.log(` ucli run ${entry.name} <operation>`)\n console.log(` ucli run ${entry.name} <operation> --format table`)\n console.log(` ucli run ${entry.name} <operation> --query \"results[*].id\"`)\n console.log(` ucli run ${entry.name} <operation> --data '{\"key\":\"value\"}'`)\n })\n}\n\nfunction printGeneralHelp(): void {\n console.log(`\nucli — OpenAPI & MCP Gateway for AI Agents\n════════════════════════════════════════\n\nSETUP\n ucli configure --server <url> --token <jwt>\n Configure server connection and authentication.\n\nDISCOVERY\n ucli services list\n List all OAS services available in your group.\n\n ucli services info <service>\n Show detailed service info and all available operations.\n\n ucli help [service]\n Show this guide, or service-specific operations.\n\nEXECUTION\n ucli run <service> <operation> [options]\n Execute a service operation.\n\n Options:\n --format json|table|yaml Output format (default: json)\n --query <jmespath> Filter response with JMESPath\n --data <json|@file> Request body for POST/PUT/PATCH\n\nMAINTENANCE\n ucli refresh\n Force-refresh the local OAS cache from the server.\n\n ucli doctor\n Check configuration, server connectivity, and token validity.\n\nSHELL COMPLETIONS\n eval \"$(ucli completions bash)\"\n eval \"$(ucli completions zsh)\"\n ucli completions fish | source\n\nGLOBAL FLAGS\n --debug Enable verbose debug logging\n -v, --version Show version number\n\nERRORS\n 401 Unauthorized → Run: ucli configure --server <url> --token <jwt>\n 404 Not Found → Check service name: ucli services list\n 4xx Client Error → Check operation args: ucli services info <service>\n 5xx Server Error → Retry or run: ucli refresh\n`)\n}\n","/**\n * MCP tool runner using @tronsfey/mcp2cli programmatic API.\n *\n * Auth credentials are injected via McpServerConfig (headers or env) —\n * never passed as CLI arguments (which would be visible in `ps`).\n */\nimport type { McpEntryPublic } from './server-client.js'\n\n/**\n * Resolve a named export from a module that may be CJS-wrapped (exports live\n * under `module.default`) or a plain ESM module (named exports at top level).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction resolve(mod: any, name: string): unknown {\n if (typeof mod[name] === 'function') return mod[name]\n if (mod.default && typeof mod.default[name] === 'function') return mod.default[name]\n throw new Error(`Cannot resolve export \"${name}\" from module`)\n}\n\nasync function getMcp2cli() {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const clientMod = await import('@tronsfey/mcp2cli/dist/client/index.js') as any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const runnerMod = await import('@tronsfey/mcp2cli/dist/runner/index.js') as any\n return {\n createMcpClient: resolve(clientMod, 'createMcpClient') as (...args: unknown[]) => Promise<unknown>,\n getTools: resolve(runnerMod, 'getTools') as (...args: unknown[]) => Promise<{ name: string; description?: string }[]>,\n runTool: resolve(runnerMod, 'runTool') as (...args: unknown[]) => Promise<void>,\n }\n}\n\nasync function closeClient(client: unknown): Promise<void> {\n if (typeof (client as { close?: unknown }).close === 'function') {\n await (client as { close: () => Promise<void> }).close()\n }\n}\n\nfunction buildMcpConfig(entry: McpEntryPublic): Record<string, unknown> {\n const base: Record<string, unknown> = { type: entry.transport }\n if (entry.transport === 'http') {\n base.url = entry.serverUrl\n } else {\n base.command = entry.command\n }\n const auth = entry.authConfig\n if (auth.type === 'http_headers') {\n base.headers = auth.headers\n } else if (auth.type === 'env') {\n base.env = auth.env\n }\n return base\n}\n\nexport async function listMcpTools(entry: McpEntryPublic): Promise<{ name: string; description?: string }[]> {\n const { createMcpClient, getTools } = await getMcp2cli()\n const config = buildMcpConfig(entry)\n const client = await createMcpClient(config)\n try {\n const tools = await getTools(client, config, { noCache: true })\n return tools\n } finally {\n await closeClient(client)\n }\n}\n\nexport async function runMcpTool(entry: McpEntryPublic, toolName: string, rawArgs: string[]): Promise<void> {\n const { createMcpClient, getTools, runTool } = await getMcp2cli()\n const config = buildMcpConfig(entry)\n const client = await createMcpClient(config)\n try {\n const tools = await getTools(client, config, { noCache: false, cacheTtl: 3600 })\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const tool = tools.find((t: any) => t.name === toolName)\n if (!tool) throw new Error(`Tool \"${toolName}\" not found on MCP server \"${entry.name}\"`)\n const normalizedArgs: string[] = []\n for (const arg of rawArgs) {\n if (arg.includes('=') && !arg.startsWith('--')) {\n const idx = arg.indexOf('=')\n const key = arg.slice(0, idx)\n const value = arg.slice(idx + 1)\n normalizedArgs.push(`--${key}`, value)\n } else {\n normalizedArgs.push(arg)\n }\n }\n await runTool(client, tool, normalizedArgs, {})\n } finally {\n await closeClient(client)\n }\n}\n","import type { Command } from 'commander'\nimport { getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { listMcpTools, runMcpTool } from '../lib/mcp-runner.js'\nimport { toYaml } from '../lib/yaml.js'\nimport { ExitCode } from '../lib/exit-codes.js'\n\nexport function registerMcp(program: Command): void {\n const mcp = program\n .command('mcp')\n .description('Interact with MCP servers registered in your group')\n\n // mcp list\n mcp\n .command('list')\n .description('List all MCP servers available in the current group')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .action(async (opts: { format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n const entries = await client.listMCP()\n\n if (entries.length === 0) {\n console.log('No MCP servers registered in this group.')\n return\n }\n\n const format = (opts.format ?? 'table').toLowerCase()\n if (format === 'json') {\n // Strip authConfig secrets from JSON output — only expose { type }\n const safe = entries.map(({ authConfig, ...rest }) => ({\n ...rest,\n authConfig: { type: authConfig.type },\n }))\n console.log(JSON.stringify(safe, null, 2))\n return\n }\n\n if (format === 'yaml') {\n const safe = entries.map(({ authConfig, ...rest }) => ({\n ...rest,\n authConfig: { type: authConfig.type },\n }))\n console.log(toYaml(safe))\n return\n }\n\n const nameWidth = Math.max(10, ...entries.map(e => e.name.length))\n console.log(`\\n${'SERVER'.padEnd(nameWidth)} TRANSPORT DESCRIPTION`)\n console.log(`${'-'.repeat(nameWidth)} --------- ${'-'.repeat(40)}`)\n for (const e of entries) {\n const desc = e.description.length > 60 ? e.description.slice(0, 57) + '...' : e.description\n console.log(`${e.name.padEnd(nameWidth)} ${e.transport.padEnd(9)} ${desc}`)\n }\n console.log()\n })\n\n // mcp tools <server>\n mcp\n .command('tools <server>')\n .description('List tools available on a MCP server')\n .option('--format <fmt>', 'Output format: table | json | yaml', 'table')\n .action(async (serverName: string, opts: { format?: string }) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getMCP(serverName)\n } catch {\n console.error(`Unknown MCP server: ${serverName}`)\n console.error('Run `ucli mcp list` to see available servers.')\n process.exit(ExitCode.NOT_FOUND)\n }\n\n let tools\n try {\n tools = await listMcpTools(entry)\n } catch (err) {\n console.error('Failed to fetch tools:', (err as Error).message)\n process.exit(ExitCode.GENERAL_ERROR)\n }\n\n if (tools.length === 0) {\n console.log(`No tools found on MCP server \"${serverName}\".`)\n return\n }\n\n const format = (opts.format ?? 'table').toLowerCase()\n if (format === 'json') {\n console.log(JSON.stringify(tools, null, 2))\n return\n }\n\n if (format === 'yaml') {\n console.log(toYaml(tools))\n return\n }\n\n console.log(`\\nTools on \"${serverName}\":`)\n console.log('─'.repeat(60))\n for (const t of tools) {\n console.log(` ${t.name}`)\n if (t.description) console.log(` ${t.description}`)\n }\n console.log()\n })\n\n // mcp run <server> <tool> [args...]\n mcp\n .command('run <server> <tool> [args...]')\n .description('Call a tool on a MCP server')\n .action(async (serverName: string, toolName: string, args: string[]) => {\n const cfg = getConfig()\n const client = new ServerClient(cfg)\n\n let entry\n try {\n entry = await client.getMCP(serverName)\n } catch {\n console.error(`Unknown MCP server: ${serverName}`)\n console.error('Run `ucli mcp list` to see available servers.')\n process.exit(ExitCode.NOT_FOUND)\n }\n\n try {\n await runMcpTool(entry, toolName, args)\n } catch (err) {\n console.error('Tool execution failed:', (err as Error).message)\n process.exit(ExitCode.GENERAL_ERROR)\n }\n })\n}\n","/**\n * Consistent error formatting utility.\n *\n * Provides a unified error output with actionable hints so that both\n * humans and AI agents can quickly understand what went wrong and how\n * to fix it.\n */\nimport { ExitCode, type ExitCodeValue } from './exit-codes.js'\n\nlet debugEnabled = false\n\nexport function setDebugMode(enabled: boolean): void {\n debugEnabled = enabled\n}\n\nexport function isDebugMode(): boolean {\n return debugEnabled\n}\n\n/** Log a debug message (only when --debug is active). */\nexport function debug(message: string): void {\n if (debugEnabled) {\n console.error(`[DEBUG] ${message}`)\n }\n}\n\nexport interface FormattedError {\n code: ExitCodeValue\n message: string\n hint?: string\n}\n\nconst HINT_MAP: Record<number, string> = {\n [ExitCode.CONFIG_ERROR]:\n 'Run: ucli configure --server <url> --token <jwt>',\n [ExitCode.AUTH_ERROR]:\n 'Your token may be expired or revoked. Run: ucli configure --server <url> --token <jwt>',\n [ExitCode.CONNECTIVITY_ERROR]:\n 'Check that the server URL is correct and the server is running. Run: ucli doctor',\n [ExitCode.NOT_FOUND]:\n 'Check the resource name. Run: ucli services list or ucli mcp list',\n [ExitCode.SERVER_ERROR]:\n 'The server returned an unexpected error. Try again or run: ucli doctor',\n}\n\n/**\n * Print a formatted error to stderr and exit with the given code.\n * When --debug is active, the full stack trace is also printed.\n */\nexport function formatError(err: unknown, code?: ExitCodeValue): never {\n const exitCode = code ?? classifyError(err)\n const message = err instanceof Error ? err.message : String(err)\n const hint = HINT_MAP[exitCode]\n\n console.error(`\\n✖ Error: ${message}`)\n if (hint) {\n console.error(` Hint: ${hint}`)\n }\n\n if (debugEnabled && err instanceof Error && err.stack) {\n console.error(`\\n${err.stack}`)\n }\n\n process.exit(exitCode)\n}\n\n/** Classify an error into an exit code based on common patterns. */\nfunction classifyError(err: unknown): ExitCodeValue {\n if (!(err instanceof Error)) return ExitCode.GENERAL_ERROR\n\n const msg = err.message.toLowerCase()\n\n if (msg.includes('not configured') || msg.includes('missing')) {\n return ExitCode.CONFIG_ERROR\n }\n if (msg.includes('401') || msg.includes('unauthorized') || msg.includes('authentication')) {\n return ExitCode.AUTH_ERROR\n }\n if (msg.includes('econnrefused') || msg.includes('enotfound') || msg.includes('timeout') || msg.includes('network')) {\n return ExitCode.CONNECTIVITY_ERROR\n }\n if (msg.includes('404') || msg.includes('not found')) {\n return ExitCode.NOT_FOUND\n }\n if (msg.includes('5') && msg.includes('server error')) {\n return ExitCode.SERVER_ERROR\n }\n\n return ExitCode.GENERAL_ERROR\n}\n","/**\n * `ucli doctor` — diagnostic tool for configuration, connectivity, and token validation.\n *\n * Checks:\n * 1. Configuration file exists and is readable\n * 2. Server URL is reachable (GET /api/v1/health)\n * 3. JWT token is accepted (GET /api/v1/oas — expects 200 or empty list)\n */\nimport type { Command } from 'commander'\nimport { isConfigured, getConfig } from '../config.js'\nimport { ServerClient } from '../lib/server-client.js'\nimport { ExitCode } from '../lib/exit-codes.js'\nimport { debug } from '../lib/errors.js'\nimport axios from 'axios'\n\ninterface CheckResult {\n name: string\n ok: boolean\n detail: string\n}\n\nexport function registerDoctor(program: Command): void {\n program\n .command('doctor')\n .description('Check configuration, server connectivity, and token validity')\n .action(async () => {\n const results: CheckResult[] = []\n\n // ── Check 1: Configuration ──────────────────────────────────────\n debug('Checking configuration...')\n if (!isConfigured()) {\n results.push({\n name: 'Configuration',\n ok: false,\n detail: 'Not configured. Run: ucli configure --server <url> --token <jwt>',\n })\n printResults(results)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n let cfg: { serverUrl: string; token: string }\n try {\n cfg = getConfig()\n results.push({\n name: 'Configuration',\n ok: true,\n detail: `Server: ${cfg.serverUrl}`,\n })\n } catch (err) {\n results.push({\n name: 'Configuration',\n ok: false,\n detail: `Failed to read config: ${(err as Error).message}`,\n })\n printResults(results)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // ── Check 2: Connectivity (health endpoint, no auth required) ──\n debug(`Checking connectivity to ${cfg.serverUrl}...`)\n try {\n const healthUrl = `${cfg.serverUrl}/api/v1/health`\n const resp = await axios.get(healthUrl, { timeout: 10_000 })\n results.push({\n name: 'Server connectivity',\n ok: resp.status === 200,\n detail: resp.status === 200\n ? `Health endpoint OK (${cfg.serverUrl})`\n : `Unexpected status: ${resp.status}`,\n })\n } catch (err) {\n const msg = axios.isAxiosError(err)\n ? err.code ?? err.message\n : (err as Error).message\n results.push({\n name: 'Server connectivity',\n ok: false,\n detail: `Cannot reach server: ${msg}`,\n })\n }\n\n // ── Check 3: Token validity (authenticated request) ────────────\n debug('Validating JWT token...')\n try {\n const client = new ServerClient(cfg)\n await client.listOAS()\n results.push({\n name: 'Authentication',\n ok: true,\n detail: 'Token accepted by server',\n })\n } catch (err) {\n const msg = (err as Error).message\n results.push({\n name: 'Authentication',\n ok: false,\n detail: `Token rejected: ${msg}`,\n })\n }\n\n printResults(results)\n\n const allOk = results.every((r) => r.ok)\n process.exit(allOk ? ExitCode.SUCCESS : ExitCode.GENERAL_ERROR)\n })\n}\n\nfunction printResults(results: CheckResult[]): void {\n console.log('\\nucli doctor\\n' + '═'.repeat(40))\n for (const r of results) {\n const icon = r.ok ? '✓' : '✖'\n console.log(` ${icon} ${r.name}: ${r.detail}`)\n }\n console.log()\n}\n","/**\n * `ucli completions` — generate shell completion scripts for bash/zsh/fish.\n *\n * Usage:\n * eval \"$(ucli completions bash)\"\n * eval \"$(ucli completions zsh)\"\n * ucli completions fish | source\n */\nimport type { Command } from 'commander'\nimport { ExitCode } from '../lib/exit-codes.js'\n\nexport function registerCompletions(program: Command): void {\n program\n .command('completions <shell>')\n .description('Generate shell completion script (bash | zsh | fish)')\n .action((shell: string) => {\n const normalized = shell.toLowerCase().trim()\n\n switch (normalized) {\n case 'bash':\n console.log(bashCompletions())\n break\n case 'zsh':\n console.log(zshCompletions())\n break\n case 'fish':\n console.log(fishCompletions())\n break\n default:\n console.error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`)\n process.exit(ExitCode.USAGE_ERROR)\n }\n })\n}\n\nfunction bashCompletions(): string {\n return `# ucli bash completions — eval \"$(ucli completions bash)\"\n_ucli_completions() {\n local cur prev commands\n COMPREPLY=()\n cur=\"\\${COMP_WORDS[COMP_CWORD]}\"\n prev=\"\\${COMP_WORDS[COMP_CWORD-1]}\"\n commands=\"configure services run refresh help mcp doctor completions\"\n\n case \"\\${COMP_WORDS[1]}\" in\n services)\n COMPREPLY=( $(compgen -W \"list info\" -- \"$cur\") )\n return 0\n ;;\n mcp)\n COMPREPLY=( $(compgen -W \"list tools run\" -- \"$cur\") )\n return 0\n ;;\n completions)\n COMPREPLY=( $(compgen -W \"bash zsh fish\" -- \"$cur\") )\n return 0\n ;;\n run|help)\n # dynamic completions would require server calls; skip for now\n return 0\n ;;\n esac\n\n if [ \"$COMP_CWORD\" -eq 1 ]; then\n COMPREPLY=( $(compgen -W \"$commands\" -- \"$cur\") )\n fi\n\n return 0\n}\ncomplete -F _ucli_completions ucli`\n}\n\nfunction zshCompletions(): string {\n return `# ucli zsh completions — eval \"$(ucli completions zsh)\"\n#compdef ucli\n\n_ucli() {\n local -a commands\n commands=(\n 'configure:Configure server URL and authentication token'\n 'services:Manage and inspect available OAS services'\n 'run:Execute an operation on a service'\n 'refresh:Force-refresh the local OAS cache'\n 'help:Show usage guide'\n 'mcp:Interact with MCP servers'\n 'doctor:Check configuration and connectivity'\n 'completions:Generate shell completion script'\n )\n\n _arguments -C \\\\\n '1: :->command' \\\\\n '*::arg:->args'\n\n case $state in\n command)\n _describe -t commands 'ucli commands' commands\n ;;\n args)\n case $words[1] in\n services)\n _values 'subcommand' 'list[List all OAS services]' 'info[Show service details]'\n ;;\n mcp)\n _values 'subcommand' 'list[List MCP servers]' 'tools[List tools]' 'run[Call a tool]'\n ;;\n completions)\n _values 'shell' bash zsh fish\n ;;\n esac\n ;;\n esac\n}\n\n_ucli \"$@\"`\n}\n\nfunction fishCompletions(): string {\n return `# ucli fish completions — ucli completions fish | source\ncomplete -c ucli -e\n\n# Top-level commands\ncomplete -c ucli -n __fish_use_subcommand -a configure -d 'Configure server URL and token'\ncomplete -c ucli -n __fish_use_subcommand -a services -d 'Manage OAS services'\ncomplete -c ucli -n __fish_use_subcommand -a run -d 'Execute a service operation'\ncomplete -c ucli -n __fish_use_subcommand -a refresh -d 'Refresh local cache'\ncomplete -c ucli -n __fish_use_subcommand -a help -d 'Show usage guide'\ncomplete -c ucli -n __fish_use_subcommand -a mcp -d 'Interact with MCP servers'\ncomplete -c ucli -n __fish_use_subcommand -a doctor -d 'Check config and connectivity'\ncomplete -c ucli -n __fish_use_subcommand -a completions -d 'Generate shell completions'\n\n# services subcommands\ncomplete -c ucli -n '__fish_seen_subcommand_from services' -a list -d 'List services'\ncomplete -c ucli -n '__fish_seen_subcommand_from services' -a info -d 'Show service details'\n\n# mcp subcommands\ncomplete -c ucli -n '__fish_seen_subcommand_from mcp' -a list -d 'List MCP servers'\ncomplete -c ucli -n '__fish_seen_subcommand_from mcp' -a tools -d 'List tools'\ncomplete -c ucli -n '__fish_seen_subcommand_from mcp' -a run -d 'Call a tool'\n\n# completions subcommands\ncomplete -c ucli -n '__fish_seen_subcommand_from completions' -a 'bash zsh fish' -d 'Shell type'`\n}\n"],"mappings":"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","names":["createRequire","program","join","join","join","dirname","require","pkg","resolve","program","program","program","program","cfg","client","program","axios","program","program","require","createRequire"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tronsfey/ucli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "ucli — proxy OpenAPI and MCP services for AI agents",
5
5
  "keywords": [
6
6
  "openapi",
@@ -30,6 +30,7 @@
30
30
  "scripts": {
31
31
  "dev": "tsx watch src/index.ts",
32
32
  "build": "tsup && chmod +x dist/index.js",
33
+ "prepack": "tsup && chmod +x dist/index.js",
33
34
  "test": "vitest run",
34
35
  "test:watch": "vitest",
35
36
  "lint": "tsc --noEmit",