@tronsfey/ucli 0.5.0 → 0.5.1

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
@@ -166,23 +166,59 @@ var ExitCode = {
166
166
  SERVER_ERROR: 7
167
167
  };
168
168
 
169
+ // src/lib/output.ts
170
+ var currentMode = "text";
171
+ function setOutputMode(mode) {
172
+ currentMode = mode;
173
+ }
174
+ function isJsonOutput() {
175
+ return currentMode === "json";
176
+ }
177
+ function outputSuccess(data) {
178
+ if (currentMode === "json") {
179
+ console.log(JSON.stringify({ success: true, data }, null, 2));
180
+ }
181
+ }
182
+ function outputError(code, message, hint) {
183
+ if (currentMode === "json") {
184
+ const envelope = {
185
+ success: false,
186
+ error: { code, message, ...hint ? { hint } : {} }
187
+ };
188
+ console.log(JSON.stringify(envelope, null, 2));
189
+ process.exit(code);
190
+ }
191
+ console.error(`
192
+ \u2716 Error: ${message}`);
193
+ if (hint) console.error(` Hint: ${hint}`);
194
+ process.exit(code);
195
+ }
196
+
169
197
  // src/commands/configure.ts
170
198
  function registerConfigure(program2) {
171
199
  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) => {
172
200
  const serverUrl = opts.server.replace(/\/$/, "");
173
201
  const token = opts.token;
174
- console.log(`Connecting to ${serverUrl}...`);
202
+ if (!isJsonOutput()) {
203
+ console.log(`Connecting to ${serverUrl}...`);
204
+ }
175
205
  const client = new ServerClient({ serverUrl, token });
176
206
  try {
177
207
  await client.listOAS();
178
208
  saveConfig({ serverUrl, token });
209
+ if (isJsonOutput()) {
210
+ outputSuccess({ serverUrl, configured: true });
211
+ return;
212
+ }
179
213
  console.log("\u2713 Configuration saved successfully.");
180
214
  console.log(` Server: ${serverUrl}`);
181
215
  console.log(` Token: ${token.slice(0, 20)}...`);
182
216
  } catch (err) {
183
- console.error("Connection failed:", err.message);
184
- console.error("Please check the server URL and token.");
185
- process.exit(ExitCode.CONNECTIVITY_ERROR);
217
+ outputError(
218
+ ExitCode.CONNECTIVITY_ERROR,
219
+ `Connection failed: ${err.message}`,
220
+ "Check the server URL and token"
221
+ );
186
222
  }
187
223
  });
188
224
  }
@@ -466,24 +502,24 @@ function registerServices(program2) {
466
502
  await writeOASListCache(entries, maxTtl);
467
503
  }
468
504
  }
505
+ const safe = entries.map(({ authConfig, ...rest }) => ({
506
+ ...rest,
507
+ authConfig: { type: authConfig["type"] ?? rest.authType }
508
+ }));
509
+ if (isJsonOutput()) {
510
+ outputSuccess(safe);
511
+ return;
512
+ }
469
513
  const format = (opts.format ?? "table").toLowerCase();
470
514
  if (entries.length === 0) {
471
515
  console.log("No services registered in this group.");
472
516
  return;
473
517
  }
474
518
  if (format === "json") {
475
- const safe = entries.map(({ authConfig, ...rest }) => ({
476
- ...rest,
477
- authConfig: { type: authConfig["type"] ?? rest.authType }
478
- }));
479
519
  console.log(JSON.stringify(safe, null, 2));
480
520
  return;
481
521
  }
482
522
  if (format === "yaml") {
483
- const safe = entries.map(({ authConfig, ...rest }) => ({
484
- ...rest,
485
- authConfig: { type: authConfig["type"] ?? rest.authType }
486
- }));
487
523
  console.log(toYaml(safe));
488
524
  return;
489
525
  }
