opentool 0.8.29 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -128,10 +128,7 @@ var X402PaymentSchema = z.object({
128
128
  }),
129
129
  metadata: z.record(z.string(), z.unknown()).optional()
130
130
  }).passthrough();
131
- var PaymentConfigSchema = z.union([
132
- X402PaymentSchema,
133
- z.record(z.string(), z.unknown())
134
- ]);
131
+ var PaymentConfigSchema = z.union([X402PaymentSchema, z.record(z.string(), z.unknown())]);
135
132
  var DiscoveryMetadataSchema = z.object({
136
133
  keywords: z.array(z.string()).optional(),
137
134
  category: z.string().optional(),
@@ -460,7 +457,7 @@ function buildDiscovery(authored) {
460
457
  }
461
458
  const merged = {
462
459
  ...legacyDiscovery,
463
- ...authored.discovery ?? {}
460
+ ...authored.discovery
464
461
  };
465
462
  return Object.keys(merged).length > 0 ? merged : void 0;
466
463
  }
@@ -592,7 +589,10 @@ async function verifyX402Payment(attempt, definition, options = {}) {
592
589
  console.log("[x402] Facilitator /verify response", { status: verifyResponse.status });
593
590
  if (!verifyResponse.ok) {
594
591
  const errorText = await verifyResponse.text().catch(() => "");
595
- console.error("[x402] Facilitator /verify error", { status: verifyResponse.status, body: errorText });
592
+ console.error("[x402] Facilitator /verify error", {
593
+ status: verifyResponse.status,
594
+ body: errorText
595
+ });
596
596
  return {
597
597
  success: false,
598
598
  failure: {
@@ -640,7 +640,10 @@ async function verifyX402Payment(attempt, definition, options = {}) {
640
640
  console.log("[x402] Facilitator /settle response", { status: settleResponse.status });
641
641
  if (!settleResponse.ok) {
642
642
  const errorText = await settleResponse.text().catch(() => "");
643
- console.error("[x402] Facilitator /settle error", { status: settleResponse.status, body: errorText });
643
+ console.error("[x402] Facilitator /settle error", {
644
+ status: settleResponse.status,
645
+ body: errorText
646
+ });
644
647
  return {
645
648
  success: false,
646
649
  failure: {
@@ -658,7 +661,9 @@ async function verifyX402Payment(attempt, definition, options = {}) {
658
661
  });
659
662
  }
660
663
  } catch (error) {
661
- console.error("[x402] Settlement exception", { error: error instanceof Error ? error.message : String(error) });
664
+ console.error("[x402] Settlement exception", {
665
+ error: error instanceof Error ? error.message : String(error)
666
+ });
662
667
  return {
663
668
  success: false,
664
669
  failure: {
@@ -747,7 +752,7 @@ function ensureTrailingSlash(url) {
747
752
  }
748
753
 
749
754
  // src/x402/index.ts
750
- var PAYMENT_CONTEXT_SYMBOL = Symbol.for("opentool.x402.context");
755
+ var PAYMENT_CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("opentool.x402.context");
751
756
  var X402PaymentRequiredError = class extends Error {
752
757
  constructor(response, verification) {
753
758
  super("X402 Payment required");
@@ -838,9 +843,7 @@ function createMcpAdapter(options) {
838
843
  const defaultMethod = resolveDefaultMethod(options);
839
844
  const httpHandler = options.httpHandlers[defaultMethod];
840
845
  if (!httpHandler) {
841
- throw new Error(
842
- `Tool "${options.name}" does not export an HTTP handler for ${defaultMethod}`
843
- );
846
+ throw new Error(`Tool "${options.name}" does not export an HTTP handler for ${defaultMethod}`);
844
847
  }
845
848
  return async function invoke(rawArguments) {
846
849
  const validated = normalizedSchema ? normalizedSchema.parse(rawArguments ?? {}) : rawArguments;
@@ -948,15 +951,7 @@ async function responseToToolResponse(response) {
948
951
  }
949
952
 
950
953
  // src/types/index.ts
951
- var HTTP_METHODS = [
952
- "GET",
953
- "HEAD",
954
- "POST",
955
- "PUT",
956
- "DELETE",
957
- "PATCH",
958
- "OPTIONS"
959
- ];
954
+ var HTTP_METHODS = ["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
960
955
 
961
956
  // src/utils/schedule.ts
962
957
  var CRON_WRAPPED_REGEX = /^cron\((.*)\)$/i;
@@ -969,7 +964,9 @@ function normalizeScheduleExpression(raw, context) {
969
964
  const cronBody = extractCronBody(value);
970
965
  const cronFields = cronBody.trim().split(/\s+/).filter(Boolean);
971
966
  if (cronFields.length !== 5 && cronFields.length !== 6) {
972
- throw new Error(`${context}: cron expression must have 5 or 6 fields (got ${cronFields.length})`);
967
+ throw new Error(
968
+ `${context}: cron expression must have 5 or 6 fields (got ${cronFields.length})`
969
+ );
973
970
  }
974
971
  validateCronTokens(cronFields, context);
975
972
  return {
@@ -993,14 +990,7 @@ function validateCronTokens(fields, context) {
993
990
  }
994
991
 
995
992
  // src/cli/validate.ts
996
- var SUPPORTED_EXTENSIONS = [
997
- ".ts",
998
- ".tsx",
999
- ".js",
1000
- ".jsx",
1001
- ".mjs",
1002
- ".cjs"
1003
- ];
993
+ var SUPPORTED_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
1004
994
  var MIN_TEMPLATE_CONFIG_VERSION = 2;
1005
995
  var TEMPLATE_PREVIEW_TITLE_MAX = 80;
1006
996
  var TEMPLATE_PREVIEW_SUBTITLE_MAX = 120;
@@ -1070,14 +1060,10 @@ function normalizeTemplatePreview(value, file, toolName, requirePreview) {
1070
1060
  required: true,
1071
1061
  max: TEMPLATE_PREVIEW_SUBTITLE_MAX
1072
1062
  });
1073
- const description = parseNonEmptyString(
1074
- record.description,
1075
- `${pathPrefix}.description`,
1076
- {
1077
- required: true,
1078
- max: TEMPLATE_PREVIEW_DESCRIPTION_MAX
1079
- }
1080
- );
1063
+ const description = parseNonEmptyString(record.description, `${pathPrefix}.description`, {
1064
+ required: true,
1065
+ max: TEMPLATE_PREVIEW_DESCRIPTION_MAX
1066
+ });
1081
1067
  const descriptionLineCount = description.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).length;
1082
1068
  if (descriptionLineCount < TEMPLATE_PREVIEW_MIN_LINES || descriptionLineCount > TEMPLATE_PREVIEW_MAX_LINES) {
1083
1069
  throw new Error(
@@ -1204,15 +1190,13 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1204
1190
  const profileRaw = toolModule?.profile && typeof toolModule.profile === "object" ? toolModule.profile : null;
1205
1191
  const schedule = profileRaw?.schedule ?? null;
1206
1192
  const profileNotifyEmail = typeof profileRaw?.notifyEmail === "boolean" ? profileRaw.notifyEmail : void 0;
1207
- const allowedProfileCategories = [
1208
- "strategy",
1209
- "tracker",
1210
- "orchestrator"
1211
- ];
1193
+ const allowedProfileCategories = ["strategy", "tracker", "orchestrator"];
1212
1194
  const profileCategoryCandidate = typeof profileRaw?.category === "string" ? profileRaw.category : void 0;
1213
1195
  let profileCategoryRaw;
1214
1196
  if (profileCategoryCandidate !== void 0) {
1215
- const isAllowed = allowedProfileCategories.includes(profileCategoryCandidate);
1197
+ const isAllowed = allowedProfileCategories.includes(
1198
+ profileCategoryCandidate
1199
+ );
1216
1200
  if (!isAllowed) {
1217
1201
  throw new Error(
1218
1202
  `${file}: profile.category must be one of ${allowedProfileCategories.join(", ")}`
@@ -1227,22 +1211,16 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1227
1211
  }
1228
1212
  profileAssetsRaw.forEach((entry, index) => {
1229
1213
  if (!entry || typeof entry !== "object") {
1230
- throw new Error(
1231
- `${file}: profile.assets[${index}] must be an object.`
1232
- );
1214
+ throw new Error(`${file}: profile.assets[${index}] must be an object.`);
1233
1215
  }
1234
1216
  const record = entry;
1235
1217
  const venue = typeof record.venue === "string" ? record.venue.trim() : "";
1236
1218
  if (!venue) {
1237
- throw new Error(
1238
- `${file}: profile.assets[${index}].venue must be a non-empty string.`
1239
- );
1219
+ throw new Error(`${file}: profile.assets[${index}].venue must be a non-empty string.`);
1240
1220
  }
1241
1221
  const chain = record.chain;
1242
1222
  if (typeof chain !== "string" && typeof chain !== "number") {
1243
- throw new Error(
1244
- `${file}: profile.assets[${index}].chain must be a string or number.`
1245
- );
1223
+ throw new Error(`${file}: profile.assets[${index}].chain must be a string or number.`);
1246
1224
  }
1247
1225
  const symbols = record.assetSymbols;
1248
1226
  if (!Array.isArray(symbols) || symbols.length === 0) {
@@ -1336,14 +1314,14 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1336
1314
  throw new Error(`${file}: POST tools must export a Zod schema as 'schema'`);
1337
1315
  }
1338
1316
  if (schedule && typeof schedule.cron === "string") {
1339
- throw new Error(`${file}: POST tools must not define profile.schedule; use GET + cron for scheduled tasks.`);
1317
+ throw new Error(
1318
+ `${file}: POST tools must not define profile.schedule; use GET + cron for scheduled tasks.`
1319
+ );
1340
1320
  }
1341
1321
  }
1342
1322
  const httpHandlers = [...httpHandlersRaw];
1343
1323
  if (httpHandlers.length === 0) {
1344
- throw new Error(
1345
- `${file} must export at least one HTTP handler (e.g. POST)`
1346
- );
1324
+ throw new Error(`${file} must export at least one HTTP handler (e.g. POST)`);
1347
1325
  }
1348
1326
  if (paymentExport) {
1349
1327
  for (let index = 0; index < httpHandlers.length; index += 1) {
@@ -1369,7 +1347,7 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1369
1347
  ...metadataOverrides,
1370
1348
  payment: metadataOverrides.payment ?? paymentExport,
1371
1349
  annotations: {
1372
- ...metadataOverrides.annotations ?? {},
1350
+ ...metadataOverrides.annotations,
1373
1351
  requiresPayment: metadataOverrides.annotations?.requiresPayment ?? true
1374
1352
  }
1375
1353
  };
@@ -1625,10 +1603,6 @@ async function buildProject(options) {
1625
1603
  compiledTools,
1626
1604
  outputDir
1627
1605
  });
1628
- const workflowBundles = await buildWorkflowsIfPresent({
1629
- projectRoot,
1630
- outputDir
1631
- });
1632
1606
  const shouldBuildMcpServer = compiledTools.some((artifact) => artifact.mcpEnabled);
1633
1607
  if (shouldBuildMcpServer) {
1634
1608
  await writeMcpServer({
@@ -1647,7 +1621,6 @@ async function buildProject(options) {
1647
1621
  defaultsApplied,
1648
1622
  tools,
1649
1623
  compiledTools,
1650
- workflowBundles,
1651
1624
  toolsManifestPath,
1652
1625
  sharedModules
1653
1626
  };
@@ -1836,19 +1809,12 @@ async function writeMcpServer(options) {
1836
1809
  }
1837
1810
  function writeToolsManifest(options) {
1838
1811
  const manifestPath = path6.join(options.outputDir, "tools.json");
1839
- const legacyManifestPath = path6.join(
1840
- options.outputDir,
1841
- ".well-known",
1842
- "opentool",
1843
- "cron.json"
1844
- );
1812
+ const legacyManifestPath = path6.join(options.outputDir, ".well-known", "opentool", "cron.json");
1845
1813
  if (fs4.existsSync(legacyManifestPath)) {
1846
1814
  fs4.rmSync(legacyManifestPath, { force: true });
1847
1815
  }
1848
1816
  const entries = options.tools.map((tool) => {
1849
- const compiled = options.compiledTools.find(
1850
- (artifact) => artifact.filename === tool.filename
1851
- );
1817
+ const compiled = options.compiledTools.find((artifact) => artifact.filename === tool.filename);
1852
1818
  if (!compiled) {
1853
1819
  throw new Error(`Internal error: missing compiled artifact for ${tool.filename}`);
1854
1820
  }
@@ -1898,18 +1864,6 @@ function logBuildSummary(artifacts, options) {
1898
1864
  if (artifacts.toolsManifestPath) {
1899
1865
  console.log(" \u2022 tools.json (runtime tool manifest)");
1900
1866
  }
1901
- if (artifacts.workflowBundles) {
1902
- console.log(" \u2022 .well-known/workflow/v1/ (workflow bundles)");
1903
- console.log(" - flow.js");
1904
- console.log(" - step.js");
1905
- console.log(" - webhook.js");
1906
- if (artifacts.workflowBundles.clientBundlePath) {
1907
- console.log(" - client.js");
1908
- }
1909
- if (artifacts.workflowBundles.manifestPath) {
1910
- console.log(" - manifest.json");
1911
- }
1912
- }
1913
1867
  if (artifacts.defaultsApplied.length > 0) {
1914
1868
  console.log("\nDefaults applied during metadata synthesis:");
1915
1869
  artifacts.defaultsApplied.forEach((entry) => console.log(` \u2022 ${entry}`));
@@ -1918,183 +1872,6 @@ function logBuildSummary(artifacts, options) {
1918
1872
  console.log("\n\u2139\uFE0F MCP adapter skipped (no tools opted in)");
1919
1873
  }
1920
1874
  }
1921
- async function buildWorkflowsIfPresent(options) {
1922
- const workflowsDir = options.workflowsDir ?? path6.join(options.projectRoot, "workflows");
1923
- if (!fs4.existsSync(workflowsDir)) {
1924
- return null;
1925
- }
1926
- if (!hasWorkflowSourceFiles(workflowsDir)) {
1927
- return null;
1928
- }
1929
- const nodeVersion = process.versions?.node ?? "0.0.0";
1930
- const nodeMajor = Number(nodeVersion.split(".")[0] ?? 0);
1931
- if (!Number.isFinite(nodeMajor) || nodeMajor < 22) {
1932
- console.warn(
1933
- `[${timestamp()}] Workflow bundles skipped (requires Node >= 22, current ${nodeVersion})`
1934
- );
1935
- return null;
1936
- }
1937
- let BaseBuilder;
1938
- try {
1939
- ({ BaseBuilder } = await import('@workflow/cli/dist/lib/builders/base-builder.js'));
1940
- } catch (error) {
1941
- const details = error instanceof Error ? `
1942
- Reason: ${error.message}` : "";
1943
- throw new Error(
1944
- `[${timestamp()}] Workflow sources detected, but optional dependency '@workflow/cli' is not installed. Install it with "npm install @workflow/cli" (or add it to devDependencies) and rerun the build.` + details
1945
- );
1946
- }
1947
- class OpenToolWorkflowBuilder extends BaseBuilder {
1948
- constructor(config) {
1949
- super(config);
1950
- }
1951
- async build() {
1952
- const inputFiles = await this.getInputFiles();
1953
- const tsConfig = await this.getTsConfigOptions();
1954
- const shared = {
1955
- inputFiles,
1956
- ...tsConfig.baseUrl ? { tsBaseUrl: tsConfig.baseUrl } : {},
1957
- ...tsConfig.paths ? { tsPaths: tsConfig.paths } : {}
1958
- };
1959
- await this.buildStepsBundle(shared);
1960
- await this.buildWorkflowsBundle(shared);
1961
- await this.buildWebhookRoute();
1962
- await this.buildClientLibrary();
1963
- }
1964
- async buildStepsBundle(options2) {
1965
- console.log(
1966
- "Creating OpenTool workflow steps bundle at",
1967
- this.config.stepsBundlePath
1968
- );
1969
- const stepsBundlePath2 = path6.resolve(
1970
- this.config.workingDir,
1971
- this.config.stepsBundlePath
1972
- );
1973
- await fs4.promises.mkdir(path6.dirname(stepsBundlePath2), { recursive: true });
1974
- await this.createStepsBundle({
1975
- outfile: stepsBundlePath2,
1976
- ...options2
1977
- });
1978
- }
1979
- async buildWorkflowsBundle(options2) {
1980
- console.log(
1981
- "Creating OpenTool workflow bundle at",
1982
- this.config.workflowsBundlePath
1983
- );
1984
- const workflowBundlePath = path6.resolve(
1985
- this.config.workingDir,
1986
- this.config.workflowsBundlePath
1987
- );
1988
- await fs4.promises.mkdir(path6.dirname(workflowBundlePath), {
1989
- recursive: true
1990
- });
1991
- await this.createWorkflowsBundle({
1992
- outfile: workflowBundlePath,
1993
- bundleFinalOutput: false,
1994
- ...options2
1995
- });
1996
- }
1997
- async buildWebhookRoute() {
1998
- console.log(
1999
- "Creating OpenTool workflow webhook bundle at",
2000
- this.config.webhookBundlePath
2001
- );
2002
- const webhookBundlePath2 = path6.resolve(
2003
- this.config.workingDir,
2004
- this.config.webhookBundlePath
2005
- );
2006
- await fs4.promises.mkdir(path6.dirname(webhookBundlePath2), {
2007
- recursive: true
2008
- });
2009
- await this.createWebhookBundle({ outfile: webhookBundlePath2 });
2010
- }
2011
- async buildClientLibrary() {
2012
- if (!this.config?.clientBundlePath) {
2013
- return;
2014
- }
2015
- const clientBundlePath2 = path6.resolve(
2016
- this.config.workingDir,
2017
- this.config.clientBundlePath
2018
- );
2019
- await fs4.promises.mkdir(path6.dirname(clientBundlePath2), {
2020
- recursive: true
2021
- });
2022
- await this.createWorkflowsBundle({
2023
- outfile: clientBundlePath2,
2024
- bundleFinalOutput: true
2025
- });
2026
- }
2027
- }
2028
- const relativeSourceDir = path6.relative(options.projectRoot, workflowsDir) || ".";
2029
- const outputBase = path6.join(
2030
- options.outputDir,
2031
- ".well-known",
2032
- "workflow",
2033
- "v1"
2034
- );
2035
- const stepsBundlePath = path6.join(outputBase, "step.js");
2036
- const workflowsBundlePath = path6.join(outputBase, "flow.js");
2037
- const webhookBundlePath = path6.join(outputBase, "webhook.js");
2038
- const manifestPath = path6.join(outputBase, "manifest.json");
2039
- const builder = new OpenToolWorkflowBuilder({
2040
- workingDir: options.projectRoot,
2041
- dirs: [relativeSourceDir],
2042
- buildTarget: "standalone",
2043
- stepsBundlePath,
2044
- workflowsBundlePath,
2045
- webhookBundlePath,
2046
- ...{},
2047
- workflowManifestPath: manifestPath,
2048
- externalPackages: [
2049
- "workflow",
2050
- "workflow/internal/builtins",
2051
- "workflow/internal/private",
2052
- "workflow/runtime",
2053
- "workflow/api"
2054
- ]
2055
- });
2056
- console.log(
2057
- `[${timestamp()}] Building workflows from ${workflowsDir} -> ${outputBase}`
2058
- );
2059
- await builder.build();
2060
- return {
2061
- sourceDir: workflowsDir,
2062
- outputDir: outputBase,
2063
- stepsBundlePath,
2064
- workflowsBundlePath,
2065
- webhookBundlePath,
2066
- ...{},
2067
- manifestPath
2068
- };
2069
- }
2070
- function hasWorkflowSourceFiles(directory) {
2071
- const entries = fs4.readdirSync(directory, { withFileTypes: true });
2072
- for (const entry of entries) {
2073
- if (entry.isDirectory()) {
2074
- if (hasWorkflowSourceFiles(path6.join(directory, entry.name))) {
2075
- return true;
2076
- }
2077
- continue;
2078
- }
2079
- if (entry.isFile()) {
2080
- const extension = path6.extname(entry.name).toLowerCase();
2081
- if (WORKFLOW_SOURCE_EXTENSIONS.has(extension)) {
2082
- return true;
2083
- }
2084
- }
2085
- }
2086
- return false;
2087
- }
2088
- var WORKFLOW_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
2089
- ".ts",
2090
- ".tsx",
2091
- ".js",
2092
- ".jsx",
2093
- ".mjs",
2094
- ".cjs",
2095
- ".mts",
2096
- ".cts"
2097
- ]);
2098
1875
  function timestamp() {
2099
1876
  return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
2100
1877
  }
@@ -2141,10 +1918,8 @@ async function devCommand(options) {
2141
1918
  return;
2142
1919
  }
2143
1920
  reloading = true;
2144
- log(
2145
- `${dim}
2146
- Detected change in ${changedPath ?? "tools directory"}, reloading...${reset}`
2147
- );
1921
+ log(`${dim}
1922
+ Detected change in ${changedPath ?? "tools directory"}, reloading...${reset}`);
2148
1923
  try {
2149
1924
  toolDefinitions = await loadToolDefinitions(toolsDir, projectRoot);
2150
1925
  routes = expandRoutes(toolDefinitions);
@@ -2177,9 +1952,7 @@ Detected change in ${changedPath ?? "tools directory"}, reloading...${reset}`
2177
1952
  log(`${dim}[request] ${method} ${routePath}${reset}`);
2178
1953
  try {
2179
1954
  await handleRequest({ req, res, port, routes });
2180
- log(
2181
- `${dim}[response] ${method} ${routePath} ${res.statusCode}${reset}`
2182
- );
1955
+ log(`${dim}[response] ${method} ${routePath} ${res.statusCode}${reset}`);
2183
1956
  } catch (error) {
2184
1957
  console.error("Error handling request:", error);
2185
1958
  res.writeHead(500, { "Content-Type": "application/json" });
@@ -2189,9 +1962,7 @@ Detected change in ${changedPath ?? "tools directory"}, reloading...${reset}`
2189
1962
  });
2190
1963
  server.listen(port, () => {
2191
1964
  log(`${bold}${dim}> dev opentool${reset}`);
2192
- log(
2193
- ` * ${bold}opentool${reset} ${cyan}v${packageJson.version}${reset}`
2194
- );
1965
+ log(` * ${bold}opentool${reset} ${cyan}v${packageJson.version}${reset}`);
2195
1966
  log(` * ${bold}HTTP:${reset} http://localhost:${port}`);
2196
1967
  logStartup(toolDefinitions, enableStdio, log);
2197
1968
  });
@@ -2244,9 +2015,7 @@ async function startMcpServer(getTools) {
2244
2015
  throw new Error(`Tool ${request.params.name} not found`);
2245
2016
  }
2246
2017
  try {
2247
- const validatedParams = tool.schema.parse(
2248
- request.params.arguments
2249
- );
2018
+ const validatedParams = tool.schema.parse(request.params.arguments);
2250
2019
  const handler = tool.handler ?? createMcpAdapter({
2251
2020
  name: tool.metadata?.name ?? tool.filename,
2252
2021
  httpHandlers: toHttpHandlerMap2(tool.httpHandlers),
@@ -2330,10 +2099,7 @@ function printToolList(tools, log) {
2330
2099
  async function handleRequest(params) {
2331
2100
  const { req, res, port, routes } = params;
2332
2101
  res.setHeader("Access-Control-Allow-Origin", "*");
2333
- res.setHeader(
2334
- "Access-Control-Allow-Methods",
2335
- HTTP_METHODS.join(", ") + ", OPTIONS"
2336
- );
2102
+ res.setHeader("Access-Control-Allow-Methods", HTTP_METHODS.join(", ") + ", OPTIONS");
2337
2103
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
2338
2104
  if (req.method === "OPTIONS") {
2339
2105
  res.writeHead(200);
@@ -2386,9 +2152,7 @@ function findRoute(toolName, method, routes) {
2386
2152
  return direct;
2387
2153
  }
2388
2154
  if (method === "HEAD") {
2389
- return routes.find(
2390
- (route) => routeName(route.tool) === toolName && route.method === "GET"
2391
- );
2155
+ return routes.find((route) => routeName(route.tool) === toolName && route.method === "GET");
2392
2156
  }
2393
2157
  return void 0;
2394
2158
  }
@@ -2435,13 +2199,10 @@ function createWebRequest(params) {
2435
2199
  return new Request(url, init);
2436
2200
  }
2437
2201
  function toHttpHandlerMap2(handlers) {
2438
- return handlers.reduce(
2439
- (acc, handler) => {
2440
- acc[handler.method.toUpperCase()] = handler.handler;
2441
- return acc;
2442
- },
2443
- {}
2444
- );
2202
+ return handlers.reduce((acc, handler) => {
2203
+ acc[handler.method.toUpperCase()] = handler.handler;
2204
+ return acc;
2205
+ }, {});
2445
2206
  }
2446
2207
  function isMcpEnabled(tool) {
2447
2208
  return Boolean(tool.mcpConfig?.enabled);
@@ -2541,7 +2302,7 @@ async function updateMetadata(targetDir, name, description) {
2541
2302
  const raw = await promises.readFile(filePath, "utf-8");
2542
2303
  const displayName = toDisplayName(name);
2543
2304
  const resolvedDescription = description || "OpenTool project";
2544
- const updated = raw.replace(/name:\s*\".*?\"/, `name: "${toPackageName(name)}"`).replace(/displayName:\s*\".*?\"/, `displayName: "${displayName}"`).replace(/description:\s*\".*?\"/, `description: "${resolvedDescription}"`);
2305
+ const updated = raw.replace(/name:\s*".*?"/, `name: "${toPackageName(name)}"`).replace(/displayName:\s*".*?"/, `displayName: "${displayName}"`).replace(/description:\s*".*?"/, `description: "${resolvedDescription}"`);
2545
2306
  await promises.writeFile(filePath, updated, "utf-8");
2546
2307
  }
2547
2308
  async function initCommand(options) {
@@ -2549,9 +2310,7 @@ async function initCommand(options) {
2549
2310
  const templateDir = resolveTemplateDir();
2550
2311
  const empty = await directoryIsEmpty(targetDir);
2551
2312
  if (!empty && !options.force) {
2552
- throw new Error(
2553
- `Directory not empty: ${targetDir}. Use --force to overwrite.`
2554
- );
2313
+ throw new Error(`Directory not empty: ${targetDir}. Use --force to overwrite.`);
2555
2314
  }
2556
2315
  await copyDir(templateDir, targetDir);
2557
2316
  const projectName = options.name || path6__default.basename(targetDir);
@@ -2573,11 +2332,7 @@ program.command("dev").description("Start HTTP dev server (optional MCP stdio)")
2573
2332
  program.command("build").description("Build tools for deployment").option("-i, --input <dir>", "Input directory containing tools", "tools").option("-o, --output <dir>", "Output directory for built tools", "dist").option("--name <name>", "Server name", "opentool-server").option("--version <version>", "Server version", "1.0.0").action(buildCommand);
2574
2333
  program.command("validate").description("Validate metadata for registry submission").option("-i, --input <dir>", "Input directory containing tools", "tools").action(validateCommand);
2575
2334
  program.command("validate-full").description("Full validation of tools and metadata").option("-i, --input <dir>", "Input directory containing tools", "tools").action(validateFullCommand);
2576
- program.command("metadata").description("Generate OpenTool metadata JSON without building").option("-i, --input <dir>", "Input directory containing tools", "tools").option(
2577
- "-o, --output <file>",
2578
- "Output file path for metadata.json",
2579
- "metadata.json"
2580
- ).option("--name <name>", "Server name", "opentool-server").option("--version <version>", "Server version", "1.0.0").action(generateMetadataCommand);
2335
+ program.command("metadata").description("Generate OpenTool metadata JSON without building").option("-i, --input <dir>", "Input directory containing tools", "tools").option("-o, --output <file>", "Output file path for metadata.json", "metadata.json").option("--name <name>", "Server name", "opentool-server").option("--version <version>", "Server version", "1.0.0").action(generateMetadataCommand);
2581
2336
  program.command("init").description("Create a new OpenTool project in the target directory").option("-d, --dir <dir>", "Target directory", ".").option("-n, --name <name>", "Project name").option("--description <description>", "Project description").option("--force", "Overwrite existing files", false).action(async (cmdOptions) => {
2582
2337
  await initCommand({
2583
2338
  dir: cmdOptions.dir,