dynmcp 0.5.0 → 0.6.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.cjs CHANGED
@@ -23,13 +23,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
 
25
25
  // src/cli.ts
26
- var import_node_process12 = __toESM(require("process"), 1);
26
+ var import_node_process14 = __toESM(require("process"), 1);
27
27
  var import_commander = require("commander");
28
28
 
29
29
  // package.json
30
30
  var package_default = {
31
31
  name: "dynmcp",
32
- version: "0.5.0",
32
+ version: "0.6.0",
33
33
  description: "Dynamic MCP context management tool for AI MCP-enabled agents and clients.",
34
34
  author: "Brandon Burrus <brandon@burrus.io>",
35
35
  license: "MIT",
@@ -487,14 +487,14 @@ var sseTransport = import_zod.z.object({
487
487
  headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
488
488
  auth: authConfig
489
489
  }).strict();
490
- var transportConfig = import_zod.z.discriminatedUnion("transport", [
490
+ var transportConfigSchema = import_zod.z.discriminatedUnion("transport", [
491
491
  stdioTransport,
492
492
  streamableHttpTransport,
493
493
  sseTransport
494
494
  ]);
495
495
  var mcpConfigSchema = import_zod.z.object({
496
496
  env: envModeSchema.optional(),
497
- mcp: import_zod.z.record(mcpName, transportConfig).refine((obj) => Object.keys(obj).length > 0, { message: "At least one MCP must be configured" })
497
+ mcp: import_zod.z.record(mcpName, transportConfigSchema).refine((obj) => Object.keys(obj).length > 0, { message: "At least one MCP must be configured" })
498
498
  });
499
499
 
500
500
  // src/config/loader.ts
@@ -726,7 +726,7 @@ var import_node_child_process = require("child_process");
726
726
  var import_node_process3 = __toESM(require("process"), 1);
727
727
  async function openUrl(url) {
728
728
  const { command, args } = openerForPlatform(url);
729
- return new Promise((resolve3, reject) => {
729
+ return new Promise((resolve4, reject) => {
730
730
  const child = (0, import_node_child_process.spawn)(command, args, {
731
731
  stdio: "ignore",
732
732
  detached: true
@@ -734,7 +734,7 @@ async function openUrl(url) {
734
734
  child.once("error", reject);
735
735
  child.once("spawn", () => {
736
736
  child.unref();
737
- resolve3();
737
+ resolve4();
738
738
  });
739
739
  });
740
740
  }
@@ -809,14 +809,14 @@ var CallbackServer = class _CallbackServer {
809
809
  throw new Error("CallbackServer is already started.");
810
810
  }
811
811
  const server = (0, import_node_http.createServer)((req, res) => this.handleRequest(req, res));
812
- await new Promise((resolve3, reject) => {
812
+ await new Promise((resolve4, reject) => {
813
813
  const onError = (err) => {
814
814
  server.removeListener("listening", onListening);
815
815
  reject(err);
816
816
  };
817
817
  const onListening = () => {
818
818
  server.removeListener("error", onError);
819
- resolve3();
819
+ resolve4();
820
820
  };
821
821
  server.once("error", onError);
822
822
  server.once("listening", onListening);
@@ -854,12 +854,12 @@ var CallbackServer = class _CallbackServer {
854
854
  if (this.pending !== null) {
855
855
  return Promise.reject(new Error("awaitCallback already in progress."));
856
856
  }
857
- return new Promise((resolve3, reject) => {
857
+ return new Promise((resolve4, reject) => {
858
858
  const timer = setTimeout(() => {
859
859
  this.pending = null;
860
860
  reject(new CallbackTimeoutError(timeoutMs));
861
861
  }, timeoutMs);
862
- this.pending = { resolve: resolve3, reject, timer };
862
+ this.pending = { resolve: resolve4, reject, timer };
863
863
  });
864
864
  }
865
865
  /** Closes the listening socket. Safe to call multiple times. */
@@ -869,8 +869,8 @@ var CallbackServer = class _CallbackServer {
869
869
  this.pending = null;
870
870
  }
871
871
  if (this.server === null) return;
872
- await new Promise((resolve3) => {
873
- this.server.close(() => resolve3());
872
+ await new Promise((resolve4) => {
873
+ this.server.close(() => resolve4());
874
874
  });
875
875
  this.server = null;
876
876
  this.boundPort = null;
@@ -914,10 +914,10 @@ var CallbackServer = class _CallbackServer {
914
914
  }
915
915
  res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
916
916
  res.end(SUCCESS_HTML);
917
- const { resolve: resolve3, timer } = this.pending;
917
+ const { resolve: resolve4, timer } = this.pending;
918
918
  clearTimeout(timer);
919
919
  this.pending = null;
920
- resolve3({ code, state });
920
+ resolve4({ code, state });
921
921
  }
922
922
  respondError(res, errorCode, description2) {
923
923
  res.writeHead(400, { "content-type": "text/html; charset=utf-8" });
@@ -3309,6 +3309,215 @@ async function runProxy(orchestrator) {
3309
3309
  }
3310
3310
  }
3311
3311
 
3312
+ // src/scaffold/init.ts
3313
+ var import_node_fs3 = require("fs");
3314
+ var import_node_path4 = require("path");
3315
+ var import_node_process12 = __toESM(require("process"), 1);
3316
+
3317
+ // src/scaffold/format.ts
3318
+ var import_node_path3 = require("path");
3319
+ function detectFormat(filePath) {
3320
+ const ext = (0, import_node_path3.extname)(filePath).toLowerCase();
3321
+ return ext === ".yml" || ext === ".yaml" ? "yaml" : "json";
3322
+ }
3323
+ var SCHEMA_URL = "https://dynamicmcp.tools/config.json";
3324
+
3325
+ // src/scaffold/init.ts
3326
+ function init(options = {}) {
3327
+ const cwd = options.cwd ?? import_node_process12.default.cwd();
3328
+ const stdout = options.write ?? ((chunk) => void import_node_process12.default.stdout.write(chunk));
3329
+ const fileWriter = options.fileWriter ?? ((p, c) => (0, import_node_fs3.writeFileSync)(p, c, "utf-8"));
3330
+ const fileExists = options.fileExists ?? ((p) => (0, import_node_fs3.existsSync)(p));
3331
+ const targetPath = resolveInitPath({ cwd, path: options.path, yaml: options.yaml === true });
3332
+ const format = detectFormat(targetPath);
3333
+ if (fileExists(targetPath) && options.force !== true) {
3334
+ throw new Error(`File already exists: ${targetPath}
3335
+ Use --force to overwrite.`);
3336
+ }
3337
+ const contents = format === "yaml" ? renderYamlSkeleton() : renderJsonSkeleton();
3338
+ fileWriter(targetPath, contents);
3339
+ stdout(`Wrote ${targetPath}
3340
+ `);
3341
+ stdout("\nThis config has no MCPs yet. Add one with:\n");
3342
+ stdout(" dynmcp add <name> --command <cmd> (stdio upstream)\n");
3343
+ stdout(" dynmcp add <name> --transport streamable-http --url <url> (remote HTTP upstream)\n");
3344
+ stdout("\nSee https://dynamicmcp.tools for full documentation.\n");
3345
+ }
3346
+ function resolveInitPath(opts) {
3347
+ if (opts.path !== void 0) {
3348
+ return (0, import_node_path4.resolve)(opts.cwd, opts.path);
3349
+ }
3350
+ return (0, import_node_path4.resolve)(opts.cwd, opts.yaml ? "mcp.yaml" : "mcp.json");
3351
+ }
3352
+ function renderJsonSkeleton() {
3353
+ const body = JSON.stringify({ $schema: SCHEMA_URL, mcp: {} }, null, 2);
3354
+ return `${body}
3355
+ `;
3356
+ }
3357
+ function renderYamlSkeleton() {
3358
+ return `# yaml-language-server: $schema=${SCHEMA_URL}
3359
+
3360
+ mcp: {}
3361
+ `;
3362
+ }
3363
+
3364
+ // src/scaffold/add.ts
3365
+ var import_node_fs4 = require("fs");
3366
+ var import_node_process13 = __toESM(require("process"), 1);
3367
+ var import_yaml2 = require("yaml");
3368
+ function add(options) {
3369
+ validateName(options.name);
3370
+ const stdout = options.write ?? ((chunk) => void import_node_process13.default.stdout.write(chunk));
3371
+ const fileReader = options.fileReader ?? ((p) => (0, import_node_fs4.readFileSync)(p, "utf-8"));
3372
+ const fileWriter = options.fileWriter ?? ((p, c) => (0, import_node_fs4.writeFileSync)(p, c, "utf-8"));
3373
+ const resolvePath = options.resolvePath ?? resolveConfigPath;
3374
+ let targetPath;
3375
+ try {
3376
+ targetPath = resolvePath(options.configPath);
3377
+ } catch (error) {
3378
+ const message = error instanceof Error ? error.message : String(error);
3379
+ throw new Error(`${message}
3380
+ Hint: run 'dynmcp init' to create a starter config file.`);
3381
+ }
3382
+ const raw = fileReader(targetPath);
3383
+ const format = detectFormat(targetPath);
3384
+ const entry = buildEntry(options);
3385
+ const parsed = transportConfigSchema.safeParse(entry);
3386
+ if (!parsed.success) {
3387
+ const issues = parsed.error.issues.map((i) => ` - ${i.path.join(".") || "<root>"}: ${i.message}`).join("\n");
3388
+ throw new Error(`Invalid MCP entry:
3389
+ ${issues}`);
3390
+ }
3391
+ const next = format === "yaml" ? writeYaml(raw, options.name, parsed.data, options.force === true) : writeJson(raw, options.name, parsed.data, options.force === true);
3392
+ fileWriter(targetPath, next);
3393
+ stdout(`Added '${options.name}' (${options.transport}) to ${targetPath}
3394
+ `);
3395
+ }
3396
+ function validateName(name) {
3397
+ if (!MCP_NAME_PATTERN.test(name)) {
3398
+ throw new Error(
3399
+ `Invalid MCP name '${name}'. Names must match ${MCP_NAME_PATTERN.source} (lowercase letters, digits, and dashes; starting with a letter or digit).`
3400
+ );
3401
+ }
3402
+ }
3403
+ function buildEntry(options) {
3404
+ if (options.transport === "stdio") {
3405
+ if (options.command === void 0 || options.command.length === 0) {
3406
+ throw new Error("--command is required for stdio transport");
3407
+ }
3408
+ const entry2 = {
3409
+ transport: "stdio",
3410
+ command: options.command
3411
+ };
3412
+ if (options.description !== void 0) entry2.description = options.description;
3413
+ if (options.args !== void 0 && options.args.length > 0) {
3414
+ entry2.args = options.args;
3415
+ }
3416
+ if (options.envVars !== void 0 && options.envVars.length > 0) {
3417
+ entry2.env = parseKeyValuePairs(options.envVars, "--env");
3418
+ }
3419
+ return entry2;
3420
+ }
3421
+ if (options.url === void 0 || options.url.length === 0) {
3422
+ throw new Error(`--url is required for ${options.transport} transport`);
3423
+ }
3424
+ const entry = {
3425
+ transport: options.transport,
3426
+ url: options.url
3427
+ };
3428
+ if (options.description !== void 0) entry.description = options.description;
3429
+ if (options.headers !== void 0 && options.headers.length > 0) {
3430
+ entry.headers = parseHeaderPairs(options.headers);
3431
+ }
3432
+ const auth2 = buildAuthBlock(options);
3433
+ if (auth2 !== void 0) entry.auth = auth2;
3434
+ return entry;
3435
+ }
3436
+ function buildAuthBlock(options) {
3437
+ const hasAny = options.clientId !== void 0 || options.clientSecret !== void 0 || options.scope !== void 0;
3438
+ if (!hasAny) return void 0;
3439
+ if (options.clientId === void 0) {
3440
+ throw new Error("--client-id is required when --client-secret or --scope is provided");
3441
+ }
3442
+ const auth2 = { client_id: options.clientId };
3443
+ if (options.clientSecret !== void 0) auth2.client_secret = options.clientSecret;
3444
+ if (options.scope !== void 0) auth2.scope = options.scope;
3445
+ return auth2;
3446
+ }
3447
+ function parseKeyValuePairs(pairs, flag) {
3448
+ const out = {};
3449
+ for (const pair of pairs) {
3450
+ const eq = pair.indexOf("=");
3451
+ if (eq <= 0) {
3452
+ throw new Error(`${flag} expects KEY=VALUE (got: ${JSON.stringify(pair)})`);
3453
+ }
3454
+ const key = pair.slice(0, eq);
3455
+ out[key] = pair.slice(eq + 1);
3456
+ }
3457
+ return out;
3458
+ }
3459
+ function parseHeaderPairs(pairs) {
3460
+ const out = {};
3461
+ for (const pair of pairs) {
3462
+ const colon = pair.indexOf(":");
3463
+ if (colon <= 0) {
3464
+ throw new Error(`--header expects "Name: Value" (got: ${JSON.stringify(pair)})`);
3465
+ }
3466
+ const key = pair.slice(0, colon).trim();
3467
+ const value = pair.slice(colon + 1).trim();
3468
+ if (key.length === 0) {
3469
+ throw new Error(`--header name cannot be empty (got: ${JSON.stringify(pair)})`);
3470
+ }
3471
+ out[key] = value;
3472
+ }
3473
+ return out;
3474
+ }
3475
+ function writeJson(raw, name, entry, force) {
3476
+ let parsed;
3477
+ try {
3478
+ parsed = JSON.parse(raw);
3479
+ } catch (error) {
3480
+ const message = error instanceof Error ? error.message : String(error);
3481
+ throw new Error(`Failed to parse config as JSON: ${message}`);
3482
+ }
3483
+ if (!isPlainObject(parsed)) {
3484
+ throw new Error("Top-level config must be a JSON object.");
3485
+ }
3486
+ let mcp = parsed.mcp;
3487
+ if (mcp === void 0) {
3488
+ mcp = {};
3489
+ parsed.mcp = mcp;
3490
+ } else if (!isPlainObject(mcp)) {
3491
+ throw new Error("Config field 'mcp' must be an object.");
3492
+ }
3493
+ const mcpRecord = mcp;
3494
+ if (mcpRecord[name] !== void 0 && !force) {
3495
+ throw new Error(`Entry '${name}' already exists. Use --force to overwrite.`);
3496
+ }
3497
+ mcpRecord[name] = entry;
3498
+ return `${JSON.stringify(parsed, null, 2)}
3499
+ `;
3500
+ }
3501
+ function writeYaml(raw, name, entry, force) {
3502
+ const doc = (0, import_yaml2.parseDocument)(raw);
3503
+ if (doc.errors.length > 0) {
3504
+ const first = doc.errors[0]?.message ?? "unknown error";
3505
+ throw new Error(`Failed to parse config as YAML: ${first}`);
3506
+ }
3507
+ if (!doc.has("mcp")) {
3508
+ doc.set("mcp", {});
3509
+ }
3510
+ const path = ["mcp", name];
3511
+ if (doc.hasIn(path) && !force) {
3512
+ throw new Error(`Entry '${name}' already exists. Use --force to overwrite.`);
3513
+ }
3514
+ doc.setIn(path, entry);
3515
+ return doc.toString();
3516
+ }
3517
+ function isPlainObject(value) {
3518
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3519
+ }
3520
+
3312
3521
  // src/cli.ts
3313
3522
  var cliBanner = import_chalk.default.bold.magentaBright(
3314
3523
  import_figlet.default.textSync("DYNAMIC MCP", {
@@ -3319,36 +3528,100 @@ var cliBanner = import_chalk.default.bold.magentaBright(
3319
3528
  );
3320
3529
  var cli = new import_commander.Command(package_default.name).description(package_default.description).version(package_default.version).addHelpText("beforeAll", cliBanner).addHelpText(
3321
3530
  "after",
3322
- "\nExamples:\n dynmcp -- npx -y chrome-devtools-mcp@latest\n dynmcp --config ./mcp.json\n dynmcp ls\n dynmcp test github\n dynmcp login github\n dynmcp logout github\n"
3531
+ "\nExamples:\n dynmcp -- npx -y chrome-devtools-mcp@latest\n dynmcp --config ./mcp.json\n dynmcp init\n dynmcp add filesystem --command npx --arg -y --arg @modelcontextprotocol/server-filesystem --arg /tmp\n dynmcp add github --transport streamable-http --url https://api.githubcopilot.com/mcp\n dynmcp ls\n dynmcp test github\n dynmcp login github\n dynmcp logout github\n"
3323
3532
  ).option("-c, --config <path>", "Path to config file (JSON or YAML)").option("-e, --env <path>", "Path to a .env file for environment variable interpolation").allowExcessArguments(true).passThroughOptions(true).action(async (_options, cmd) => {
3324
- const separatorIndex = import_node_process12.default.argv.indexOf("--");
3533
+ const separatorIndex = import_node_process14.default.argv.indexOf("--");
3325
3534
  const configPath = cmd.opts().config;
3326
3535
  const envFilePath = cmd.opts().env;
3327
3536
  if (separatorIndex !== -1) {
3328
- const [command, ...args] = import_node_process12.default.argv.slice(separatorIndex + 1);
3537
+ const [command, ...args] = import_node_process14.default.argv.slice(separatorIndex + 1);
3329
3538
  if (command === void 0) {
3330
- import_node_process12.default.stderr.write(
3539
+ import_node_process14.default.stderr.write(
3331
3540
  "dynmcp: no upstream command provided after --.\nUsage: dynmcp -- <command> [args...]\n"
3332
3541
  );
3333
- import_node_process12.default.exit(1);
3542
+ import_node_process14.default.exit(1);
3334
3543
  }
3335
3544
  try {
3336
3545
  await startProxy(command, args);
3337
3546
  } catch (error) {
3338
- import_node_process12.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3547
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3339
3548
  `);
3340
- import_node_process12.default.exit(1);
3549
+ import_node_process14.default.exit(1);
3341
3550
  }
3342
3551
  return;
3343
3552
  }
3344
3553
  try {
3345
3554
  await startProxyFromConfig({ configPath, envFilePath });
3346
3555
  } catch (error) {
3347
- import_node_process12.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3556
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3348
3557
  `);
3349
- import_node_process12.default.exit(1);
3558
+ import_node_process14.default.exit(1);
3350
3559
  }
3351
3560
  });
3561
+ cli.command("init").description("Write a starter config file (mcp.json by default) in the current directory.").option("--path <path>", "Explicit target path (extension determines format).").option("--yaml", "Write mcp.yaml instead of mcp.json (ignored if --path is set).").option("--force", "Overwrite an existing file.").action((options) => {
3562
+ try {
3563
+ init({
3564
+ ...options.path !== void 0 ? { path: options.path } : {},
3565
+ ...options.yaml === true ? { yaml: true } : {},
3566
+ ...options.force === true ? { force: true } : {}
3567
+ });
3568
+ } catch (error) {
3569
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3570
+ `);
3571
+ import_node_process14.default.exit(1);
3572
+ }
3573
+ });
3574
+ var collectRepeatable = (value, previous) => [...previous, value];
3575
+ cli.command("add <name>").description("Insert a new MCP entry into the resolved config file.").option(
3576
+ "-t, --transport <transport>",
3577
+ "Transport: stdio | streamable-http | sse (default: stdio).",
3578
+ "stdio"
3579
+ ).option("-c, --config <path>", "Path to config file (otherwise auto-discovered).").option("--description <text>", "Per-entry description; presence makes the entry lazy.").option("--command <cmd>", "(stdio) Command to spawn for the upstream MCP.").option(
3580
+ "--arg <arg>",
3581
+ "(stdio) Repeatable positional argument passed after --command.",
3582
+ collectRepeatable,
3583
+ []
3584
+ ).option(
3585
+ "--env <KEY=VAL>",
3586
+ "(stdio) Repeatable env var for the spawned process.",
3587
+ collectRepeatable,
3588
+ []
3589
+ ).option("--url <url>", "(http/sse) Endpoint URL.").option(
3590
+ "--header <header>",
3591
+ '(http/sse) Repeatable "Name: Value" header.',
3592
+ collectRepeatable,
3593
+ []
3594
+ ).option("--client-id <id>", "(http/sse) Pre-registered OAuth client_id (skips DCR).").option("--client-secret <secret>", "(http/sse) Pre-registered OAuth client_secret.").option("--scope <scope>", "(http/sse) OAuth scope to request.").option("--force", "Overwrite an existing entry with the same name.").action(
3595
+ (name, options) => {
3596
+ try {
3597
+ const transport = options.transport;
3598
+ if (transport !== "stdio" && transport !== "streamable-http" && transport !== "sse") {
3599
+ throw new Error(
3600
+ `Invalid --transport '${options.transport}'. Must be one of: stdio, streamable-http, sse.`
3601
+ );
3602
+ }
3603
+ add({
3604
+ name,
3605
+ transport,
3606
+ ...options.config !== void 0 ? { configPath: options.config } : {},
3607
+ ...options.force === true ? { force: true } : {},
3608
+ ...options.description !== void 0 ? { description: options.description } : {},
3609
+ ...options.command !== void 0 ? { command: options.command } : {},
3610
+ ...options.arg.length > 0 ? { args: options.arg } : {},
3611
+ ...options.env.length > 0 ? { envVars: options.env } : {},
3612
+ ...options.url !== void 0 ? { url: options.url } : {},
3613
+ ...options.header.length > 0 ? { headers: options.header } : {},
3614
+ ...options.clientId !== void 0 ? { clientId: options.clientId } : {},
3615
+ ...options.clientSecret !== void 0 ? { clientSecret: options.clientSecret } : {},
3616
+ ...options.scope !== void 0 ? { scope: options.scope } : {}
3617
+ });
3618
+ } catch (error) {
3619
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3620
+ `);
3621
+ import_node_process14.default.exit(1);
3622
+ }
3623
+ }
3624
+ );
3352
3625
  cli.command("login <name>").description("Run the OAuth authorization-code flow for an upstream MCP and store tokens.").option("-c, --config <path>", "Path to config file (JSON or YAML)").option("-e, --env <path>", "Path to a .env file for environment variable interpolation").action(async (name, options) => {
3353
3626
  try {
3354
3627
  await login({
@@ -3357,9 +3630,9 @@ cli.command("login <name>").description("Run the OAuth authorization-code flow f
3357
3630
  ...options.env !== void 0 ? { envFilePath: options.env } : {}
3358
3631
  });
3359
3632
  } catch (error) {
3360
- import_node_process12.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3633
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3361
3634
  `);
3362
- import_node_process12.default.exit(1);
3635
+ import_node_process14.default.exit(1);
3363
3636
  }
3364
3637
  });
3365
3638
  cli.command("logout <name>").description("Delete the OAuth keychain entry for an upstream MCP.").option("-c, --config <path>", "Path to config file (JSON or YAML)").option("-e, --env <path>", "Path to a .env file for environment variable interpolation").action(async (name, options) => {
@@ -3370,9 +3643,9 @@ cli.command("logout <name>").description("Delete the OAuth keychain entry for an
3370
3643
  ...options.env !== void 0 ? { envFilePath: options.env } : {}
3371
3644
  });
3372
3645
  } catch (error) {
3373
- import_node_process12.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3646
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3374
3647
  `);
3375
- import_node_process12.default.exit(1);
3648
+ import_node_process14.default.exit(1);
3376
3649
  }
3377
3650
  });
3378
3651
  cli.command("ls").description("List configured upstream MCPs with transport, mode, endpoint, and auth status.").option("-c, --config <path>", "Path to config file (JSON or YAML)").option("-e, --env <path>", "Path to a .env file for environment variable interpolation").option("--json", "Emit JSON instead of the aligned text table").action(async (options) => {
@@ -3383,9 +3656,9 @@ cli.command("ls").description("List configured upstream MCPs with transport, mod
3383
3656
  ...options.json === true ? { json: true } : {}
3384
3657
  });
3385
3658
  } catch (error) {
3386
- import_node_process12.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3659
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3387
3660
  `);
3388
- import_node_process12.default.exit(1);
3661
+ import_node_process14.default.exit(1);
3389
3662
  }
3390
3663
  });
3391
3664
  cli.command("test [name]").description("Probe one or all configured upstream MCPs and print their discovered catalogs.").option("-c, --config <path>", "Path to config file (JSON or YAML)").option("-e, --env <path>", "Path to a .env file for environment variable interpolation").option("--json", "Emit JSON instead of the formatted text output").option("--timeout <ms>", "Per-MCP timeout in milliseconds (default: 15000)", (v) => Number(v)).action(
@@ -3398,19 +3671,19 @@ cli.command("test [name]").description("Probe one or all configured upstream MCP
3398
3671
  ...options.json === true ? { json: true } : {},
3399
3672
  ...options.timeout !== void 0 && !Number.isNaN(options.timeout) ? { timeoutMs: options.timeout } : {}
3400
3673
  });
3401
- if (exitCode !== 0) import_node_process12.default.exit(exitCode);
3674
+ if (exitCode !== 0) import_node_process14.default.exit(exitCode);
3402
3675
  } catch (error) {
3403
- import_node_process12.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3676
+ import_node_process14.default.stderr.write(`dynmcp: ${error instanceof Error ? error.message : String(error)}
3404
3677
  `);
3405
- import_node_process12.default.exit(1);
3678
+ import_node_process14.default.exit(1);
3406
3679
  }
3407
3680
  }
3408
3681
  );
3409
3682
 
3410
3683
  // src/index.ts
3411
- var import_node_process13 = __toESM(require("process"), 1);
3684
+ var import_node_process15 = __toESM(require("process"), 1);
3412
3685
  async function main() {
3413
- cli.parse(import_node_process13.default.argv);
3686
+ cli.parse(import_node_process15.default.argv);
3414
3687
  }
3415
3688
  main();
3416
3689
  //# sourceMappingURL=index.cjs.map