@alcyone-labs/arg-parser 2.5.0 → 2.7.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
@@ -35,6 +35,7 @@ var __flags, _throwForDuplicateFlags, _appName, _appCommandName, _subCommandName
35
35
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
36
36
  const fs = require("node:fs");
37
37
  const path = require("node:path");
38
+ const node_url = require("node:url");
38
39
  const magicRegexp = require("magic-regexp");
39
40
  const getTsconfig = require("get-tsconfig");
40
41
  const zod = require("zod");
@@ -1075,6 +1076,29 @@ class ConfigurationManager {
1075
1076
  }
1076
1077
  }
1077
1078
  }
1079
+ const zodDxtOptionsSchema = zod.z.object({
1080
+ sensitive: zod.z.boolean().optional().describe("Whether this field should be marked as sensitive in DXT user_config"),
1081
+ localDefault: zod.z.string().optional().describe("Default value specific to DXT sandbox environment"),
1082
+ type: zod.z.enum(["string", "directory", "file", "boolean", "number"]).optional().describe("DXT input type - determines UI component in DXT clients"),
1083
+ multiple: zod.z.boolean().optional().describe("Allow multiple values (for arrays)"),
1084
+ min: zod.z.number().optional().describe("Minimum value (for number type)"),
1085
+ max: zod.z.number().optional().describe("Maximum value (for number type)"),
1086
+ default: zod.z.any().optional().describe("DXT-specific default value (overrides localDefault if provided)"),
1087
+ title: zod.z.string().optional().describe("Custom title for the user_config field")
1088
+ }).strict().refine(
1089
+ (data2) => {
1090
+ if ((data2.min !== void 0 || data2.max !== void 0) && data2.type !== "number") {
1091
+ return false;
1092
+ }
1093
+ if (data2.min !== void 0 && data2.max !== void 0 && data2.min > data2.max) {
1094
+ return false;
1095
+ }
1096
+ return true;
1097
+ },
1098
+ {
1099
+ message: "Invalid dxtOptions: min/max can only be used with type 'number', and min must be <= max"
1100
+ }
1101
+ );
1078
1102
  const zodFlagSchema = zod.z.object({
1079
1103
  name: zod.z.string().min(1, "Flag name cannot be empty").describe(
1080
1104
  "The output property name, used as a return key `{name: value}`. Must be unique."
@@ -1146,7 +1170,8 @@ const zodFlagSchema = zod.z.object({
1146
1170
  enum: zod.z.array(zod.z.any()).optional().describe("Array of allowed values for the flag."),
1147
1171
  env: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).optional().describe(
1148
1172
  "Environment variables that should be set from this flag's value in DXT packages."
1149
- )
1173
+ ),
1174
+ dxtOptions: zodDxtOptionsSchema.optional().describe("DXT-specific configuration options for enhanced DXT manifest generation")
1150
1175
  }).transform((obj) => {
1151
1176
  const newObj = { ...obj };
1152
1177
  if ("default" in newObj && newObj["default"] !== void 0 && !("defaultValue" in newObj)) {
@@ -1344,6 +1369,353 @@ echo "Mock DXT build script for ${serverInfo.name}"`;
1344
1369
  return process.env["NODE_ENV"] === "test" || ((_a = process.argv[0]) == null ? void 0 : _a.includes("vitest")) || ((_b = process.argv[1]) == null ? void 0 : _b.includes("vitest")) || ((_c = process.argv[1]) == null ? void 0 : _c.includes("tinypool"));
1345
1370
  }
1346
1371
  }
1372
+ function detectEntryPoint() {
1373
+ try {
1374
+ if (process.argv[1] && fs__namespace.existsSync(process.argv[1])) {
1375
+ return process.argv[1];
1376
+ }
1377
+ if (typeof require !== "undefined" && require.main && require.main.filename) {
1378
+ return require.main.filename;
1379
+ }
1380
+ return null;
1381
+ } catch {
1382
+ return null;
1383
+ }
1384
+ }
1385
+ function getEntryPointFromImportMeta(importMetaUrl) {
1386
+ if (importMetaUrl.startsWith("file://")) {
1387
+ return decodeURIComponent(importMetaUrl.replace("file://", ""));
1388
+ }
1389
+ return importMetaUrl;
1390
+ }
1391
+ function normalizePath(path2) {
1392
+ return path2.trim();
1393
+ }
1394
+ function resolveLogPath(logPath, fallbackEntryPoint) {
1395
+ if (typeof logPath === "string") {
1396
+ const pathWithVariables2 = DxtPathResolver.substituteVariables(
1397
+ logPath,
1398
+ DxtPathResolver.detectContext()
1399
+ );
1400
+ const normalizedPath2 = normalizePath(pathWithVariables2);
1401
+ if (path__namespace.isAbsolute(normalizedPath2)) {
1402
+ return normalizedPath2;
1403
+ }
1404
+ if (normalizedPath2.startsWith("cwd:")) {
1405
+ const relativePath = normalizedPath2.slice(4);
1406
+ return path__namespace.resolve(process.cwd(), relativePath);
1407
+ }
1408
+ const entryPoint = detectEntryPoint() || fallbackEntryPoint;
1409
+ if (entryPoint) {
1410
+ return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath2);
1411
+ }
1412
+ console.warn(
1413
+ `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath2}`
1414
+ );
1415
+ return path__namespace.resolve(process.cwd(), normalizedPath2);
1416
+ }
1417
+ const { path: logFilePath, relativeTo = "entry", basePath } = logPath;
1418
+ const pathWithVariables = DxtPathResolver.substituteVariables(
1419
+ logFilePath,
1420
+ DxtPathResolver.detectContext()
1421
+ );
1422
+ const normalizedPath = normalizePath(pathWithVariables);
1423
+ switch (relativeTo) {
1424
+ case "absolute":
1425
+ if (basePath) {
1426
+ const resolvedBasePath = DxtPathResolver.substituteVariables(
1427
+ basePath,
1428
+ DxtPathResolver.detectContext()
1429
+ );
1430
+ return path__namespace.resolve(resolvedBasePath, normalizedPath);
1431
+ }
1432
+ if (path__namespace.isAbsolute(normalizedPath)) {
1433
+ return normalizedPath;
1434
+ }
1435
+ console.warn(
1436
+ `Warning: relativeTo 'absolute' specified but no basePath provided and path is not absolute. Using process.cwd() as fallback. Path: ${normalizedPath}`
1437
+ );
1438
+ return path__namespace.resolve(process.cwd(), normalizedPath);
1439
+ case "cwd":
1440
+ return path__namespace.resolve(process.cwd(), normalizedPath);
1441
+ case "entry":
1442
+ default:
1443
+ const entryPoint = detectEntryPoint() || fallbackEntryPoint;
1444
+ if (entryPoint) {
1445
+ return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath);
1446
+ }
1447
+ console.warn(
1448
+ `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath}`
1449
+ );
1450
+ return path__namespace.resolve(process.cwd(), normalizedPath);
1451
+ }
1452
+ }
1453
+ function entryRelative(path2) {
1454
+ return {
1455
+ path: path2,
1456
+ relativeTo: "entry"
1457
+ };
1458
+ }
1459
+ function cwdRelative(path2) {
1460
+ return {
1461
+ path: path2,
1462
+ relativeTo: "cwd"
1463
+ };
1464
+ }
1465
+ function absolutePath(path2, basePath) {
1466
+ return {
1467
+ path: path2,
1468
+ relativeTo: "absolute",
1469
+ basePath
1470
+ };
1471
+ }
1472
+ function legacyCwdPath(path2) {
1473
+ return `cwd:${path2}`;
1474
+ }
1475
+ const _DxtPathResolver = class _DxtPathResolver {
1476
+ /**
1477
+ * Detects the current execution context
1478
+ * @param forceRefresh - Force refresh of cached context
1479
+ * @returns Path context information
1480
+ */
1481
+ static detectContext(forceRefresh = false) {
1482
+ if (!forceRefresh && this._cachedContext) {
1483
+ return this._cachedContext;
1484
+ }
1485
+ const context = {
1486
+ isDxt: this.isDxtEnvironment(),
1487
+ userHome: void 0,
1488
+ cwd: typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd() : void 0
1489
+ };
1490
+ const entryPoint = detectEntryPoint();
1491
+ if (entryPoint) {
1492
+ context.entryDir = path__namespace.dirname(entryPoint);
1493
+ }
1494
+ if (context.isDxt) {
1495
+ context.extensionDir = this.detectDxtExtensionDir();
1496
+ }
1497
+ this._cachedContext = context;
1498
+ return context;
1499
+ }
1500
+ /**
1501
+ * Checks if the current environment is a DXT environment
1502
+ * @returns True if running in DXT, false otherwise
1503
+ */
1504
+ static isDxtEnvironment() {
1505
+ if (process.env["DXT_EXTENSION_DIR"] || process.env["CLAUDE_DESKTOP_DXT"]) {
1506
+ return true;
1507
+ }
1508
+ const dxtIndicators = [
1509
+ "manifest.json",
1510
+ // DXT packages have manifest.json
1511
+ ".dxt"
1512
+ // DXT marker file
1513
+ ];
1514
+ for (const indicator of dxtIndicators) {
1515
+ const indicatorPath = path__namespace.join(process.cwd(), indicator);
1516
+ if (fs__namespace.existsSync(indicatorPath)) {
1517
+ if (indicator === "manifest.json") {
1518
+ try {
1519
+ const manifest = JSON.parse(fs__namespace.readFileSync(indicatorPath, "utf-8"));
1520
+ if (manifest.server && manifest.user_config) {
1521
+ return true;
1522
+ }
1523
+ } catch {
1524
+ }
1525
+ } else {
1526
+ return true;
1527
+ }
1528
+ }
1529
+ }
1530
+ const cwd = process.cwd();
1531
+ if (cwd.includes("claude-desktop") || cwd.includes("extensions")) {
1532
+ return true;
1533
+ }
1534
+ return false;
1535
+ }
1536
+ /**
1537
+ * Detects the DXT extension directory
1538
+ * @returns DXT extension directory path or undefined
1539
+ */
1540
+ static detectDxtExtensionDir() {
1541
+ if (process.env["DXT_EXTENSION_DIR"]) {
1542
+ return process.env["DXT_EXTENSION_DIR"];
1543
+ }
1544
+ const cwd = process.cwd();
1545
+ if (fs__namespace.existsSync(path__namespace.join(cwd, "manifest.json"))) {
1546
+ return cwd;
1547
+ }
1548
+ let currentDir = cwd;
1549
+ for (let i = 0; i < 3; i++) {
1550
+ const parentDir = path__namespace.dirname(currentDir);
1551
+ if (parentDir === currentDir) break;
1552
+ if (fs__namespace.existsSync(path__namespace.join(parentDir, "manifest.json"))) {
1553
+ return parentDir;
1554
+ }
1555
+ currentDir = parentDir;
1556
+ }
1557
+ return void 0;
1558
+ }
1559
+ /**
1560
+ * Resolves a path with DXT variable substitution
1561
+ * @param inputPath - Path that may contain DXT variables
1562
+ * @param context - Optional context (will be detected if not provided)
1563
+ * @param config - Optional configuration for variable substitution
1564
+ * @returns Resolved absolute path
1565
+ */
1566
+ static resolvePath(inputPath, context, config) {
1567
+ const ctx = context || this.detectContext();
1568
+ const resolvedPath = this.substituteVariables(inputPath, ctx, config);
1569
+ if (path__namespace.isAbsolute(resolvedPath)) {
1570
+ return resolvedPath;
1571
+ }
1572
+ if (ctx.isDxt && ctx.extensionDir) {
1573
+ return path__namespace.resolve(ctx.extensionDir, resolvedPath);
1574
+ } else if (ctx.entryDir) {
1575
+ return path__namespace.resolve(ctx.entryDir, resolvedPath);
1576
+ } else {
1577
+ return path__namespace.resolve(ctx.cwd || process.cwd(), resolvedPath);
1578
+ }
1579
+ }
1580
+ /**
1581
+ * Substitutes DXT variables in a path string
1582
+ * @param inputPath - Path containing variables like ${HOME}, ${__dirname}, etc.
1583
+ * @param context - Path context
1584
+ * @param config - Variable substitution configuration
1585
+ * @returns Path with variables substituted
1586
+ */
1587
+ static substituteVariables(inputPath, context, config) {
1588
+ const safeHomedir = () => "/tmp";
1589
+ const homeDir = context.userHome || safeHomedir();
1590
+ const variables = {
1591
+ // Standard DXT variables
1592
+ HOME: homeDir,
1593
+ DOCUMENTS: path__namespace.join(homeDir, "Documents"),
1594
+ DOWNLOADS: path__namespace.join(homeDir, "Downloads"),
1595
+ DESKTOP: path__namespace.join(homeDir, "Desktop"),
1596
+ pathSeparator: path__namespace.sep,
1597
+ // Context-specific variables
1598
+ __dirname: context.isDxt && context.extensionDir ? context.extensionDir : context.entryDir || context.cwd || process.cwd(),
1599
+ // DXT-specific variables
1600
+ ...context.isDxt && context.extensionDir && {
1601
+ DXT_DIR: context.extensionDir,
1602
+ EXTENSION_DIR: context.extensionDir
1603
+ },
1604
+ // Custom variables override defaults
1605
+ ...config == null ? void 0 : config.customVariables
1606
+ };
1607
+ return inputPath.replace(/\$\{([^}]*)\}/g, (match, variableName) => {
1608
+ if (!variableName.trim()) {
1609
+ if (config == null ? void 0 : config.allowUndefined) {
1610
+ return match;
1611
+ }
1612
+ throw new Error(
1613
+ `Undefined DXT variable: ${variableName}. Available variables: ${Object.keys(variables).join(", ")}`
1614
+ );
1615
+ }
1616
+ const value = variables[variableName];
1617
+ if (value !== void 0) {
1618
+ return value;
1619
+ }
1620
+ if (config == null ? void 0 : config.allowUndefined) {
1621
+ return match;
1622
+ }
1623
+ throw new Error(
1624
+ `Undefined DXT variable: ${variableName}. Available variables: ${Object.keys(variables).join(", ")}`
1625
+ );
1626
+ });
1627
+ }
1628
+ /**
1629
+ * Creates a path for user data storage
1630
+ * @param filename - Name of the file or subdirectory
1631
+ * @param context - Optional context (will be detected if not provided)
1632
+ * @returns Absolute path for user data
1633
+ */
1634
+ static createUserDataPath(filename, context) {
1635
+ const ctx = context || this.detectContext();
1636
+ if (ctx.isDxt && ctx.extensionDir) {
1637
+ return path__namespace.join(ctx.extensionDir, "data", filename);
1638
+ } else {
1639
+ const safeHomedir = () => "/tmp";
1640
+ const userDataDir = process.env["XDG_DATA_HOME"] || path__namespace.join(ctx.userHome || safeHomedir(), ".local", "share");
1641
+ const appName = this.getAppName(ctx);
1642
+ return path__namespace.join(userDataDir, appName, filename);
1643
+ }
1644
+ }
1645
+ /**
1646
+ * Creates a path for temporary files
1647
+ * @param filename - Name of the temporary file
1648
+ * @param context - Optional context (will be detected if not provided)
1649
+ * @returns Absolute path for temporary file
1650
+ */
1651
+ static createTempPath(filename, context) {
1652
+ const ctx = context || this.detectContext();
1653
+ if (ctx.isDxt && ctx.extensionDir) {
1654
+ return path__namespace.join(ctx.extensionDir, "temp", filename);
1655
+ } else {
1656
+ const safeTmpdir = () => "/tmp";
1657
+ const appName = this.getAppName(ctx);
1658
+ return path__namespace.join(safeTmpdir(), appName, filename);
1659
+ }
1660
+ }
1661
+ /**
1662
+ * Creates a path for configuration files
1663
+ * @param filename - Name of the configuration file
1664
+ * @param context - Optional context (will be detected if not provided)
1665
+ * @returns Absolute path for configuration file
1666
+ */
1667
+ static createConfigPath(filename, context) {
1668
+ const ctx = context || this.detectContext();
1669
+ if (ctx.isDxt && ctx.extensionDir) {
1670
+ return path__namespace.join(ctx.extensionDir, "config", filename);
1671
+ } else {
1672
+ const safeHomedir = () => "/tmp";
1673
+ const configDir = process.env["XDG_CONFIG_HOME"] || path__namespace.join(ctx.userHome || safeHomedir(), ".config");
1674
+ const appName = this.getAppName(ctx);
1675
+ return path__namespace.join(configDir, appName, filename);
1676
+ }
1677
+ }
1678
+ /**
1679
+ * Gets the application name for directory creation
1680
+ * @param context - Path context
1681
+ * @returns Application name or default
1682
+ */
1683
+ static getAppName(context) {
1684
+ try {
1685
+ const packageJsonPath = path__namespace.join(context.entryDir || context.cwd || process.cwd(), "package.json");
1686
+ if (fs__namespace.existsSync(packageJsonPath)) {
1687
+ const packageJson = JSON.parse(fs__namespace.readFileSync(packageJsonPath, "utf-8"));
1688
+ return packageJson.name || "argparser-app";
1689
+ }
1690
+ } catch {
1691
+ }
1692
+ return "argparser-app";
1693
+ }
1694
+ /**
1695
+ * Ensures a directory exists, creating it if necessary
1696
+ * @param dirPath - Directory path to ensure
1697
+ * @returns True if directory exists or was created successfully
1698
+ */
1699
+ static ensureDirectory(dirPath) {
1700
+ try {
1701
+ if (!fs__namespace.existsSync(dirPath)) {
1702
+ fs__namespace.mkdirSync(dirPath, { recursive: true });
1703
+ }
1704
+ return true;
1705
+ } catch (error) {
1706
+ console.warn(`Failed to create directory: ${dirPath}`, error);
1707
+ return false;
1708
+ }
1709
+ }
1710
+ /**
1711
+ * Clears the cached context (useful for testing)
1712
+ */
1713
+ static clearCache() {
1714
+ this._cachedContext = null;
1715
+ }
1716
+ };
1717
+ _DxtPathResolver._cachedContext = null;
1718
+ let DxtPathResolver = _DxtPathResolver;
1347
1719
  class DxtGenerator {
1348
1720
  constructor(argParserInstance) {
1349
1721
  this.argParserInstance = argParserInstance;
@@ -1753,100 +2125,128 @@ class DxtGenerator {
1753
2125
  silent: process.env["NO_SILENCE"] !== "1",
1754
2126
  unbundle: true,
1755
2127
  external: (id, importer) => {
1756
- const external = this.shouldModuleBeExternal(
1757
- id,
1758
- importer,
1759
- withNodeModules
1760
- );
1761
- if (Boolean(process.env["DEBUG"]))
1762
- console.log(
1763
- `[${simpleChalk.blue("External")}] ${simpleChalk.yellow(external ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2128
+ try {
2129
+ const external = this.shouldModuleBeExternal(
2130
+ id,
2131
+ importer,
2132
+ withNodeModules
1764
2133
  );
1765
- return external;
2134
+ if (Boolean(process.env["DEBUG"]))
2135
+ console.log(
2136
+ `[${simpleChalk.blue("External")}] ${simpleChalk.yellow(external ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2137
+ );
2138
+ return Boolean(external);
2139
+ } catch (error) {
2140
+ console.warn(`Warning: Error in external function for ${id}:`, error);
2141
+ return true;
2142
+ }
1766
2143
  },
1767
2144
  noExternal: (id, importer) => {
1768
- const external = this.shouldModuleBeExternal(
1769
- id,
1770
- importer,
1771
- withNodeModules
1772
- );
1773
- if (Boolean(process.env["DEBUG"]))
1774
- console.log(
1775
- `[${simpleChalk.yellow("noExternal")}] ${simpleChalk.yellow(external === false ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2145
+ try {
2146
+ const external = this.shouldModuleBeExternal(
2147
+ id,
2148
+ importer,
2149
+ withNodeModules
1776
2150
  );
1777
- return external === false;
2151
+ if (Boolean(process.env["DEBUG"]))
2152
+ console.log(
2153
+ `[${simpleChalk.yellow("noExternal")}] ${simpleChalk.yellow(external === false ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2154
+ );
2155
+ return Boolean(external === false);
2156
+ } catch (error) {
2157
+ console.warn(`Warning: Error in noExternal function for ${id}:`, error);
2158
+ return false;
2159
+ }
1778
2160
  },
1779
2161
  copy: async (options) => {
1780
2162
  var _a2;
1781
- const outputPaths = [
1782
- "package.json"
1783
- ];
1784
- if (withNodeModules) {
1785
- console.log(
1786
- simpleChalk.gray(
1787
- "📦 Including node_modules in bundle (may take longer)..."
1788
- )
1789
- );
1790
- outputPaths.push("node_modules");
1791
- }
1792
- const dxtPackageRoot = entryDir !== "." && entryDir !== "" ? path__namespace.dirname(options.outDir) : options.outDir;
1793
- if (logoFilename) {
1794
- const currentDir = typeof process !== "undefined" ? process.cwd() : "/test";
1795
- const logoPath = path__namespace.join(currentDir, logoFilename);
1796
- if (fs__namespace.existsSync(logoPath)) {
1797
- console.log(simpleChalk.gray(`Adding logo from: ${logoPath}`));
1798
- outputPaths.push({
1799
- from: logoPath,
1800
- to: path__namespace.join(dxtPackageRoot, logoFilename)
1801
- });
2163
+ try {
2164
+ const outputPaths = [
2165
+ "package.json"
2166
+ ];
2167
+ if (withNodeModules) {
2168
+ console.log(
2169
+ simpleChalk.gray(
2170
+ "📦 Including node_modules in bundle (may take longer)..."
2171
+ )
2172
+ );
2173
+ outputPaths.push("node_modules");
1802
2174
  }
1803
- }
1804
- if ((_a2 = mcpConfig == null ? void 0 : mcpConfig.dxt) == null ? void 0 : _a2.include) {
1805
- console.log(
1806
- simpleChalk.gray(
1807
- "📁 Including additional files from DXT configuration..."
1808
- )
1809
- );
1810
- for (const includeItem of mcpConfig.dxt.include) {
1811
- if (typeof includeItem === "string") {
1812
- const sourcePath = path__namespace.resolve(projectRoot, includeItem);
1813
- if (fs__namespace.existsSync(sourcePath)) {
1814
- console.log(simpleChalk.gray(` • ${includeItem}`));
1815
- outputPaths.push({
1816
- from: sourcePath,
1817
- to: path__namespace.join(dxtPackageRoot, includeItem)
1818
- });
1819
- } else {
1820
- console.warn(
1821
- simpleChalk.yellow(
1822
- ` ⚠ File not found: ${includeItem} (resolved to ${sourcePath})`
1823
- )
1824
- );
1825
- }
1826
- } else {
1827
- const sourcePath = path__namespace.resolve(
1828
- projectRoot,
1829
- includeItem.from
1830
- );
1831
- if (fs__namespace.existsSync(sourcePath)) {
1832
- console.log(
1833
- simpleChalk.gray(` • ${includeItem.from} → ${includeItem.to}`)
2175
+ const dxtPackageRoot = entryDir !== "." && entryDir !== "" ? path__namespace.dirname(options.outDir) : options.outDir;
2176
+ if (logoFilename) {
2177
+ const currentDir = typeof process !== "undefined" ? process.cwd() : "/test";
2178
+ const logoPath = path__namespace.join(currentDir, logoFilename);
2179
+ if (fs__namespace.existsSync(logoPath)) {
2180
+ console.log(simpleChalk.gray(`Adding logo from: ${logoPath}`));
2181
+ outputPaths.push({
2182
+ from: logoPath,
2183
+ to: path__namespace.join(dxtPackageRoot, logoFilename)
2184
+ });
2185
+ }
2186
+ }
2187
+ if ((_a2 = mcpConfig == null ? void 0 : mcpConfig.dxt) == null ? void 0 : _a2.include) {
2188
+ console.log(
2189
+ simpleChalk.gray(
2190
+ "📁 Including additional files from DXT configuration..."
2191
+ )
2192
+ );
2193
+ for (const includeItem of mcpConfig.dxt.include) {
2194
+ if (typeof includeItem === "string") {
2195
+ const resolvedIncludePath = DxtPathResolver.substituteVariables(
2196
+ includeItem,
2197
+ DxtPathResolver.detectContext(),
2198
+ { allowUndefined: true }
2199
+ // Allow undefined variables for flexibility
1834
2200
  );
1835
- outputPaths.push({
1836
- from: sourcePath,
1837
- to: path__namespace.join(dxtPackageRoot, includeItem.to)
1838
- });
2201
+ const sourcePath = path__namespace.resolve(projectRoot, resolvedIncludePath);
2202
+ if (fs__namespace.existsSync(sourcePath)) {
2203
+ console.log(simpleChalk.gray(` • ${resolvedIncludePath}`));
2204
+ outputPaths.push({
2205
+ from: sourcePath,
2206
+ to: path__namespace.join(dxtPackageRoot, resolvedIncludePath)
2207
+ });
2208
+ } else {
2209
+ console.warn(
2210
+ simpleChalk.yellow(
2211
+ ` ⚠ File not found: ${resolvedIncludePath} (resolved to ${sourcePath})`
2212
+ )
2213
+ );
2214
+ }
1839
2215
  } else {
1840
- console.warn(
1841
- simpleChalk.yellow(
1842
- ` ⚠ File not found: ${includeItem.from} (resolved to ${sourcePath})`
1843
- )
2216
+ const resolvedFromPath = DxtPathResolver.substituteVariables(
2217
+ includeItem.from,
2218
+ DxtPathResolver.detectContext(),
2219
+ { allowUndefined: true }
2220
+ );
2221
+ const resolvedToPath = DxtPathResolver.substituteVariables(
2222
+ includeItem.to,
2223
+ DxtPathResolver.detectContext(),
2224
+ { allowUndefined: true }
1844
2225
  );
2226
+ const sourcePath = path__namespace.resolve(projectRoot, resolvedFromPath);
2227
+ if (fs__namespace.existsSync(sourcePath)) {
2228
+ console.log(
2229
+ simpleChalk.gray(` • ${resolvedFromPath} → ${resolvedToPath}`)
2230
+ );
2231
+ outputPaths.push({
2232
+ from: sourcePath,
2233
+ to: path__namespace.join(dxtPackageRoot, resolvedToPath)
2234
+ });
2235
+ } else {
2236
+ console.warn(
2237
+ simpleChalk.yellow(
2238
+ ` ⚠ File not found: ${resolvedFromPath} (resolved to ${sourcePath})`
2239
+ )
2240
+ );
2241
+ }
1845
2242
  }
1846
2243
  }
1847
2244
  }
2245
+ return outputPaths;
2246
+ } catch (error) {
2247
+ console.warn(`Warning: Error in copy function:`, error);
2248
+ return ["package.json"];
1848
2249
  }
1849
- return outputPaths;
1850
2250
  },
1851
2251
  platform: "node",
1852
2252
  plugins: []
@@ -1874,8 +2274,18 @@ export default ${JSON.stringify(buildConfig, null, 2)};
1874
2274
  simpleChalk.gray("📝 Debug config written to dxt/tsdown.config.dxt.ts")
1875
2275
  );
1876
2276
  }
1877
- await build(buildConfig);
1878
- console.log(simpleChalk.green("✅ TSDown bundling completed"));
2277
+ try {
2278
+ await build(buildConfig);
2279
+ console.log(simpleChalk.green("✅ TSDown bundling completed"));
2280
+ } catch (buildError) {
2281
+ console.error(simpleChalk.red("❌ TSDown build failed with error:"));
2282
+ console.error(buildError);
2283
+ if (buildError instanceof Error) {
2284
+ console.error(simpleChalk.red("Error message:"), buildError.message);
2285
+ console.error(simpleChalk.red("Error stack:"), buildError.stack);
2286
+ }
2287
+ throw new Error(`TSDown DXT build failed: ${buildError instanceof Error ? buildError.message : String(buildError)}`);
2288
+ }
1879
2289
  const detectedOutputFile = this.detectTsdownOutputFile(
1880
2290
  outputDir,
1881
2291
  relativeEntryPath.replace(/\.ts$/, ".js")
@@ -2134,7 +2544,7 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2134
2544
  if (flag.enum) {
2135
2545
  properties2[flag.name].enum = flag.enum;
2136
2546
  }
2137
- if (flag.defaultValue !== void 0) {
2547
+ if (flag.defaultValue !== void 0 && typeof flag.defaultValue !== "function") {
2138
2548
  properties2[flag.name].default = flag.defaultValue;
2139
2549
  }
2140
2550
  if (flag.mandatory) {
@@ -2309,11 +2719,62 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2309
2719
  `Could not find package.json within ${maxAttempts} directories up from ${entryPointFile}. Please ensure your entry point is within a project that has a package.json file.`
2310
2720
  );
2311
2721
  }
2722
+ /**
2723
+ * Validate dxtOptions for common mistakes and security issues
2724
+ * @param flag The flag with dxtOptions to validate
2725
+ * @param envVar The environment variable name for context
2726
+ */
2727
+ validateDxtOptions(flag, envVar) {
2728
+ const dxtOptions = flag.dxtOptions;
2729
+ if (!dxtOptions) return;
2730
+ if (dxtOptions.min !== void 0 && dxtOptions.max !== void 0) {
2731
+ if (dxtOptions.min > dxtOptions.max) {
2732
+ throw new Error(
2733
+ `Invalid dxtOptions for ${envVar}: min (${dxtOptions.min}) cannot be greater than max (${dxtOptions.max})`
2734
+ );
2735
+ }
2736
+ }
2737
+ if (dxtOptions.type !== void 0) {
2738
+ const validTypes = ["string", "directory", "file", "boolean", "number"];
2739
+ if (!validTypes.includes(dxtOptions.type)) {
2740
+ throw new Error(
2741
+ `Invalid dxtOptions.type for ${envVar}: "${dxtOptions.type}". Must be one of: ${validTypes.join(", ")}`
2742
+ );
2743
+ }
2744
+ }
2745
+ if (dxtOptions.default !== void 0 && dxtOptions.type !== void 0) {
2746
+ const defaultType = typeof dxtOptions.default;
2747
+ if (dxtOptions.type === "number" && defaultType !== "number") {
2748
+ throw new Error(
2749
+ `Invalid dxtOptions.default for ${envVar}: expected number, got ${defaultType}`
2750
+ );
2751
+ }
2752
+ if (dxtOptions.type === "boolean" && defaultType !== "boolean") {
2753
+ throw new Error(
2754
+ `Invalid dxtOptions.default for ${envVar}: expected boolean, got ${defaultType}`
2755
+ );
2756
+ }
2757
+ }
2758
+ const sensitiveKeywords = ["key", "token", "password", "secret", "auth"];
2759
+ const envLower = envVar.toLowerCase();
2760
+ const hasSensitiveKeyword = sensitiveKeywords.some((keyword2) => envLower.includes(keyword2));
2761
+ if (hasSensitiveKeyword && dxtOptions.sensitive === false) {
2762
+ console.warn(
2763
+ `⚠️ Security Warning: ${envVar} contains sensitive keyword but dxtOptions.sensitive is false`
2764
+ );
2765
+ }
2766
+ if (flag.mandatory === true && dxtOptions.sensitive !== false) {
2767
+ console.warn(
2768
+ `⚠️ Security Warning: ${envVar} is required and sensitive - consider providing a secure default or making it optional`
2769
+ );
2770
+ }
2771
+ }
2312
2772
  /**
2313
2773
  * Generate environment variables and user configuration from ArgParser flags
2314
2774
  * @returns Object containing envVars and userConfig
2315
2775
  */
2316
2776
  generateEnvAndUserConfig() {
2777
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2317
2778
  const envVars = {};
2318
2779
  const userConfig = {};
2319
2780
  const shouldBeRequired = (flag) => {
@@ -2326,23 +2787,78 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2326
2787
  return false;
2327
2788
  };
2328
2789
  const shouldBeSensitive = (flag) => {
2790
+ var _a2;
2791
+ if (((_a2 = flag.dxtOptions) == null ? void 0 : _a2.sensitive) !== void 0) {
2792
+ return flag.dxtOptions.sensitive;
2793
+ }
2329
2794
  const envVar = flag.env || flag.envVar;
2330
2795
  return !!envVar;
2331
2796
  };
2797
+ const getDxtType = (flag) => {
2798
+ var _a2;
2799
+ if ((_a2 = flag.dxtOptions) == null ? void 0 : _a2.type) {
2800
+ return flag.dxtOptions.type;
2801
+ }
2802
+ if (typeof flag.type === "string") {
2803
+ const lowerType = flag.type.toLowerCase();
2804
+ if (["string", "boolean", "number"].includes(lowerType)) {
2805
+ return lowerType;
2806
+ }
2807
+ } else if (flag.type === String) {
2808
+ return "string";
2809
+ } else if (flag.type === Boolean) {
2810
+ return "boolean";
2811
+ } else if (flag.type === Number) {
2812
+ return "number";
2813
+ }
2814
+ return "string";
2815
+ };
2816
+ const getDxtTitle = (flag, envVar) => {
2817
+ var _a2;
2818
+ if ((_a2 = flag.dxtOptions) == null ? void 0 : _a2.title) {
2819
+ return flag.dxtOptions.title;
2820
+ }
2821
+ return envVar.replace(/_/g, " ").toLowerCase().replace(/\b\w/g, (l) => l.toUpperCase());
2822
+ };
2823
+ const getDxtDescription = (flag, envVar) => {
2824
+ var _a2, _b2;
2825
+ let baseDescription = flag.description || `${envVar} environment variable`;
2826
+ const defaultValue = ((_a2 = flag.dxtOptions) == null ? void 0 : _a2.default) ?? ((_b2 = flag.dxtOptions) == null ? void 0 : _b2.localDefault) ?? flag.defaultValue;
2827
+ if (defaultValue !== void 0 && typeof defaultValue !== "function") {
2828
+ baseDescription += ` (default: ${defaultValue})`;
2829
+ }
2830
+ return baseDescription;
2831
+ };
2332
2832
  const mainFlags = this.argParserInstance.flags;
2333
2833
  for (const flag of mainFlags) {
2334
2834
  const envVar = flag.env || flag.envVar;
2335
2835
  if (envVar) {
2836
+ this.validateDxtOptions(flag, envVar);
2336
2837
  envVars[envVar] = `\${user_config.${envVar}}`;
2337
- userConfig[envVar] = {
2338
- type: "string",
2339
- title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
2340
- description: flag.description || `${envVar} environment variable`,
2838
+ const userConfigEntry = {
2839
+ type: getDxtType(flag),
2840
+ title: getDxtTitle(flag, envVar),
2841
+ description: getDxtDescription(flag, envVar),
2341
2842
  required: shouldBeRequired(flag),
2342
2843
  // Respect the flag's mandatory setting
2343
2844
  sensitive: shouldBeSensitive(flag)
2344
- // Set to sensitive if tied to ENV
2845
+ // Use dxtOptions or default logic
2345
2846
  };
2847
+ if (((_a = flag.dxtOptions) == null ? void 0 : _a.multiple) !== void 0) {
2848
+ userConfigEntry.multiple = flag.dxtOptions.multiple;
2849
+ }
2850
+ if (((_b = flag.dxtOptions) == null ? void 0 : _b.min) !== void 0) {
2851
+ userConfigEntry.min = flag.dxtOptions.min;
2852
+ }
2853
+ if (((_c = flag.dxtOptions) == null ? void 0 : _c.max) !== void 0) {
2854
+ userConfigEntry.max = flag.dxtOptions.max;
2855
+ }
2856
+ if (((_d = flag.dxtOptions) == null ? void 0 : _d.default) !== void 0 && typeof flag.dxtOptions.default !== "function") {
2857
+ userConfigEntry.default = flag.dxtOptions.default;
2858
+ } else if (((_e = flag.dxtOptions) == null ? void 0 : _e.localDefault) !== void 0 && typeof flag.dxtOptions.localDefault !== "function") {
2859
+ userConfigEntry.default = flag.dxtOptions.localDefault;
2860
+ }
2861
+ userConfig[envVar] = userConfigEntry;
2346
2862
  }
2347
2863
  }
2348
2864
  if (typeof this.argParserInstance.getTools === "function") {
@@ -2352,16 +2868,32 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2352
2868
  for (const flag of toolFlags) {
2353
2869
  const envVar = flag.env || flag.envVar;
2354
2870
  if (envVar && !envVars[envVar]) {
2871
+ this.validateDxtOptions(flag, envVar);
2355
2872
  envVars[envVar] = `\${user_config.${envVar}}`;
2356
- userConfig[envVar] = {
2357
- type: "string",
2358
- title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
2359
- description: flag.description || `${envVar} environment variable`,
2873
+ const userConfigEntry = {
2874
+ type: getDxtType(flag),
2875
+ title: getDxtTitle(flag, envVar),
2876
+ description: getDxtDescription(flag, envVar),
2360
2877
  required: shouldBeRequired(flag),
2361
2878
  // Respect the flag's mandatory setting
2362
2879
  sensitive: shouldBeSensitive(flag)
2363
- // Set to sensitive if tied to ENV
2880
+ // Use dxtOptions or default logic
2364
2881
  };
2882
+ if (((_f = flag.dxtOptions) == null ? void 0 : _f.multiple) !== void 0) {
2883
+ userConfigEntry.multiple = flag.dxtOptions.multiple;
2884
+ }
2885
+ if (((_g = flag.dxtOptions) == null ? void 0 : _g.min) !== void 0) {
2886
+ userConfigEntry.min = flag.dxtOptions.min;
2887
+ }
2888
+ if (((_h = flag.dxtOptions) == null ? void 0 : _h.max) !== void 0) {
2889
+ userConfigEntry.max = flag.dxtOptions.max;
2890
+ }
2891
+ if (((_i = flag.dxtOptions) == null ? void 0 : _i.default) !== void 0 && typeof flag.dxtOptions.default !== "function") {
2892
+ userConfigEntry.default = flag.dxtOptions.default;
2893
+ } else if (((_j = flag.dxtOptions) == null ? void 0 : _j.localDefault) !== void 0 && typeof flag.dxtOptions.localDefault !== "function") {
2894
+ userConfigEntry.default = flag.dxtOptions.localDefault;
2895
+ }
2896
+ userConfig[envVar] = userConfigEntry;
2365
2897
  }
2366
2898
  }
2367
2899
  }
@@ -2392,10 +2924,10 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2392
2924
  );
2393
2925
  }
2394
2926
  const pathsMatcher = getTsconfig.createPathsMatcher(tsconfig);
2395
- if (!pathsMatcher) {
2927
+ if (!pathsMatcher || typeof pathsMatcher !== "function") {
2396
2928
  if (Boolean(process.env["DEBUG"])) {
2397
2929
  console.log(
2398
- ` <${simpleChalk.gray("ts-paths")}> Failed to create paths matcher`
2930
+ ` <${simpleChalk.gray("ts-paths")}> Failed to create paths matcher or matcher is not a function`
2399
2931
  );
2400
2932
  }
2401
2933
  } else {
@@ -3105,7 +3637,8 @@ const _FlagManager = class _FlagManager {
3105
3637
  validate: parsedFromZod["validate"],
3106
3638
  enum: parsedFromZod["enum"],
3107
3639
  mandatory: parsedFromZod["mandatory"],
3108
- env: parsedFromZod["env"]
3640
+ env: parsedFromZod["env"],
3641
+ dxtOptions: parsedFromZod["dxtOptions"]
3109
3642
  };
3110
3643
  }
3111
3644
  addFlag(flag) {
@@ -3154,97 +3687,6 @@ const _FlagManager = class _FlagManager {
3154
3687
  __flags = new WeakMap();
3155
3688
  _throwForDuplicateFlags = new WeakMap();
3156
3689
  let FlagManager = _FlagManager;
3157
- function detectEntryPoint() {
3158
- try {
3159
- if (process.argv[1] && fs__namespace.existsSync(process.argv[1])) {
3160
- return process.argv[1];
3161
- }
3162
- if (typeof require !== "undefined" && require.main && require.main.filename) {
3163
- return require.main.filename;
3164
- }
3165
- return null;
3166
- } catch {
3167
- return null;
3168
- }
3169
- }
3170
- function getEntryPointFromImportMeta(importMetaUrl) {
3171
- if (importMetaUrl.startsWith("file://")) {
3172
- return decodeURIComponent(importMetaUrl.replace("file://", ""));
3173
- }
3174
- return importMetaUrl;
3175
- }
3176
- function normalizePath(path2) {
3177
- return path2.trim();
3178
- }
3179
- function resolveLogPath(logPath, fallbackEntryPoint) {
3180
- if (typeof logPath === "string") {
3181
- const normalizedPath2 = normalizePath(logPath);
3182
- if (path__namespace.isAbsolute(normalizedPath2)) {
3183
- return normalizedPath2;
3184
- }
3185
- if (normalizedPath2.startsWith("cwd:")) {
3186
- const relativePath = normalizedPath2.slice(4);
3187
- return path__namespace.resolve(process.cwd(), relativePath);
3188
- }
3189
- const entryPoint = detectEntryPoint() || fallbackEntryPoint;
3190
- if (entryPoint) {
3191
- return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath2);
3192
- }
3193
- console.warn(
3194
- `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath2}`
3195
- );
3196
- return path__namespace.resolve(process.cwd(), normalizedPath2);
3197
- }
3198
- const { path: logFilePath, relativeTo = "entry", basePath } = logPath;
3199
- const normalizedPath = normalizePath(logFilePath);
3200
- switch (relativeTo) {
3201
- case "absolute":
3202
- if (basePath) {
3203
- return path__namespace.resolve(basePath, normalizedPath);
3204
- }
3205
- if (path__namespace.isAbsolute(normalizedPath)) {
3206
- return normalizedPath;
3207
- }
3208
- console.warn(
3209
- `Warning: relativeTo 'absolute' specified but no basePath provided and path is not absolute. Using process.cwd() as fallback. Path: ${normalizedPath}`
3210
- );
3211
- return path__namespace.resolve(process.cwd(), normalizedPath);
3212
- case "cwd":
3213
- return path__namespace.resolve(process.cwd(), normalizedPath);
3214
- case "entry":
3215
- default:
3216
- const entryPoint = detectEntryPoint() || fallbackEntryPoint;
3217
- if (entryPoint) {
3218
- return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath);
3219
- }
3220
- console.warn(
3221
- `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath}`
3222
- );
3223
- return path__namespace.resolve(process.cwd(), normalizedPath);
3224
- }
3225
- }
3226
- function entryRelative(path2) {
3227
- return {
3228
- path: path2,
3229
- relativeTo: "entry"
3230
- };
3231
- }
3232
- function cwdRelative(path2) {
3233
- return {
3234
- path: path2,
3235
- relativeTo: "cwd"
3236
- };
3237
- }
3238
- function absolutePath(path2, basePath) {
3239
- return {
3240
- path: path2,
3241
- relativeTo: "absolute",
3242
- basePath
3243
- };
3244
- }
3245
- function legacyCwdPath(path2) {
3246
- return `cwd:${path2}`;
3247
- }
3248
3690
  class ArgParserError extends Error {
3249
3691
  constructor(message, cmdChain = []) {
3250
3692
  super(message);
@@ -3511,22 +3953,41 @@ const _ArgParserBase = class _ArgParserBase {
3511
3953
  console.log("--- End Configuration Dump ---\\n");
3512
3954
  }
3513
3955
  }
3956
+ /**
3957
+ * Detects if the current script is being executed directly (not imported)
3958
+ * Uses a robust method that works across different environments and sandboxes
3959
+ * @param importMetaUrl The import.meta.url from the calling script (optional)
3960
+ * @returns true if the script is being executed directly, false if imported
3961
+ */
3962
+ static isExecutedDirectly(importMetaUrl) {
3963
+ try {
3964
+ if (importMetaUrl) {
3965
+ const currentFile = node_url.fileURLToPath(importMetaUrl);
3966
+ const executedFile = path__namespace.resolve(process.argv[1]);
3967
+ return currentFile === executedFile;
3968
+ }
3969
+ if (typeof process !== "undefined" && process.argv && process.argv[1]) {
3970
+ return false;
3971
+ }
3972
+ return false;
3973
+ } catch {
3974
+ return false;
3975
+ }
3976
+ }
3514
3977
  async parse(processArgs, options) {
3515
- var _a, _b;
3978
+ var _a;
3516
3979
  debug.log("ArgParserBase.parse() called with args:", processArgs);
3980
+ const shouldCheckAutoExecution = (options == null ? void 0 : options.importMetaUrl) && (options == null ? void 0 : options.autoExecute) !== false;
3981
+ if (shouldCheckAutoExecution) {
3982
+ const isDirectExecution = _ArgParserBase.isExecutedDirectly(options.importMetaUrl);
3983
+ if (!isDirectExecution) {
3984
+ debug.log("Auto-execution enabled but script is imported, skipping execution");
3985
+ return {};
3986
+ }
3987
+ }
3517
3988
  if (processArgs === void 0) {
3518
3989
  if (typeof process !== "undefined" && process.argv && Array.isArray(process.argv)) {
3519
3990
  processArgs = process.argv.slice(2);
3520
- const isCliMode = !__privateGet(this, _parentParser) && !!__privateGet(this, _appCommandName);
3521
- const isMcpMode = (options == null ? void 0 : options.isMcp) || ((_a = globalThis.console) == null ? void 0 : _a.mcpError);
3522
- if (isCliMode && !isMcpMode) {
3523
- console.warn(
3524
- `Warning: parse() called without arguments. Auto-detected Node.js environment and using process.argv.slice(2).`
3525
- );
3526
- console.warn(
3527
- `For explicit control, call parse(process.argv.slice(2)) instead.`
3528
- );
3529
- }
3530
3991
  } else {
3531
3992
  throw new Error(
3532
3993
  "parse() called without arguments in non-Node.js environment. Please provide arguments explicitly: parse(['--flag', 'value'])"
@@ -3551,7 +4012,7 @@ const _ArgParserBase = class _ArgParserBase {
3551
4012
  commandChain: identifiedCommandChain,
3552
4013
  parserChain: identifiedParserChain
3553
4014
  } = __privateMethod(this, _ArgParserBase_instances, _identifyCommandChainAndParsers_fn).call(this, processArgs, this, [], [this]);
3554
- const saveToEnvResult = __privateMethod(_b = identifiedFinalParser, _ArgParserBase_instances, _handleSaveToEnvFlag_fn).call(_b, processArgs, identifiedParserChain);
4015
+ const saveToEnvResult = __privateMethod(_a = identifiedFinalParser, _ArgParserBase_instances, _handleSaveToEnvFlag_fn).call(_a, processArgs, identifiedParserChain);
3555
4016
  if (saveToEnvResult !== false) {
3556
4017
  return saveToEnvResult === true ? {} : saveToEnvResult;
3557
4018
  }
@@ -4870,7 +5331,10 @@ _startUnifiedMcpServer_fn = async function(mcpServerConfig, transportOptions) {
4870
5331
  const finalTransportOptions = {
4871
5332
  port: transportOptions.port,
4872
5333
  host: transportOptions.host || "localhost",
4873
- path: transportOptions.path || "/mcp"
5334
+ path: transportOptions.path || "/mcp",
5335
+ // Pass-through for streamable-http only; harmlessly ignored for others
5336
+ cors: transportOptions.cors,
5337
+ auth: transportOptions.auth
4874
5338
  };
4875
5339
  await mcpParser.startMcpServerWithTransport(
4876
5340
  serverInfo,
@@ -4978,6 +5442,27 @@ _parseMcpTransportOptions_fn = function(processArgs) {
4978
5442
  i++;
4979
5443
  }
4980
5444
  break;
5445
+ // Streamable HTTP extras (accept JSON string)
5446
+ case "--s-mcp-cors":
5447
+ if (nextArg && !nextArg.startsWith("-")) {
5448
+ try {
5449
+ options.cors = JSON.parse(nextArg);
5450
+ } catch {
5451
+ options.cors = nextArg;
5452
+ }
5453
+ i++;
5454
+ }
5455
+ break;
5456
+ case "--s-mcp-auth":
5457
+ if (nextArg && !nextArg.startsWith("-")) {
5458
+ try {
5459
+ options.auth = JSON.parse(nextArg);
5460
+ } catch {
5461
+ options.auth = nextArg;
5462
+ }
5463
+ i++;
5464
+ }
5465
+ break;
4981
5466
  // Backward compatibility: support old flags but with deprecation warning
4982
5467
  case "--transport":
4983
5468
  case "--port":
@@ -7015,6 +7500,34 @@ Migration guide: https://github.com/alcyone-labs/arg-parser/blob/main/docs/MCP-M
7015
7500
  parseAsync(processArgs, options) {
7016
7501
  return this.parse(processArgs, options);
7017
7502
  }
7503
+ /**
7504
+ * Convenience method for auto-execution: only runs if the script is executed directly (not imported).
7505
+ * This eliminates the need for boilerplate code to check if the script is being run directly.
7506
+ *
7507
+ * @param importMetaUrl Pass import.meta.url from your script for reliable detection
7508
+ * @param processArgs Optional arguments to parse (defaults to process.argv.slice(2))
7509
+ * @param options Additional parse options
7510
+ * @returns Promise that resolves to the parse result, or empty object if script is imported
7511
+ *
7512
+ * @example
7513
+ * ```typescript
7514
+ * // At the bottom of your CLI script:
7515
+ * await cli.parseIfExecutedDirectly(import.meta.url);
7516
+ *
7517
+ * // With error handling:
7518
+ * await cli.parseIfExecutedDirectly(import.meta.url).catch((error) => {
7519
+ * console.error("Fatal error:", error instanceof Error ? error.message : String(error));
7520
+ * process.exit(1);
7521
+ * });
7522
+ * ```
7523
+ */
7524
+ async parseIfExecutedDirectly(importMetaUrl, processArgs, options) {
7525
+ return this.parse(processArgs, {
7526
+ ...options,
7527
+ autoExecute: true,
7528
+ importMetaUrl
7529
+ });
7530
+ }
7018
7531
  addMcpSubCommand(subCommandName = "mcp-server", serverInfo, optionsOrToolOptions) {
7019
7532
  console.warn(`[DEPRECATED] addMcpSubCommand() is deprecated and will be removed in v2.0.
7020
7533
  Please use withMcp() to configure server metadata and the --s-mcp-serve system flag instead.
@@ -7293,6 +7806,7 @@ registerToolAsSubCommand_fn = function(toolConfig) {
7293
7806
  });
7294
7807
  };
7295
7808
  _startSingleTransport_fn = async function(server, serverInfo, transportConfig, logPath) {
7809
+ var _a, _b, _c, _d, _e, _f;
7296
7810
  const resolvedLogPath = resolveLogPath(logPath || "./logs/mcp.log");
7297
7811
  const logger = simpleMcpLogger.createMcpLogger("MCP Transport", resolvedLogPath);
7298
7812
  try {
@@ -7336,10 +7850,142 @@ _startSingleTransport_fn = async function(server, serverInfo, transportConfig, l
7336
7850
  const express = (await import("express")).default;
7337
7851
  const app = express();
7338
7852
  app.use(express.json());
7853
+ try {
7854
+ (_c = (_b = (_a = this._mcpServerConfig) == null ? void 0 : _a.httpServer) == null ? void 0 : _b.configureExpress) == null ? void 0 : _c.call(_b, app);
7855
+ } catch (e) {
7856
+ }
7339
7857
  const port = transportConfig.port || 3e3;
7340
7858
  const path2 = transportConfig.path || "/mcp";
7859
+ if (transportConfig.cors) {
7860
+ const cors = transportConfig.cors;
7861
+ const allowMethods = ((_d = cors.methods) == null ? void 0 : _d.join(", ")) || "GET,POST,PUT,PATCH,DELETE,OPTIONS";
7862
+ const allowHeaders = (req) => {
7863
+ var _a2;
7864
+ return ((_a2 = cors.headers) == null ? void 0 : _a2.join(", ")) || req.headers["access-control-request-headers"] || "Content-Type, Authorization, MCP-Session-Id";
7865
+ };
7866
+ const exposed = ((_e = cors.exposedHeaders) == null ? void 0 : _e.join(", ")) || void 0;
7867
+ const resolveOrigin = (req) => {
7868
+ const reqOrigin = req.headers.origin;
7869
+ const origins = cors.origins ?? "*";
7870
+ if (origins === "*") return cors.credentials ? reqOrigin : "*";
7871
+ if (!reqOrigin) return void 0;
7872
+ const list = Array.isArray(origins) ? origins : [origins];
7873
+ for (const o of list) {
7874
+ if (typeof o === "string" && o === reqOrigin) return reqOrigin;
7875
+ if (o instanceof RegExp && o.test(reqOrigin)) return reqOrigin;
7876
+ }
7877
+ return void 0;
7878
+ };
7879
+ const applyCorsHeaders = (req, res) => {
7880
+ const origin = resolveOrigin(req);
7881
+ if (origin) res.setHeader("Access-Control-Allow-Origin", origin);
7882
+ if (cors.credentials) res.setHeader("Access-Control-Allow-Credentials", "true");
7883
+ res.setHeader("Vary", "Origin");
7884
+ res.setHeader("Access-Control-Allow-Methods", allowMethods);
7885
+ const hdrs = allowHeaders(req);
7886
+ if (hdrs) res.setHeader("Access-Control-Allow-Headers", hdrs);
7887
+ if (exposed) res.setHeader("Access-Control-Expose-Headers", exposed);
7888
+ if (typeof cors.maxAge === "number") res.setHeader("Access-Control-Max-Age", String(cors.maxAge));
7889
+ };
7890
+ app.options(path2, (req, res) => {
7891
+ applyCorsHeaders(req, res);
7892
+ res.status(204).end();
7893
+ });
7894
+ app.use((req, res, next) => {
7895
+ if (req.path === path2) applyCorsHeaders(req, res);
7896
+ next();
7897
+ });
7898
+ }
7899
+ if ((_f = transportConfig.auth) == null ? void 0 : _f.customMiddleware) {
7900
+ app.use(transportConfig.auth.customMiddleware);
7901
+ }
7902
+ const authOpts = transportConfig.auth;
7903
+ const shouldRequireAuthFor = (req) => {
7904
+ if (!authOpts) return false;
7905
+ const reqPath = req.path;
7906
+ const pub = authOpts.publicPaths || [];
7907
+ const prot = authOpts.protectedPaths;
7908
+ if (pub.includes(reqPath)) return false;
7909
+ if (prot && !prot.includes(reqPath)) return false;
7910
+ return authOpts.required !== false;
7911
+ };
7912
+ const base64urlDecode = (s) => Buffer.from(s.replace(/-/g, "+").replace(/_/g, "/"), "base64");
7913
+ const verifyJwt = async (token) => {
7914
+ if (!(authOpts == null ? void 0 : authOpts.jwt)) return false;
7915
+ const [h, p, sig] = token.split(".");
7916
+ if (!h || !p || !sig) return false;
7917
+ const header = JSON.parse(base64urlDecode(h).toString("utf8"));
7918
+ const payload = JSON.parse(base64urlDecode(p).toString("utf8"));
7919
+ const alg = header.alg;
7920
+ if (authOpts.jwt.algorithms && !authOpts.jwt.algorithms.includes(alg)) return false;
7921
+ const data2 = Buffer.from(`${h}.${p}`);
7922
+ const signature = base64urlDecode(sig);
7923
+ if (alg === "HS256") {
7924
+ const secret = authOpts.jwt.secret;
7925
+ if (!secret) return false;
7926
+ const hmac = (await import("node:crypto")).createHmac("sha256", secret).update(data2).digest();
7927
+ if (!hmac.equals(signature)) return false;
7928
+ } else if (alg === "RS256") {
7929
+ const crypto = await import("node:crypto");
7930
+ let key = authOpts.jwt.publicKey;
7931
+ if (!key && authOpts.jwt.getPublicKey) {
7932
+ key = await authOpts.jwt.getPublicKey(header, payload);
7933
+ }
7934
+ if (!key) return false;
7935
+ const verify = crypto.createVerify("RSA-SHA256");
7936
+ verify.update(data2);
7937
+ verify.end();
7938
+ const ok = verify.verify(key, signature);
7939
+ if (!ok) return false;
7940
+ } else {
7941
+ return false;
7942
+ }
7943
+ if (authOpts.jwt.audience) {
7944
+ const allowed = Array.isArray(authOpts.jwt.audience) ? authOpts.jwt.audience : [authOpts.jwt.audience];
7945
+ if (!allowed.includes(payload.aud)) return false;
7946
+ }
7947
+ if (authOpts.jwt.issuer) {
7948
+ const allowed = Array.isArray(authOpts.jwt.issuer) ? authOpts.jwt.issuer : [authOpts.jwt.issuer];
7949
+ if (!allowed.includes(payload.iss)) return false;
7950
+ }
7951
+ const nowSec = Math.floor(Date.now() / 1e3);
7952
+ const tol = authOpts.jwt.clockToleranceSec || 0;
7953
+ if (payload.nbf && nowSec + tol < payload.nbf) return false;
7954
+ if (payload.exp && nowSec - tol >= payload.exp) return false;
7955
+ return true;
7956
+ };
7957
+ const authenticate = async (req) => {
7958
+ if (!authOpts) return true;
7959
+ const authz = req.headers.authorization;
7960
+ const token = (authz == null ? void 0 : authz.startsWith("Bearer ")) ? authz.slice(7) : void 0;
7961
+ if (!token) {
7962
+ if (authOpts.validator) return !!await authOpts.validator(req, token);
7963
+ return false;
7964
+ }
7965
+ if (authOpts.scheme === "jwt" || authOpts.jwt) {
7966
+ const ok = await verifyJwt(token);
7967
+ if (!ok) return false;
7968
+ } else if (authOpts.scheme === "bearer" || !authOpts.scheme) {
7969
+ if (authOpts.allowedTokens && !authOpts.allowedTokens.includes(token)) {
7970
+ if (authOpts.validator) return !!await authOpts.validator(req, token);
7971
+ return false;
7972
+ }
7973
+ }
7974
+ if (authOpts.validator) {
7975
+ const ok = await authOpts.validator(req, token);
7976
+ if (!ok) return false;
7977
+ }
7978
+ return true;
7979
+ };
7341
7980
  const transports = {};
7342
7981
  app.all(path2, async (req, res) => {
7982
+ if (shouldRequireAuthFor(req)) {
7983
+ const ok = await authenticate(req);
7984
+ if (!ok) {
7985
+ res.status(401).json({ error: "Unauthorized" });
7986
+ return;
7987
+ }
7988
+ }
7343
7989
  const sessionId = req.headers["mcp-session-id"];
7344
7990
  let transport;
7345
7991
  if (sessionId && transports[sessionId]) {
@@ -7352,9 +7998,7 @@ _startSingleTransport_fn = async function(server, serverInfo, transportConfig, l
7352
7998
  }
7353
7999
  });
7354
8000
  transport.onclose = () => {
7355
- if (transport.sessionId) {
7356
- delete transports[transport.sessionId];
7357
- }
8001
+ if (transport.sessionId) delete transports[transport.sessionId];
7358
8002
  };
7359
8003
  await server.connect(transport);
7360
8004
  }
@@ -25030,6 +25674,7 @@ exports.ArgParserFuzzyTester = ArgParserFuzzyTester;
25030
25674
  exports.ArgParserMcp = ArgParserMcp;
25031
25675
  exports.ConfigPlugin = ConfigPlugin;
25032
25676
  exports.ConfigPluginRegistry = ConfigPluginRegistry;
25677
+ exports.DxtPathResolver = DxtPathResolver;
25033
25678
  exports.EnvConfigPlugin = EnvConfigPlugin;
25034
25679
  exports.JsonConfigPlugin = JsonConfigPlugin;
25035
25680
  exports.OutputSchemaPatterns = OutputSchemaPatterns;
@@ -25064,5 +25709,6 @@ exports.isValidMcpToolName = isValidMcpToolName;
25064
25709
  exports.legacyCwdPath = legacyCwdPath;
25065
25710
  exports.resolveLogPath = resolveLogPath;
25066
25711
  exports.sanitizeMcpToolName = sanitizeMcpToolName;
25712
+ exports.zodDxtOptionsSchema = zodDxtOptionsSchema;
25067
25713
  exports.zodFlagSchema = zodFlagSchema;
25068
25714
  //# sourceMappingURL=index.cjs.map