opentool 0.10.0 → 0.10.3

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.
@@ -1,4 +1,4 @@
1
- import { c as WalletFullContext } from '../../types-BVLpaY4O.js';
1
+ import { c as WalletFullContext } from '../../types-3w880w_t.js';
2
2
  import { StoreOptions, StoreResponse } from '../../store/index.js';
3
3
  import 'viem';
4
4
  import 'viem/accounts';
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { M as Metadata, I as InternalToolDefinition } from '../validate-3WEA0Ezt.js';
3
- export { G as GenerateMetadataOptions, a as GenerateMetadataResult, V as ValidateOptions, b as generateMetadata, g as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand, c as validateFullCommand } from '../validate-3WEA0Ezt.js';
2
+ import { M as Metadata, I as InternalToolDefinition } from '../validate-DbhJ_r0Z.js';
3
+ export { G as GenerateMetadataOptions, a as GenerateMetadataResult, V as ValidateOptions, g as generateMetadata, b as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand, c as validateFullCommand } from '../validate-DbhJ_r0Z.js';
4
4
  import 'zod';
5
- import '../x402/index.js';
6
- import 'viem';
5
+ import '../payment-orkZA9se.js';
7
6
 
8
7
  interface BuildOptions {
9
8
  input: string;
package/dist/cli/index.js CHANGED
@@ -1,28 +1,22 @@
1
1
  #!/usr/bin/env node
2
- import * as path6 from 'path';
3
- import path6__default from 'path';
4
- import { fileURLToPath, pathToFileURL } from 'url';
5
2
  import { program } from 'commander';
6
3
  import * as fs4 from 'fs';
7
4
  import { promises } from 'fs';
5
+ import * as path5 from 'path';
8
6
  import { tmpdir } from 'os';
9
7
  import { build } from 'esbuild';
10
8
  import { z } from 'zod';
11
9
  import { createRequire } from 'module';
10
+ import { fileURLToPath, pathToFileURL } from 'url';
12
11
  import { zodToJsonSchema } from '@alcyone-labs/zod-to-json-schema';
13
- import 'viem';
14
- import 'viem/accounts';
15
- import 'viem/chains';
16
12
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
17
13
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
18
14
  import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
19
- import * as http2 from 'http';
15
+ import * as http from 'http';
20
16
  import dotenv from 'dotenv';
21
17
 
22
- var getFilename = () => fileURLToPath(import.meta.url);
23
- var __filename = /* @__PURE__ */ getFilename();
24
18
  function resolveTsconfig(projectRoot) {
25
- const candidate = path6.join(projectRoot, "tsconfig.json");
19
+ const candidate = path5.join(projectRoot, "tsconfig.json");
26
20
  if (fs4.existsSync(candidate)) {
27
21
  return candidate;
28
22
  }
@@ -33,7 +27,7 @@ async function transpileWithEsbuild(options) {
33
27
  throw new Error("No entry points provided for esbuild transpilation");
34
28
  }
35
29
  const projectRoot = options.projectRoot;
36
- const tempBase = options.outDir ?? fs4.mkdtempSync(path6.join(tmpdir(), "opentool-"));
30
+ const tempBase = options.outDir ?? fs4.mkdtempSync(path5.join(tmpdir(), "opentool-"));
37
31
  if (!fs4.existsSync(tempBase)) {
38
32
  fs4.mkdirSync(tempBase, { recursive: true });
39
33
  }
@@ -66,6 +60,9 @@ async function transpileWithEsbuild(options) {
66
60
  if (options.external && options.external.length > 0) {
67
61
  buildOptions.external = options.external;
68
62
  }
63
+ if (options.nodePaths && options.nodePaths.length > 0) {
64
+ buildOptions.nodePaths = options.nodePaths;
65
+ }
69
66
  if (options.outBase) {
70
67
  buildOptions.outbase = options.outBase;
71
68
  }
@@ -77,7 +74,7 @@ async function transpileWithEsbuild(options) {
77
74
  }
78
75
  await build(buildOptions);
79
76
  if (options.format === "esm") {
80
- const packageJsonPath = path6.join(tempBase, "package.json");
77
+ const packageJsonPath = path5.join(tempBase, "package.json");
81
78
  if (!fs4.existsSync(packageJsonPath)) {
82
79
  fs4.writeFileSync(packageJsonPath, JSON.stringify({ type: "module" }), "utf8");
83
80
  }
@@ -211,8 +208,8 @@ createRequire(
211
208
  typeof __filename !== "undefined" ? __filename : import.meta.url
212
209
  );
213
210
  function resolveCompiledPath(outDir, originalFile, extension = ".js") {
214
- const baseName = path6.basename(originalFile).replace(/\.[^.]+$/, "");
215
- return path6.join(outDir, `${baseName}${extension}`);
211
+ const baseName = path5.basename(originalFile).replace(/\.[^.]+$/, "");
212
+ return path5.join(outDir, `${baseName}${extension}`);
216
213
  }
217
214
  async function importFresh(modulePath) {
218
215
  const fileUrl = pathToFileURL(modulePath).href;
@@ -224,14 +221,14 @@ async function importFresh(modulePath) {
224
221
  // src/cli/shared/metadata.ts
225
222
  var METADATA_ENTRY = "metadata.ts";
226
223
  async function loadMetadata(projectRoot) {
227
- const absPath = path6.join(projectRoot, METADATA_ENTRY);
224
+ const absPath = path5.join(projectRoot, METADATA_ENTRY);
228
225
  if (!fs4.existsSync(absPath)) {
229
226
  return {
230
227
  metadata: MetadataSchema.parse({}),
231
228
  sourcePath: "smart defaults (metadata.ts missing)"
232
229
  };
233
230
  }
234
- const tempDir = path6.join(projectRoot, ".opentool-temp");
231
+ const tempDir = path5.join(projectRoot, ".opentool-temp");
235
232
  if (fs4.existsSync(tempDir)) {
236
233
  fs4.rmSync(tempDir, { recursive: true, force: true });
237
234
  }
@@ -272,7 +269,7 @@ function extractMetadataExport(moduleExports) {
272
269
  return moduleExports;
273
270
  }
274
271
  function readPackageJson(projectRoot) {
275
- const packagePath = path6.join(projectRoot, "package.json");
272
+ const packagePath = path5.join(projectRoot, "package.json");
276
273
  if (!fs4.existsSync(packagePath)) {
277
274
  return {};
278
275
  }
@@ -288,7 +285,7 @@ async function buildMetadataArtifact(options) {
288
285
  const packageInfo = readPackageJson(projectRoot);
289
286
  const { metadata: authored, sourcePath } = await loadMetadata(projectRoot);
290
287
  const defaultsApplied = [];
291
- const folderName = path6.basename(projectRoot);
288
+ const folderName = path5.basename(projectRoot);
292
289
  const name = resolveField(
293
290
  "name",
294
291
  authored.name,
@@ -751,7 +748,7 @@ function ensureTrailingSlash(url) {
751
748
  return url.endsWith("/") ? url : `${url}/`;
752
749
  }
753
750
 
754
- // src/x402/index.ts
751
+ // src/x402/payment.ts
755
752
  var PAYMENT_CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("opentool.x402.context");
756
753
  var X402PaymentRequiredError = class extends Error {
757
754
  constructor(response, verification) {
@@ -991,6 +988,8 @@ function validateCronTokens(fields, context) {
991
988
 
992
989
  // src/cli/validate.ts
993
990
  var SUPPORTED_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
991
+ var OPENTOOL_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../..");
992
+ var OPENTOOL_NODE_MODULES = path5.join(OPENTOOL_ROOT, "node_modules");
994
993
  var MIN_TEMPLATE_CONFIG_VERSION = 2;
995
994
  var TEMPLATE_PREVIEW_TITLE_MAX = 80;
996
995
  var TEMPLATE_PREVIEW_SUBTITLE_MAX = 120;
@@ -1077,36 +1076,36 @@ function normalizeTemplatePreview(value, file, toolName, requirePreview) {
1077
1076
  };
1078
1077
  }
1079
1078
  async function validateCommand(options) {
1080
- console.log("\u{1F50D} Validating OpenTool metadata...");
1079
+ console.log("\u{1F50D} Validating OpenTool project...");
1081
1080
  try {
1082
- const toolsDir = path6.resolve(options.input);
1081
+ const toolsDir = path5.resolve(options.input);
1083
1082
  if (!fs4.existsSync(toolsDir)) {
1084
1083
  throw new Error(`Tools directory not found: ${toolsDir}`);
1085
1084
  }
1086
- const projectRoot = path6.dirname(toolsDir);
1085
+ const projectRoot = path5.dirname(toolsDir);
1087
1086
  const tools = await loadAndValidateTools(toolsDir, { projectRoot });
1088
1087
  if (tools.length === 0) {
1089
- throw new Error("No valid tools found - metadata validation aborted");
1088
+ throw new Error("No valid tools found - validation aborted");
1090
1089
  }
1091
1090
  const { metadata, defaultsApplied, sourceMetadataPath } = await buildMetadataArtifact({
1092
1091
  projectRoot,
1093
1092
  tools
1094
1093
  });
1095
1094
  logMetadataSummary(metadata, defaultsApplied, sourceMetadataPath);
1096
- console.log("\n\u2705 Metadata validation passed!\n");
1095
+ console.log("\n\u2705 OpenTool validation passed!\n");
1097
1096
  } catch (error) {
1098
- console.error("\u274C Metadata validation failed:", error);
1097
+ console.error("\u274C OpenTool validation failed:", error);
1099
1098
  process.exit(1);
1100
1099
  }
1101
1100
  }
1102
1101
  async function validateFullCommand(options) {
1103
1102
  console.log("\u{1F50D} Running full OpenTool validation...\n");
1104
1103
  try {
1105
- const toolsDir = path6.resolve(options.input);
1104
+ const toolsDir = path5.resolve(options.input);
1106
1105
  if (!fs4.existsSync(toolsDir)) {
1107
1106
  throw new Error(`Tools directory not found: ${toolsDir}`);
1108
1107
  }
1109
- const projectRoot = path6.dirname(toolsDir);
1108
+ const projectRoot = path5.dirname(toolsDir);
1110
1109
  const tools = await loadAndValidateTools(toolsDir, { projectRoot });
1111
1110
  if (tools.length === 0) {
1112
1111
  throw new Error("No tools discovered in the target directory");
@@ -1134,12 +1133,12 @@ async function validateFullCommand(options) {
1134
1133
  }
1135
1134
  }
1136
1135
  async function loadAndValidateTools(toolsDir, options = {}) {
1137
- const files = fs4.readdirSync(toolsDir).filter((file) => SUPPORTED_EXTENSIONS.includes(path6.extname(file)));
1136
+ const files = fs4.readdirSync(toolsDir).filter((file) => SUPPORTED_EXTENSIONS.includes(path5.extname(file)));
1138
1137
  if (files.length === 0) {
1139
1138
  return [];
1140
1139
  }
1141
- const projectRoot = options.projectRoot ?? path6.dirname(toolsDir);
1142
- const tempDir = path6.join(toolsDir, ".opentool-temp");
1140
+ const projectRoot = options.projectRoot ?? path5.dirname(toolsDir);
1141
+ const tempDir = path5.join(toolsDir, ".opentool-temp");
1143
1142
  if (fs4.existsSync(tempDir)) {
1144
1143
  fs4.rmSync(tempDir, { recursive: true, force: true });
1145
1144
  }
@@ -1149,17 +1148,20 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1149
1148
  throw new Error(`Tool filename must be kebab-case: ${f}`);
1150
1149
  }
1151
1150
  }
1152
- const entryPoints = files.map((file) => path6.join(toolsDir, file));
1151
+ const entryPoints = files.map((file) => path5.join(toolsDir, file));
1152
+ const fallbackNodePaths = [OPENTOOL_NODE_MODULES].filter((dir) => fs4.existsSync(dir));
1153
1153
  const { outDir, cleanup } = await transpileWithEsbuild({
1154
1154
  entryPoints,
1155
1155
  projectRoot,
1156
1156
  format: "esm",
1157
1157
  outDir: tempDir,
1158
1158
  bundle: true,
1159
- external: ["opentool", "opentool/*"]
1159
+ external: ["opentool", "opentool/*"],
1160
+ ...fallbackNodePaths.length > 0 ? { nodePaths: fallbackNodePaths } : {}
1160
1161
  });
1161
1162
  const tools = [];
1162
1163
  try {
1164
+ ensureLocalRuntimeLinks(tempDir);
1163
1165
  for (const file of files) {
1164
1166
  const compiledPath = resolveCompiledPath(outDir, file);
1165
1167
  if (!fs4.existsSync(compiledPath)) {
@@ -1313,11 +1315,6 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1313
1315
  if (!schema) {
1314
1316
  throw new Error(`${file}: POST tools must export a Zod schema as 'schema'`);
1315
1317
  }
1316
- if (schedule && typeof schedule.cron === "string") {
1317
- throw new Error(
1318
- `${file}: POST tools must not define profile.schedule; use GET + cron for scheduled tasks.`
1319
- );
1320
- }
1321
1318
  }
1322
1319
  const httpHandlers = [...httpHandlersRaw];
1323
1320
  if (httpHandlers.length === 0) {
@@ -1365,7 +1362,7 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1365
1362
  httpHandlers,
1366
1363
  mcpConfig: normalizeMcpConfig(toolModule.mcp, file),
1367
1364
  filename: toBaseName(file),
1368
- sourcePath: path6.join(toolsDir, file),
1365
+ sourcePath: path5.join(toolsDir, file),
1369
1366
  handler: async (params) => adapter(params),
1370
1367
  payment: paymentExport ?? null,
1371
1368
  schedule: normalizedSchedule,
@@ -1384,6 +1381,24 @@ async function loadAndValidateTools(toolsDir, options = {}) {
1384
1381
  }
1385
1382
  return tools;
1386
1383
  }
1384
+ function ensureLocalRuntimeLinks(tempDir) {
1385
+ const nodeModulesDir = path5.join(tempDir, "node_modules");
1386
+ fs4.mkdirSync(nodeModulesDir, { recursive: true });
1387
+ const packageLinks = [
1388
+ { name: "opentool", target: OPENTOOL_ROOT },
1389
+ { name: "zod", target: path5.join(OPENTOOL_NODE_MODULES, "zod") }
1390
+ ];
1391
+ for (const { name, target } of packageLinks) {
1392
+ if (!fs4.existsSync(target)) {
1393
+ continue;
1394
+ }
1395
+ const linkPath = path5.join(nodeModulesDir, name);
1396
+ if (fs4.existsSync(linkPath)) {
1397
+ continue;
1398
+ }
1399
+ fs4.symlinkSync(target, linkPath, "junction");
1400
+ }
1401
+ }
1387
1402
  function extractToolModule(exportsObject, filename) {
1388
1403
  const candidates = [exportsObject, exportsObject?.default];
1389
1404
  for (const candidate of candidates) {
@@ -1571,12 +1586,12 @@ async function buildCommand(options) {
1571
1586
  }
1572
1587
  }
1573
1588
  async function buildProject(options) {
1574
- const toolsDir = path6.resolve(options.input);
1589
+ const toolsDir = path5.resolve(options.input);
1575
1590
  if (!fs4.existsSync(toolsDir)) {
1576
1591
  throw new Error(`Tools directory not found: ${toolsDir}`);
1577
1592
  }
1578
- const projectRoot = path6.dirname(toolsDir);
1579
- const outputDir = path6.resolve(options.output);
1593
+ const projectRoot = path5.dirname(toolsDir);
1594
+ const outputDir = path5.resolve(options.output);
1580
1595
  fs4.mkdirSync(outputDir, { recursive: true });
1581
1596
  const serverName = options.name ?? "opentool-server";
1582
1597
  const serverVersion = options.version ?? "1.0.0";
@@ -1588,7 +1603,7 @@ async function buildProject(options) {
1588
1603
  projectRoot,
1589
1604
  tools
1590
1605
  });
1591
- const metadataPath = path6.join(outputDir, "metadata.json");
1606
+ const metadataPath = path5.join(outputDir, "metadata.json");
1592
1607
  fs4.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
1593
1608
  const compiledTools = await emitTools(tools, {
1594
1609
  projectRoot,
@@ -1611,7 +1626,7 @@ async function buildProject(options) {
1611
1626
  serverVersion,
1612
1627
  compiledTools});
1613
1628
  } else {
1614
- const serverPath = path6.join(outputDir, "mcp-server.js");
1629
+ const serverPath = path5.join(outputDir, "mcp-server.js");
1615
1630
  if (fs4.existsSync(serverPath)) {
1616
1631
  fs4.rmSync(serverPath);
1617
1632
  }
@@ -1626,7 +1641,7 @@ async function buildProject(options) {
1626
1641
  };
1627
1642
  }
1628
1643
  async function emitTools(tools, config) {
1629
- const toolsOutDir = path6.join(config.outputDir, "tools");
1644
+ const toolsOutDir = path5.join(config.outputDir, "tools");
1630
1645
  if (fs4.existsSync(toolsOutDir)) {
1631
1646
  fs4.rmSync(toolsOutDir, { recursive: true, force: true });
1632
1647
  }
@@ -1648,9 +1663,9 @@ async function emitTools(tools, config) {
1648
1663
  if (!tool.sourcePath) {
1649
1664
  throw new Error(`Missing sourcePath for tool ${tool.filename}`);
1650
1665
  }
1651
- const base = path6.basename(tool.sourcePath).replace(/\.[^.]+$/, "");
1652
- const modulePath = path6.join("tools", `${base}.js`);
1653
- if (!fs4.existsSync(path6.join(config.outputDir, modulePath))) {
1666
+ const base = path5.basename(tool.sourcePath).replace(/\.[^.]+$/, "");
1667
+ const modulePath = path5.join("tools", `${base}.js`);
1668
+ if (!fs4.existsSync(path5.join(config.outputDir, modulePath))) {
1654
1669
  throw new Error(`Expected compiled output missing: ${modulePath}`);
1655
1670
  }
1656
1671
  const defaultMcpMethod = tool.mcpConfig?.defaultMethod;
@@ -1667,7 +1682,7 @@ async function emitTools(tools, config) {
1667
1682
  return compiled;
1668
1683
  }
1669
1684
  async function emitSharedModules(config) {
1670
- const srcDir = path6.join(config.projectRoot, "src");
1685
+ const srcDir = path5.join(config.projectRoot, "src");
1671
1686
  if (!fs4.existsSync(srcDir)) {
1672
1687
  return null;
1673
1688
  }
@@ -1675,7 +1690,7 @@ async function emitSharedModules(config) {
1675
1690
  if (sharedFiles.length === 0) {
1676
1691
  return null;
1677
1692
  }
1678
- const sharedOutDir = path6.join(config.outputDir, "src");
1693
+ const sharedOutDir = path5.join(config.outputDir, "src");
1679
1694
  await transpileWithEsbuild({
1680
1695
  entryPoints: sharedFiles,
1681
1696
  projectRoot: config.projectRoot,
@@ -1693,7 +1708,7 @@ function collectSourceFiles(dir) {
1693
1708
  const ignoreDirs = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".opentool-temp"]);
1694
1709
  const entries = fs4.readdirSync(dir, { withFileTypes: true });
1695
1710
  for (const entry of entries) {
1696
- const fullPath = path6.join(dir, entry.name);
1711
+ const fullPath = path5.join(dir, entry.name);
1697
1712
  if (entry.isDirectory()) {
1698
1713
  if (ignoreDirs.has(entry.name)) {
1699
1714
  continue;
@@ -1701,7 +1716,7 @@ function collectSourceFiles(dir) {
1701
1716
  results.push(...collectSourceFiles(fullPath));
1702
1717
  continue;
1703
1718
  }
1704
- const ext = path6.extname(entry.name);
1719
+ const ext = path5.extname(entry.name);
1705
1720
  if (supported.has(ext) && !entry.name.endsWith(".d.ts")) {
1706
1721
  results.push(fullPath);
1707
1722
  }
@@ -1803,13 +1818,13 @@ module.exports = { server };
1803
1818
  }
1804
1819
  async function writeMcpServer(options) {
1805
1820
  const serverCode = renderMcpServer(options);
1806
- const serverPath = path6.join(options.outputDir, "mcp-server.js");
1821
+ const serverPath = path5.join(options.outputDir, "mcp-server.js");
1807
1822
  fs4.writeFileSync(serverPath, serverCode);
1808
1823
  fs4.chmodSync(serverPath, 493);
1809
1824
  }
1810
1825
  function writeToolsManifest(options) {
1811
- const manifestPath = path6.join(options.outputDir, "tools.json");
1812
- const legacyManifestPath = path6.join(options.outputDir, ".well-known", "opentool", "cron.json");
1826
+ const manifestPath = path5.join(options.outputDir, "tools.json");
1827
+ const legacyManifestPath = path5.join(options.outputDir, ".well-known", "opentool", "cron.json");
1813
1828
  if (fs4.existsSync(legacyManifestPath)) {
1814
1829
  fs4.rmSync(legacyManifestPath, { force: true });
1815
1830
  }
@@ -1843,7 +1858,7 @@ function writeToolsManifest(options) {
1843
1858
  function logBuildSummary(artifacts, options) {
1844
1859
  const end = timestamp();
1845
1860
  console.log(`[${end}] Build completed successfully!`);
1846
- console.log(`Output directory: ${path6.resolve(options.output)}`);
1861
+ console.log(`Output directory: ${path5.resolve(options.output)}`);
1847
1862
  console.log("Generated files:");
1848
1863
  const hasMcp = artifacts.compiledTools.some((tool) => tool.mcpEnabled);
1849
1864
  if (hasMcp) {
@@ -1878,9 +1893,9 @@ function timestamp() {
1878
1893
  function escapeForJs(value) {
1879
1894
  return value.replace(/'/g, "\\'");
1880
1895
  }
1881
- var __dirname2 = path6.dirname(fileURLToPath(import.meta.url));
1896
+ var __dirname$1 = path5.dirname(fileURLToPath(import.meta.url));
1882
1897
  var packageJson = JSON.parse(
1883
- fs4.readFileSync(path6.resolve(__dirname2, "../../package.json"), "utf-8")
1898
+ fs4.readFileSync(path5.resolve(__dirname$1, "../../package.json"), "utf-8")
1884
1899
  );
1885
1900
  var cyan = "\x1B[36m";
1886
1901
  var bold = "\x1B[1m";
@@ -1893,11 +1908,11 @@ async function devCommand(options) {
1893
1908
  const log = enableStdio ? (_message) => {
1894
1909
  } : (message) => console.log(message);
1895
1910
  try {
1896
- const toolsDir = path6.resolve(options.input);
1911
+ const toolsDir = path5.resolve(options.input);
1897
1912
  if (!fs4.existsSync(toolsDir)) {
1898
1913
  throw new Error(`Tools directory not found: ${toolsDir}`);
1899
1914
  }
1900
- const projectRoot = path6.dirname(toolsDir);
1915
+ const projectRoot = path5.dirname(toolsDir);
1901
1916
  loadEnvFiles(projectRoot);
1902
1917
  let toolDefinitions = await loadToolDefinitions(toolsDir, projectRoot);
1903
1918
  if (toolDefinitions.length === 0) {
@@ -1907,7 +1922,7 @@ async function devCommand(options) {
1907
1922
  const stdioController = enableStdio ? await startMcpServer(() => toolDefinitions) : null;
1908
1923
  if (watch2) {
1909
1924
  const reloadableExtensions = /\.(ts|js|mjs|cjs|tsx|jsx)$/i;
1910
- const tempDir = path6.join(toolsDir, ".opentool-temp");
1925
+ const tempDir = path5.join(toolsDir, ".opentool-temp");
1911
1926
  const watchTargets = /* @__PURE__ */ new Set([toolsDir]);
1912
1927
  if (projectRoot !== toolsDir) {
1913
1928
  watchTargets.add(projectRoot);
@@ -1936,16 +1951,16 @@ Detected change in ${changedPath ?? "tools directory"}, reloading...${reset}`);
1936
1951
  if (filename && !reloadableExtensions.test(filename)) {
1937
1952
  return;
1938
1953
  }
1939
- const fullPath = filename ? path6.join(target, filename) : void 0;
1954
+ const fullPath = filename ? path5.join(target, filename) : void 0;
1940
1955
  if (fullPath && fullPath.startsWith(tempDir)) {
1941
1956
  return;
1942
1957
  }
1943
- const displayPath = fullPath ? path6.relative(projectRoot, fullPath) || path6.basename(fullPath) : path6.relative(projectRoot, target) || path6.basename(target);
1958
+ const displayPath = fullPath ? path5.relative(projectRoot, fullPath) || path5.basename(fullPath) : path5.relative(projectRoot, target) || path5.basename(target);
1944
1959
  await scheduleReload(displayPath);
1945
1960
  });
1946
1961
  }
1947
1962
  }
1948
- const server = http2.createServer(async (req, res) => {
1963
+ const server = http.createServer(async (req, res) => {
1949
1964
  const method = (req.method || "GET").toUpperCase();
1950
1965
  const url = new URL(req.url || "/", `http://localhost:${port}`);
1951
1966
  const routePath = url.pathname;
@@ -2162,7 +2177,7 @@ function routeName(tool) {
2162
2177
  function loadEnvFiles(projectRoot) {
2163
2178
  const envFiles = [".env.local", ".env"];
2164
2179
  for (const file of envFiles) {
2165
- const candidate = path6.join(projectRoot, file);
2180
+ const candidate = path5.join(projectRoot, file);
2166
2181
  if (fs4.existsSync(candidate)) {
2167
2182
  dotenv.config({ path: candidate, override: false });
2168
2183
  }
@@ -2230,17 +2245,17 @@ async function generateMetadataCommand(options) {
2230
2245
  }
2231
2246
  }
2232
2247
  async function generateMetadata(options) {
2233
- const toolsDir = path6.resolve(options.input);
2248
+ const toolsDir = path5.resolve(options.input);
2234
2249
  if (!fs4.existsSync(toolsDir)) {
2235
2250
  throw new Error(`Tools directory not found: ${toolsDir}`);
2236
2251
  }
2237
- const projectRoot = path6.dirname(toolsDir);
2252
+ const projectRoot = path5.dirname(toolsDir);
2238
2253
  const tools = await loadAndValidateTools(toolsDir, { projectRoot });
2239
2254
  const { metadata, defaultsApplied } = await buildMetadataArtifact({
2240
2255
  projectRoot,
2241
2256
  tools
2242
2257
  });
2243
- const outputPath = options.output ? path6.resolve(options.output) : path6.join(projectRoot, "metadata.json");
2258
+ const outputPath = options.output ? path5.resolve(options.output) : path5.join(projectRoot, "metadata.json");
2244
2259
  fs4.writeFileSync(outputPath, JSON.stringify(metadata, null, 2));
2245
2260
  return {
2246
2261
  metadata,
@@ -2253,8 +2268,8 @@ function timestamp2() {
2253
2268
  return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
2254
2269
  }
2255
2270
  function resolveTemplateDir() {
2256
- const here = path6__default.dirname(fileURLToPath(import.meta.url));
2257
- return path6__default.resolve(here, "../../templates/base");
2271
+ const here = path5.dirname(fileURLToPath(import.meta.url));
2272
+ return path5.resolve(here, "../../templates/base");
2258
2273
  }
2259
2274
  async function directoryIsEmpty(targetDir) {
2260
2275
  try {
@@ -2271,8 +2286,8 @@ async function copyDir(src, dest) {
2271
2286
  await promises.mkdir(dest, { recursive: true });
2272
2287
  const entries = await promises.readdir(src, { withFileTypes: true });
2273
2288
  for (const entry of entries) {
2274
- const srcPath = path6__default.join(src, entry.name);
2275
- const destPath = path6__default.join(dest, entry.name);
2289
+ const srcPath = path5.join(src, entry.name);
2290
+ const destPath = path5.join(dest, entry.name);
2276
2291
  if (entry.isDirectory()) {
2277
2292
  await copyDir(srcPath, destPath);
2278
2293
  } else if (entry.isFile()) {
@@ -2287,7 +2302,7 @@ function toDisplayName(value) {
2287
2302
  return value.trim().replace(/[-_]+/g, " ").replace(/\b\w/g, (ch) => ch.toUpperCase()) || "OpenTool Project";
2288
2303
  }
2289
2304
  async function updatePackageJson(targetDir, name, description) {
2290
- const filePath = path6__default.join(targetDir, "package.json");
2305
+ const filePath = path5.join(targetDir, "package.json");
2291
2306
  const raw = await promises.readFile(filePath, "utf-8");
2292
2307
  const pkg = JSON.parse(raw);
2293
2308
  pkg.name = toPackageName(name);
@@ -2298,7 +2313,7 @@ async function updatePackageJson(targetDir, name, description) {
2298
2313
  `, "utf-8");
2299
2314
  }
2300
2315
  async function updateMetadata(targetDir, name, description) {
2301
- const filePath = path6__default.join(targetDir, "metadata.ts");
2316
+ const filePath = path5.join(targetDir, "metadata.ts");
2302
2317
  const raw = await promises.readFile(filePath, "utf-8");
2303
2318
  const displayName = toDisplayName(name);
2304
2319
  const resolvedDescription = description || "OpenTool project";
@@ -2306,14 +2321,14 @@ async function updateMetadata(targetDir, name, description) {
2306
2321
  await promises.writeFile(filePath, updated, "utf-8");
2307
2322
  }
2308
2323
  async function initCommand(options) {
2309
- const targetDir = path6__default.resolve(process.cwd(), options.dir || ".");
2324
+ const targetDir = path5.resolve(process.cwd(), options.dir || ".");
2310
2325
  const templateDir = resolveTemplateDir();
2311
2326
  const empty = await directoryIsEmpty(targetDir);
2312
2327
  if (!empty && !options.force) {
2313
2328
  throw new Error(`Directory not empty: ${targetDir}. Use --force to overwrite.`);
2314
2329
  }
2315
2330
  await copyDir(templateDir, targetDir);
2316
- const projectName = options.name || path6__default.basename(targetDir);
2331
+ const projectName = options.name || path5.basename(targetDir);
2317
2332
  const description = options.description;
2318
2333
  await updatePackageJson(targetDir, projectName, description);
2319
2334
  await updateMetadata(targetDir, projectName, description);
@@ -2330,8 +2345,8 @@ program.command("dev").description("Start HTTP dev server (optional MCP stdio)")
2330
2345
  });
2331
2346
  });
2332
2347
  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);
2333
- program.command("validate").description("Validate metadata for registry submission").option("-i, --input <dir>", "Input directory containing tools", "tools").action(validateCommand);
2334
- program.command("validate-full").description("Full validation of tools and metadata").option("-i, --input <dir>", "Input directory containing tools", "tools").action(validateFullCommand);
2348
+ program.command("validate").description("Validate OpenTool project (tool handlers, profile/schema rules, metadata synthesis)").option("-i, --input <dir>", "Input directory containing tools", "tools").action(validateCommand);
2349
+ program.command("validate-full").description("Full OpenTool validation with detailed tool summary").option("-i, --input <dir>", "Input directory containing tools", "tools").action(validateFullCommand);
2335
2350
  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);
2336
2351
  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) => {
2337
2352
  await initCommand({