@@ -504,30 +540,30 @@ ${"SERVICE".padEnd(nameWidth)} AUTH DESCRIPTION`);
504
540
  let entry;
505
541
  try {
506
542
  entry = await client.getOAS(name);
507
- } catch (err) {
508
- console.error(`Service not found: ${name}`);
509
- console.error("Run `ucli services list` to see available services.");
510
- process.exit(ExitCode.NOT_FOUND);
543
+ } catch {
544
+ outputError(
545
+ ExitCode.NOT_FOUND,
546
+ `Service not found: ${name}`,
547
+ "Run: ucli services list to see available services"
548
+ );
511
549
  }
512
550
  const help = await getServiceHelp(entry);
551
+ const { authConfig, ...rest } = entry;
552
+ const safe = {
553
+ ...rest,
554
+ authConfig: { type: authConfig["type"] ?? rest.authType },
555
+ operationsHelp: help
556
+ };
557
+ if (isJsonOutput()) {
558
+ outputSuccess(safe);
559
+ return;
560
+ }
513
561
  const format = (opts.format ?? "table").toLowerCase();
514
562
  if (format === "json") {
515
- const { authConfig, ...rest } = entry;
516
- const safe = {
517
- ...rest,
518
- authConfig: { type: authConfig["type"] ?? rest.authType },
519
- operationsHelp: help
520
- };
521
563
  console.log(JSON.stringify(safe, null, 2));
522
564
  return;
523
565
  }
524
566
  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
567
  console.log(toYaml(safe));
532
568
  return;
533
569
  }
@@ -548,13 +584,18 @@ Service: ${entry.name}`);
548
584
  function registerRun(program2) {
549
585
  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) => {
550
586
  if (serviceArg && opts.service && serviceArg !== opts.service) {
551
- console.error(`Conflicting service values: positional "${serviceArg}" and --service "${opts.service}". Use either the positional argument or --service flag, not both.`);
552
- process.exit(ExitCode.USAGE_ERROR);
587
+ outputError(
588
+ ExitCode.USAGE_ERROR,
589
+ `Conflicting service values: positional "${serviceArg}" and --service "${opts.service}". Use either the positional argument or --service flag, not both.`
590
+ );
553
591
  }
554
592
  const service = opts.service ?? serviceArg;
555
593
  if (!service) {
556
- console.error("Missing service name. Use positional <service> or --service <name>.");
557
- process.exit(ExitCode.USAGE_ERROR);
594
+ outputError(
595
+ ExitCode.USAGE_ERROR,
596
+ "Missing service name. Use positional <service> or --service <name>.",
597
+ "Run: ucli services list to see available services"
598
+ );
558
599
  }
559
600
  const cfg = getConfig();
560
601
  const client = new ServerClient(cfg);
@@ -562,9 +603,11 @@ function registerRun(program2) {
562
603
  try {
563
604
  entry = await client.getOAS(service);
564
605
  } catch {
565
- console.error(`Unknown service: ${service}`);
566
- console.error("Run `ucli services list` to see available services.");
567
- process.exit(ExitCode.NOT_FOUND);
606
+ outputError(
607
+ ExitCode.NOT_FOUND,
608
+ `Unknown service: ${service}`,
609
+ "Run: ucli services list to see available services"
610
+ );
568
611
  }
569
612
  const extraArgs = opts.args ?? [];
570
613
  const operationArgs = [...args, ...extraArgs];
@@ -576,8 +619,11 @@ function registerRun(program2) {
576
619
  try {
577
620
  parsed = JSON.parse(opts.params);
578
621
  } catch {
579
- console.error(`Invalid --params JSON. Example: --params '{"petId": 1}'`);
580
- process.exit(ExitCode.USAGE_ERROR);
622
+ outputError(
623
+ ExitCode.USAGE_ERROR,
624
+ "Invalid --params JSON.",
625
+ `Example: --params '{"petId": 1}'`
626
+ );
581
627
  }
582
628
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
583
629
  for (const [k, v] of Object.entries(parsed)) {
@@ -600,8 +646,10 @@ function registerRun(program2) {
600
646
  ...query !== void 0 ? { query } : {}
601
647
  });
602
648
  } catch (err) {
603
- console.error("Operation failed:", err.message);
604
- process.exit(ExitCode.GENERAL_ERROR);
649
+ outputError(
650
+ ExitCode.GENERAL_ERROR,
651
+ `Operation failed: ${err.message}`
652
+ );
605
653
  }
606
654
  });
