@alcyone-labs/arg-parser 2.2.0 → 2.3.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/README.md +226 -20
- package/dist/assets/.dxtignore.template +0 -1
- package/dist/config/ConfigurationManager.d.ts.map +1 -1
- package/dist/config/plugins/ConfigPlugin.d.ts.map +1 -1
- package/dist/config/plugins/ConfigPluginRegistry.d.ts +1 -1
- package/dist/config/plugins/ConfigPluginRegistry.d.ts.map +1 -1
- package/dist/config/plugins/TomlConfigPlugin.d.ts +1 -1
- package/dist/config/plugins/TomlConfigPlugin.d.ts.map +1 -1
- package/dist/config/plugins/YamlConfigPlugin.d.ts +1 -1
- package/dist/config/plugins/YamlConfigPlugin.d.ts.map +1 -1
- package/dist/config/plugins/index.d.ts +4 -4
- package/dist/config/plugins/index.d.ts.map +1 -1
- package/dist/core/ArgParser.d.ts +14 -3
- package/dist/core/ArgParser.d.ts.map +1 -1
- package/dist/core/ArgParserBase.d.ts.map +1 -1
- package/dist/core/log-path-utils.d.ts +59 -0
- package/dist/core/log-path-utils.d.ts.map +1 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/dxt/DxtGenerator-testUtils.d.ts +22 -0
- package/dist/dxt/DxtGenerator-testUtils.d.ts.map +1 -0
- package/dist/dxt/DxtGenerator.d.ts +11 -65
- package/dist/dxt/DxtGenerator.d.ts.map +1 -1
- package/dist/index.cjs +799 -1260
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.min.mjs +6303 -6736
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +799 -1260
- package/dist/index.mjs.map +1 -1
- package/dist/mcp/ArgParserMcp.d.ts.map +1 -1
- package/dist/mcp/mcp-notifications.d.ts +4 -4
- package/dist/mcp/mcp-notifications.d.ts.map +1 -1
- package/dist/mcp/mcp-prompts.d.ts.map +1 -1
- package/dist/mcp/mcp-protocol-versions.d.ts +11 -11
- package/dist/mcp/mcp-protocol-versions.d.ts.map +1 -1
- package/dist/mcp/mcp-resources.d.ts.map +1 -1
- package/dist/testing/fuzzy-test-cli.d.ts.map +1 -1
- package/dist/testing/fuzzy-tester.d.ts.map +1 -1
- package/package.json +2 -3
- package/dist/assets/tsdown.dxt.config.ts +0 -37
package/dist/index.cjs
CHANGED
|
@@ -325,7 +325,9 @@ class JsonConfigPlugin extends ConfigPlugin {
|
|
|
325
325
|
const { _meta, ...config } = parsed;
|
|
326
326
|
return config;
|
|
327
327
|
} catch (error) {
|
|
328
|
-
throw new Error(
|
|
328
|
+
throw new Error(
|
|
329
|
+
`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
330
|
+
);
|
|
329
331
|
}
|
|
330
332
|
}
|
|
331
333
|
generate(_config, flags, parsedArgs) {
|
|
@@ -541,7 +543,9 @@ function enableConfigPlugins(pluginNames) {
|
|
|
541
543
|
globalConfigPluginRegistry.registerPlugin(tomlPlugin);
|
|
542
544
|
}
|
|
543
545
|
} catch (error) {
|
|
544
|
-
console.warn(
|
|
546
|
+
console.warn(
|
|
547
|
+
`Failed to enable TOML plugin: ${error instanceof Error ? error.message : String(error)}`
|
|
548
|
+
);
|
|
545
549
|
}
|
|
546
550
|
break;
|
|
547
551
|
case "yaml":
|
|
@@ -552,7 +556,9 @@ function enableConfigPlugins(pluginNames) {
|
|
|
552
556
|
globalConfigPluginRegistry.registerPlugin(yamlPlugin);
|
|
553
557
|
}
|
|
554
558
|
} catch (error) {
|
|
555
|
-
console.warn(
|
|
559
|
+
console.warn(
|
|
560
|
+
`Failed to enable YAML plugin: ${error instanceof Error ? error.message : String(error)}`
|
|
561
|
+
);
|
|
556
562
|
}
|
|
557
563
|
break;
|
|
558
564
|
default:
|
|
@@ -576,14 +582,18 @@ class ConfigurationManager {
|
|
|
576
582
|
} else if (appName && appName !== "Argument Parser") {
|
|
577
583
|
baseName = appName;
|
|
578
584
|
}
|
|
579
|
-
baseName = baseName.split(/[\s-_]+/).map(
|
|
585
|
+
baseName = baseName.split(/[\s-_]+/).map(
|
|
586
|
+
(word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
587
|
+
).join("");
|
|
580
588
|
return `${baseName}.env`;
|
|
581
589
|
}
|
|
582
590
|
/**
|
|
583
591
|
* Handles the --s-save-to-env system flag at the final parser level
|
|
584
592
|
*/
|
|
585
593
|
handleSaveToEnvFlag(processArgs, parserChain) {
|
|
586
|
-
const saveToEnvIndex = processArgs.findIndex(
|
|
594
|
+
const saveToEnvIndex = processArgs.findIndex(
|
|
595
|
+
(arg) => arg === "--s-save-to-env"
|
|
596
|
+
);
|
|
587
597
|
if (saveToEnvIndex !== -1) {
|
|
588
598
|
let filePath;
|
|
589
599
|
if (saveToEnvIndex + 1 < processArgs.length) {
|
|
@@ -609,7 +619,11 @@ class ConfigurationManager {
|
|
|
609
619
|
const finalParser = parserChain[parserChain.length - 1];
|
|
610
620
|
const parsedArgs = finalParser.getLastParseResult();
|
|
611
621
|
if (!parsedArgs) {
|
|
612
|
-
console.log(
|
|
622
|
+
console.log(
|
|
623
|
+
simpleChalk.yellow(
|
|
624
|
+
"No parsed arguments available. Run the command first to generate configuration."
|
|
625
|
+
)
|
|
626
|
+
);
|
|
613
627
|
return;
|
|
614
628
|
}
|
|
615
629
|
const allFlags = [];
|
|
@@ -642,10 +656,18 @@ class ConfigurationManager {
|
|
|
642
656
|
fs__namespace.writeFileSync(filePath, content, "utf8");
|
|
643
657
|
console.log(simpleChalk.green(`✅ Configuration saved to: ${filePath}`));
|
|
644
658
|
console.log(simpleChalk.gray(`Format: ${ext || ".env"}`));
|
|
645
|
-
console.log(
|
|
659
|
+
console.log(
|
|
660
|
+
simpleChalk.gray(`Flags saved: ${Object.keys(parsedArgs.args).length}`)
|
|
661
|
+
);
|
|
646
662
|
} catch (error) {
|
|
647
|
-
console.error(
|
|
648
|
-
|
|
663
|
+
console.error(
|
|
664
|
+
simpleChalk.red(
|
|
665
|
+
`❌ Failed to save configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
666
|
+
)
|
|
667
|
+
);
|
|
668
|
+
throw new Error(
|
|
669
|
+
`Failed to save configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
670
|
+
);
|
|
649
671
|
}
|
|
650
672
|
}
|
|
651
673
|
/**
|
|
@@ -682,7 +704,11 @@ class ConfigurationManager {
|
|
|
682
704
|
}
|
|
683
705
|
return this.convertConfigToFlagValues(rawConfig, parserChain);
|
|
684
706
|
} catch (error) {
|
|
685
|
-
console.warn(
|
|
707
|
+
console.warn(
|
|
708
|
+
simpleChalk.yellow(
|
|
709
|
+
`Warning: Could not load config file ${filePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
710
|
+
)
|
|
711
|
+
);
|
|
686
712
|
return {};
|
|
687
713
|
}
|
|
688
714
|
}
|
|
@@ -716,7 +742,9 @@ class ConfigurationManager {
|
|
|
716
742
|
if (plugin) {
|
|
717
743
|
return plugin.parse(content);
|
|
718
744
|
}
|
|
719
|
-
console.warn(
|
|
745
|
+
console.warn(
|
|
746
|
+
"YAML plugin not available, using simple parser. Install js-yaml and enable YAML plugin for full support."
|
|
747
|
+
);
|
|
720
748
|
const config = {};
|
|
721
749
|
const lines = content.split("\n");
|
|
722
750
|
let currentKey = null;
|
|
@@ -767,7 +795,9 @@ class ConfigurationManager {
|
|
|
767
795
|
try {
|
|
768
796
|
return JSON.parse(content) || {};
|
|
769
797
|
} catch (error) {
|
|
770
|
-
throw new Error(
|
|
798
|
+
throw new Error(
|
|
799
|
+
`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
800
|
+
);
|
|
771
801
|
}
|
|
772
802
|
}
|
|
773
803
|
/**
|
|
@@ -778,7 +808,9 @@ class ConfigurationManager {
|
|
|
778
808
|
if (plugin) {
|
|
779
809
|
return plugin.parse(content);
|
|
780
810
|
}
|
|
781
|
-
console.warn(
|
|
811
|
+
console.warn(
|
|
812
|
+
"TOML plugin not available, using simple parser. Install smol-toml and enable TOML plugin for full support."
|
|
813
|
+
);
|
|
782
814
|
const config = {};
|
|
783
815
|
const lines = content.split("\n");
|
|
784
816
|
for (const line of lines) {
|
|
@@ -809,13 +841,19 @@ class ConfigurationManager {
|
|
|
809
841
|
for (const [key, value] of Object.entries(rawConfig)) {
|
|
810
842
|
let flag = allFlags.find((f) => f["name"] === key);
|
|
811
843
|
if (!flag) {
|
|
812
|
-
flag = allFlags.find(
|
|
844
|
+
flag = allFlags.find(
|
|
845
|
+
(f) => f["name"].toLowerCase() === key.toLowerCase()
|
|
846
|
+
);
|
|
813
847
|
}
|
|
814
848
|
if (flag) {
|
|
815
849
|
try {
|
|
816
850
|
flagValues[flag["name"]] = this.convertValueToFlagType(value, flag);
|
|
817
851
|
} catch (error) {
|
|
818
|
-
console.warn(
|
|
852
|
+
console.warn(
|
|
853
|
+
simpleChalk.yellow(
|
|
854
|
+
`Warning: Could not convert config value for flag '${key}': ${error instanceof Error ? error.message : String(error)}`
|
|
855
|
+
)
|
|
856
|
+
);
|
|
819
857
|
}
|
|
820
858
|
}
|
|
821
859
|
}
|
|
@@ -852,17 +890,23 @@ class ConfigurationManager {
|
|
|
852
890
|
}
|
|
853
891
|
const num = Number(value);
|
|
854
892
|
if (isNaN(num)) {
|
|
855
|
-
throw new Error(
|
|
893
|
+
throw new Error(
|
|
894
|
+
`Cannot convert '${value}' to number for flag '${flag["name"]}'`
|
|
895
|
+
);
|
|
856
896
|
}
|
|
857
897
|
return num;
|
|
858
898
|
} else if (isBooleanType) {
|
|
859
899
|
if (typeof value === "boolean") return value;
|
|
860
900
|
if (typeof value === "string") {
|
|
861
901
|
const lower = value.toLowerCase();
|
|
862
|
-
if (lower === "true" || lower === "1" || lower === "yes" || lower === "on")
|
|
863
|
-
|
|
902
|
+
if (lower === "true" || lower === "1" || lower === "yes" || lower === "on")
|
|
903
|
+
return true;
|
|
904
|
+
if (lower === "false" || lower === "0" || lower === "no" || lower === "off")
|
|
905
|
+
return false;
|
|
864
906
|
}
|
|
865
|
-
throw new Error(
|
|
907
|
+
throw new Error(
|
|
908
|
+
`Cannot convert '${value}' to boolean for flag '${flag["name"]}'`
|
|
909
|
+
);
|
|
866
910
|
} else if (flagType === "table") {
|
|
867
911
|
if (Array.isArray(value)) return value;
|
|
868
912
|
if (typeof value === "string") {
|
|
@@ -873,13 +917,17 @@ class ConfigurationManager {
|
|
|
873
917
|
return value.split(",").map((v) => v.trim());
|
|
874
918
|
}
|
|
875
919
|
}
|
|
876
|
-
throw new Error(
|
|
920
|
+
throw new Error(
|
|
921
|
+
`Cannot convert '${value}' to table for flag '${flag["name"]}'`
|
|
922
|
+
);
|
|
877
923
|
} else {
|
|
878
924
|
if (typeof flagType === "function") {
|
|
879
925
|
try {
|
|
880
926
|
return flagType(value);
|
|
881
927
|
} catch (error) {
|
|
882
|
-
throw new Error(
|
|
928
|
+
throw new Error(
|
|
929
|
+
`Custom type conversion failed for flag '${flag["name"]}': ${error instanceof Error ? error.message : String(error)}`
|
|
930
|
+
);
|
|
883
931
|
}
|
|
884
932
|
}
|
|
885
933
|
return String(value);
|
|
@@ -954,7 +1002,9 @@ class ConfigurationManager {
|
|
|
954
1002
|
if (Array.isArray(value)) {
|
|
955
1003
|
lines.push(`${flag["name"]}:`);
|
|
956
1004
|
for (const item of value) {
|
|
957
|
-
lines.push(
|
|
1005
|
+
lines.push(
|
|
1006
|
+
` - ${typeof item === "string" && item.includes(" ") ? `"${item}"` : item}`
|
|
1007
|
+
);
|
|
958
1008
|
}
|
|
959
1009
|
} else if (typeof value === "string" && value.includes(" ")) {
|
|
960
1010
|
lines.push(`${flag["name"]}: "${value}"`);
|
|
@@ -1188,64 +1238,22 @@ function createOutputSchema(pattern2) {
|
|
|
1188
1238
|
}
|
|
1189
1239
|
return OutputSchemaPatterns.successError();
|
|
1190
1240
|
}
|
|
1191
|
-
class
|
|
1192
|
-
constructor(argParserInstance) {
|
|
1241
|
+
class DxtGeneratorTestUtils {
|
|
1242
|
+
constructor(argParserInstance, extractMcpServerInfo, handleExit) {
|
|
1193
1243
|
this.argParserInstance = argParserInstance;
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
* Helper method to handle exit logic based on autoExit setting
|
|
1197
|
-
*/
|
|
1198
|
-
_handleExit(exitCode, message, type2, data2) {
|
|
1199
|
-
const result = {
|
|
1200
|
-
success: exitCode === 0,
|
|
1201
|
-
exitCode,
|
|
1202
|
-
message,
|
|
1203
|
-
type: type2 || (exitCode === 0 ? "success" : "error"),
|
|
1204
|
-
shouldExit: true,
|
|
1205
|
-
data: data2
|
|
1206
|
-
};
|
|
1207
|
-
if (this.argParserInstance.getAutoExit() && typeof process === "object" && typeof process.exit === "function") {
|
|
1208
|
-
process.exit(exitCode);
|
|
1209
|
-
}
|
|
1210
|
-
return result;
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* Handles the --s-build-dxt system flag to generate DXT packages for MCP servers
|
|
1214
|
-
*/
|
|
1215
|
-
async handleBuildDxtFlag(processArgs, buildDxtIndex) {
|
|
1216
|
-
var _a, _b, _c;
|
|
1217
|
-
try {
|
|
1218
|
-
const isTestMode = 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"));
|
|
1219
|
-
if (isTestMode) {
|
|
1220
|
-
return await this.handleTestModeDxtGeneration(processArgs, buildDxtIndex);
|
|
1221
|
-
}
|
|
1222
|
-
const entryPointFile = process.argv[1];
|
|
1223
|
-
if (!entryPointFile || !fs__namespace.existsSync(entryPointFile)) {
|
|
1224
|
-
console.error(simpleChalk.red(`Error: Entry point file not found: ${entryPointFile}`));
|
|
1225
|
-
return this._handleExit(1, "Entry point file not found", "error");
|
|
1226
|
-
}
|
|
1227
|
-
const outputDir = processArgs[buildDxtIndex + 1] || "./dxt";
|
|
1228
|
-
console.log(simpleChalk.cyan(`
|
|
1229
|
-
🔧 Building DXT package for entry point: ${path__namespace.basename(entryPointFile)}`));
|
|
1230
|
-
console.log(simpleChalk.gray(`Output directory: ${outputDir}`));
|
|
1231
|
-
await this.buildDxtWithTsdown(entryPointFile, outputDir);
|
|
1232
|
-
console.log(simpleChalk.green(`
|
|
1233
|
-
✅ DXT package generation completed!`));
|
|
1234
|
-
return this._handleExit(0, "DXT package generation completed", "success", { entryPoint: entryPointFile, outputDir });
|
|
1235
|
-
} catch (error) {
|
|
1236
|
-
console.error(simpleChalk.red(`Error generating DXT package: ${error instanceof Error ? error.message : String(error)}`));
|
|
1237
|
-
return this._handleExit(1, `Error generating DXT package: ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
1238
|
-
}
|
|
1244
|
+
this.extractMcpServerInfo = extractMcpServerInfo;
|
|
1245
|
+
this.handleExit = handleExit;
|
|
1239
1246
|
}
|
|
1240
1247
|
/**
|
|
1241
1248
|
* Handles DXT generation in test mode by creating mock DXT package structure
|
|
1249
|
+
* This method creates simplified mock files for testing purposes
|
|
1242
1250
|
*/
|
|
1243
1251
|
async handleTestModeDxtGeneration(processArgs, buildDxtIndex) {
|
|
1244
1252
|
try {
|
|
1245
1253
|
const outputDir = processArgs[buildDxtIndex + 1] || "./dxt-packages";
|
|
1246
1254
|
const mcpTools = this.argParserInstance.toMcpTools();
|
|
1247
1255
|
if (mcpTools.length === 0) {
|
|
1248
|
-
return this.
|
|
1256
|
+
return this.handleExit(0, "No MCP servers found", "success");
|
|
1249
1257
|
}
|
|
1250
1258
|
const serverInfo = this.extractMcpServerInfo();
|
|
1251
1259
|
const folderName = `${serverInfo.name.replace(/[^a-zA-Z0-9_-]/g, "_")}-dxt`;
|
|
@@ -1274,7 +1282,10 @@ class DxtGenerator {
|
|
|
1274
1282
|
})),
|
|
1275
1283
|
icon: "logo.jpg"
|
|
1276
1284
|
};
|
|
1277
|
-
fs__namespace.writeFileSync(
|
|
1285
|
+
fs__namespace.writeFileSync(
|
|
1286
|
+
path__namespace.join(buildDir, "manifest.json"),
|
|
1287
|
+
JSON.stringify(manifest, null, 2)
|
|
1288
|
+
);
|
|
1278
1289
|
const packageJson = {
|
|
1279
1290
|
name: serverInfo.name,
|
|
1280
1291
|
version: serverInfo.version,
|
|
@@ -1282,7 +1293,10 @@ class DxtGenerator {
|
|
|
1282
1293
|
main: "index.mjs",
|
|
1283
1294
|
type: "module"
|
|
1284
1295
|
};
|
|
1285
|
-
fs__namespace.writeFileSync(
|
|
1296
|
+
fs__namespace.writeFileSync(
|
|
1297
|
+
path__namespace.join(buildDir, "package.json"),
|
|
1298
|
+
JSON.stringify(packageJson, null, 2)
|
|
1299
|
+
);
|
|
1286
1300
|
const readme = `# ${serverInfo.name}
|
|
1287
1301
|
|
|
1288
1302
|
${serverInfo.description}
|
|
@@ -1291,88 +1305,172 @@ Generated by @alcyone-labs/arg-parser`;
|
|
|
1291
1305
|
fs__namespace.writeFileSync(path__namespace.join(buildDir, "README.md"), readme);
|
|
1292
1306
|
const buildScript = `#!/bin/bash
|
|
1293
1307
|
echo "Mock DXT build script for ${serverInfo.name}"`;
|
|
1294
|
-
fs__namespace.writeFileSync(
|
|
1295
|
-
|
|
1308
|
+
fs__namespace.writeFileSync(
|
|
1309
|
+
path__namespace.join(buildDir, "build-dxt-package.sh"),
|
|
1310
|
+
buildScript
|
|
1311
|
+
);
|
|
1312
|
+
return this.handleExit(0, "DXT package generation completed", "success", {
|
|
1296
1313
|
entryPoint: "test-mode",
|
|
1297
1314
|
outputDir: buildDir
|
|
1298
1315
|
});
|
|
1299
1316
|
} catch (error) {
|
|
1300
|
-
return this.
|
|
1317
|
+
return this.handleExit(
|
|
1318
|
+
1,
|
|
1319
|
+
`Test mode DXT generation failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1320
|
+
"error"
|
|
1321
|
+
);
|
|
1301
1322
|
}
|
|
1302
1323
|
}
|
|
1303
1324
|
/**
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1325
|
+
* Checks if the current environment is in test mode
|
|
1326
|
+
* Used to determine whether to use test utilities or production code
|
|
1306
1327
|
*/
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
fs__namespace.chmodSync(serverScriptPath, 493);
|
|
1331
|
-
} catch (error) {
|
|
1332
|
-
console.warn("⚠ Could not set executable permission on server script:", error instanceof Error ? error.message : String(error));
|
|
1333
|
-
}
|
|
1334
|
-
const packageJson = this.createDxtPackageJson(serverInfo);
|
|
1335
|
-
fs__namespace.writeFileSync(path__namespace.join(buildDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
1336
|
-
const readme = this.createDxtReadme(serverInfo);
|
|
1337
|
-
fs__namespace.writeFileSync(path__namespace.join(buildDir, "README.md"), readme);
|
|
1338
|
-
const buildScript = this.createSimpleBuildScript(serverInfo);
|
|
1339
|
-
fs__namespace.writeFileSync(path__namespace.join(buildDir, "build-dxt.sh"), buildScript);
|
|
1340
|
-
const dxtIgnore = this.createDxtIgnore();
|
|
1341
|
-
fs__namespace.writeFileSync(path__namespace.join(buildDir, ".dxtignore"), dxtIgnore);
|
|
1342
|
-
try {
|
|
1343
|
-
fs__namespace.chmodSync(path__namespace.join(buildDir, "build-dxt.sh"), 493);
|
|
1344
|
-
} catch (error) {
|
|
1328
|
+
static isTestMode() {
|
|
1329
|
+
var _a, _b, _c;
|
|
1330
|
+
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"));
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
class DxtGenerator {
|
|
1334
|
+
constructor(argParserInstance) {
|
|
1335
|
+
this.argParserInstance = argParserInstance;
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Helper method to handle exit logic based on autoExit setting
|
|
1339
|
+
*/
|
|
1340
|
+
_handleExit(exitCode, message, type2, data2) {
|
|
1341
|
+
const result = {
|
|
1342
|
+
success: exitCode === 0,
|
|
1343
|
+
exitCode,
|
|
1344
|
+
message,
|
|
1345
|
+
type: type2 || (exitCode === 0 ? "success" : "error"),
|
|
1346
|
+
shouldExit: true,
|
|
1347
|
+
data: data2
|
|
1348
|
+
};
|
|
1349
|
+
if (this.argParserInstance.getAutoExit() && typeof process === "object" && typeof process.exit === "function") {
|
|
1350
|
+
process.exit(exitCode);
|
|
1345
1351
|
}
|
|
1346
|
-
|
|
1347
|
-
console.log(simpleChalk.gray(` Server: ${serverInfo.name} v${serverInfo.version}`));
|
|
1348
|
-
console.log(simpleChalk.gray(` Tools: ${tools.length} tool(s)`));
|
|
1349
|
-
console.log(simpleChalk.gray(` Location: ${buildDir}`));
|
|
1350
|
-
console.log(simpleChalk.cyan(`
|
|
1351
|
-
📦 Creating DXT package using Anthropic's dxt pack...`));
|
|
1352
|
-
console.log(simpleChalk.cyan(`
|
|
1353
|
-
📋 Manual steps to create your DXT package:`));
|
|
1354
|
-
console.log(simpleChalk.white(` cd ${path__namespace.relative(process.cwd(), buildDir)}`));
|
|
1355
|
-
console.log(simpleChalk.white(` ./build-dxt.sh`));
|
|
1352
|
+
return result;
|
|
1356
1353
|
}
|
|
1357
1354
|
/**
|
|
1358
|
-
*
|
|
1355
|
+
* Handles the --s-build-dxt system flag to generate DXT packages for MCP servers
|
|
1359
1356
|
*/
|
|
1360
|
-
|
|
1357
|
+
async handleBuildDxtFlag(processArgs, buildDxtIndex) {
|
|
1361
1358
|
try {
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1359
|
+
if (DxtGeneratorTestUtils.isTestMode()) {
|
|
1360
|
+
const testUtils = new DxtGeneratorTestUtils(
|
|
1361
|
+
this.argParserInstance,
|
|
1362
|
+
() => this.extractMcpServerInfo(),
|
|
1363
|
+
(exitCode, message, type2, data2) => this._handleExit(exitCode, message, type2, data2)
|
|
1364
|
+
);
|
|
1365
|
+
return await testUtils.handleTestModeDxtGeneration(
|
|
1366
|
+
processArgs,
|
|
1367
|
+
buildDxtIndex
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
const withNodeModules = processArgs.includes("--s-with-node-modules");
|
|
1371
|
+
if (withNodeModules) {
|
|
1372
|
+
console.log(
|
|
1373
|
+
simpleChalk.yellow(
|
|
1374
|
+
"🗂️ --s-with-node-modules detected: will include node_modules in bundle"
|
|
1375
|
+
)
|
|
1376
|
+
);
|
|
1377
|
+
const nodeModulesPath = path__namespace.resolve("./node_modules");
|
|
1378
|
+
if (!fs__namespace.existsSync(nodeModulesPath)) {
|
|
1379
|
+
console.error(
|
|
1380
|
+
simpleChalk.red(
|
|
1381
|
+
"❌ Error: node_modules directory not found. Please run the installation command first."
|
|
1382
|
+
)
|
|
1383
|
+
);
|
|
1384
|
+
console.log(
|
|
1385
|
+
simpleChalk.cyan(
|
|
1386
|
+
"💡 Required command: pnpm install --prod --node-linker=hoisted"
|
|
1387
|
+
)
|
|
1388
|
+
);
|
|
1389
|
+
return this._handleExit(
|
|
1390
|
+
1,
|
|
1391
|
+
"node_modules directory not found",
|
|
1392
|
+
"error"
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
const nodeModulesContents = fs__namespace.readdirSync(nodeModulesPath);
|
|
1397
|
+
const hasNestedNodeModules = nodeModulesContents.filter((item) => !item.startsWith(".") && !item.startsWith("@")).some((item) => {
|
|
1398
|
+
const itemPath = path__namespace.join(nodeModulesPath, item);
|
|
1399
|
+
try {
|
|
1400
|
+
return fs__namespace.statSync(itemPath).isDirectory() && fs__namespace.existsSync(path__namespace.join(itemPath, "node_modules"));
|
|
1401
|
+
} catch {
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
if (hasNestedNodeModules) {
|
|
1406
|
+
console.warn(
|
|
1407
|
+
simpleChalk.yellow(
|
|
1408
|
+
"⚠️ Warning: Detected nested node_modules. For best results, ensure hoisted installation:"
|
|
1409
|
+
)
|
|
1410
|
+
);
|
|
1411
|
+
console.log(
|
|
1412
|
+
simpleChalk.cyan(
|
|
1413
|
+
" rm -rf node_modules && pnpm install --prod --node-linker=hoisted"
|
|
1414
|
+
)
|
|
1415
|
+
);
|
|
1416
|
+
} else {
|
|
1417
|
+
console.log(
|
|
1418
|
+
simpleChalk.green(
|
|
1419
|
+
"✅ node_modules appears properly hoisted and ready for bundling"
|
|
1420
|
+
)
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
} catch (error) {
|
|
1424
|
+
console.warn(
|
|
1425
|
+
simpleChalk.yellow(
|
|
1426
|
+
`⚠️ Could not validate node_modules structure: ${error instanceof Error ? error.message : String(error)}`
|
|
1427
|
+
)
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
console.log(
|
|
1431
|
+
simpleChalk.gray(
|
|
1432
|
+
"💡 This will create a fully autonomous DXT with all native dependencies included"
|
|
1433
|
+
)
|
|
1434
|
+
);
|
|
1372
1435
|
}
|
|
1436
|
+
const entryPointFile = process.argv[1];
|
|
1437
|
+
if (!entryPointFile || !fs__namespace.existsSync(entryPointFile)) {
|
|
1438
|
+
console.error(
|
|
1439
|
+
simpleChalk.red(`Error: Entry point file not found: ${entryPointFile}`)
|
|
1440
|
+
);
|
|
1441
|
+
return this._handleExit(1, "Entry point file not found", "error");
|
|
1442
|
+
}
|
|
1443
|
+
let outputDir = processArgs[buildDxtIndex + 1] || "./dxt";
|
|
1444
|
+
if (outputDir.startsWith("--s-")) outputDir = "./dxt";
|
|
1445
|
+
console.log(
|
|
1446
|
+
simpleChalk.cyan(
|
|
1447
|
+
`
|
|
1448
|
+
🔧 Building DXT package for entry point: ${entryPointFile}`
|
|
1449
|
+
)
|
|
1450
|
+
);
|
|
1451
|
+
console.log(simpleChalk.gray(`Output directory: ${outputDir}`));
|
|
1452
|
+
console.log(simpleChalk.gray(`Entrypoint file: ${entryPointFile}`));
|
|
1453
|
+
await this.buildDxtWithTsdown(entryPointFile, outputDir, withNodeModules);
|
|
1454
|
+
console.log(simpleChalk.green(`
|
|
1455
|
+
✅ DXT package generation completed!`));
|
|
1456
|
+
return this._handleExit(
|
|
1457
|
+
0,
|
|
1458
|
+
"DXT package generation completed",
|
|
1459
|
+
"success",
|
|
1460
|
+
{ entryPoint: entryPointFile, outputDir }
|
|
1461
|
+
);
|
|
1373
1462
|
} catch (error) {
|
|
1463
|
+
console.error(
|
|
1464
|
+
simpleChalk.red(
|
|
1465
|
+
`Error generating DXT package: ${error instanceof Error ? error.message : String(error)}`
|
|
1466
|
+
)
|
|
1467
|
+
);
|
|
1468
|
+
return this._handleExit(
|
|
1469
|
+
1,
|
|
1470
|
+
`Error generating DXT package: ${error instanceof Error ? error.message : String(error)}`,
|
|
1471
|
+
"error"
|
|
1472
|
+
);
|
|
1374
1473
|
}
|
|
1375
|
-
return null;
|
|
1376
1474
|
}
|
|
1377
1475
|
/**
|
|
1378
1476
|
* Extracts server information from MCP configuration
|
|
@@ -1411,7 +1509,9 @@ echo "Mock DXT build script for ${serverInfo.name}"`;
|
|
|
1411
1509
|
toolOptions = mcpConfig.toolOptions;
|
|
1412
1510
|
}
|
|
1413
1511
|
}
|
|
1414
|
-
const mcpTools = this.argParserInstance.toMcpTools(
|
|
1512
|
+
const mcpTools = this.argParserInstance.toMcpTools(
|
|
1513
|
+
toolOptions
|
|
1514
|
+
);
|
|
1415
1515
|
return mcpTools.map((tool) => ({
|
|
1416
1516
|
name: tool.name,
|
|
1417
1517
|
description: tool.description
|
|
@@ -1435,511 +1535,29 @@ echo "Mock DXT build script for ${serverInfo.name}"`;
|
|
|
1435
1535
|
});
|
|
1436
1536
|
}
|
|
1437
1537
|
}
|
|
1438
|
-
return tools.length > 0 ? tools : [
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
} catch (error) {
|
|
1443
|
-
console.warn(simpleChalk.yellow(`Warning: Could not generate detailed tool list: ${error instanceof Error ? error.message : String(error)}`));
|
|
1444
|
-
return [{
|
|
1445
|
-
name: "main",
|
|
1446
|
-
description: "Main command tool"
|
|
1447
|
-
}];
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
createDxtManifest(serverInfo, tools, mcpSubCommand, logoFilename) {
|
|
1451
|
-
var _a;
|
|
1452
|
-
const packageInfo = this.readPackageJsonInfo();
|
|
1453
|
-
let author = serverInfo.author;
|
|
1454
|
-
if (!author && (packageInfo == null ? void 0 : packageInfo.author)) {
|
|
1455
|
-
if (typeof packageInfo.author === "string") {
|
|
1456
|
-
const match = packageInfo.author.match(/^([^<]+?)(?:\s*<([^>]+)>)?$/);
|
|
1457
|
-
if (match) {
|
|
1458
|
-
author = {
|
|
1459
|
-
name: match[1].trim(),
|
|
1460
|
-
email: (_a = match[2]) == null ? void 0 : _a.trim()
|
|
1461
|
-
};
|
|
1462
|
-
} else {
|
|
1463
|
-
author = { name: packageInfo.author };
|
|
1464
|
-
}
|
|
1465
|
-
} else {
|
|
1466
|
-
author = packageInfo.author;
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
if (!author) {
|
|
1470
|
-
throw new Error("DXT manifest requires author information. Please provide it via withMcp() serverInfo.author, addMcpSubCommand serverInfo.author, or in package.json");
|
|
1471
|
-
}
|
|
1472
|
-
const cliArgs = this.generateCliArgsForDxt(mcpSubCommand);
|
|
1473
|
-
const { envVars, userConfig } = this.generateEnvAndUserConfig();
|
|
1474
|
-
const manifest = {
|
|
1475
|
-
dxt_version: "0.1",
|
|
1476
|
-
name: serverInfo.name,
|
|
1477
|
-
version: serverInfo.version,
|
|
1478
|
-
description: serverInfo.description || "MCP server generated from ArgParser",
|
|
1479
|
-
author,
|
|
1480
|
-
server: {
|
|
1481
|
-
type: "node",
|
|
1482
|
-
entry_point: "server/index.mjs",
|
|
1483
|
-
mcp_config: {
|
|
1484
|
-
command: "node",
|
|
1485
|
-
args: ["${__dirname}/server/index.mjs", ...cliArgs],
|
|
1486
|
-
env: envVars
|
|
1487
|
-
}
|
|
1488
|
-
},
|
|
1489
|
-
tools: tools.map((tool) => ({
|
|
1490
|
-
name: tool.name,
|
|
1491
|
-
description: tool.description
|
|
1492
|
-
}))
|
|
1493
|
-
};
|
|
1494
|
-
if (logoFilename) {
|
|
1495
|
-
manifest.icon = logoFilename;
|
|
1496
|
-
}
|
|
1497
|
-
if (userConfig && Object.keys(userConfig).length > 0) {
|
|
1498
|
-
manifest.user_config = userConfig;
|
|
1499
|
-
}
|
|
1500
|
-
if (serverInfo.repository || (packageInfo == null ? void 0 : packageInfo.repository)) {
|
|
1501
|
-
manifest.repository = serverInfo.repository || (packageInfo == null ? void 0 : packageInfo.repository);
|
|
1502
|
-
}
|
|
1503
|
-
if (serverInfo.license || (packageInfo == null ? void 0 : packageInfo.license)) {
|
|
1504
|
-
manifest.license = serverInfo.license || (packageInfo == null ? void 0 : packageInfo.license);
|
|
1505
|
-
}
|
|
1506
|
-
if (serverInfo.homepage || (packageInfo == null ? void 0 : packageInfo.homepage)) {
|
|
1507
|
-
manifest.homepage = serverInfo.homepage || (packageInfo == null ? void 0 : packageInfo.homepage);
|
|
1508
|
-
}
|
|
1509
|
-
return manifest;
|
|
1510
|
-
}
|
|
1511
|
-
validateDxtManifest(manifest) {
|
|
1512
|
-
const errors = [];
|
|
1513
|
-
if (!manifest.dxt_version) errors.push("Missing required field: dxt_version");
|
|
1514
|
-
if (!manifest.name) errors.push("Missing required field: name");
|
|
1515
|
-
if (!manifest.version) errors.push("Missing required field: version");
|
|
1516
|
-
if (!manifest.server) errors.push("Missing required field: server");
|
|
1517
|
-
if (!manifest.author) errors.push("Missing required field: author");
|
|
1518
|
-
if (manifest.server) {
|
|
1519
|
-
if (!manifest.server.type) errors.push("Missing required field: server.type");
|
|
1520
|
-
if (!manifest.server.entry_point) errors.push("Missing required field: server.entry_point");
|
|
1521
|
-
if (!manifest.server.mcp_config) errors.push("Missing required field: server.mcp_config");
|
|
1522
|
-
if (manifest.server.mcp_config) {
|
|
1523
|
-
if (!manifest.server.mcp_config.command) errors.push("Missing required field: server.mcp_config.command");
|
|
1524
|
-
if (!manifest.server.mcp_config.args || !Array.isArray(manifest.server.mcp_config.args)) {
|
|
1525
|
-
errors.push("Missing or invalid field: server.mcp_config.args (must be array)");
|
|
1538
|
+
return tools.length > 0 ? tools : [
|
|
1539
|
+
{
|
|
1540
|
+
name: "main",
|
|
1541
|
+
description: "Main command tool"
|
|
1526
1542
|
}
|
|
1527
|
-
|
|
1528
|
-
}
|
|
1529
|
-
if (manifest.author && typeof manifest.author === "object") {
|
|
1530
|
-
if (!manifest.author.name) errors.push("Missing required field: author.name");
|
|
1531
|
-
}
|
|
1532
|
-
if (manifest.dxt_version && manifest.dxt_version !== "0.1") {
|
|
1533
|
-
errors.push("Unsupported dxt_version: only '0.1' is currently supported");
|
|
1534
|
-
}
|
|
1535
|
-
if (errors.length > 0) {
|
|
1536
|
-
throw new Error(`DXT manifest validation failed:
|
|
1537
|
-
${errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
createServerScript(serverInfo, bundledCliPath) {
|
|
1541
|
-
const cliImportPath = bundledCliPath || "original-cli.mjs";
|
|
1542
|
-
return `#!/usr/bin/env node
|
|
1543
|
-
|
|
1544
|
-
// Generated MCP server for ${serverInfo.name}
|
|
1545
|
-
// This server uses @alcyone-labs/arg-parser's built-in MCP functionality for full protocol compliance
|
|
1546
|
-
|
|
1547
|
-
// FIRST: Set up MCP-safe logging to prevent STDOUT contamination
|
|
1548
|
-
import { createMcpLogger } from '@alcyone-labs/simple-mcp-logger';
|
|
1549
|
-
|
|
1550
|
-
// Auto-detect MCP mode and hijack console to prevent protocol corruption
|
|
1551
|
-
const mcpLogger = createMcpLogger('${serverInfo.name}');
|
|
1552
|
-
globalThis.console = mcpLogger;
|
|
1553
|
-
|
|
1554
|
-
// Now import the CLI which already has MCP functionality configured
|
|
1555
|
-
import originalCli from './${cliImportPath}';
|
|
1556
|
-
|
|
1557
|
-
// Server configuration
|
|
1558
|
-
const serverInfo = ${JSON.stringify(serverInfo, null, 2)};
|
|
1559
|
-
|
|
1560
|
-
// Use mcpError for debugging output (safe STDERR, visible in client logs)
|
|
1561
|
-
console.error(\`MCP Server: \${serverInfo.name} v\${serverInfo.version}\`);
|
|
1562
|
-
console.error(\`Description: \${serverInfo.description}\`);
|
|
1563
|
-
console.error(\`Generated from @alcyone-labs/arg-parser with built-in MCP functionality\`);
|
|
1564
|
-
${bundledCliPath ? "console.error(`Using bundled CLI for autonomous execution`);" : ""}
|
|
1565
|
-
|
|
1566
|
-
// The original CLI has MCP functionality configured via withMcp() or addMcpSubCommand()
|
|
1567
|
-
// We use the centralized --s-mcp-serve system flag to start the unified MCP server
|
|
1568
|
-
|
|
1569
|
-
// Start the MCP server using the library's built-in centralized serving
|
|
1570
|
-
// This works with both withMcp() configuration and legacy addMcpSubCommand() setups
|
|
1571
|
-
originalCli.parse(['--s-mcp-serve']);
|
|
1572
|
-
`;
|
|
1573
|
-
}
|
|
1574
|
-
createDxtPackageJson(serverInfo) {
|
|
1575
|
-
const useLocalBuild = process.env["LOCAL_BUILD"] === "1";
|
|
1576
|
-
const argParserDependency = useLocalBuild ? "file:../../arg-parser-local.tgz" : "^1.3.0";
|
|
1577
|
-
let originalDependencies = {};
|
|
1578
|
-
try {
|
|
1579
|
-
const originalPackageJsonPath = path__namespace.join(process.cwd(), "package.json");
|
|
1580
|
-
if (fs__namespace.existsSync(originalPackageJsonPath)) {
|
|
1581
|
-
const originalPackageJson = JSON.parse(fs__namespace.readFileSync(originalPackageJsonPath, "utf8"));
|
|
1582
|
-
originalDependencies = originalPackageJson.dependencies || {};
|
|
1583
|
-
}
|
|
1543
|
+
];
|
|
1584
1544
|
} catch (error) {
|
|
1585
|
-
console.warn(
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
const devDependencies = {
|
|
1595
|
-
"tsup": "^8.3.5"
|
|
1596
|
-
};
|
|
1597
|
-
Object.keys(dependencies2).forEach((key) => {
|
|
1598
|
-
const depValue = dependencies2[key];
|
|
1599
|
-
if (key !== "@alcyone-labs/arg-parser" && typeof depValue === "string" && depValue.startsWith("file:")) {
|
|
1600
|
-
delete dependencies2[key];
|
|
1601
|
-
console.warn(`⚠ Removed file: dependency ${key} from DXT package (not suitable for distribution)`);
|
|
1602
|
-
}
|
|
1603
|
-
});
|
|
1604
|
-
return {
|
|
1605
|
-
name: serverInfo.name,
|
|
1606
|
-
version: serverInfo.version,
|
|
1607
|
-
description: serverInfo.description,
|
|
1608
|
-
main: "server/index.mjs",
|
|
1609
|
-
type: "module",
|
|
1610
|
-
scripts: {
|
|
1611
|
-
start: "node server/index.mjs",
|
|
1612
|
-
"build-dxt": "./build-dxt.sh"
|
|
1613
|
-
},
|
|
1614
|
-
dependencies: dependencies2,
|
|
1615
|
-
devDependencies,
|
|
1616
|
-
engines: {
|
|
1617
|
-
node: ">=22.0.0"
|
|
1618
|
-
},
|
|
1619
|
-
author: serverInfo.author,
|
|
1620
|
-
license: serverInfo.license || "MIT",
|
|
1621
|
-
repository: serverInfo.repository
|
|
1622
|
-
};
|
|
1623
|
-
}
|
|
1624
|
-
/**
|
|
1625
|
-
* Creates a .dxtignore file to exclude build artifacts and unnecessary files
|
|
1626
|
-
*/
|
|
1627
|
-
createDxtIgnore() {
|
|
1628
|
-
return `# DXT ignore file - exclude these files from the DXT package
|
|
1629
|
-
# Generated by @alcyone-labs/arg-parser
|
|
1630
|
-
|
|
1631
|
-
# Build artifacts and logs
|
|
1632
|
-
*.log
|
|
1633
|
-
*.tmp
|
|
1634
|
-
temp-dxt-build/
|
|
1635
|
-
|
|
1636
|
-
# Build scripts (not needed in final package)
|
|
1637
|
-
build-dxt.sh
|
|
1638
|
-
arg-parser-local.tgz
|
|
1639
|
-
tsup.config.autonomous.js
|
|
1640
|
-
tsdown.config.mjs
|
|
1641
|
-
|
|
1642
|
-
# Original files (replaced by bundled autonomous build)
|
|
1643
|
-
server/index.original.mjs
|
|
1644
|
-
server/*.autonomous.mjs
|
|
1645
|
-
|
|
1646
|
-
# NOTE: server/original-cli.mjs is NOT excluded because it's needed for the MCP server to function
|
|
1647
|
-
# The bundled version (if created) will be server/original-cli.bundled.mjs
|
|
1648
|
-
|
|
1649
|
-
# NOTE: node_modules/ is NOT excluded because TSDown bundling may not be 100% autonomous
|
|
1650
|
-
# If bundling is successful, node_modules won't be needed, but we include it as fallback
|
|
1651
|
-
# The bundled server/index.mjs should be fully autonomous and not require node_modules
|
|
1652
|
-
|
|
1653
|
-
# Development files
|
|
1654
|
-
.git/
|
|
1655
|
-
.gitignore
|
|
1656
|
-
.env
|
|
1657
|
-
.env.*
|
|
1658
|
-
|
|
1659
|
-
# OS files
|
|
1660
|
-
.DS_Store
|
|
1661
|
-
Thumbs.db
|
|
1662
|
-
|
|
1663
|
-
# IDE files
|
|
1664
|
-
.vscode/
|
|
1665
|
-
.idea/
|
|
1666
|
-
*.swp
|
|
1667
|
-
*.swo
|
|
1668
|
-
`;
|
|
1669
|
-
}
|
|
1670
|
-
/**
|
|
1671
|
-
* Creates a simple build script that uses TSDown bundling and Anthropic's dxt pack
|
|
1672
|
-
*/
|
|
1673
|
-
createSimpleBuildScript(serverInfo) {
|
|
1674
|
-
return `#!/bin/bash
|
|
1675
|
-
|
|
1676
|
-
# Simple DXT Build Script for ${serverInfo.name}
|
|
1677
|
-
# Generated by @alcyone-labs/arg-parser with TSDown bundling
|
|
1678
|
-
|
|
1679
|
-
set -e
|
|
1680
|
-
|
|
1681
|
-
echo "📦 Creating DXT package for ${serverInfo.name}..."
|
|
1682
|
-
|
|
1683
|
-
# Step 1: Make server executable (required for MCP)
|
|
1684
|
-
echo "🔧 Making server executable..."
|
|
1685
|
-
chmod +x server/index.mjs
|
|
1686
|
-
|
|
1687
|
-
# Step 2: Handle local development dependencies
|
|
1688
|
-
if grep -q "file:.*arg-parser-local.tgz" package.json; then
|
|
1689
|
-
echo "🔧 Checking for local package tarball..."
|
|
1690
|
-
|
|
1691
|
-
# Check if the tarball exists in the parent directory
|
|
1692
|
-
if [ -f "../../arg-parser-local.tgz" ]; then
|
|
1693
|
-
echo "✅ Found local package tarball: ../../arg-parser-local.tgz"
|
|
1694
|
-
else
|
|
1695
|
-
echo "⚠️ Local tarball not found, falling back to npm registry"
|
|
1696
|
-
echo "💡 To use local build, run: cd /path/to/arg-parser && npm pack && cp *.tgz examples/community/canny-cli/"
|
|
1697
|
-
|
|
1698
|
-
# Replace with npm version
|
|
1699
|
-
sed -i.bak 's|"file:.*arg-parser-local.tgz"|"^1.3.0"|g' package.json 2>/dev/null || \\
|
|
1700
|
-
sed -i 's|"file:.*arg-parser-local.tgz"|"^1.3.0"|g' package.json
|
|
1701
|
-
fi
|
|
1702
|
-
fi
|
|
1703
|
-
|
|
1704
|
-
# Step 3: Install dependencies (for runtime only, bundling was done during generation)
|
|
1705
|
-
echo "📦 Installing dependencies..."
|
|
1706
|
-
npm install
|
|
1707
|
-
|
|
1708
|
-
# Step 4: Validate manifest
|
|
1709
|
-
echo "🔍 Validating DXT manifest..."
|
|
1710
|
-
if command -v npx >/dev/null 2>&1; then
|
|
1711
|
-
if npx @anthropic-ai/dxt validate manifest.json; then
|
|
1712
|
-
echo "✅ DXT manifest validation passed"
|
|
1713
|
-
else
|
|
1714
|
-
echo "❌ DXT manifest validation failed"
|
|
1715
|
-
exit 1
|
|
1716
|
-
fi
|
|
1717
|
-
else
|
|
1718
|
-
echo "⚠️ npx not found, skipping DXT validation"
|
|
1719
|
-
fi
|
|
1720
|
-
|
|
1721
|
-
# Step 5: Create DXT package using Anthropic's official packer
|
|
1722
|
-
echo "📦 Creating DXT package..."
|
|
1723
|
-
if command -v npx >/dev/null 2>&1; then
|
|
1724
|
-
# Use dxt pack directly with .dxtignore for clean packaging
|
|
1725
|
-
npx @anthropic-ai/dxt pack . "${serverInfo.name}.dxt"
|
|
1726
|
-
else
|
|
1727
|
-
# Fallback to standard zip if npx not available
|
|
1728
|
-
echo "⚠️ npx not found, using zip fallback"
|
|
1729
|
-
zip -r "${serverInfo.name}.dxt" . -x "node_modules/*" "*.log" ".git/*" "build-dxt.sh" "temp-dxt-build/*"
|
|
1730
|
-
fi
|
|
1731
|
-
|
|
1732
|
-
# Step 6: Sign the DXT package (optional)
|
|
1733
|
-
echo "🔐 Signing DXT package..."
|
|
1734
|
-
if command -v npx >/dev/null 2>&1 && command -v openssl >/dev/null 2>&1; then
|
|
1735
|
-
if npx @anthropic-ai/dxt sign "${serverInfo.name}.dxt" --self-signed; then
|
|
1736
|
-
echo "✅ DXT package signed successfully"
|
|
1737
|
-
else
|
|
1738
|
-
echo "⚠️ DXT signing failed, but package is still usable"
|
|
1739
|
-
fi
|
|
1740
|
-
else
|
|
1741
|
-
echo "⚠️ npx or openssl not found, skipping DXT signing"
|
|
1742
|
-
fi
|
|
1743
|
-
|
|
1744
|
-
echo "✅ DXT package created: ${serverInfo.name}.dxt"
|
|
1745
|
-
echo "🎯 This package includes bundled CLI with all dependencies!"
|
|
1746
|
-
echo ""
|
|
1747
|
-
echo "🎉 Installation Instructions:"
|
|
1748
|
-
echo "You can now take the file '${serverInfo.name}.dxt' and install it on Claude Desktop"
|
|
1749
|
-
echo "or supporting applications by using drag & drop on the Extensions Settings page,"
|
|
1750
|
-
echo "or directly pointing the file selector to this file."
|
|
1751
|
-
echo ""
|
|
1752
|
-
echo "📁 DXT file location: $(pwd)/${serverInfo.name}.dxt"
|
|
1753
|
-
`;
|
|
1754
|
-
}
|
|
1755
|
-
createDxtReadme(serverInfo) {
|
|
1756
|
-
return `# ${serverInfo.name}
|
|
1757
|
-
|
|
1758
|
-
${serverInfo.description}
|
|
1759
|
-
|
|
1760
|
-
## Installation
|
|
1761
|
-
|
|
1762
|
-
This is a Desktop Extension (DXT) package generated from @alcyone-labs/arg-parser.
|
|
1763
|
-
|
|
1764
|
-
### Automatic Installation
|
|
1765
|
-
Open this .dxt file with Claude Desktop or other DXT-compatible applications for single-click installation.
|
|
1766
|
-
|
|
1767
|
-
### Manual Installation
|
|
1768
|
-
1. Extract the .dxt file (it's a ZIP archive)
|
|
1769
|
-
2. Run \`npm install\` to install dependencies
|
|
1770
|
-
3. Start the server with \`npm start\`
|
|
1771
|
-
|
|
1772
|
-
## Tools
|
|
1773
|
-
|
|
1774
|
-
This MCP server provides the following tools:
|
|
1775
|
-
${this.generateMcpToolsForDxt().map((tool) => `- **${tool.name}**: ${tool.description}`).join("\n")}
|
|
1776
|
-
|
|
1777
|
-
## Building DXT Packages
|
|
1778
|
-
|
|
1779
|
-
To rebuild the DXT package:
|
|
1780
|
-
|
|
1781
|
-
### Prerequisites
|
|
1782
|
-
- Node.js 18+ installed
|
|
1783
|
-
- npm package manager
|
|
1784
|
-
|
|
1785
|
-
### Build Steps
|
|
1786
|
-
|
|
1787
|
-
\`\`\`bash
|
|
1788
|
-
# 1. Install dependencies
|
|
1789
|
-
npm install
|
|
1790
|
-
|
|
1791
|
-
# 2. Build DXT package
|
|
1792
|
-
npm run build-dxt
|
|
1793
|
-
# or
|
|
1794
|
-
./build-dxt.sh
|
|
1795
|
-
|
|
1796
|
-
# 3. The build script will:
|
|
1797
|
-
# - Install dependencies
|
|
1798
|
-
# - Validate the manifest
|
|
1799
|
-
# - Create the DXT package using Anthropic's official packer
|
|
1800
|
-
# - Sign the package (optional)
|
|
1801
|
-
\`\`\`
|
|
1802
|
-
|
|
1803
|
-
### Manual Build Process
|
|
1804
|
-
|
|
1805
|
-
If the automated build script doesn't work, you can build manually:
|
|
1806
|
-
|
|
1807
|
-
\`\`\`bash
|
|
1808
|
-
# 1. Install dependencies
|
|
1809
|
-
npm install
|
|
1810
|
-
|
|
1811
|
-
# 2. Create DXT package
|
|
1812
|
-
npx @anthropic-ai/dxt pack . ${serverInfo.name}.dxt
|
|
1813
|
-
|
|
1814
|
-
# 2. Update manifest.json
|
|
1815
|
-
# Change "entry_point" from "server/index.js" to "dist-autonomous/server.cjs"
|
|
1816
|
-
|
|
1817
|
-
# 3. Create new DXT with bundled server
|
|
1818
|
-
# Replace server/index.js with dist-autonomous/server.cjs
|
|
1819
|
-
# Remove package.json dependencies (optional)
|
|
1820
|
-
\`\`\`
|
|
1821
|
-
|
|
1822
|
-
### Result
|
|
1823
|
-
The resulting DXT package will be completely autonomous and won't require \`npm install\`.
|
|
1824
|
-
|
|
1825
|
-
## Generated Information
|
|
1826
|
-
|
|
1827
|
-
- **Generator**: @alcyone-labs/arg-parser v1.3.0
|
|
1828
|
-
- **Generated**: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1829
|
-
- **DXT Version**: 0.1
|
|
1830
|
-
|
|
1831
|
-
## Note
|
|
1832
|
-
|
|
1833
|
-
This is a simplified DXT package. For full functionality and the latest features, use the original CLI directly.
|
|
1834
|
-
For autonomous packages, follow the build instructions above.
|
|
1835
|
-
`;
|
|
1836
|
-
}
|
|
1837
|
-
/**
|
|
1838
|
-
* Maps ArgParser flag types to DXT user config types
|
|
1839
|
-
*/
|
|
1840
|
-
mapFlagTypeToUserConfigType(flagType) {
|
|
1841
|
-
if (typeof flagType === "function") {
|
|
1842
|
-
if (flagType === String) return "string";
|
|
1843
|
-
if (flagType === Number) return "number";
|
|
1844
|
-
if (flagType === Boolean) return "boolean";
|
|
1845
|
-
if (flagType === Array) return "array";
|
|
1846
|
-
if (flagType === Object) return "object";
|
|
1847
|
-
return "string";
|
|
1848
|
-
}
|
|
1849
|
-
switch (String(flagType).toLowerCase()) {
|
|
1850
|
-
case "string":
|
|
1851
|
-
return "string";
|
|
1852
|
-
case "number":
|
|
1853
|
-
return "number";
|
|
1854
|
-
case "boolean":
|
|
1855
|
-
return "boolean";
|
|
1856
|
-
case "table":
|
|
1857
|
-
return "array";
|
|
1858
|
-
case "array":
|
|
1859
|
-
return "array";
|
|
1860
|
-
case "object":
|
|
1861
|
-
return "object";
|
|
1862
|
-
default:
|
|
1863
|
-
return "string";
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
/**
|
|
1867
|
-
* Generates CLI arguments for DXT manifest based on ArgParser flags
|
|
1868
|
-
*/
|
|
1869
|
-
generateCliArgsForDxt(_mcpSubCommand) {
|
|
1870
|
-
const args = [];
|
|
1871
|
-
args.push("--s-mcp-serve");
|
|
1872
|
-
return args;
|
|
1873
|
-
}
|
|
1874
|
-
/**
|
|
1875
|
-
* Generates environment variables and user config for DXT manifest
|
|
1876
|
-
*/
|
|
1877
|
-
generateEnvAndUserConfig() {
|
|
1878
|
-
const envVars = {};
|
|
1879
|
-
const userConfig = {};
|
|
1880
|
-
const flags = this.argParserInstance.flags || [];
|
|
1881
|
-
for (const flag of flags) {
|
|
1882
|
-
const flagName = flag["name"];
|
|
1883
|
-
if (flagName === "help" || flagName === "mcp") continue;
|
|
1884
|
-
if (flag["env"]) {
|
|
1885
|
-
const envVarName = flag["env"];
|
|
1886
|
-
envVars[envVarName] = `\${user_config.${envVarName}}`;
|
|
1887
|
-
userConfig[envVarName] = {
|
|
1888
|
-
type: this.mapFlagTypeToUserConfigType(flag["type"]),
|
|
1889
|
-
title: this.generateUserConfigTitle(envVarName),
|
|
1890
|
-
description: flag["description"] || `${envVarName} environment variable`,
|
|
1891
|
-
required: true,
|
|
1892
|
-
// Always require env vars in user_config for better UX
|
|
1893
|
-
sensitive: this.isSensitiveField(envVarName)
|
|
1894
|
-
};
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
if (typeof this.argParserInstance.getTools === "function") {
|
|
1898
|
-
const tools = this.argParserInstance.getTools();
|
|
1899
|
-
for (const [, toolConfig] of tools) {
|
|
1900
|
-
const toolFlags = toolConfig.flags || [];
|
|
1901
|
-
for (const flag of toolFlags) {
|
|
1902
|
-
const flagName = flag["name"];
|
|
1903
|
-
if (flagName === "help" || flagName.startsWith("s-")) continue;
|
|
1904
|
-
if (flag["env"]) {
|
|
1905
|
-
const envVarName = flag["env"];
|
|
1906
|
-
if (!envVars[envVarName]) {
|
|
1907
|
-
envVars[envVarName] = `\${user_config.${envVarName}}`;
|
|
1908
|
-
userConfig[envVarName] = {
|
|
1909
|
-
type: this.mapFlagTypeToUserConfigType(flag["type"]),
|
|
1910
|
-
title: this.generateUserConfigTitle(envVarName),
|
|
1911
|
-
description: flag["description"] || `${envVarName} environment variable`,
|
|
1912
|
-
required: true,
|
|
1913
|
-
// Always require env vars in user_config for better UX
|
|
1914
|
-
sensitive: this.isSensitiveField(envVarName)
|
|
1915
|
-
};
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1545
|
+
console.warn(
|
|
1546
|
+
simpleChalk.yellow(
|
|
1547
|
+
`Warning: Could not generate detailed tool list: ${error instanceof Error ? error.message : String(error)}`
|
|
1548
|
+
)
|
|
1549
|
+
);
|
|
1550
|
+
return [
|
|
1551
|
+
{
|
|
1552
|
+
name: "main",
|
|
1553
|
+
description: "Main command tool"
|
|
1918
1554
|
}
|
|
1919
|
-
|
|
1555
|
+
];
|
|
1920
1556
|
}
|
|
1921
|
-
return { envVars, userConfig };
|
|
1922
|
-
}
|
|
1923
|
-
/**
|
|
1924
|
-
* Generates a user-friendly title for user config fields
|
|
1925
|
-
*/
|
|
1926
|
-
generateUserConfigTitle(flagName) {
|
|
1927
|
-
return flagName.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
1928
1557
|
}
|
|
1929
1558
|
/**
|
|
1930
|
-
*
|
|
1559
|
+
* Maps ArgParser flag types to DXT user config types
|
|
1931
1560
|
*/
|
|
1932
|
-
isSensitiveField(fieldName) {
|
|
1933
|
-
const sensitivePatterns = [
|
|
1934
|
-
/key/i,
|
|
1935
|
-
/token/i,
|
|
1936
|
-
/secret/i,
|
|
1937
|
-
/password/i,
|
|
1938
|
-
/auth/i,
|
|
1939
|
-
/credential/i
|
|
1940
|
-
];
|
|
1941
|
-
return sensitivePatterns.some((pattern2) => pattern2.test(fieldName));
|
|
1942
|
-
}
|
|
1943
1561
|
/**
|
|
1944
1562
|
* Adds the logo to the build folder if available
|
|
1945
1563
|
* @returns The filename of the logo that was added, or undefined if no logo was added
|
|
@@ -1959,27 +1577,38 @@ For autonomous packages, follow the build instructions above.
|
|
|
1959
1577
|
const urlPath = new URL(customLogo).pathname;
|
|
1960
1578
|
const urlFilename = path__namespace.basename(urlPath);
|
|
1961
1579
|
if (urlFilename && urlFilename.includes(".")) {
|
|
1962
|
-
|
|
1580
|
+
const ext = path__namespace.extname(urlFilename);
|
|
1581
|
+
logoFilename = `logo${ext}`;
|
|
1582
|
+
} else {
|
|
1583
|
+
logoFilename = "logo.jpg";
|
|
1963
1584
|
}
|
|
1964
1585
|
console.log("✓ Downloaded logo from URL");
|
|
1965
1586
|
} else {
|
|
1966
|
-
console.warn(
|
|
1587
|
+
console.warn(
|
|
1588
|
+
`⚠ Failed to download logo: HTTP ${response.status}`
|
|
1589
|
+
);
|
|
1967
1590
|
}
|
|
1968
1591
|
} catch (error) {
|
|
1969
|
-
console.warn(
|
|
1592
|
+
console.warn(
|
|
1593
|
+
"⚠ Failed to download logo from URL:",
|
|
1594
|
+
error instanceof Error ? error.message : String(error)
|
|
1595
|
+
);
|
|
1970
1596
|
}
|
|
1971
1597
|
} else {
|
|
1972
1598
|
let logoPath;
|
|
1973
1599
|
if (entryPointFile && !path__namespace.isAbsolute(customLogo)) {
|
|
1974
1600
|
const entryDir = path__namespace.dirname(entryPointFile);
|
|
1975
1601
|
logoPath = path__namespace.resolve(entryDir, customLogo);
|
|
1976
|
-
console.log(
|
|
1602
|
+
console.log(
|
|
1603
|
+
`📍 Resolving logo path relative to entry point: ${logoPath}`
|
|
1604
|
+
);
|
|
1977
1605
|
} else {
|
|
1978
1606
|
logoPath = path__namespace.resolve(customLogo);
|
|
1979
1607
|
}
|
|
1980
1608
|
if (fs__namespace.existsSync(logoPath)) {
|
|
1981
1609
|
logoBuffer = fs__namespace.readFileSync(logoPath);
|
|
1982
|
-
|
|
1610
|
+
const ext = path__namespace.extname(logoPath);
|
|
1611
|
+
logoFilename = `logo${ext}`;
|
|
1983
1612
|
console.log("✓ Added custom logo from local file");
|
|
1984
1613
|
} else {
|
|
1985
1614
|
console.warn(`⚠ Custom logo file not found: ${logoPath}`);
|
|
@@ -1990,17 +1619,52 @@ For autonomous packages, follow the build instructions above.
|
|
|
1990
1619
|
const currentDir = path__namespace.dirname(new URL(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href).pathname);
|
|
1991
1620
|
let logoPath = path__namespace.join(currentDir, "assets", "logo_1_small.jpg");
|
|
1992
1621
|
if (!fs__namespace.existsSync(logoPath)) {
|
|
1993
|
-
logoPath = path__namespace.join(
|
|
1622
|
+
logoPath = path__namespace.join(
|
|
1623
|
+
currentDir,
|
|
1624
|
+
"..",
|
|
1625
|
+
"docs",
|
|
1626
|
+
"MCP",
|
|
1627
|
+
"icons",
|
|
1628
|
+
"logo_1_small.jpg"
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
if (!fs__namespace.existsSync(logoPath)) {
|
|
1632
|
+
logoPath = path__namespace.join(
|
|
1633
|
+
process.cwd(),
|
|
1634
|
+
"docs",
|
|
1635
|
+
"MCP",
|
|
1636
|
+
"icons",
|
|
1637
|
+
"logo_1_small.jpg"
|
|
1638
|
+
);
|
|
1994
1639
|
}
|
|
1995
1640
|
if (!fs__namespace.existsSync(logoPath)) {
|
|
1996
|
-
logoPath = path__namespace.join(
|
|
1641
|
+
logoPath = path__namespace.join(
|
|
1642
|
+
process.cwd(),
|
|
1643
|
+
"node_modules",
|
|
1644
|
+
"@alcyone-labs",
|
|
1645
|
+
"arg-parser",
|
|
1646
|
+
"dist",
|
|
1647
|
+
"assets",
|
|
1648
|
+
"logo_1_small.jpg"
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
if (!fs__namespace.existsSync(logoPath)) {
|
|
1652
|
+
logoPath = path__namespace.join(
|
|
1653
|
+
process.cwd(),
|
|
1654
|
+
"dist",
|
|
1655
|
+
"assets",
|
|
1656
|
+
"logo_1_small.jpg"
|
|
1657
|
+
);
|
|
1997
1658
|
}
|
|
1998
1659
|
if (fs__namespace.existsSync(logoPath)) {
|
|
1999
1660
|
logoBuffer = fs__namespace.readFileSync(logoPath);
|
|
2000
|
-
|
|
1661
|
+
const ext = path__namespace.extname(logoPath);
|
|
1662
|
+
logoFilename = `logo${ext}`;
|
|
2001
1663
|
console.log("✓ Added default logo to build folder");
|
|
2002
1664
|
} else {
|
|
2003
|
-
console.warn(
|
|
1665
|
+
console.warn(
|
|
1666
|
+
"⚠ No logo found (custom or default), build folder will be created without icon"
|
|
1667
|
+
);
|
|
2004
1668
|
return void 0;
|
|
2005
1669
|
}
|
|
2006
1670
|
}
|
|
@@ -2010,260 +1674,89 @@ For autonomous packages, follow the build instructions above.
|
|
|
2010
1674
|
}
|
|
2011
1675
|
return void 0;
|
|
2012
1676
|
} catch (error) {
|
|
2013
|
-
console.warn(
|
|
1677
|
+
console.warn(
|
|
1678
|
+
"⚠ Failed to add logo to build folder:",
|
|
1679
|
+
error instanceof Error ? error.message : String(error)
|
|
1680
|
+
);
|
|
2014
1681
|
return void 0;
|
|
2015
1682
|
}
|
|
2016
1683
|
}
|
|
2017
|
-
/**
|
|
2018
|
-
* Processes CLI source code to replace global console with MCP-compliant Logger
|
|
2019
|
-
*/
|
|
2020
|
-
processCliSourceForMcp(cliSource) {
|
|
2021
|
-
const consoleReplacement = `import { createMcpLogger } from '@alcyone-labs/arg-parser';
|
|
2022
|
-
|
|
2023
|
-
// Replace global console with MCP-compliant logger for DXT packages
|
|
2024
|
-
const mcpLogger = createMcpLogger('[CLI]');
|
|
2025
|
-
const originalConsole = globalThis.console;
|
|
2026
|
-
globalThis.console = {
|
|
2027
|
-
...originalConsole,
|
|
2028
|
-
log: (...args) => mcpLogger.info(...args),
|
|
2029
|
-
info: (...args) => mcpLogger.info(...args),
|
|
2030
|
-
warn: (...args) => mcpLogger.warn(...args),
|
|
2031
|
-
debug: (...args) => mcpLogger.debug(...args),
|
|
2032
|
-
// Keep error/trace/etc as-is since they use stderr (MCP-compliant)
|
|
2033
|
-
error: originalConsole.error,
|
|
2034
|
-
trace: originalConsole.trace,
|
|
2035
|
-
assert: originalConsole.assert,
|
|
2036
|
-
clear: originalConsole.clear,
|
|
2037
|
-
count: originalConsole.count,
|
|
2038
|
-
countReset: originalConsole.countReset,
|
|
2039
|
-
dir: originalConsole.dir,
|
|
2040
|
-
dirxml: originalConsole.dirxml,
|
|
2041
|
-
group: originalConsole.group,
|
|
2042
|
-
groupCollapsed: originalConsole.groupCollapsed,
|
|
2043
|
-
groupEnd: originalConsole.groupEnd,
|
|
2044
|
-
table: originalConsole.table,
|
|
2045
|
-
time: originalConsole.time,
|
|
2046
|
-
timeEnd: originalConsole.timeEnd,
|
|
2047
|
-
timeLog: originalConsole.timeLog,
|
|
2048
|
-
timeStamp: originalConsole.timeStamp,
|
|
2049
|
-
};
|
|
2050
|
-
|
|
2051
|
-
`;
|
|
2052
|
-
const lines = cliSource.split("\n");
|
|
2053
|
-
let lastImportIndex = -1;
|
|
2054
|
-
for (let i = 0; i < lines.length; i++) {
|
|
2055
|
-
const line = lines[i].trim();
|
|
2056
|
-
if (line.startsWith("import ") && line.includes("from")) {
|
|
2057
|
-
lastImportIndex = i;
|
|
2058
|
-
} else if (line && !line.startsWith("//") && !line.startsWith("/*") && lastImportIndex >= 0) {
|
|
2059
|
-
break;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
if (lastImportIndex >= 0) {
|
|
2063
|
-
lines.splice(lastImportIndex + 1, 0, "", ...consoleReplacement.trim().split("\n"));
|
|
2064
|
-
return lines.join("\n");
|
|
2065
|
-
} else {
|
|
2066
|
-
return consoleReplacement + cliSource;
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
/**
|
|
2070
|
-
* Adds the original CLI source to the build folder for handler execution
|
|
2071
|
-
*/
|
|
2072
|
-
addOriginalCliToFolder(buildDir) {
|
|
2073
|
-
try {
|
|
2074
|
-
const appCommandName = this.argParserInstance.getAppCommandName();
|
|
2075
|
-
const appName = this.argParserInstance.getAppName();
|
|
2076
|
-
const possibleCliFiles = [
|
|
2077
|
-
// Current working directory common patterns
|
|
2078
|
-
path__namespace.join(process.cwd(), "index.js"),
|
|
2079
|
-
path__namespace.join(process.cwd(), "index.mjs"),
|
|
2080
|
-
path__namespace.join(process.cwd(), "cli.js"),
|
|
2081
|
-
path__namespace.join(process.cwd(), "cli.mjs"),
|
|
2082
|
-
path__namespace.join(process.cwd(), "main.js"),
|
|
2083
|
-
path__namespace.join(process.cwd(), "main.mjs"),
|
|
2084
|
-
// Look for files with the app command name
|
|
2085
|
-
path__namespace.join(process.cwd(), `${appCommandName}.js`),
|
|
2086
|
-
path__namespace.join(process.cwd(), `${appCommandName}.mjs`),
|
|
2087
|
-
// Look for files with the app command name (sanitized)
|
|
2088
|
-
path__namespace.join(process.cwd(), `${appCommandName.replace(/[^a-zA-Z0-9-]/g, "-")}.js`),
|
|
2089
|
-
path__namespace.join(process.cwd(), `${appCommandName.replace(/[^a-zA-Z0-9-]/g, "-")}.mjs`),
|
|
2090
|
-
// Look for files with app name patterns
|
|
2091
|
-
path__namespace.join(process.cwd(), `${appName.toLowerCase().replace(/\s+/g, "-")}-cli.js`),
|
|
2092
|
-
path__namespace.join(process.cwd(), `${appName.toLowerCase().replace(/\s+/g, "-")}-cli.mjs`),
|
|
2093
|
-
// Look for files with first word of app name + cli
|
|
2094
|
-
path__namespace.join(process.cwd(), `${appName.split(" ")[0].toLowerCase()}-cli.js`),
|
|
2095
|
-
path__namespace.join(process.cwd(), `${appName.split(" ")[0].toLowerCase()}-cli.mjs`)
|
|
2096
|
-
];
|
|
2097
|
-
let cliSourcePath = null;
|
|
2098
|
-
for (const filePath of possibleCliFiles) {
|
|
2099
|
-
if (fs__namespace.existsSync(filePath)) {
|
|
2100
|
-
cliSourcePath = filePath;
|
|
2101
|
-
break;
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
if (cliSourcePath) {
|
|
2105
|
-
let cliSource = fs__namespace.readFileSync(cliSourcePath, "utf8");
|
|
2106
|
-
cliSource = cliSource.replace(
|
|
2107
|
-
/import\s*{\s*([^}]+)\s*}\s*from\s*['"][^'"]*\/dist\/index\.mjs['"];?/g,
|
|
2108
|
-
"import { $1 } from '@alcyone-labs/arg-parser';"
|
|
2109
|
-
);
|
|
2110
|
-
cliSource = cliSource.replace(
|
|
2111
|
-
/import\s+(\w+)\s+from\s*['"][^'"]*\/dist\/index\.mjs['"];?/g,
|
|
2112
|
-
"import $1 from '@alcyone-labs/arg-parser';"
|
|
2113
|
-
);
|
|
2114
|
-
cliSource = this.processCliSourceForMcp(cliSource);
|
|
2115
|
-
const parserVariableMatch = cliSource.match(/const\s+(\w+)\s*=\s*ArgParser\.withMcp\(/);
|
|
2116
|
-
if (parserVariableMatch) {
|
|
2117
|
-
const parserVariable = parserVariableMatch[1];
|
|
2118
|
-
cliSource += `
|
|
2119
|
-
|
|
2120
|
-
// Export the parser instance for MCP server use
|
|
2121
|
-
export default ${parserVariable};
|
|
2122
|
-
|
|
2123
|
-
// Add debugging for main execution
|
|
2124
|
-
console.error('[MCP-DEBUG] CLI source loaded, checking execution context...');
|
|
2125
|
-
console.error('[MCP-DEBUG] import.meta.url:', import.meta.url);
|
|
2126
|
-
console.error('[MCP-DEBUG] process.argv[1]:', process.argv[1]);
|
|
2127
|
-
|
|
2128
|
-
// Ensure MCP server processes don't exit prematurely
|
|
2129
|
-
console.error('[MCP-DEBUG] Process argv:', process.argv);
|
|
2130
|
-
console.error('[MCP-DEBUG] Checking for serve command...');
|
|
2131
|
-
|
|
2132
|
-
if (process.argv.includes('serve')) {
|
|
2133
|
-
console.error('[MCP-DEBUG] Detected serve command, setting up MCP server lifecycle...');
|
|
2134
|
-
|
|
2135
|
-
// Override the original parse method to handle async MCP server
|
|
2136
|
-
const originalParse = ${parserVariable}.parse;
|
|
2137
|
-
${parserVariable}.parse = async function(args) {
|
|
2138
|
-
console.error('[MCP-DEBUG] Starting parse with args:', args);
|
|
2139
|
-
|
|
2140
|
-
try {
|
|
2141
|
-
const result = originalParse.call(this, args);
|
|
2142
|
-
console.error('[MCP-DEBUG] Parse result:', typeof result, result?.constructor?.name);
|
|
2143
|
-
|
|
2144
|
-
// If result is a Promise (MCP server), await it and keep process alive
|
|
2145
|
-
if (result && typeof result.then === 'function') {
|
|
2146
|
-
console.error('[MCP-DEBUG] Detected Promise result, awaiting...');
|
|
2147
|
-
const mcpResult = await result;
|
|
2148
|
-
console.error('[MCP-DEBUG] MCP server started, keeping process alive...');
|
|
2149
|
-
|
|
2150
|
-
// Keep the process alive indefinitely for MCP server
|
|
2151
|
-
const keepAlive = setInterval(() => {
|
|
2152
|
-
// Do nothing, just keep the event loop alive
|
|
2153
|
-
}, 30000);
|
|
2154
|
-
|
|
2155
|
-
// Handle graceful shutdown
|
|
2156
|
-
process.on('SIGINT', () => {
|
|
2157
|
-
console.error('[MCP-INFO] Received SIGINT, shutting down gracefully...');
|
|
2158
|
-
clearInterval(keepAlive);
|
|
2159
|
-
process.exit(0);
|
|
2160
|
-
});
|
|
2161
|
-
|
|
2162
|
-
process.on('SIGTERM', () => {
|
|
2163
|
-
console.error('[MCP-INFO] Received SIGTERM, shutting down gracefully...');
|
|
2164
|
-
clearInterval(keepAlive);
|
|
2165
|
-
process.exit(0);
|
|
2166
|
-
});
|
|
2167
|
-
|
|
2168
|
-
return mcpResult;
|
|
2169
|
-
} else {
|
|
2170
|
-
console.error('[MCP-DEBUG] Non-Promise result, returning normally');
|
|
2171
|
-
return result;
|
|
2172
|
-
}
|
|
2173
|
-
} catch (error) {
|
|
2174
|
-
console.error('[MCP-ERROR] Error in parse:', error);
|
|
2175
|
-
throw error;
|
|
2176
|
-
}
|
|
2177
|
-
};
|
|
2178
|
-
}
|
|
2179
|
-
`;
|
|
2180
|
-
} else {
|
|
2181
|
-
console.warn("⚠ Could not find ArgParser instance in CLI source, MCP server may not work properly");
|
|
2182
|
-
}
|
|
2183
|
-
const serverDir = path__namespace.join(buildDir, "server");
|
|
2184
|
-
if (!fs__namespace.existsSync(serverDir)) {
|
|
2185
|
-
fs__namespace.mkdirSync(serverDir, { recursive: true });
|
|
2186
|
-
}
|
|
2187
|
-
fs__namespace.writeFileSync(path__namespace.join(serverDir, "original-cli.mjs"), cliSource);
|
|
2188
|
-
console.log(`✓ Added original CLI source to build folder: ${path__namespace.basename(cliSourcePath)}`);
|
|
2189
|
-
} else {
|
|
2190
|
-
console.warn("⚠ Original CLI source not found, handlers may not work properly");
|
|
2191
|
-
console.warn(" Searched for:", possibleCliFiles.map((f) => path__namespace.basename(f)).join(", "));
|
|
2192
|
-
}
|
|
2193
|
-
} catch (error) {
|
|
2194
|
-
console.warn("⚠ Failed to add original CLI source:", error instanceof Error ? error.message : String(error));
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
1684
|
/**
|
|
2198
1685
|
* Builds a complete DXT package using TSDown CLI for autonomous execution
|
|
2199
1686
|
*/
|
|
2200
|
-
async buildDxtWithTsdown(entryPointFile, outputDir = "./dxt") {
|
|
1687
|
+
async buildDxtWithTsdown(entryPointFile, outputDir = "./dxt", withNodeModules = false) {
|
|
2201
1688
|
try {
|
|
2202
1689
|
console.log(simpleChalk.cyan("🔧 Building DXT package with TSDown..."));
|
|
2203
|
-
const
|
|
1690
|
+
const projectRoot = this.findProjectRoot(entryPointFile);
|
|
1691
|
+
const absoluteEntryPath = path__namespace.resolve(entryPointFile);
|
|
1692
|
+
const relativeEntryPath = path__namespace.relative(projectRoot, absoluteEntryPath);
|
|
2204
1693
|
const entryFileName = path__namespace.basename(entryPointFile);
|
|
2205
1694
|
console.log(simpleChalk.gray(`Entry point: ${entryPointFile}`));
|
|
2206
|
-
console.log(simpleChalk.gray(`
|
|
1695
|
+
console.log(simpleChalk.gray(`Project root: ${projectRoot}`));
|
|
1696
|
+
console.log(simpleChalk.gray(`Relative entry path: ${relativeEntryPath}`));
|
|
2207
1697
|
const dxtIgnorePath = this.getDxtIgnoreTemplatePath();
|
|
2208
1698
|
if (fs__namespace.existsSync(dxtIgnorePath)) {
|
|
2209
|
-
fs__namespace.copyFileSync(dxtIgnorePath, path__namespace.join(
|
|
1699
|
+
fs__namespace.copyFileSync(dxtIgnorePath, path__namespace.join(projectRoot, ".dxtignore"));
|
|
2210
1700
|
}
|
|
1701
|
+
const serverInfo = this.extractMcpServerInfo();
|
|
1702
|
+
const logoFilename = await this.addLogoToFolder(
|
|
1703
|
+
projectRoot,
|
|
1704
|
+
serverInfo,
|
|
1705
|
+
entryPointFile
|
|
1706
|
+
);
|
|
1707
|
+
console.log(
|
|
1708
|
+
logoFilename ? simpleChalk.gray(`✓ Logo prepared: ${logoFilename}`) : simpleChalk.gray("⚠ No logo available")
|
|
1709
|
+
);
|
|
2211
1710
|
const originalCwd = process.cwd();
|
|
2212
1711
|
try {
|
|
2213
|
-
process.chdir(
|
|
1712
|
+
process.chdir(projectRoot);
|
|
2214
1713
|
const { build } = await import("tsdown");
|
|
2215
|
-
console.log(simpleChalk.gray(`Building with TSDown: ${
|
|
1714
|
+
console.log(simpleChalk.gray(`Building with TSDown: ${relativeEntryPath}`));
|
|
1715
|
+
console.log(
|
|
1716
|
+
simpleChalk.green(
|
|
1717
|
+
`${withNodeModules ? "with node_modules" : "without node_modules"}`
|
|
1718
|
+
)
|
|
1719
|
+
);
|
|
2216
1720
|
const buildConfig = {
|
|
2217
|
-
entry: [
|
|
2218
|
-
outDir: path__namespace.resolve(
|
|
2219
|
-
format: ["
|
|
1721
|
+
entry: [relativeEntryPath],
|
|
1722
|
+
outDir: path__namespace.resolve(originalCwd, outputDir),
|
|
1723
|
+
format: ["es"],
|
|
2220
1724
|
target: "node22",
|
|
2221
|
-
|
|
1725
|
+
define: {
|
|
1726
|
+
// Define any compile-time constants
|
|
1727
|
+
NODE_ENV: '"production"'
|
|
1728
|
+
},
|
|
2222
1729
|
minify: false,
|
|
2223
1730
|
sourcemap: false,
|
|
2224
|
-
|
|
1731
|
+
// Remove all output folders and artefacts
|
|
1732
|
+
clean: [outputDir, "./.dxtignore", `${outputDir}.dxt`],
|
|
2225
1733
|
silent: process.env["NO_SILENCE"] !== "1",
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
}
|
|
1734
|
+
external: (_, importer) => withNodeModules ? importer == null ? void 0 : importer.includes("node_modules") : false,
|
|
1735
|
+
noExternal: (_, importer) => withNodeModules ? (importer == null ? void 0 : importer.includes("node_modules")) === false : true,
|
|
1736
|
+
copy: async (options) => {
|
|
1737
|
+
const outputPaths = [
|
|
1738
|
+
"package.json"
|
|
1739
|
+
];
|
|
1740
|
+
if (withNodeModules) {
|
|
1741
|
+
console.log(
|
|
1742
|
+
simpleChalk.gray(
|
|
1743
|
+
"📦 Including node_modules in bundle (may take longer)..."
|
|
1744
|
+
)
|
|
1745
|
+
);
|
|
1746
|
+
outputPaths.push("node_modules");
|
|
1747
|
+
}
|
|
1748
|
+
if (logoFilename) {
|
|
1749
|
+
const logoPath = path__namespace.join(process.cwd(), logoFilename);
|
|
1750
|
+
if (fs__namespace.existsSync(logoPath)) {
|
|
1751
|
+
console.log(simpleChalk.gray(`Adding logo from: ${logoPath}`));
|
|
1752
|
+
outputPaths.push({
|
|
1753
|
+
from: logoPath,
|
|
1754
|
+
to: path__namespace.join(options.outDir, logoFilename)
|
|
1755
|
+
});
|
|
2244
1756
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
],
|
|
2249
|
-
external: [
|
|
2250
|
-
// Node.js built-ins only - everything else should be bundled for true autonomy
|
|
2251
|
-
"stream",
|
|
2252
|
-
"fs",
|
|
2253
|
-
"path",
|
|
2254
|
-
"url",
|
|
2255
|
-
"util",
|
|
2256
|
-
"events",
|
|
2257
|
-
"child_process",
|
|
2258
|
-
"os",
|
|
2259
|
-
"tty",
|
|
2260
|
-
"process",
|
|
2261
|
-
"crypto",
|
|
2262
|
-
"http",
|
|
2263
|
-
"https",
|
|
2264
|
-
"net",
|
|
2265
|
-
"zlib"
|
|
2266
|
-
],
|
|
1757
|
+
}
|
|
1758
|
+
return outputPaths;
|
|
1759
|
+
},
|
|
2267
1760
|
platform: "node",
|
|
2268
1761
|
plugins: []
|
|
2269
1762
|
};
|
|
@@ -2282,262 +1775,40 @@ export default ${JSON.stringify(buildConfig, null, 2)};
|
|
|
2282
1775
|
// To run manually:
|
|
2283
1776
|
// npx tsdown -c tsdown.config.dxt.ts
|
|
2284
1777
|
`;
|
|
2285
|
-
fs__namespace.writeFileSync(
|
|
2286
|
-
|
|
1778
|
+
fs__namespace.writeFileSync(
|
|
1779
|
+
path__namespace.join("dxt", "tsdown.config.dxt.ts"),
|
|
1780
|
+
configContent
|
|
1781
|
+
);
|
|
1782
|
+
console.log(
|
|
1783
|
+
simpleChalk.gray("📝 Debug config written to dxt/tsdown.config.dxt.ts")
|
|
1784
|
+
);
|
|
2287
1785
|
}
|
|
2288
1786
|
await build(buildConfig);
|
|
2289
1787
|
console.log(simpleChalk.green("✅ TSDown bundling completed"));
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
const { build } = await import("tsdown");
|
|
2307
|
-
console.log(simpleChalk.cyan("🔧 Bundling CLI with TSDown for autonomous execution..."));
|
|
2308
|
-
const configContent = this.getTsdownConfigContent();
|
|
2309
|
-
const localConfigPath = path__namespace.join(serverDir, "tsdown.config.mjs");
|
|
2310
|
-
fs__namespace.writeFileSync(localConfigPath, configContent);
|
|
2311
|
-
const originalCliPath = path__namespace.join(serverDir, "original-cli.mjs");
|
|
2312
|
-
if (!fs__namespace.existsSync(originalCliPath)) {
|
|
2313
|
-
console.warn(simpleChalk.yellow("⚠ Original CLI not found, skipping TSDown bundling"));
|
|
2314
|
-
return null;
|
|
2315
|
-
}
|
|
2316
|
-
const buildOptions = {
|
|
2317
|
-
entry: ["original-cli.mjs"],
|
|
2318
|
-
// Use relative path since we'll chdir to serverDir
|
|
2319
|
-
outDir: ".",
|
|
2320
|
-
// Output to current directory (serverDir)
|
|
2321
|
-
format: "esm",
|
|
2322
|
-
target: "node22",
|
|
2323
|
-
// Bundle EVERYTHING except Node.js built-ins for true autonomy
|
|
2324
|
-
noExternal: (id) => {
|
|
2325
|
-
if (!id.startsWith("node:") && !this.isNodeBuiltin(id)) return true;
|
|
2326
|
-
return false;
|
|
2327
|
-
},
|
|
2328
|
-
minify: false,
|
|
2329
|
-
sourcemap: false,
|
|
2330
|
-
clean: false,
|
|
2331
|
-
outExtension: () => ({ js: ".bundled.mjs" }),
|
|
2332
|
-
alias: {
|
|
2333
|
-
// Alias chalk to SimpleChalk for autonomous builds
|
|
2334
|
-
chalk: path__namespace.resolve(process.cwd(), "node_modules/@alcyone-labs/arg-parser/dist/SimpleChalk.mjs")
|
|
2335
|
-
},
|
|
2336
|
-
external: [
|
|
2337
|
-
// Only Node.js built-ins - everything else gets bundled for true autonomy
|
|
2338
|
-
"node:stream",
|
|
2339
|
-
"node:fs",
|
|
2340
|
-
"node:path",
|
|
2341
|
-
"node:url",
|
|
2342
|
-
"node:util",
|
|
2343
|
-
"node:events",
|
|
2344
|
-
"node:child_process",
|
|
2345
|
-
"node:os",
|
|
2346
|
-
"node:tty",
|
|
2347
|
-
"node:process",
|
|
2348
|
-
"node:crypto",
|
|
2349
|
-
"node:http",
|
|
2350
|
-
"node:https",
|
|
2351
|
-
"node:net",
|
|
2352
|
-
"node:zlib",
|
|
2353
|
-
"node:fs/promises",
|
|
2354
|
-
"node:timers",
|
|
2355
|
-
"stream",
|
|
2356
|
-
"fs",
|
|
2357
|
-
"path",
|
|
2358
|
-
"url",
|
|
2359
|
-
"util",
|
|
2360
|
-
"events",
|
|
2361
|
-
"child_process",
|
|
2362
|
-
"os",
|
|
2363
|
-
"tty",
|
|
2364
|
-
"process",
|
|
2365
|
-
"crypto",
|
|
2366
|
-
"http",
|
|
2367
|
-
"https",
|
|
2368
|
-
"net",
|
|
2369
|
-
"zlib",
|
|
2370
|
-
"fs/promises",
|
|
2371
|
-
"timers",
|
|
2372
|
-
"timers/promises",
|
|
2373
|
-
"perf_hooks",
|
|
2374
|
-
"async_hooks",
|
|
2375
|
-
"inspector",
|
|
2376
|
-
"v8",
|
|
2377
|
-
"vm",
|
|
2378
|
-
"assert",
|
|
2379
|
-
"constants",
|
|
2380
|
-
"module",
|
|
2381
|
-
"repl",
|
|
2382
|
-
"string_decoder",
|
|
2383
|
-
"punycode",
|
|
2384
|
-
"domain",
|
|
2385
|
-
"querystring",
|
|
2386
|
-
"readline",
|
|
2387
|
-
"worker_threads",
|
|
2388
|
-
"cluster",
|
|
2389
|
-
"dgram",
|
|
2390
|
-
"dns",
|
|
2391
|
-
"buffer"
|
|
2392
|
-
],
|
|
2393
|
-
platform: "node",
|
|
2394
|
-
plugins: [],
|
|
2395
|
-
// Resolve local dependencies properly
|
|
2396
|
-
resolve: {
|
|
2397
|
-
alias: {
|
|
2398
|
-
// Handle local monorepo dependencies
|
|
2399
|
-
"@alcyone-labs/arg-parser": path__namespace.resolve(process.cwd())
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
};
|
|
2403
|
-
const originalCwd = process.cwd();
|
|
2404
|
-
try {
|
|
2405
|
-
process.chdir(serverDir);
|
|
2406
|
-
await build(buildOptions);
|
|
1788
|
+
const detectedOutputFile = this.detectTsdownOutputFile(
|
|
1789
|
+
outputDir,
|
|
1790
|
+
entryFileName
|
|
1791
|
+
);
|
|
1792
|
+
await this.setupDxtPackageFiles(
|
|
1793
|
+
entryPointFile,
|
|
1794
|
+
outputDir,
|
|
1795
|
+
detectedOutputFile ?? void 0,
|
|
1796
|
+
logoFilename ?? "logo.jpg"
|
|
1797
|
+
);
|
|
1798
|
+
console.log(simpleChalk.cyan("📦 DXT package ready for packing"));
|
|
1799
|
+
console.log(
|
|
1800
|
+
simpleChalk.gray(
|
|
1801
|
+
`To complete the process, run: npx @anthropic-ai/dxt pack ${outputDir}/`
|
|
1802
|
+
)
|
|
1803
|
+
);
|
|
2407
1804
|
} finally {
|
|
2408
1805
|
process.chdir(originalCwd);
|
|
2409
1806
|
}
|
|
2410
|
-
const possibleBundledFiles = [
|
|
2411
|
-
"original-cli.bundled.mjs",
|
|
2412
|
-
"original-cli.js",
|
|
2413
|
-
"original-cli.mjs"
|
|
2414
|
-
];
|
|
2415
|
-
let bundledPath = null;
|
|
2416
|
-
let bundledFileName = null;
|
|
2417
|
-
for (const fileName of possibleBundledFiles) {
|
|
2418
|
-
const filePath = path__namespace.join(serverDir, fileName);
|
|
2419
|
-
if (fs__namespace.existsSync(filePath) && fileName !== "original-cli.mjs") {
|
|
2420
|
-
bundledPath = filePath;
|
|
2421
|
-
bundledFileName = fileName;
|
|
2422
|
-
break;
|
|
2423
|
-
}
|
|
2424
|
-
}
|
|
2425
|
-
if (bundledPath && bundledFileName) {
|
|
2426
|
-
console.log(simpleChalk.green(`✅ TSDown bundling completed successfully: ${bundledFileName}`));
|
|
2427
|
-
const expectedBundledPath = path__namespace.join(serverDir, "original-cli.bundled.mjs");
|
|
2428
|
-
if (bundledPath !== expectedBundledPath) {
|
|
2429
|
-
fs__namespace.renameSync(bundledPath, expectedBundledPath);
|
|
2430
|
-
bundledFileName = "original-cli.bundled.mjs";
|
|
2431
|
-
}
|
|
2432
|
-
try {
|
|
2433
|
-
fs__namespace.unlinkSync(localConfigPath);
|
|
2434
|
-
} catch (error) {
|
|
2435
|
-
}
|
|
2436
|
-
try {
|
|
2437
|
-
fs__namespace.chmodSync(expectedBundledPath, 493);
|
|
2438
|
-
} catch (error) {
|
|
2439
|
-
console.warn("⚠ Could not set executable permission on bundled file:", error instanceof Error ? error.message : String(error));
|
|
2440
|
-
}
|
|
2441
|
-
return bundledFileName;
|
|
2442
|
-
} else {
|
|
2443
|
-
console.warn(simpleChalk.yellow("⚠ TSDown bundling failed, bundled file not found"));
|
|
2444
|
-
return null;
|
|
2445
|
-
}
|
|
2446
1807
|
} catch (error) {
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
/**
|
|
2453
|
-
* Checks if a module ID is a Node.js built-in
|
|
2454
|
-
*/
|
|
2455
|
-
isNodeBuiltin(id) {
|
|
2456
|
-
const nodeBuiltins = [
|
|
2457
|
-
"stream",
|
|
2458
|
-
"fs",
|
|
2459
|
-
"path",
|
|
2460
|
-
"url",
|
|
2461
|
-
"util",
|
|
2462
|
-
"events",
|
|
2463
|
-
"child_process",
|
|
2464
|
-
"os",
|
|
2465
|
-
"tty",
|
|
2466
|
-
"process",
|
|
2467
|
-
"crypto",
|
|
2468
|
-
"http",
|
|
2469
|
-
"https",
|
|
2470
|
-
"net",
|
|
2471
|
-
"zlib",
|
|
2472
|
-
"fs/promises",
|
|
2473
|
-
"timers",
|
|
2474
|
-
"timers/promises",
|
|
2475
|
-
"perf_hooks",
|
|
2476
|
-
"async_hooks",
|
|
2477
|
-
"inspector",
|
|
2478
|
-
"v8",
|
|
2479
|
-
"vm",
|
|
2480
|
-
"assert",
|
|
2481
|
-
"constants",
|
|
2482
|
-
"module",
|
|
2483
|
-
"repl",
|
|
2484
|
-
"string_decoder",
|
|
2485
|
-
"punycode",
|
|
2486
|
-
"domain",
|
|
2487
|
-
"querystring",
|
|
2488
|
-
"readline",
|
|
2489
|
-
"worker_threads",
|
|
2490
|
-
"cluster",
|
|
2491
|
-
"dgram",
|
|
2492
|
-
"dns",
|
|
2493
|
-
"buffer"
|
|
2494
|
-
];
|
|
2495
|
-
return nodeBuiltins.includes(id) || id.startsWith("node:");
|
|
2496
|
-
}
|
|
2497
|
-
/**
|
|
2498
|
-
* Gets the TSDown configuration content as a string
|
|
2499
|
-
*/
|
|
2500
|
-
getTsdownConfigContent() {
|
|
2501
|
-
const currentDir = path__namespace.dirname(new URL(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href).pathname);
|
|
2502
|
-
const assetsConfigPath = path__namespace.join(currentDir, "..", "assets", "tsdown.dxt.config.ts");
|
|
2503
|
-
if (fs__namespace.existsSync(assetsConfigPath)) {
|
|
2504
|
-
try {
|
|
2505
|
-
const content = fs__namespace.readFileSync(assetsConfigPath, "utf-8");
|
|
2506
|
-
return content.replace('/// <reference types="tsdown" />', "").replace('import { defineConfig } from "tsdown/config";', 'import { defineConfig } from "tsdown";').replace("export default defineConfig(", "export default defineConfig(");
|
|
2507
|
-
} catch (error) {
|
|
2508
|
-
console.warn(simpleChalk.yellow("⚠ Could not read TSDown config from assets, using fallback"));
|
|
2509
|
-
}
|
|
2510
|
-
}
|
|
2511
|
-
const rootConfigPath = path__namespace.join(process.cwd(), "tsdown.dxt.config.ts");
|
|
2512
|
-
if (fs__namespace.existsSync(rootConfigPath)) {
|
|
2513
|
-
try {
|
|
2514
|
-
const content = fs__namespace.readFileSync(rootConfigPath, "utf-8");
|
|
2515
|
-
return content.replace('/// <reference types="tsdown" />', "").replace('import { defineConfig } from "tsdown/config";', 'import { defineConfig } from "tsdown";');
|
|
2516
|
-
} catch (error) {
|
|
2517
|
-
console.warn(simpleChalk.yellow("⚠ Could not read TSDown config from root, using default"));
|
|
2518
|
-
}
|
|
1808
|
+
throw new Error(
|
|
1809
|
+
`TSDown DXT build failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1810
|
+
);
|
|
2519
1811
|
}
|
|
2520
|
-
return `import { defineConfig } from "tsdown";
|
|
2521
|
-
import path from "path";
|
|
2522
|
-
|
|
2523
|
-
export default defineConfig({
|
|
2524
|
-
outDir: "server",
|
|
2525
|
-
format: ["esm", "module"],
|
|
2526
|
-
target: "node22",
|
|
2527
|
-
noExternal: () => true,
|
|
2528
|
-
minify: false,
|
|
2529
|
-
sourcemap: false,
|
|
2530
|
-
clean: false,
|
|
2531
|
-
alias: {
|
|
2532
|
-
chalk: path.resolve(process.cwd(), "node_modules/@alcyone-labs/arg-parser/dist/SimpleChalk.mjs"),
|
|
2533
|
-
},
|
|
2534
|
-
external: [
|
|
2535
|
-
"stream", "fs", "path", "url", "util", "events", "child_process",
|
|
2536
|
-
"os", "tty", "process", "crypto", "http", "https", "net", "zlib",
|
|
2537
|
-
],
|
|
2538
|
-
platform: "node",
|
|
2539
|
-
plugins: [],
|
|
2540
|
-
});`;
|
|
2541
1812
|
}
|
|
2542
1813
|
/**
|
|
2543
1814
|
* Gets the path to the .dxtignore template file in assets
|
|
@@ -2545,9 +1816,22 @@ export default defineConfig({
|
|
|
2545
1816
|
getDxtIgnoreTemplatePath() {
|
|
2546
1817
|
const possiblePaths = [
|
|
2547
1818
|
// 1. From the built library assets (when installed via npm)
|
|
2548
|
-
path__namespace.join(
|
|
1819
|
+
path__namespace.join(
|
|
1820
|
+
path__namespace.dirname(new URL(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href).pathname),
|
|
1821
|
+
"..",
|
|
1822
|
+
"assets",
|
|
1823
|
+
".dxtignore.template"
|
|
1824
|
+
),
|
|
2549
1825
|
// 2. From node_modules/@alcyone-labs/arg-parser/dist/assets (when installed via npm)
|
|
2550
|
-
path__namespace.join(
|
|
1826
|
+
path__namespace.join(
|
|
1827
|
+
process.cwd(),
|
|
1828
|
+
"node_modules",
|
|
1829
|
+
"@alcyone-labs",
|
|
1830
|
+
"arg-parser",
|
|
1831
|
+
"dist",
|
|
1832
|
+
"assets",
|
|
1833
|
+
".dxtignore.template"
|
|
1834
|
+
),
|
|
2551
1835
|
// 3. From the root directory (development/local build)
|
|
2552
1836
|
path__namespace.join(process.cwd(), ".dxtignore.template"),
|
|
2553
1837
|
// 4. From the library root (when using local file dependency)
|
|
@@ -2565,8 +1849,8 @@ export default defineConfig({
|
|
|
2565
1849
|
/**
|
|
2566
1850
|
* Sets up DXT package files (manifest.json) in the output directory
|
|
2567
1851
|
*/
|
|
2568
|
-
async setupDxtPackageFiles(entryPointFile, outputDir = "./dxt") {
|
|
2569
|
-
var _a, _b, _c, _d, _e;
|
|
1852
|
+
async setupDxtPackageFiles(entryPointFile, outputDir = "./dxt", actualOutputFilename, logoFilename = "logo.jpg") {
|
|
1853
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2570
1854
|
const dxtDir = path__namespace.resolve(process.cwd(), outputDir);
|
|
2571
1855
|
if (!fs__namespace.existsSync(dxtDir)) {
|
|
2572
1856
|
throw new Error(`TSDown output directory (${outputDir}) not found`);
|
|
@@ -2588,11 +1872,15 @@ export default defineConfig({
|
|
|
2588
1872
|
description: tool.description
|
|
2589
1873
|
}));
|
|
2590
1874
|
} catch (error) {
|
|
2591
|
-
console.warn(
|
|
2592
|
-
|
|
1875
|
+
console.warn(
|
|
1876
|
+
simpleChalk.yellow(
|
|
1877
|
+
`Warning: Could not generate unified tool list: ${error instanceof Error ? error.message : String(error)}`
|
|
1878
|
+
)
|
|
1879
|
+
);
|
|
1880
|
+
const mainFlags = this.argParserInstance.flags;
|
|
2593
1881
|
const properties2 = {};
|
|
2594
1882
|
const required2 = [];
|
|
2595
|
-
for (const flag of
|
|
1883
|
+
for (const flag of mainFlags) {
|
|
2596
1884
|
if (flag.name === "help" || flag.name.startsWith("s-")) continue;
|
|
2597
1885
|
properties2[flag.name] = {
|
|
2598
1886
|
type: getJsonSchemaTypeFromFlag(flag.type),
|
|
@@ -2609,59 +1897,24 @@ export default defineConfig({
|
|
|
2609
1897
|
}
|
|
2610
1898
|
}
|
|
2611
1899
|
const commandName = this.argParserInstance.getAppCommandName();
|
|
2612
|
-
tools = [
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
}
|
|
2617
|
-
const envVars = {};
|
|
2618
|
-
const userConfig = {};
|
|
2619
|
-
const mainFlags = this.argParserInstance.flags;
|
|
2620
|
-
for (const flag of mainFlags) {
|
|
2621
|
-
const envVar = flag.env || flag.envVar;
|
|
2622
|
-
if (envVar) {
|
|
2623
|
-
envVars[envVar] = `\${user_config.${envVar}}`;
|
|
2624
|
-
userConfig[envVar] = {
|
|
2625
|
-
type: "string",
|
|
2626
|
-
title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
2627
|
-
description: flag.description || `${envVar} environment variable`,
|
|
2628
|
-
required: true,
|
|
2629
|
-
// Always require env vars in user_config for better UX
|
|
2630
|
-
sensitive: true
|
|
2631
|
-
// Assume env vars are sensitive
|
|
2632
|
-
};
|
|
2633
|
-
}
|
|
2634
|
-
}
|
|
2635
|
-
if (typeof this.argParserInstance.getTools === "function") {
|
|
2636
|
-
const tools2 = this.argParserInstance.getTools();
|
|
2637
|
-
for (const [, toolConfig] of tools2) {
|
|
2638
|
-
const toolFlags = toolConfig.flags || [];
|
|
2639
|
-
for (const flag of toolFlags) {
|
|
2640
|
-
const envVar = flag.env || flag.envVar;
|
|
2641
|
-
if (envVar && !envVars[envVar]) {
|
|
2642
|
-
envVars[envVar] = `\${user_config.${envVar}}`;
|
|
2643
|
-
userConfig[envVar] = {
|
|
2644
|
-
type: "string",
|
|
2645
|
-
title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
2646
|
-
description: flag.description || `${envVar} environment variable`,
|
|
2647
|
-
required: true,
|
|
2648
|
-
// Always require env vars in user_config for better UX
|
|
2649
|
-
sensitive: true
|
|
2650
|
-
// Assume env vars are sensitive
|
|
2651
|
-
};
|
|
2652
|
-
}
|
|
1900
|
+
tools = [
|
|
1901
|
+
{
|
|
1902
|
+
name: commandName || packageInfo.name || "cli-tool",
|
|
1903
|
+
description: packageInfo.description || this.argParserInstance.getDescription() || "CLI tool"
|
|
2653
1904
|
}
|
|
2654
|
-
|
|
1905
|
+
];
|
|
2655
1906
|
}
|
|
1907
|
+
const { envVars, userConfig } = this.generateEnvAndUserConfig();
|
|
2656
1908
|
const serverInfo = this.extractMcpServerInfo();
|
|
2657
|
-
let
|
|
2658
|
-
if (
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
1909
|
+
let entryFileName;
|
|
1910
|
+
if (actualOutputFilename) {
|
|
1911
|
+
entryFileName = actualOutputFilename;
|
|
1912
|
+
} else {
|
|
1913
|
+
const projectRoot = this.findProjectRoot(entryPointFile);
|
|
1914
|
+
const absoluteEntryPath = path__namespace.resolve(entryPointFile);
|
|
1915
|
+
const relativeEntryPath = path__namespace.relative(projectRoot, absoluteEntryPath);
|
|
1916
|
+
entryFileName = relativeEntryPath.replace(/\.ts$/, ".js");
|
|
2663
1917
|
}
|
|
2664
|
-
const entryFileName = path__namespace.basename(entryPointFile);
|
|
2665
1918
|
const manifest = {
|
|
2666
1919
|
dxt_version: "0.1",
|
|
2667
1920
|
name: serverInfo.name || packageInfo.name || "mcp-server",
|
|
@@ -2679,7 +1932,10 @@ export default defineConfig({
|
|
|
2679
1932
|
command: "node",
|
|
2680
1933
|
args: [
|
|
2681
1934
|
`\${__dirname}/${entryFileName}`,
|
|
2682
|
-
"--s-mcp-serve"
|
|
1935
|
+
"--s-mcp-serve",
|
|
1936
|
+
// Overwrite the CLI config to only use stdio to avoid conflicts
|
|
1937
|
+
"--s-mcp-transport",
|
|
1938
|
+
"stdio"
|
|
2683
1939
|
],
|
|
2684
1940
|
env: envVars
|
|
2685
1941
|
}
|
|
@@ -2687,46 +1943,147 @@ export default defineConfig({
|
|
|
2687
1943
|
tools,
|
|
2688
1944
|
icon: logoFilename,
|
|
2689
1945
|
...Object.keys(userConfig).length > 0 && { user_config: userConfig },
|
|
2690
|
-
repository: {
|
|
1946
|
+
repository: ((_e = packageInfo.repository) == null ? void 0 : _e.url) ? {
|
|
2691
1947
|
type: "git",
|
|
2692
|
-
url: (
|
|
2693
|
-
},
|
|
1948
|
+
url: (_f = packageInfo.repository) == null ? void 0 : _f.url
|
|
1949
|
+
} : void 0,
|
|
2694
1950
|
license: packageInfo.license || "MIT"
|
|
2695
1951
|
};
|
|
2696
|
-
fs__namespace.writeFileSync(
|
|
1952
|
+
fs__namespace.writeFileSync(
|
|
1953
|
+
path__namespace.join(dxtDir, "manifest.json"),
|
|
1954
|
+
JSON.stringify(manifest, null, 2)
|
|
1955
|
+
);
|
|
2697
1956
|
console.log(simpleChalk.gray("✅ DXT package files set up"));
|
|
2698
1957
|
}
|
|
2699
1958
|
/**
|
|
2700
|
-
*
|
|
1959
|
+
* Detects the actual output filename generated by TSDown
|
|
2701
1960
|
*/
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
1961
|
+
detectTsdownOutputFile(outputDir, expectedBaseName) {
|
|
1962
|
+
try {
|
|
1963
|
+
const dxtDir = path__namespace.resolve(process.cwd(), outputDir);
|
|
1964
|
+
if (!fs__namespace.existsSync(dxtDir)) {
|
|
1965
|
+
console.warn(
|
|
1966
|
+
simpleChalk.yellow(`⚠ Output directory (${outputDir}) not found`)
|
|
1967
|
+
);
|
|
1968
|
+
return null;
|
|
1969
|
+
}
|
|
1970
|
+
const files = fs__namespace.readdirSync(dxtDir).filter(
|
|
1971
|
+
(file) => (file.endsWith(".js") || file.endsWith(".mjs")) && !file.includes("chunk-") && !file.includes("dist-") && !file.startsWith(".")
|
|
1972
|
+
);
|
|
1973
|
+
const baseNameWithoutExt = path__namespace.parse(expectedBaseName).name;
|
|
1974
|
+
for (const ext of [".js", ".mjs"]) {
|
|
1975
|
+
const exactMatch = `${baseNameWithoutExt}${ext}`;
|
|
1976
|
+
if (files.includes(exactMatch)) {
|
|
1977
|
+
console.log(simpleChalk.gray(`✓ Detected TSDown output: ${exactMatch}`));
|
|
1978
|
+
return exactMatch;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
const mainFiles = files.filter(
|
|
1982
|
+
(file) => !file.includes("chunk") && !file.includes("dist") && file !== "logo.jpg" && file !== "manifest.json"
|
|
1983
|
+
);
|
|
1984
|
+
if (mainFiles.length === 1) {
|
|
1985
|
+
console.log(simpleChalk.gray(`✓ Detected TSDown output: ${mainFiles[0]}`));
|
|
1986
|
+
return mainFiles[0];
|
|
1987
|
+
}
|
|
1988
|
+
if (mainFiles.length > 1) {
|
|
1989
|
+
let bestMatch = mainFiles[0];
|
|
1990
|
+
let bestScore = 0;
|
|
1991
|
+
for (const file of mainFiles) {
|
|
1992
|
+
const filePath = path__namespace.join(dxtDir, file);
|
|
1993
|
+
const stats = fs__namespace.statSync(filePath);
|
|
1994
|
+
const nameScore = file.includes(baseNameWithoutExt) ? 100 : 0;
|
|
1995
|
+
const sizeScore = Math.min(stats.size / 1e3, 50);
|
|
1996
|
+
const totalScore = nameScore + sizeScore;
|
|
1997
|
+
if (totalScore > bestScore) {
|
|
1998
|
+
bestScore = totalScore;
|
|
1999
|
+
bestMatch = file;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
console.log(
|
|
2003
|
+
simpleChalk.gray(
|
|
2004
|
+
`✓ Detected TSDown output: ${bestMatch} (best match from ${mainFiles.length} candidates)`
|
|
2005
|
+
)
|
|
2006
|
+
);
|
|
2007
|
+
return bestMatch;
|
|
2008
|
+
}
|
|
2009
|
+
console.warn(
|
|
2010
|
+
simpleChalk.yellow(`⚠ Could not detect TSDown output file in ${outputDir}`)
|
|
2011
|
+
);
|
|
2012
|
+
return null;
|
|
2013
|
+
} catch (error) {
|
|
2014
|
+
console.warn(
|
|
2015
|
+
simpleChalk.yellow(
|
|
2016
|
+
`⚠ Error detecting TSDown output: ${error instanceof Error ? error.message : String(error)}`
|
|
2017
|
+
)
|
|
2018
|
+
);
|
|
2019
|
+
return null;
|
|
2707
2020
|
}
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
path__namespace.join(
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
if (
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2021
|
+
}
|
|
2022
|
+
findProjectRoot(entryPointFile) {
|
|
2023
|
+
let currentDir = path__namespace.dirname(path__namespace.resolve(entryPointFile));
|
|
2024
|
+
let attempts = 0;
|
|
2025
|
+
const maxAttempts = 5;
|
|
2026
|
+
while (attempts < maxAttempts) {
|
|
2027
|
+
const packageJsonPath = path__namespace.join(currentDir, "package.json");
|
|
2028
|
+
if (fs__namespace.existsSync(packageJsonPath)) {
|
|
2029
|
+
return currentDir;
|
|
2030
|
+
}
|
|
2031
|
+
const parentDir = path__namespace.dirname(currentDir);
|
|
2032
|
+
if (parentDir === currentDir) {
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
currentDir = parentDir;
|
|
2036
|
+
attempts++;
|
|
2037
|
+
}
|
|
2038
|
+
throw new Error(
|
|
2039
|
+
`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.`
|
|
2040
|
+
);
|
|
2041
|
+
}
|
|
2042
|
+
/**
|
|
2043
|
+
* Generate environment variables and user configuration from ArgParser flags
|
|
2044
|
+
* @returns Object containing envVars and userConfig
|
|
2045
|
+
*/
|
|
2046
|
+
generateEnvAndUserConfig() {
|
|
2047
|
+
const envVars = {};
|
|
2048
|
+
const userConfig = {};
|
|
2049
|
+
const mainFlags = this.argParserInstance.flags;
|
|
2050
|
+
for (const flag of mainFlags) {
|
|
2051
|
+
const envVar = flag.env || flag.envVar;
|
|
2052
|
+
if (envVar) {
|
|
2053
|
+
envVars[envVar] = `\${user_config.${envVar}}`;
|
|
2054
|
+
userConfig[envVar] = {
|
|
2055
|
+
type: "string",
|
|
2056
|
+
title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
2057
|
+
description: flag.description || `${envVar} environment variable`,
|
|
2058
|
+
required: true,
|
|
2059
|
+
// Always require env vars in user_config for better UX
|
|
2060
|
+
sensitive: true
|
|
2061
|
+
// Assume env vars are sensitive
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
if (typeof this.argParserInstance.getTools === "function") {
|
|
2066
|
+
const tools = this.argParserInstance.getTools();
|
|
2067
|
+
for (const [, toolConfig] of tools) {
|
|
2068
|
+
const toolFlags = toolConfig.flags || [];
|
|
2069
|
+
for (const flag of toolFlags) {
|
|
2070
|
+
const envVar = flag.env || flag.envVar;
|
|
2071
|
+
if (envVar && !envVars[envVar]) {
|
|
2072
|
+
envVars[envVar] = `\${user_config.${envVar}}`;
|
|
2073
|
+
userConfig[envVar] = {
|
|
2074
|
+
type: "string",
|
|
2075
|
+
title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
2076
|
+
description: flag.description || `${envVar} environment variable`,
|
|
2077
|
+
required: true,
|
|
2078
|
+
// Always require env vars in user_config for better UX
|
|
2079
|
+
sensitive: true
|
|
2080
|
+
// Assume env vars are sensitive
|
|
2081
|
+
};
|
|
2082
|
+
}
|
|
2726
2083
|
}
|
|
2727
2084
|
}
|
|
2728
2085
|
}
|
|
2729
|
-
|
|
2086
|
+
return { envVars, userConfig };
|
|
2730
2087
|
}
|
|
2731
2088
|
}
|
|
2732
2089
|
class McpNotificationsManager {
|
|
@@ -2881,10 +2238,16 @@ class McpNotificationsManager {
|
|
|
2881
2238
|
sendNotificationToClient(client, type2) {
|
|
2882
2239
|
try {
|
|
2883
2240
|
if (client.connection && typeof client.connection.sendNotification === "function") {
|
|
2884
|
-
client.connection.sendNotification(
|
|
2241
|
+
client.connection.sendNotification(
|
|
2242
|
+
`notifications/${type2}/list_changed`,
|
|
2243
|
+
{}
|
|
2244
|
+
);
|
|
2885
2245
|
}
|
|
2886
2246
|
} catch (error) {
|
|
2887
|
-
console.error(
|
|
2247
|
+
console.error(
|
|
2248
|
+
`Error sending notification to client ${client.clientId}:`,
|
|
2249
|
+
error
|
|
2250
|
+
);
|
|
2888
2251
|
this.removeClient(client.clientId);
|
|
2889
2252
|
}
|
|
2890
2253
|
}
|
|
@@ -2973,7 +2336,9 @@ class McpPromptsManager {
|
|
|
2973
2336
|
return await entry.config.handler(validatedArgs);
|
|
2974
2337
|
} catch (error) {
|
|
2975
2338
|
if (error instanceof zod.z.ZodError) {
|
|
2976
|
-
throw new Error(
|
|
2339
|
+
throw new Error(
|
|
2340
|
+
`Invalid arguments for prompt '${name}': ${error.message}`
|
|
2341
|
+
);
|
|
2977
2342
|
}
|
|
2978
2343
|
throw error;
|
|
2979
2344
|
}
|
|
@@ -3173,7 +2538,9 @@ class McpResourcesManager {
|
|
|
3173
2538
|
try {
|
|
3174
2539
|
new ResourceTemplateParser(config.uriTemplate);
|
|
3175
2540
|
} catch (error) {
|
|
3176
|
-
throw new Error(
|
|
2541
|
+
throw new Error(
|
|
2542
|
+
`Invalid URI template '${config.uriTemplate}': ${error instanceof Error ? error.message : String(error)}`
|
|
2543
|
+
);
|
|
3177
2544
|
}
|
|
3178
2545
|
}
|
|
3179
2546
|
/**
|
|
@@ -3278,6 +2645,97 @@ const _FlagManager = class _FlagManager {
|
|
|
3278
2645
|
__flags = new WeakMap();
|
|
3279
2646
|
_throwForDuplicateFlags = new WeakMap();
|
|
3280
2647
|
let FlagManager = _FlagManager;
|
|
2648
|
+
function detectEntryPoint() {
|
|
2649
|
+
try {
|
|
2650
|
+
if (process.argv[1] && fs__namespace.existsSync(process.argv[1])) {
|
|
2651
|
+
return process.argv[1];
|
|
2652
|
+
}
|
|
2653
|
+
if (typeof require !== "undefined" && require.main && require.main.filename) {
|
|
2654
|
+
return require.main.filename;
|
|
2655
|
+
}
|
|
2656
|
+
return null;
|
|
2657
|
+
} catch {
|
|
2658
|
+
return null;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
function getEntryPointFromImportMeta(importMetaUrl) {
|
|
2662
|
+
if (importMetaUrl.startsWith("file://")) {
|
|
2663
|
+
return decodeURIComponent(importMetaUrl.replace("file://", ""));
|
|
2664
|
+
}
|
|
2665
|
+
return importMetaUrl;
|
|
2666
|
+
}
|
|
2667
|
+
function normalizePath(path2) {
|
|
2668
|
+
return path2.trim();
|
|
2669
|
+
}
|
|
2670
|
+
function resolveLogPath(logPath, fallbackEntryPoint) {
|
|
2671
|
+
if (typeof logPath === "string") {
|
|
2672
|
+
const normalizedPath2 = normalizePath(logPath);
|
|
2673
|
+
if (path__namespace.isAbsolute(normalizedPath2)) {
|
|
2674
|
+
return normalizedPath2;
|
|
2675
|
+
}
|
|
2676
|
+
if (normalizedPath2.startsWith("cwd:")) {
|
|
2677
|
+
const relativePath = normalizedPath2.slice(4);
|
|
2678
|
+
return path__namespace.resolve(process.cwd(), relativePath);
|
|
2679
|
+
}
|
|
2680
|
+
const entryPoint = detectEntryPoint() || fallbackEntryPoint;
|
|
2681
|
+
if (entryPoint) {
|
|
2682
|
+
return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath2);
|
|
2683
|
+
}
|
|
2684
|
+
console.warn(
|
|
2685
|
+
`Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath2}`
|
|
2686
|
+
);
|
|
2687
|
+
return path__namespace.resolve(process.cwd(), normalizedPath2);
|
|
2688
|
+
}
|
|
2689
|
+
const { path: logFilePath, relativeTo = "entry", basePath } = logPath;
|
|
2690
|
+
const normalizedPath = normalizePath(logFilePath);
|
|
2691
|
+
switch (relativeTo) {
|
|
2692
|
+
case "absolute":
|
|
2693
|
+
if (basePath) {
|
|
2694
|
+
return path__namespace.resolve(basePath, normalizedPath);
|
|
2695
|
+
}
|
|
2696
|
+
if (path__namespace.isAbsolute(normalizedPath)) {
|
|
2697
|
+
return normalizedPath;
|
|
2698
|
+
}
|
|
2699
|
+
console.warn(
|
|
2700
|
+
`Warning: relativeTo 'absolute' specified but no basePath provided and path is not absolute. Using process.cwd() as fallback. Path: ${normalizedPath}`
|
|
2701
|
+
);
|
|
2702
|
+
return path__namespace.resolve(process.cwd(), normalizedPath);
|
|
2703
|
+
case "cwd":
|
|
2704
|
+
return path__namespace.resolve(process.cwd(), normalizedPath);
|
|
2705
|
+
case "entry":
|
|
2706
|
+
default:
|
|
2707
|
+
const entryPoint = detectEntryPoint() || fallbackEntryPoint;
|
|
2708
|
+
if (entryPoint) {
|
|
2709
|
+
return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath);
|
|
2710
|
+
}
|
|
2711
|
+
console.warn(
|
|
2712
|
+
`Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath}`
|
|
2713
|
+
);
|
|
2714
|
+
return path__namespace.resolve(process.cwd(), normalizedPath);
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
function entryRelative(path2) {
|
|
2718
|
+
return {
|
|
2719
|
+
path: path2,
|
|
2720
|
+
relativeTo: "entry"
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
function cwdRelative(path2) {
|
|
2724
|
+
return {
|
|
2725
|
+
path: path2,
|
|
2726
|
+
relativeTo: "cwd"
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2729
|
+
function absolutePath(path2, basePath) {
|
|
2730
|
+
return {
|
|
2731
|
+
path: path2,
|
|
2732
|
+
relativeTo: "absolute",
|
|
2733
|
+
basePath
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
function legacyCwdPath(path2) {
|
|
2737
|
+
return `cwd:${path2}`;
|
|
2738
|
+
}
|
|
3281
2739
|
class ArgParserError extends Error {
|
|
3282
2740
|
constructor(message, cmdChain = []) {
|
|
3283
2741
|
super(message);
|
|
@@ -4675,15 +4133,14 @@ _handleBuildDxtFlag_fn = async function(processArgs, buildDxtIndex) {
|
|
|
4675
4133
|
};
|
|
4676
4134
|
_handleMcpServeFlag_fn = async function(processArgs, _mcpServeIndex) {
|
|
4677
4135
|
var _a;
|
|
4136
|
+
const transportOptions = __privateMethod(this, _ArgParserBase_instances, _parseMcpTransportOptions_fn).call(this, processArgs);
|
|
4137
|
+
const mcpServerConfig = __privateMethod(this, _ArgParserBase_instances, _getMcpServerConfiguration_fn).call(this);
|
|
4138
|
+
const effectiveLogPath = transportOptions.logPath || (mcpServerConfig == null ? void 0 : mcpServerConfig.logPath) || "./logs/mcp.log";
|
|
4139
|
+
const resolvedLogPath = resolveLogPath(effectiveLogPath);
|
|
4678
4140
|
let mcpLogger;
|
|
4679
4141
|
try {
|
|
4680
|
-
const mcpLoggerModule = await
|
|
4681
|
-
|
|
4682
|
-
)();
|
|
4683
|
-
mcpLogger = mcpLoggerModule.createMcpLogger(
|
|
4684
|
-
"MCP Serve",
|
|
4685
|
-
"./logs/mcp.log"
|
|
4686
|
-
);
|
|
4142
|
+
const mcpLoggerModule = await import("@alcyone-labs/simple-mcp-logger");
|
|
4143
|
+
mcpLogger = mcpLoggerModule.createMcpLogger("MCP Serve", resolvedLogPath);
|
|
4687
4144
|
globalThis.console = mcpLogger;
|
|
4688
4145
|
} catch {
|
|
4689
4146
|
mcpLogger = {
|
|
@@ -4694,7 +4151,6 @@ _handleMcpServeFlag_fn = async function(processArgs, _mcpServeIndex) {
|
|
|
4694
4151
|
mcpLogger.mcpError(
|
|
4695
4152
|
"Starting --s-mcp-serve system flag handler - console hijacked for MCP safety"
|
|
4696
4153
|
);
|
|
4697
|
-
const mcpServerConfig = __privateMethod(this, _ArgParserBase_instances, _getMcpServerConfiguration_fn).call(this);
|
|
4698
4154
|
if (!mcpServerConfig) {
|
|
4699
4155
|
mcpLogger.mcpError(
|
|
4700
4156
|
"No MCP server configuration found. Use withMcp() or addMcpSubCommand() to configure MCP server."
|
|
@@ -4708,13 +4164,16 @@ _handleMcpServeFlag_fn = async function(processArgs, _mcpServeIndex) {
|
|
|
4708
4164
|
mcpLogger.mcpError(
|
|
4709
4165
|
`Found MCP server configuration: ${((_a = mcpServerConfig.serverInfo) == null ? void 0 : _a.name) || "unnamed"}`
|
|
4710
4166
|
);
|
|
4711
|
-
|
|
4167
|
+
mcpLogger.mcpError(`Using log path: ${resolvedLogPath}`);
|
|
4712
4168
|
mcpLogger.mcpError(
|
|
4713
4169
|
`Transport options: ${JSON.stringify(transportOptions)}`
|
|
4714
4170
|
);
|
|
4715
4171
|
try {
|
|
4716
4172
|
mcpLogger.mcpError("Starting unified MCP server with all tools");
|
|
4717
|
-
await __privateMethod(this, _ArgParserBase_instances, _startUnifiedMcpServer_fn).call(this, mcpServerConfig,
|
|
4173
|
+
await __privateMethod(this, _ArgParserBase_instances, _startUnifiedMcpServer_fn).call(this, mcpServerConfig, {
|
|
4174
|
+
...transportOptions,
|
|
4175
|
+
logPath: resolvedLogPath
|
|
4176
|
+
});
|
|
4718
4177
|
mcpLogger.mcpError("Successfully started unified MCP server");
|
|
4719
4178
|
} catch (error) {
|
|
4720
4179
|
mcpLogger.mcpError(
|
|
@@ -4783,18 +4242,34 @@ _startUnifiedMcpServer_fn = async function(mcpServerConfig, transportOptions) {
|
|
|
4783
4242
|
await mcpParser.startMcpServerWithMultipleTransports(
|
|
4784
4243
|
serverInfo,
|
|
4785
4244
|
transportConfigs,
|
|
4786
|
-
toolOptions
|
|
4245
|
+
toolOptions,
|
|
4246
|
+
transportOptions.logPath
|
|
4787
4247
|
);
|
|
4788
4248
|
} catch (error) {
|
|
4789
4249
|
throw new Error(
|
|
4790
4250
|
`Error parsing transports configuration: ${error.message}. Expected JSON format: '[{"type":"stdio"},{"type":"sse","port":3001}]'`
|
|
4791
4251
|
);
|
|
4792
4252
|
}
|
|
4253
|
+
} else if (transportOptions.transportType) {
|
|
4254
|
+
const transportType = transportOptions.transportType;
|
|
4255
|
+
const finalTransportOptions = {
|
|
4256
|
+
port: transportOptions.port,
|
|
4257
|
+
host: transportOptions.host || "localhost",
|
|
4258
|
+
path: transportOptions.path || "/mcp"
|
|
4259
|
+
};
|
|
4260
|
+
await mcpParser.startMcpServerWithTransport(
|
|
4261
|
+
serverInfo,
|
|
4262
|
+
transportType,
|
|
4263
|
+
finalTransportOptions,
|
|
4264
|
+
toolOptions,
|
|
4265
|
+
transportOptions.logPath
|
|
4266
|
+
);
|
|
4793
4267
|
} else if (defaultTransports && defaultTransports.length > 0) {
|
|
4794
4268
|
await mcpParser.startMcpServerWithMultipleTransports(
|
|
4795
4269
|
serverInfo,
|
|
4796
4270
|
defaultTransports,
|
|
4797
|
-
toolOptions
|
|
4271
|
+
toolOptions,
|
|
4272
|
+
transportOptions.logPath
|
|
4798
4273
|
);
|
|
4799
4274
|
} else if (defaultTransport) {
|
|
4800
4275
|
await mcpParser.startMcpServerWithTransport(
|
|
@@ -4806,20 +4281,16 @@ _startUnifiedMcpServer_fn = async function(mcpServerConfig, transportOptions) {
|
|
|
4806
4281
|
path: defaultTransport.path,
|
|
4807
4282
|
sessionIdGenerator: defaultTransport.sessionIdGenerator
|
|
4808
4283
|
},
|
|
4809
|
-
toolOptions
|
|
4284
|
+
toolOptions,
|
|
4285
|
+
transportOptions.logPath
|
|
4810
4286
|
);
|
|
4811
4287
|
} else {
|
|
4812
|
-
const transportType = transportOptions.transportType || "stdio";
|
|
4813
|
-
const finalTransportOptions = {
|
|
4814
|
-
port: transportOptions.port,
|
|
4815
|
-
host: transportOptions.host || "localhost",
|
|
4816
|
-
path: transportOptions.path || "/mcp"
|
|
4817
|
-
};
|
|
4818
4288
|
await mcpParser.startMcpServerWithTransport(
|
|
4819
4289
|
serverInfo,
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
toolOptions
|
|
4290
|
+
"stdio",
|
|
4291
|
+
{},
|
|
4292
|
+
toolOptions,
|
|
4293
|
+
transportOptions.logPath
|
|
4823
4294
|
);
|
|
4824
4295
|
}
|
|
4825
4296
|
};
|
|
@@ -4886,6 +4357,12 @@ _parseMcpTransportOptions_fn = function(processArgs) {
|
|
|
4886
4357
|
i++;
|
|
4887
4358
|
}
|
|
4888
4359
|
break;
|
|
4360
|
+
case "--s-mcp-log-path":
|
|
4361
|
+
if (nextArg && !nextArg.startsWith("-")) {
|
|
4362
|
+
options.logPath = nextArg;
|
|
4363
|
+
i++;
|
|
4364
|
+
}
|
|
4365
|
+
break;
|
|
4889
4366
|
// Backward compatibility: support old flags but with deprecation warning
|
|
4890
4367
|
case "--transport":
|
|
4891
4368
|
case "--port":
|
|
@@ -6171,11 +5648,14 @@ Migration guide: https://github.com/alcyone-labs/arg-parser/blob/main/docs/MCP-M
|
|
|
6171
5648
|
* @param toolOptions Optional MCP tool generation options
|
|
6172
5649
|
* @returns Configured MCP server instance
|
|
6173
5650
|
*/
|
|
6174
|
-
async createMcpServer(serverInfo, toolOptions) {
|
|
6175
|
-
var _a;
|
|
6176
|
-
const
|
|
5651
|
+
async createMcpServer(serverInfo, toolOptions, logPath) {
|
|
5652
|
+
var _a, _b;
|
|
5653
|
+
const resolvedLogPath = resolveLogPath(
|
|
5654
|
+
logPath || ((_a = this._mcpServerConfig) == null ? void 0 : _a.logPath) || "./logs/mcp.log"
|
|
5655
|
+
);
|
|
5656
|
+
const logger = simpleMcpLogger.createMcpLogger("MCP Server Creation", resolvedLogPath);
|
|
6177
5657
|
try {
|
|
6178
|
-
const effectiveServerInfo = serverInfo || ((
|
|
5658
|
+
const effectiveServerInfo = serverInfo || ((_b = this._mcpServerConfig) == null ? void 0 : _b.serverInfo);
|
|
6179
5659
|
if (!effectiveServerInfo) {
|
|
6180
5660
|
throw new Error(
|
|
6181
5661
|
"No MCP server configuration found. Use withMcp() to configure server info or provide serverInfo parameter."
|
|
@@ -6356,11 +5836,11 @@ Migration guide: https://github.com/alcyone-labs/arg-parser/blob/main/docs/MCP-M
|
|
|
6356
5836
|
* @param toolOptions Optional MCP tool generation options
|
|
6357
5837
|
* @returns Promise that resolves when all servers are started
|
|
6358
5838
|
*/
|
|
6359
|
-
async startMcpServerWithMultipleTransports(serverInfo, transports, toolOptions) {
|
|
6360
|
-
const server = await this.createMcpServer(serverInfo, toolOptions);
|
|
5839
|
+
async startMcpServerWithMultipleTransports(serverInfo, transports, toolOptions, logPath) {
|
|
5840
|
+
const server = await this.createMcpServer(serverInfo, toolOptions, logPath);
|
|
6361
5841
|
const startPromises = [];
|
|
6362
5842
|
for (const transportConfig of transports) {
|
|
6363
|
-
const promise = __privateMethod(this, _ArgParser_instances, _startSingleTransport_fn).call(this, server, serverInfo, transportConfig);
|
|
5843
|
+
const promise = __privateMethod(this, _ArgParser_instances, _startSingleTransport_fn).call(this, server, serverInfo, transportConfig, logPath);
|
|
6364
5844
|
startPromises.push(promise);
|
|
6365
5845
|
}
|
|
6366
5846
|
await Promise.all(startPromises);
|
|
@@ -6373,12 +5853,12 @@ Migration guide: https://github.com/alcyone-labs/arg-parser/blob/main/docs/MCP-M
|
|
|
6373
5853
|
* @param toolOptions Optional MCP tool generation options
|
|
6374
5854
|
* @returns Promise that resolves when server is connected
|
|
6375
5855
|
*/
|
|
6376
|
-
async startMcpServerWithTransport(serverInfo, transportType, transportOptions = {}, toolOptions) {
|
|
6377
|
-
const server = await this.createMcpServer(serverInfo, toolOptions);
|
|
5856
|
+
async startMcpServerWithTransport(serverInfo, transportType, transportOptions = {}, toolOptions, logPath) {
|
|
5857
|
+
const server = await this.createMcpServer(serverInfo, toolOptions, logPath);
|
|
6378
5858
|
await __privateMethod(this, _ArgParser_instances, _startSingleTransport_fn).call(this, server, serverInfo, {
|
|
6379
5859
|
type: transportType,
|
|
6380
5860
|
...transportOptions
|
|
6381
|
-
});
|
|
5861
|
+
}, logPath);
|
|
6382
5862
|
}
|
|
6383
5863
|
async parse(processArgs, options) {
|
|
6384
5864
|
let result = await ArgParserBase.prototype.parse.call(
|
|
@@ -6640,8 +6120,9 @@ registerToolAsSubCommand_fn = function(toolConfig) {
|
|
|
6640
6120
|
handler: toolConfig.handler
|
|
6641
6121
|
});
|
|
6642
6122
|
};
|
|
6643
|
-
_startSingleTransport_fn = async function(server, serverInfo, transportConfig) {
|
|
6644
|
-
const
|
|
6123
|
+
_startSingleTransport_fn = async function(server, serverInfo, transportConfig, logPath) {
|
|
6124
|
+
const resolvedLogPath = resolveLogPath(logPath || "./logs/mcp.log");
|
|
6125
|
+
const logger = simpleMcpLogger.createMcpLogger("MCP Transport", resolvedLogPath);
|
|
6645
6126
|
try {
|
|
6646
6127
|
logger.mcpError(
|
|
6647
6128
|
`Starting ${transportConfig.type} transport for server: ${serverInfo.name}`
|
|
@@ -6817,7 +6298,9 @@ class TomlConfigPlugin extends ConfigPlugin {
|
|
|
6817
6298
|
}
|
|
6818
6299
|
return parsed;
|
|
6819
6300
|
} catch (error) {
|
|
6820
|
-
throw new Error(
|
|
6301
|
+
throw new Error(
|
|
6302
|
+
`Failed to parse TOML: ${error instanceof Error ? error.message : String(error)}`
|
|
6303
|
+
);
|
|
6821
6304
|
}
|
|
6822
6305
|
}
|
|
6823
6306
|
generate(_config, flags, parsedArgs) {
|
|
@@ -6857,7 +6340,9 @@ class TomlConfigPlugin extends ConfigPlugin {
|
|
|
6857
6340
|
const tomlContent = this.tomlModule.stringify(configWithValues);
|
|
6858
6341
|
return lines.join("\n") + "\n" + tomlContent;
|
|
6859
6342
|
} catch (error) {
|
|
6860
|
-
throw new Error(
|
|
6343
|
+
throw new Error(
|
|
6344
|
+
`Failed to generate TOML: ${error instanceof Error ? error.message : String(error)}`
|
|
6345
|
+
);
|
|
6861
6346
|
}
|
|
6862
6347
|
}
|
|
6863
6348
|
/**
|
|
@@ -6893,7 +6378,10 @@ function createTomlPlugin() {
|
|
|
6893
6378
|
try {
|
|
6894
6379
|
return new TomlConfigPlugin();
|
|
6895
6380
|
} catch (error) {
|
|
6896
|
-
console.warn(
|
|
6381
|
+
console.warn(
|
|
6382
|
+
"TOML plugin not available:",
|
|
6383
|
+
error instanceof Error ? error.message : String(error)
|
|
6384
|
+
);
|
|
6897
6385
|
return null;
|
|
6898
6386
|
}
|
|
6899
6387
|
}
|
|
@@ -6909,7 +6397,10 @@ async function createTomlPluginAsync() {
|
|
|
6909
6397
|
const tomlModule = await Promise.resolve().then(() => index$1);
|
|
6910
6398
|
return new TomlConfigPlugin(tomlModule);
|
|
6911
6399
|
} catch (error) {
|
|
6912
|
-
console.warn(
|
|
6400
|
+
console.warn(
|
|
6401
|
+
"TOML plugin not available:",
|
|
6402
|
+
error instanceof Error ? error.message : String(error)
|
|
6403
|
+
);
|
|
6913
6404
|
return null;
|
|
6914
6405
|
}
|
|
6915
6406
|
}
|
|
@@ -6955,7 +6446,9 @@ class YamlConfigPlugin extends ConfigPlugin {
|
|
|
6955
6446
|
}
|
|
6956
6447
|
return parsed;
|
|
6957
6448
|
} catch (error) {
|
|
6958
|
-
throw new Error(
|
|
6449
|
+
throw new Error(
|
|
6450
|
+
`Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`
|
|
6451
|
+
);
|
|
6959
6452
|
}
|
|
6960
6453
|
}
|
|
6961
6454
|
generate(_config, flags, parsedArgs) {
|
|
@@ -6989,7 +6482,9 @@ class YamlConfigPlugin extends ConfigPlugin {
|
|
|
6989
6482
|
});
|
|
6990
6483
|
return lines.join("\n") + "\n" + yamlContent;
|
|
6991
6484
|
} catch (error) {
|
|
6992
|
-
throw new Error(
|
|
6485
|
+
throw new Error(
|
|
6486
|
+
`Failed to generate YAML: ${error instanceof Error ? error.message : String(error)}`
|
|
6487
|
+
);
|
|
6993
6488
|
}
|
|
6994
6489
|
}
|
|
6995
6490
|
/**
|
|
@@ -7019,7 +6514,10 @@ function createYamlPlugin() {
|
|
|
7019
6514
|
try {
|
|
7020
6515
|
return new YamlConfigPlugin();
|
|
7021
6516
|
} catch (error) {
|
|
7022
|
-
console.warn(
|
|
6517
|
+
console.warn(
|
|
6518
|
+
"YAML plugin not available:",
|
|
6519
|
+
error instanceof Error ? error.message : String(error)
|
|
6520
|
+
);
|
|
7023
6521
|
return null;
|
|
7024
6522
|
}
|
|
7025
6523
|
}
|
|
@@ -7035,7 +6533,10 @@ async function createYamlPluginAsync() {
|
|
|
7035
6533
|
const yamlModule = await import("js-yaml");
|
|
7036
6534
|
return new YamlConfigPlugin(yamlModule);
|
|
7037
6535
|
} catch (error) {
|
|
7038
|
-
console.warn(
|
|
6536
|
+
console.warn(
|
|
6537
|
+
"YAML plugin not available:",
|
|
6538
|
+
error instanceof Error ? error.message : String(error)
|
|
6539
|
+
);
|
|
7039
6540
|
return null;
|
|
7040
6541
|
}
|
|
7041
6542
|
}
|
|
@@ -7064,7 +6565,9 @@ class ArgParserFuzzyTester {
|
|
|
7064
6565
|
const results = [];
|
|
7065
6566
|
if (this.options.verbose) {
|
|
7066
6567
|
console.log(`Discovered ${commandPaths.length} command paths:`);
|
|
7067
|
-
commandPaths.forEach(
|
|
6568
|
+
commandPaths.forEach(
|
|
6569
|
+
(path2) => console.log(` ${path2.join(" ") || "(root)"}`)
|
|
6570
|
+
);
|
|
7068
6571
|
}
|
|
7069
6572
|
for (const commandPath of commandPaths) {
|
|
7070
6573
|
const pathResults = await this.testCommandPath(commandPath);
|
|
@@ -7090,7 +6593,12 @@ class ArgParserFuzzyTester {
|
|
|
7090
6593
|
for (const [subCommandName, subCommand] of subCommands) {
|
|
7091
6594
|
const newPath = [...currentPath, subCommandName];
|
|
7092
6595
|
allPaths.push(newPath);
|
|
7093
|
-
this.discoverSubCommandPaths(
|
|
6596
|
+
this.discoverSubCommandPaths(
|
|
6597
|
+
subCommand.parser,
|
|
6598
|
+
newPath,
|
|
6599
|
+
allPaths,
|
|
6600
|
+
depth + 1
|
|
6601
|
+
);
|
|
7094
6602
|
}
|
|
7095
6603
|
}
|
|
7096
6604
|
/**
|
|
@@ -8307,6 +7815,7 @@ class Protocol {
|
|
|
8307
7815
|
this._responseHandlers = /* @__PURE__ */ new Map();
|
|
8308
7816
|
this._progressHandlers = /* @__PURE__ */ new Map();
|
|
8309
7817
|
this._timeoutInfo = /* @__PURE__ */ new Map();
|
|
7818
|
+
this._pendingDebouncedNotifications = /* @__PURE__ */ new Set();
|
|
8310
7819
|
this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
|
|
8311
7820
|
const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
|
|
8312
7821
|
controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
|
|
@@ -8388,6 +7897,7 @@ class Protocol {
|
|
|
8388
7897
|
const responseHandlers = this._responseHandlers;
|
|
8389
7898
|
this._responseHandlers = /* @__PURE__ */ new Map();
|
|
8390
7899
|
this._progressHandlers.clear();
|
|
7900
|
+
this._pendingDebouncedNotifications.clear();
|
|
8391
7901
|
this._transport = void 0;
|
|
8392
7902
|
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
8393
7903
|
const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
|
|
@@ -8587,10 +8097,32 @@ class Protocol {
|
|
|
8587
8097
|
* Emits a notification, which is a one-way message that does not expect a response.
|
|
8588
8098
|
*/
|
|
8589
8099
|
async notification(notification, options) {
|
|
8100
|
+
var _a, _b;
|
|
8590
8101
|
if (!this._transport) {
|
|
8591
8102
|
throw new Error("Not connected");
|
|
8592
8103
|
}
|
|
8593
8104
|
this.assertNotificationCapability(notification.method);
|
|
8105
|
+
const debouncedMethods = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.debouncedNotificationMethods) !== null && _b !== void 0 ? _b : [];
|
|
8106
|
+
const canDebounce = debouncedMethods.includes(notification.method) && !notification.params && !(options === null || options === void 0 ? void 0 : options.relatedRequestId);
|
|
8107
|
+
if (canDebounce) {
|
|
8108
|
+
if (this._pendingDebouncedNotifications.has(notification.method)) {
|
|
8109
|
+
return;
|
|
8110
|
+
}
|
|
8111
|
+
this._pendingDebouncedNotifications.add(notification.method);
|
|
8112
|
+
Promise.resolve().then(() => {
|
|
8113
|
+
var _a2;
|
|
8114
|
+
this._pendingDebouncedNotifications.delete(notification.method);
|
|
8115
|
+
if (!this._transport) {
|
|
8116
|
+
return;
|
|
8117
|
+
}
|
|
8118
|
+
const jsonrpcNotification2 = {
|
|
8119
|
+
...notification,
|
|
8120
|
+
jsonrpc: "2.0"
|
|
8121
|
+
};
|
|
8122
|
+
(_a2 = this._transport) === null || _a2 === void 0 ? void 0 : _a2.send(jsonrpcNotification2, options).catch((error) => this._onerror(error));
|
|
8123
|
+
});
|
|
8124
|
+
return;
|
|
8125
|
+
}
|
|
8594
8126
|
const jsonrpcNotification = {
|
|
8595
8127
|
...notification,
|
|
8596
8128
|
jsonrpc: "2.0"
|
|
@@ -24996,6 +24528,7 @@ exports.OutputSchemaPatterns = OutputSchemaPatterns;
|
|
|
24996
24528
|
exports.SimpleChalk = simpleChalk;
|
|
24997
24529
|
exports.TomlConfigPlugin = TomlConfigPlugin;
|
|
24998
24530
|
exports.YamlConfigPlugin = YamlConfigPlugin;
|
|
24531
|
+
exports.absolutePath = absolutePath;
|
|
24999
24532
|
exports.convertFlagToJsonSchemaProperty = convertFlagToJsonSchemaProperty;
|
|
25000
24533
|
exports.convertFlagsToJsonSchema = convertFlagsToJsonSchema;
|
|
25001
24534
|
exports.convertFlagsToZodSchema = convertFlagsToZodSchema;
|
|
@@ -25007,12 +24540,18 @@ exports.createTomlPlugin = createTomlPlugin;
|
|
|
25007
24540
|
exports.createTomlPluginAsync = createTomlPluginAsync;
|
|
25008
24541
|
exports.createYamlPlugin = createYamlPlugin;
|
|
25009
24542
|
exports.createYamlPluginAsync = createYamlPluginAsync;
|
|
24543
|
+
exports.cwdRelative = cwdRelative;
|
|
24544
|
+
exports.detectEntryPoint = detectEntryPoint;
|
|
25010
24545
|
exports.enableConfigPlugins = enableConfigPlugins;
|
|
25011
24546
|
exports.enableOptionalConfigPlugins = enableOptionalConfigPlugins;
|
|
25012
24547
|
exports.enableOptionalConfigPluginsAsync = enableOptionalConfigPluginsAsync;
|
|
24548
|
+
exports.entryRelative = entryRelative;
|
|
25013
24549
|
exports.extractSimplifiedResponse = extractSimplifiedResponse;
|
|
25014
24550
|
exports.generateMcpToolsFromArgParser = generateMcpToolsFromArgParser;
|
|
24551
|
+
exports.getEntryPointFromImportMeta = getEntryPointFromImportMeta;
|
|
25015
24552
|
exports.getJsonSchemaTypeFromFlag = getJsonSchemaTypeFromFlag;
|
|
25016
24553
|
exports.globalConfigPluginRegistry = globalConfigPluginRegistry;
|
|
24554
|
+
exports.legacyCwdPath = legacyCwdPath;
|
|
24555
|
+
exports.resolveLogPath = resolveLogPath;
|
|
25017
24556
|
exports.zodFlagSchema = zodFlagSchema;
|
|
25018
24557
|
//# sourceMappingURL=index.cjs.map
|