607
655
  }
@@ -611,7 +659,9 @@ function registerRefresh(program2) {
611
659
  program2.command("refresh").description("Force-refresh the local OAS cache from the server").option("--service <name>", "Refresh only a specific service").action(async (opts) => {
612
660
  const cfg = getConfig();
613
661
  const client = new ServerClient(cfg);
614
- console.log("Refreshing OAS list from server...");
662
+ if (!isJsonOutput()) {
663
+ console.log("Refreshing OAS list from server...");
664
+ }
615
665
  if (opts.service) {
616
666
  await clearOASCache(opts.service);
617
667
  } else {
@@ -622,6 +672,10 @@ function registerRefresh(program2) {
622
672
  const maxTtl = Math.min(...entries.map((e) => e.cacheTtl));
623
673
  await writeOASListCache(entries, maxTtl);
624
674
  }
675
+ if (isJsonOutput()) {
676
+ outputSuccess({ refreshed: entries.length });
677
+ return;
678
+ }
625
679
  console.log(`\u2713 Refreshed ${entries.length} service(s).`);
626
680
  });
627
681
  }
@@ -696,6 +750,10 @@ DISCOVERY
696
750
  ucli services info <service>
697
751
  Show detailed service info and all available operations.
698
752
 
753
+ ucli introspect
754
+ Return complete capability manifest in a single call (JSON).
755
+ Ideal for AI agents: includes services, MCP servers, and command reference.
756
+
699
757
  ucli help [service]
700
758
  Show this guide, or service-specific operations.
701
759
 
@@ -708,6 +766,16 @@ EXECUTION
708
766
  --query <jmespath> Filter response with JMESPath
709
767
  --data <json|@file> Request body for POST/PUT/PATCH
710
768
 
769
+ MCP SERVERS
770
+ ucli mcp list
771
+ List all MCP servers in your group.
772
+
773
+ ucli mcp tools <server>
774
+ List tools available on a MCP server.
775
+
776
+ ucli mcp run <server> <tool> [key=value ...]
777
+ Call a tool on a MCP server.
778
+
711
779
  MAINTENANCE
712
780
  ucli refresh
713
781
  Force-refresh the local OAS cache from the server.
@@ -722,6 +790,8 @@ SHELL COMPLETIONS
722
790
 
723
791
  GLOBAL FLAGS
724
792
  --debug Enable verbose debug logging
793
+ --output json Wrap ALL output in structured JSON envelopes
794
+ (for agent/automation consumption)
725
795
  -v, --version Show version number
726
796
 
727
797
  ERRORS
@@ -729,6 +799,11 @@ ERRORS
729
799
  404 Not Found \u2192 Check service name: ucli services list
730
800
  4xx Client Error \u2192 Check operation args: ucli services info <service>
731
801
  5xx Server Error \u2192 Retry or run: ucli refresh
802
+
803
+ AI AGENT QUICK START
804
+ 1. ucli introspect # discover everything in one call
805
+ 2. ucli run <svc> <op> [args] # execute operations
806
+ 3. Use --output json globally # get structured { success, data/error } envelopes
732
807
  `);
733
808
  }
734
809
 
@@ -739,8 +814,8 @@ function resolve(mod, name) {
739
814
  throw new Error(`Cannot resolve export "${name}" from module`);
740
815
  }
741
816
  async function getMcp2cli() {
742
- const clientMod = await import("./client-3I7XBDJU.js");
743
- const runnerMod = await import("./runner-GVYIJNHN.js");
817
+ const clientMod = await import("./client-LCWUZRZX.js");
818
+ const runnerMod = await import("./runner-HH357SRR.js");
744
819
  return {
745
820
  createMcpClient: resolve(clientMod, "createMcpClient"),
746
821
  getTools: resolve(runnerMod, "getTools"),
@@ -810,24 +885,24 @@ function registerMcp(program2) {
810
885
  const cfg = getConfig();
811
886
  const client = new ServerClient(cfg);
812
887
  const entries = await client.listMCP();
888
+ const safe = entries.map(({ authConfig, ...rest }) => ({
889
+ ...rest,
890
+ authConfig: { type: authConfig.type }
891
+ }));
892
+ if (isJsonOutput()) {
893
+ outputSuccess(safe);
894
+ return;
895
+ }
813
896
  if (entries.length === 0) {
814
897
  console.log("No MCP servers registered in this group.");
815
898
  return;
816
899
  }
817
900
  const format = (opts.format ?? "table").toLowerCase();
818
901
  if (format === "json") {
819
- const safe = entries.map(({ authConfig, ...rest }) => ({
820
- ...rest,
821
- authConfig: { type: authConfig.type }
822
- }));
823
902
  console.log(JSON.stringify(safe, null, 2));
824
903
  return;
825
904
  }
826
905
  if (format === "yaml") {
827
- const safe = entries.map(({ authConfig, ...rest }) => ({
828
- ...rest,
829
- authConfig: { type: authConfig.type }
830
- }));
831
906
  console.log(toYaml(safe));
832
907
  return;
833
908
  }
@@ -848,16 +923,21 @@ ${"SERVER".padEnd(nameWidth)} TRANSPORT DESCRIPTION`);
848
923
  try {
849
924
  entry = await client.getMCP(serverName);
850
925
  } catch {
851
- console.error(`Unknown MCP server: ${serverName}`);
852
- console.error("Run `ucli mcp list` to see available servers.");
853
- process.exit(ExitCode.NOT_FOUND);
926
+ outputError(
927
+ ExitCode.NOT_FOUND,
928
+ `Unknown MCP server: ${serverName}`,
929
+ "Run: ucli mcp list to see available servers"
930
+ );
854
931
  }
855
932
  let tools;
856
933
  try {
857
934
  tools = await listMcpTools(entry);
858
935
  } catch (err) {
859
- console.error("Failed to fetch tools:", err.message);
860
- process.exit(ExitCode.GENERAL_ERROR);
936
+ outputError(ExitCode.GENERAL_ERROR, `Failed to fetch tools: ${err.message}`);
937
+ }
938
+ if (isJsonOutput()) {
939
+ outputSuccess(tools);
940
+ return;
861
941
  }
862
942
  if (tools.length === 0) {
863
943
  console.log(`No tools found on MCP server "${serverName}".`);
@@ -888,15 +968,16 @@ Tools on "${serverName}":`);
888
968
  try {
889
969
  entry = await client.getMCP(serverName);
890
970
  } catch {
891
- console.error(`Unknown MCP server: ${serverName}`);
892
- console.error("Run `ucli mcp list` to see available servers.");
893
- process.exit(ExitCode.NOT_FOUND);
971
+ outputError(
972
+ ExitCode.NOT_FOUND,
973
+ `Unknown MCP server: ${serverName}`,
974
+ "Run: ucli mcp list to see available servers"
975
+ );
894
976
  }
895
977
  try {
896
978
  await runMcpTool(entry, toolName, args);
897
979
  } catch (err) {
898
- console.error("Tool execution failed:", err.message);
899
- process.exit(ExitCode.GENERAL_ERROR);
980
+ outputError(ExitCode.GENERAL_ERROR, `Tool execution failed: ${err.message}`);
900
981
  }
901
982
  });
902
983
  }
@@ -931,8 +1012,11 @@ function registerDoctor(program2) {
931
1012
  ok: false,
932
1013
  detail: "Not configured. Run: ucli configure --server <url> --token <jwt>"
933
1014
  });
934
- printResults(results);
935
- process.exit(ExitCode.CONFIG_ERROR);
1015
+ outputError(
1016
+ ExitCode.CONFIG_ERROR,
1017
+ "Not configured",
1018
+ "Run: ucli configure --server <url> --token <jwt>"
1019
+ );
936
1020
  }
937
1021
  let cfg;
938
1022
  try {
@@ -948,8 +1032,11 @@ function registerDoctor(program2) {
948
1032
  ok: false,
949
1033
  detail: `Failed to read config: ${err.message}`
950
1034
  });
951
- printResults(results);
952
- process.exit(ExitCode.CONFIG_ERROR);
1035
+ outputError(
1036
+ ExitCode.CONFIG_ERROR,
1037
+ `Failed to read config: ${err.message}`,
1038
+ "Run: ucli configure --server <url> --token <jwt>"
1039
+ );
953
1040
  }
954
1041
  debug(`Checking connectivity to ${cfg.serverUrl}...`);
955
1042
  try {
@@ -985,8 +1072,15 @@ function registerDoctor(program2) {
985
1072
  detail: `Token rejected: ${msg}`
986
1073
  });
987
1074
  }
988
- printResults(results);
989
1075
  const allOk = results.every((r) => r.ok);
1076
+ if (isJsonOutput()) {
1077
+ outputSuccess({
1078
+ healthy: allOk,
1079
+ checks: results
1080
+ });
1081
+ process.exit(allOk ? ExitCode.SUCCESS : ExitCode.GENERAL_ERROR);
1082
+ }
1083
+ printResults(results);
990
1084
  process.exit(allOk ? ExitCode.SUCCESS : ExitCode.GENERAL_ERROR);
991
1085
  });
992
1086
  }
@@ -1026,7 +1120,7 @@ _ucli_completions() {
1026
1120
  COMPREPLY=()
1027
1121
  cur="\${COMP_WORDS[COMP_CWORD]}"
1028
1122
  prev="\${COMP_WORDS[COMP_CWORD-1]}"
1029
- commands="configure services run refresh help mcp doctor completions"
1123
+ commands="configure services run refresh help mcp doctor completions introspect"
1030
1124
 
1031
1125
  case "\${COMP_WORDS[1]}" in
1032
1126
  services)
@@ -1070,6 +1164,7 @@ _ucli() {
1070
1164
  'mcp:Interact with MCP servers'
1071
1165
  'doctor:Check configuration and connectivity'
1072
1166
  'completions:Generate shell completion script'
1167
+ 'introspect:Return complete capability manifest for AI agents'
1073
1168
  )
1074
1169
 
1075
1170
  _arguments -C \\
@@ -1112,6 +1207,8 @@ complete -c ucli -n __fish_use_subcommand -a mcp -d 'Interact with MCP servers'
1112
1207
  complete -c ucli -n __fish_use_subcommand -a doctor -d 'Check config and connectivity'
1113
1208
  complete -c ucli -n __fish_use_subcommand -a completions -d 'Generate shell completions'
1114
1209
 
1210
+ complete -c ucli -n __fish_use_subcommand -a introspect -d 'Return capability manifest for AI agents'
1211
+
1115
1212
  # services subcommands
1116
1213
  complete -c ucli -n '__fish_seen_subcommand_from services' -a list -d 'List services'
1117
1214
  complete -c ucli -n '__fish_seen_subcommand_from services' -a info -d 'Show service details'
@@ -1125,16 +1222,175 @@ complete -c ucli -n '__fish_seen_subcommand_from mcp' -a run -d 'Call a tool'
1125
1222
  complete -c ucli -n '__fish_seen_subcommand_from completions' -a 'bash zsh fish' -d 'Shell type'`;
1126
1223
  }
1127
1224
 
1225
+ // src/commands/introspect.ts
1226
+ function registerIntrospect(program2) {
1227
+ program2.command("introspect").description("Return a complete capability manifest for AI agent discovery (services, MCP servers, commands)").option("--format <fmt>", "Output format: json | yaml", "json").action(async (opts) => {
1228
+ const cfg = getConfig();
1229
+ const client = new ServerClient(cfg);
1230
+ let oasEntries = [];
1231
+ let mcpEntries = [];
1232
+ try {
1233
+ ;
1234
+ [oasEntries, mcpEntries] = await Promise.all([
1235
+ client.listOAS(),
1236
+ client.listMCP()
1237
+ ]);
1238
+ } catch (err) {
1239
+ const message = err.message;
1240
+ outputError(
1241
+ ExitCode.CONNECTIVITY_ERROR,
1242
+ `Failed to fetch capabilities: ${message}`,
1243
+ "Check server connectivity with: ucli doctor"
1244
+ );
1245
+ }
1246
+ const manifest = {
1247
+ version: "1",
1248
+ services: oasEntries.map(toIntrospectService),
1249
+ mcpServers: mcpEntries.map(toIntrospectMcpServer),
1250
+ commands: getCommandReference()
1251
+ };
1252
+ const format = (opts.format ?? "json").toLowerCase();
1253
+ if (isJsonOutput()) {
1254
+ outputSuccess(manifest);
1255
+ return;
1256
+ }
1257
+ if (format === "json") {
1258
+ console.log(JSON.stringify(manifest, null, 2));
1259
+ return;
1260
+ }
1261
+ if (format === "yaml") {
1262
+ console.log(toYaml(manifest));
1263
+ return;
1264
+ }
1265
+ console.log(JSON.stringify(manifest, null, 2));
1266
+ });
1267
+ }
1268
+ function toIntrospectService(e) {
1269
+ return {
1270
+ name: e.name,
1271
+ description: e.description,
1272
+ authType: e.authType,
1273
+ remoteUrl: e.remoteUrl,
1274
+ baseEndpoint: e.baseEndpoint,
1275
+ cacheTtl: e.cacheTtl
1276
+ };
1277
+ }
1278
+ function toIntrospectMcpServer(e) {
1279
+ return {
1280
+ name: e.name,
1281
+ description: e.description,
1282
+ transport: e.transport,
1283
+ enabled: e.enabled
1284
+ };
1285
+ }
1286
+ function getCommandReference() {
1287
+ return [
1288
+ {
1289
+ name: "services list",
1290
+ description: "List all OAS services available in the current group",
1291
+ usage: "ucli services list [--format json|table|yaml] [--refresh]",
1292
+ examples: [
1293
+ "ucli services list",
1294
+ "ucli services list --format json",
1295
+ "ucli services list --refresh"
1296
+ ]
1297
+ },
1298
+ {
1299
+ name: "services info",
1300
+ description: "Show detailed information and available operations for a service",
1301
+ usage: "ucli services info <name> [--format json|table|yaml]",
1302
+ examples: [
1303
+ "ucli services info payments",
1304
+ "ucli services info payments --format json"
1305
+ ]
1306
+ },
1307
+ {
1308
+ name: "run",
1309
+ description: "Execute an operation on an OAS service",
1310
+ usage: "ucli run <service> <operation> [--format json|table|yaml] [--query <jmespath>] [--data <json|@file>] [--params <json>]",
1311
+ examples: [
1312
+ "ucli run payments listTransactions",
1313
+ "ucli run payments getTransaction --transactionId txn_123",
1314
+ `ucli run payments createCharge --data '{"amount": 5000, "currency": "USD"}'`,
1315
+ 'ucli run inventory listProducts --query "items[?stock > `0`].name"'
1316
+ ]
1317
+ },
1318
+ {
1319
+ name: "mcp list",
1320
+ description: "List all MCP servers available in the current group",
1321
+ usage: "ucli mcp list [--format json|table|yaml]",
1322
+ examples: [
1323
+ "ucli mcp list",
1324
+ "ucli mcp list --format json"
1325
+ ]
1326
+ },
1327
+ {
1328
+ name: "mcp tools",
1329
+ description: "List tools available on a MCP server",
1330
+ usage: "ucli mcp tools <server> [--format json|table|yaml]",
1331
+ examples: [
1332
+ "ucli mcp tools weather",
1333
+ "ucli mcp tools weather --format json"
1334
+ ]
1335
+ },
1336
+ {
1337
+ name: "mcp run",
1338
+ description: "Call a tool on a MCP server",
1339
+ usage: "ucli mcp run <server> <tool> [key=value ...]",
1340
+ examples: [
1341
+ 'ucli mcp run weather get_forecast location="New York"',
1342
+ 'ucli mcp run search web_search query="ucli docs" limit=5'
1343
+ ]
1344
+ },
1345
+ {
1346
+ name: "introspect",
1347
+ description: "Return complete capability manifest (this command)",
1348
+ usage: "ucli introspect [--format json|yaml]",
1349
+ examples: [
1350
+ "ucli introspect",
1351
+ "ucli introspect --format yaml"
1352
+ ]
1353
+ },
1354
+ {
1355
+ name: "refresh",
1356
+ description: "Force-refresh the local OAS cache from the server",
1357
+ usage: "ucli refresh [--service <name>]",
1358
+ examples: [
1359
+ "ucli refresh",
1360
+ "ucli refresh --service payments"
1361
+ ]
1362
+ },
1363
+ {
1364
+ name: "doctor",
1365
+ description: "Check configuration, server connectivity, and token validity",
1366
+ usage: "ucli doctor",
1367
+ examples: ["ucli doctor"]
1368
+ },
1369
+ {
1370
+ name: "configure",
1371
+ description: "Configure the server URL and authentication token",
1372
+ usage: "ucli configure --server <url> --token <jwt>",
1373
+ examples: ["ucli configure --server https://oas.example.com --token eyJ..."]
1374
+ }
1375
+ ];
1376
+ }
1377
+
1128
1378
  // src/index.ts
1129
1379
  var require3 = createRequire2(import.meta.url);
1130
1380
  var pkg = require3("../package.json");
1131
1381
  var program = new Command();
1132
- program.name("ucli").description(pkg.description).version(pkg.version, "-v, --version").option("--debug", "Enable verbose debug logging").addHelpCommand(false).hook("preAction", (_thisCommand, actionCommand) => {
1382
+ program.name("ucli").description(pkg.description).version(pkg.version, "-v, --version").option("--debug", "Enable verbose debug logging").option("--output <mode>", "Output mode: text | json (json wraps every result in a structured envelope for agent consumption)", "text").addHelpCommand(false).hook("preAction", (_thisCommand, actionCommand) => {
1133
1383
  let cmd = actionCommand;
1134
1384
  while (cmd) {
1135
- if (cmd.opts().debug) {
1385
+ const opts = cmd.opts();
1386
+ if (opts.debug) {
1136
1387
  setDebugMode(true);
1137
- break;
1388
+ }
1389
+ if (opts.output && typeof opts.output === "string") {
1390
+ const mode = opts.output.toLowerCase();
1391
+ if (mode === "json" || mode === "text") {
1392
+ setOutputMode(mode);
1393
+ }
1138
1394
  }
1139
1395
  cmd = cmd.parent;
1140
1396
  }
@@ -1146,6 +1402,7 @@ registerRefresh(program);
1146
1402
  registerMcp(program);
1147
1403
  registerDoctor(program);
1148
1404
  registerCompletions(program);
1405
+ registerIntrospect(program);
1149
1406
  registerHelp(program);
1150
1407
  program.parse(process.argv);
1151
1408
  //# sourceMappingURL=index.js.map