unicommand 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { z as z4 } from "zod";
2
+ import { z as z5 } from "zod";
3
3
 
4
4
  // src/command/runtime-metadata.ts
5
5
  var commandMetadata = /* @__PURE__ */ new WeakMap();
@@ -514,14 +514,13 @@ import { basename, extname, join } from "path";
514
514
  import { pathToFileURL } from "url";
515
515
  var COMMAND_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".ts"]);
516
516
  var IGNORED_COMMAND_FILE_NAMES = /* @__PURE__ */ new Set(["index", "options"]);
517
- var loadCommandModules = async (commandsDir) => {
518
- return loadCommandModulesFromFiles(await commandFiles(commandsDir));
517
+ var loadCommandModules = async (commandsDir, importModule = importCommandModule) => {
518
+ return loadCommandModulesFromFiles(await commandFiles(commandsDir), importModule);
519
519
  };
520
- var loadCommandModulesFromFiles = async (files) => {
521
- return Promise.all(
522
- files.map((file) => import(pathToFileURL(file).href))
523
- );
520
+ var loadCommandModulesFromFiles = async (files, importModule = importCommandModule) => {
521
+ return Promise.all(files.map(importModule));
524
522
  };
523
+ var importCommandModule = (file) => import(pathToFileURL(file).href);
525
524
  var commandDefinitionsFromModules = (modules) => {
526
525
  return modules.flatMap(
527
526
  (module) => Object.values(module).flatMap(
@@ -812,6 +811,7 @@ var createCommandProgram = async ({
812
811
  commandsDir,
813
812
  description,
814
813
  getContext,
814
+ importCommandModule: importCommandModule2,
815
815
  importMetaUrl,
816
816
  isDevRun = false,
817
817
  packageName,
@@ -825,6 +825,7 @@ var createCommandProgram = async ({
825
825
  binName,
826
826
  commandsDir: commandsDir ?? defaultCommandsDir(importMetaUrl),
827
827
  getContext,
828
+ importCommandModule: importCommandModule2,
828
829
  program
829
830
  });
830
831
  registerUpdateCommand(program, { isDevRun, packageName: packageName ?? binName, version });
@@ -863,9 +864,10 @@ var registerCliCommandsFromDirectory = async ({
863
864
  binName,
864
865
  commandsDir,
865
866
  getContext,
867
+ importCommandModule: importCommandModule2,
866
868
  program
867
869
  }) => {
868
- const modules = await loadCommandModules(commandsDir);
870
+ const modules = await loadCommandModules(commandsDir, importCommandModule2);
869
871
  const definitions = commandDefinitionsFromModules(modules);
870
872
  registerParentCommandsFromDefinitions(program, definitions);
871
873
  const commands = commandExportsFromModules(
@@ -1057,6 +1059,7 @@ var createCommandCliRunner = ({
1057
1059
  description,
1058
1060
  envBinName,
1059
1061
  getContext,
1062
+ importCommandModule: importCommandModule2,
1060
1063
  importMetaUrl,
1061
1064
  isDevRun,
1062
1065
  packageName,
@@ -1070,6 +1073,7 @@ var createCommandCliRunner = ({
1070
1073
  commandsDir,
1071
1074
  description,
1072
1075
  getContext,
1076
+ importCommandModule: importCommandModule2,
1073
1077
  importMetaUrl,
1074
1078
  isDevRun,
1075
1079
  packageName,
@@ -1083,14 +1087,16 @@ var createCommandCliRunner = ({
1083
1087
  };
1084
1088
 
1085
1089
  // src/mcp/router.ts
1086
- import { z as z3 } from "zod";
1090
+ import { z as z4 } from "zod";
1087
1091
 
1088
1092
  // src/mcp/constants.ts
1089
1093
  var DEFAULT_MCP_SERVER_VERSION = "0.0.0";
1090
1094
  var DEFAULT_RESOURCE_MIME_TYPE = "application/json";
1091
- var MCP_PROTOCOL_VERSION = "2024-11-05";
1095
+ var MCP_SUPPORTED_PROTOCOL_VERSIONS = ["2025-06-18", "2025-03-26", "2024-11-05"];
1092
1096
  var JSON_RPC_METHOD_NOT_FOUND = -32601;
1093
1097
  var JSON_RPC_INTERNAL_ERROR = -32603;
1098
+ var JSON_RPC_INVALID_PARAMS = -32602;
1099
+ var JSON_RPC_PARSE_ERROR = -32700;
1094
1100
  var JSON_RPC_VERSION = "2.0";
1095
1101
  var MCP_STATUS_COMPLETED = "completed";
1096
1102
  var MCP_STATUS_ERROR = "error";
@@ -1103,6 +1109,7 @@ var RESULT_ENVELOPE_PROGRESS_KEY = "progress";
1103
1109
  var PROGRESS_LIST_KEYS = ["items", "threads", "files", "events", "messages"];
1104
1110
  var CURSOR_KEYS = ["nextCursor", "nextPageToken"];
1105
1111
  var MCP_METHOD_INITIALIZE = "initialize";
1112
+ var MCP_METHOD_PING = "ping";
1106
1113
  var MCP_METHOD_TOOLS_LIST = "tools/list";
1107
1114
  var MCP_METHOD_TOOLS_CALL = "tools/call";
1108
1115
  var MCP_METHOD_RESOURCES_LIST = "resources/list";
@@ -1110,16 +1117,27 @@ var MCP_METHOD_RESOURCES_TEMPLATES_LIST = "resources/templates/list";
1110
1117
  var MCP_METHOD_RESOURCES_READ = "resources/read";
1111
1118
 
1112
1119
  // src/mcp/errors.ts
1120
+ var McpProtocolError = class extends Error {
1121
+ constructor(code, message) {
1122
+ super(message);
1123
+ this.code = code;
1124
+ }
1125
+ code;
1126
+ };
1113
1127
  var assertToolName = (expectedName, actualName) => {
1114
1128
  if (actualName !== expectedName) {
1115
1129
  throwUnknownTool(actualName);
1116
1130
  }
1117
1131
  };
1118
1132
  var throwUnknownTool = (name) => {
1119
- throw new Error(`Unknown tool: ${name ?? EMPTY_DISPLAY_VALUE2}`);
1133
+ throw new McpProtocolError(
1134
+ JSON_RPC_INVALID_PARAMS,
1135
+ `Unknown tool: ${name ?? EMPTY_DISPLAY_VALUE2}`
1136
+ );
1120
1137
  };
1121
1138
 
1122
1139
  // src/mcp/progress.ts
1140
+ import { z as z2 } from "zod";
1123
1141
  var toolResult = (result, startedAt) => {
1124
1142
  const envelope = resultEnvelope(result);
1125
1143
  const data = envelope.data;
@@ -1133,16 +1151,22 @@ var toolResult = (result, startedAt) => {
1133
1151
  content: [{ type: MCP_TEXT_CONTENT_TYPE, text: JSON.stringify(structuredContent, null, 2) }]
1134
1152
  };
1135
1153
  };
1154
+ var errorMessage = (caught) => {
1155
+ if (isZodError(caught)) return `Invalid input:
1156
+ ${z2.prettifyError(caught)}`;
1157
+ return caught instanceof Error ? caught.message : String(caught);
1158
+ };
1159
+ var isZodError = (caught) => caught instanceof Error && caught.name === "ZodError" && Array.isArray(caught.issues);
1136
1160
  var toolErrorResult = (caught, startedAt = Date.now()) => {
1137
- const message = caught instanceof Error ? caught.message : String(caught);
1138
- const structuredContent = {
1161
+ const message = errorMessage(caught);
1162
+ const errorContent = {
1139
1163
  status: MCP_STATUS_ERROR,
1140
1164
  progress: { elapsedMs: elapsedMs(startedAt), errors: [message] },
1141
1165
  error: { message }
1142
1166
  };
1143
1167
  return {
1144
- structuredContent,
1145
- content: [{ type: MCP_TEXT_CONTENT_TYPE, text: JSON.stringify(structuredContent, null, 2) }]
1168
+ isError: true,
1169
+ content: [{ type: MCP_TEXT_CONTENT_TYPE, text: JSON.stringify(errorContent, null, 2) }]
1146
1170
  };
1147
1171
  };
1148
1172
  var commandProgressSummary = (data, command) => {
@@ -1249,11 +1273,11 @@ var resourceInputNames = (uriTemplate) => [...uriTemplate.matchAll(/\{([^}]+)\}/
1249
1273
  });
1250
1274
 
1251
1275
  // src/mcp/schema.ts
1252
- import { z as z2 } from "zod";
1276
+ import { z as z3 } from "zod";
1253
1277
  var mcpToolOutputSchema = (dataSchema) => ({
1254
1278
  type: "object",
1255
1279
  properties: {
1256
- data: z2.toJSONSchema(dataSchema),
1280
+ data: z3.toJSONSchema(dataSchema),
1257
1281
  progress: {
1258
1282
  type: "object",
1259
1283
  properties: {
@@ -1293,10 +1317,10 @@ var createCommandMcpRoute = ({
1293
1317
  inputSchema,
1294
1318
  outputSchema
1295
1319
  });
1296
- var commandMcpRouteToTool = (route, prefix) => ({
1320
+ var commandMcpRouteToTool = (route, prefix, boundOptions = {}) => ({
1297
1321
  name: commandNameToMcpToolName(route.command.name, prefix),
1298
- description: route.command.description,
1299
- inputSchema: z3.toJSONSchema(route.inputSchema),
1322
+ description: commandMcpDescription(route.command),
1323
+ inputSchema: z4.toJSONSchema(commandMcpInputSchema(route, boundOptions)),
1300
1324
  outputSchema: mcpToolOutputSchema(route.outputSchema),
1301
1325
  annotations: commandMcpAnnotations(route.command)
1302
1326
  });
@@ -1304,12 +1328,51 @@ var commandNameToMcpToolName = (name, prefix) => {
1304
1328
  const baseName = name.replaceAll(COMMAND_NAME_SEPARATOR, TOOL_NAME_SEPARATOR);
1305
1329
  return prefix ? `${prefix}_${baseName}` : baseName;
1306
1330
  };
1307
- var createCommandMcpRouter = ({ prefix, routes }) => {
1331
+ var commandMcpInputSchema = (route, boundOptions = {}) => {
1332
+ const schema = route.inputSchema;
1333
+ const shape = objectShape(schema);
1334
+ if (!shape) return schema;
1335
+ const hidden = hiddenInputNames(route.command, boundOptions);
1336
+ const required = new Set(
1337
+ (route.command.options ?? []).filter((option) => option.mcp === "required").map(optionInputName)
1338
+ );
1339
+ return z4.object(
1340
+ Object.fromEntries(
1341
+ Object.entries(shape).filter(([name]) => !hidden.has(name)).map(([name, property]) => [
1342
+ name,
1343
+ required.has(name) ? requiredProperty(property) : property
1344
+ ])
1345
+ )
1346
+ );
1347
+ };
1348
+ var commandMcpInput = (route, args, boundOptions = {}) => {
1349
+ const inputNames = objectInputNames(route.inputSchema);
1350
+ const routeBoundOptions = Object.entries(boundOptions).filter(([name]) => inputNames.has(name));
1351
+ for (const [name, value] of routeBoundOptions) {
1352
+ if (args[name] !== void 0 && args[name] !== value) {
1353
+ throw new Error(`'${name}' is fixed to '${value}' by this MCP server`);
1354
+ }
1355
+ }
1356
+ commandMcpInputSchema(route, boundOptions).parse(args);
1357
+ const hidden = hiddenInputNames(route.command, boundOptions);
1358
+ const visibleArgs = Object.fromEntries(
1359
+ Object.entries(args).filter(([name]) => !hidden.has(name))
1360
+ );
1361
+ return route.inputSchema.parse({
1362
+ ...visibleArgs,
1363
+ ...Object.fromEntries(routeBoundOptions)
1364
+ });
1365
+ };
1366
+ var createCommandMcpRouter = ({
1367
+ boundOptions = {},
1368
+ prefix,
1369
+ routes
1370
+ }) => {
1308
1371
  const mcpRoutes = routes.filter((route) => route.command.mcp);
1309
1372
  const toolRoutes = mcpRoutes.filter((route) => isCommandMcpToolMetadata(route.command.mcp));
1310
1373
  const resourceRoutes = mcpRoutes.flatMap(commandMcpRouteToResourceRoute);
1311
1374
  return {
1312
- tools: toolRoutes.map((route) => commandMcpRouteToTool(route, prefix)),
1375
+ tools: toolRoutes.map((route) => commandMcpRouteToTool(route, prefix, boundOptions)),
1313
1376
  resources: resourceRoutes.filter((route) => !isResourceTemplate(route.uriTemplate)).map(commandResourceRouteToResource),
1314
1377
  resourceTemplates: resourceRoutes.filter((route) => isResourceTemplate(route.uriTemplate)).map(commandResourceRouteToResourceTemplate),
1315
1378
  callTool: async (params) => {
@@ -1320,7 +1383,7 @@ var createCommandMcpRouter = ({ prefix, routes }) => {
1320
1383
  if (!route) {
1321
1384
  return throwUnknownTool(toolCall.name);
1322
1385
  }
1323
- const input = route.inputSchema.parse(toolCall.arguments ?? {});
1386
+ const input = commandMcpInput(route, toolCall.arguments ?? {}, boundOptions);
1324
1387
  const data = route.outputSchema.parse(await route.handler(input));
1325
1388
  return { data, progress: commandProgressSummary(data, route.command) };
1326
1389
  },
@@ -1331,11 +1394,29 @@ var createCommandMcpRouter = ({ prefix, routes }) => {
1331
1394
  throw new Error(`Unknown resource: ${resourceRead.uri ?? EMPTY_DISPLAY_VALUE2}`);
1332
1395
  }
1333
1396
  return routeMatch.route.command.outputSchema.parse(
1334
- await routeMatch.route.handler(routeMatch.input)
1397
+ await routeMatch.route.handler({ ...routeMatch.input, ...boundOptions })
1335
1398
  );
1336
1399
  }
1337
1400
  };
1338
1401
  };
1402
+ var hiddenInputNames = (command, boundOptions) => /* @__PURE__ */ new Set([
1403
+ ...Object.keys(boundOptions),
1404
+ ...(command.options ?? []).filter((option) => option.mcp === false).map(optionInputName)
1405
+ ]);
1406
+ var objectShape = (schema) => schema.def.type === "object" ? schema.shape : void 0;
1407
+ var requiredProperty = (property) => property.def.type === "optional" ? property.unwrap() : property;
1408
+ var objectInputNames = (schema) => new Set(Object.keys(objectShape(schema) ?? {}));
1409
+ var commandMcpDescription = (command) => {
1410
+ const mcp = command.mcp;
1411
+ if (!isCommandMcpToolMetadata(mcp)) return command.description;
1412
+ const notes = [
1413
+ ...mcp.sideEffects?.length ? [`Side effects: ${mcp.sideEffects.join(" ")}`] : [],
1414
+ ...mcp.requiresConfirmation ? ["Confirm with the user before calling this tool."] : []
1415
+ ];
1416
+ return notes.length ? `${command.description}
1417
+
1418
+ ${notes.join("\n")}` : command.description;
1419
+ };
1339
1420
  var commandMcpAnnotations = (command) => {
1340
1421
  const mcp = command.mcp;
1341
1422
  if (!isCommandMcpToolMetadata(mcp)) return void 0;
@@ -1343,9 +1424,7 @@ var commandMcpAnnotations = (command) => {
1343
1424
  readOnlyHint: mcp.readOnly,
1344
1425
  destructiveHint: mcp.destructive,
1345
1426
  idempotentHint: mcp.idempotent,
1346
- openWorldHint: mcp.openWorld,
1347
- requiresConfirmation: mcp.requiresConfirmation,
1348
- sideEffects: mcp.sideEffects
1427
+ openWorldHint: mcp.openWorld
1349
1428
  };
1350
1429
  };
1351
1430
 
@@ -1391,12 +1470,13 @@ var generateReadmeCommandDocs = async ({
1391
1470
  binName,
1392
1471
  commandDefinitions = [],
1393
1472
  commandsDir = join4(process.cwd(), "src", "commands"),
1473
+ importCommandModule: importCommandModule2,
1394
1474
  markerName = "COMMANDS",
1395
1475
  readmePath = "README.md"
1396
1476
  }) => {
1397
1477
  const readme = readFileSync2(readmePath, "utf8");
1398
1478
  const loadedCommandDefinitions = commandDefinitionsFromModules(
1399
- await loadCommandModules(commandsDir)
1479
+ await loadCommandModules(commandsDir, importCommandModule2)
1400
1480
  );
1401
1481
  const generated = formatCommandDocs(
1402
1482
  [...commandDefinitions, ...loadedCommandDefinitions],
@@ -1480,8 +1560,14 @@ var createSingleToolMcpServer = ({
1480
1560
  }
1481
1561
  });
1482
1562
  };
1563
+ var negotiateMcpProtocolVersion = (params) => {
1564
+ const requested = params?.protocolVersion;
1565
+ return typeof requested === "string" && MCP_SUPPORTED_PROTOCOL_VERSIONS.includes(requested) ? requested : MCP_SUPPORTED_PROTOCOL_VERSIONS[0];
1566
+ };
1483
1567
  var createMcpServer = ({
1484
1568
  name,
1569
+ version = DEFAULT_MCP_SERVER_VERSION,
1570
+ instructions,
1485
1571
  tools,
1486
1572
  resources = [],
1487
1573
  resourceTemplates = [],
@@ -1498,15 +1584,24 @@ var createMcpServer = ({
1498
1584
  const error = (id, code, message) => {
1499
1585
  send({ jsonrpc: JSON_RPC_VERSION, id, error: { code, message } });
1500
1586
  };
1587
+ const protocolError = (id, caught) => {
1588
+ const code = caught instanceof McpProtocolError ? caught.code : JSON_RPC_INTERNAL_ERROR;
1589
+ error(id, code, caught instanceof Error ? caught.message : String(caught));
1590
+ };
1501
1591
  const handleRequest = async (request) => {
1502
1592
  if (request.method === MCP_METHOD_INITIALIZE) {
1503
1593
  result(request.id, {
1504
- protocolVersion: MCP_PROTOCOL_VERSION,
1594
+ protocolVersion: negotiateMcpProtocolVersion(request.params),
1505
1595
  capabilities: { resources: {}, tools: {} },
1506
- serverInfo: { name, version: DEFAULT_MCP_SERVER_VERSION }
1596
+ serverInfo: { name, version },
1597
+ instructions
1507
1598
  });
1508
1599
  return;
1509
1600
  }
1601
+ if (request.method === MCP_METHOD_PING) {
1602
+ result(request.id, {});
1603
+ return;
1604
+ }
1510
1605
  if (request.method === MCP_METHOD_TOOLS_LIST) {
1511
1606
  result(request.id, { tools });
1512
1607
  return;
@@ -1528,11 +1623,10 @@ var createMcpServer = ({
1528
1623
  );
1529
1624
  return;
1530
1625
  }
1531
- const startedAt = Date.now();
1532
1626
  try {
1533
1627
  result(request.id, resourceResult(request.params, await readResource(request.params)));
1534
1628
  } catch (caught) {
1535
- result(request.id, toolErrorResult(caught, startedAt));
1629
+ protocolError(request.id, caught);
1536
1630
  }
1537
1631
  return;
1538
1632
  }
@@ -1541,7 +1635,11 @@ var createMcpServer = ({
1541
1635
  try {
1542
1636
  result(request.id, toolResult(await callTool(request.params), startedAt));
1543
1637
  } catch (caught) {
1544
- result(request.id, toolErrorResult(caught, startedAt));
1638
+ if (caught instanceof McpProtocolError) {
1639
+ protocolError(request.id, caught);
1640
+ } else {
1641
+ result(request.id, toolErrorResult(caught, startedAt));
1642
+ }
1545
1643
  }
1546
1644
  return;
1547
1645
  }
@@ -1554,27 +1652,91 @@ var createMcpServer = ({
1554
1652
  }
1555
1653
  };
1556
1654
  return {
1655
+ handleRequest,
1557
1656
  start: async () => {
1558
1657
  const input = createInterface({ input: process.stdin });
1658
+ const pending = /* @__PURE__ */ new Set();
1559
1659
  for await (const line of input) {
1560
1660
  if (!line.trim()) continue;
1661
+ let request;
1561
1662
  try {
1562
- await handleRequest(JSON.parse(line));
1663
+ request = JSON.parse(line);
1563
1664
  } catch (caught) {
1564
- error(
1565
- void 0,
1566
- JSON_RPC_INTERNAL_ERROR,
1567
- caught instanceof Error ? caught.message : String(caught)
1568
- );
1665
+ const message = caught instanceof Error ? caught.message : String(caught);
1666
+ protocolError(void 0, new McpProtocolError(JSON_RPC_PARSE_ERROR, message));
1667
+ continue;
1569
1668
  }
1669
+ const task = handleRequest(request).catch((caught) => protocolError(request.id, caught)).finally(() => pending.delete(task));
1670
+ pending.add(task);
1570
1671
  }
1672
+ await Promise.all(pending);
1571
1673
  }
1572
1674
  };
1573
1675
  };
1574
1676
 
1677
+ // src/mcp/server-options.ts
1678
+ var parseMcpServerArgv = (argv) => {
1679
+ const flags = {};
1680
+ const positionals = [];
1681
+ for (let index = 0; index < argv.length; index += 1) {
1682
+ const token = argv[index] ?? "";
1683
+ if (!token.startsWith("--")) {
1684
+ positionals.push(token);
1685
+ continue;
1686
+ }
1687
+ const [rawName, inlineValue] = splitFlag(token.slice(2));
1688
+ const nextToken = argv[index + 1];
1689
+ if (inlineValue !== void 0) {
1690
+ flags[kebabToCamel2(rawName)] = inlineValue;
1691
+ } else if (nextToken !== void 0 && !nextToken.startsWith("--")) {
1692
+ flags[kebabToCamel2(rawName)] = nextToken;
1693
+ index += 1;
1694
+ } else {
1695
+ flags[kebabToCamel2(rawName)] = "true";
1696
+ }
1697
+ }
1698
+ return { flags, positionals };
1699
+ };
1700
+ var mcpServerOptionEnvName = (envPrefix, option) => option.env ?? `${envPrefix}_${camelToConstant(kebabToCamel2(option.name))}`;
1701
+ var resolveMcpServerOptions = ({
1702
+ argvFlags,
1703
+ definitions,
1704
+ env,
1705
+ envPrefix
1706
+ }) => {
1707
+ const values = {};
1708
+ const missing = [];
1709
+ for (const definition of definitions) {
1710
+ const inputName = kebabToCamel2(definition.name);
1711
+ const envName = mcpServerOptionEnvName(envPrefix, definition);
1712
+ const value = argvFlags[inputName] ?? nonEmpty(env[envName]);
1713
+ if (value !== void 0) {
1714
+ values[inputName] = value;
1715
+ } else if (definition.required) {
1716
+ missing.push(`--${definition.name} <value> (or ${envName})`);
1717
+ }
1718
+ }
1719
+ if (missing.length > 0) {
1720
+ throw new Error(`Missing required MCP server option: ${missing.join(", ")}`);
1721
+ }
1722
+ return values;
1723
+ };
1724
+ var withoutMcpServerOptionFlags = (flags, definitions) => {
1725
+ const optionNames = new Set(definitions.map((definition) => kebabToCamel2(definition.name)));
1726
+ return Object.fromEntries(Object.entries(flags).filter(([name]) => !optionNames.has(name)));
1727
+ };
1728
+ var splitFlag = (flag) => {
1729
+ const separatorIndex = flag.indexOf("=");
1730
+ if (separatorIndex === -1) return [flag, void 0];
1731
+ return [flag.slice(0, separatorIndex), flag.slice(separatorIndex + 1)];
1732
+ };
1733
+ var nonEmpty = (value) => value?.trim() ? value : void 0;
1734
+ var kebabToCamel2 = (value) => value.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
1735
+ var camelToConstant = (value) => value.replace(/([A-Z])/g, "_$1").toUpperCase();
1736
+
1575
1737
  // src/mcp/command-server.ts
1576
- var loadCommandMcpRoutes = async (commandsDir, getContext = () => void 0) => {
1577
- const modules = await loadCommandModules(commandsDir);
1738
+ var loadCommandMcpRoutes = async (commandsDir, getContext = () => void 0, importCommandModule2) => {
1739
+ const modules = await loadCommandModules(commandsDir, importCommandModule2);
1578
1740
  const factories = commandExportsFromModules(
1579
1741
  modules,
1580
1742
  (_name, value) => isCommandAdapterExport(value)
@@ -1582,37 +1744,103 @@ var loadCommandMcpRoutes = async (commandsDir, getContext = () => void 0) => {
1582
1744
  return factories.map((factory) => factory(getContext)).filter((route) => route.command.mcp);
1583
1745
  };
1584
1746
  var createCommandMcpServer = async ({
1747
+ argv = process.argv.slice(2),
1585
1748
  commandsDir,
1749
+ env = process.env,
1750
+ envPrefix,
1586
1751
  getContext,
1752
+ importCommandModule: importCommandModule2,
1587
1753
  importMetaUrl,
1754
+ instructions,
1588
1755
  name,
1589
- prefix
1756
+ prefix,
1757
+ serverOptions = [],
1758
+ version
1590
1759
  }) => {
1591
1760
  const commandDirectory = commandsDir ?? join5(dirname3(fileURLToPath4(importMetaUrl)), DEFAULT_COMMANDS_DIR);
1592
- const { tools, resources, resourceTemplates, callTool, readResource } = createCommandMcpRouter({
1593
- prefix,
1594
- routes: await loadCommandMcpRoutes(commandDirectory, getContext)
1761
+ const parsedArgv = parseMcpServerArgv(argv);
1762
+ const boundOptions = resolveMcpServerOptions({
1763
+ argvFlags: parsedArgv.flags,
1764
+ definitions: serverOptions,
1765
+ env,
1766
+ envPrefix: envPrefix ?? packageEnvPrefix(name)
1767
+ });
1768
+ const routes = await loadCommandMcpRoutes(
1769
+ commandDirectory,
1770
+ () => getContext ? getContext(boundOptions) : void 0,
1771
+ importCommandModule2
1772
+ );
1773
+ const router = createCommandMcpRouter({ boundOptions, prefix, routes });
1774
+ const server = createMcpServer({
1775
+ name,
1776
+ version,
1777
+ instructions: typeof instructions === "function" ? instructions(boundOptions) : instructions,
1778
+ tools: router.tools,
1779
+ resources: router.resources,
1780
+ resourceTemplates: router.resourceTemplates,
1781
+ callTool: router.callTool,
1782
+ readResource: router.readResource
1595
1783
  });
1596
- return createMcpServer({ name, tools, resources, resourceTemplates, callTool, readResource });
1784
+ return {
1785
+ ...server,
1786
+ boundOptions,
1787
+ command: parsedArgv.positionals.length > 0 ? parsedArgv.positionals.join(" ") : void 0,
1788
+ runCommand: (commandName, flags = {}) => runMcpCommandOnce(routes, commandName, withoutMcpServerOptionFlags(flags, serverOptions), {
1789
+ boundOptions
1790
+ }),
1791
+ commandFlags: withoutMcpServerOptionFlags(parsedArgv.flags, serverOptions)
1792
+ };
1793
+ };
1794
+ var runMcpCommandOnce = async (routes, commandName, flags, { boundOptions }) => {
1795
+ const route = routes.find(
1796
+ (candidate) => candidate.command.name === commandName && isCommandMcpToolMetadata(candidate.command.mcp)
1797
+ );
1798
+ if (!route) throw new Error(`Unknown command: ${commandName}`);
1799
+ const input = commandMcpInput(route, oneShotInput(flags), boundOptions);
1800
+ return route.outputSchema.parse(await route.handler(input));
1597
1801
  };
1598
1802
  var startCommandMcpServer = async (options) => {
1599
- await (await createCommandMcpServer(options)).start();
1803
+ try {
1804
+ const server = await createCommandMcpServer(options);
1805
+ if (!server.command) {
1806
+ await server.start();
1807
+ return;
1808
+ }
1809
+ const data = await server.runCommand(server.command, server.commandFlags);
1810
+ process.stdout.write(`${JSON.stringify(data)}
1811
+ `);
1812
+ } catch (caught) {
1813
+ process.stderr.write(`${errorMessage(caught)}
1814
+ `);
1815
+ process.exitCode = 1;
1816
+ }
1600
1817
  };
1601
1818
  var startPackageCommandMcpServer = async ({
1819
+ envPrefix,
1602
1820
  importMetaUrl,
1603
1821
  mcpServerPrefix,
1604
1822
  name,
1605
1823
  prefix,
1824
+ version,
1606
1825
  ...options
1607
1826
  }) => {
1608
1827
  const metadata = packageCommandMetadata(importMetaUrl, { mcpServerPrefix });
1609
1828
  await startCommandMcpServer({
1610
1829
  ...options,
1830
+ envPrefix: envPrefix ?? packageEnvPrefix(metadata.packageName),
1611
1831
  importMetaUrl,
1612
1832
  name: name ?? metadata.mcpServerName,
1613
- prefix: prefix ?? metadata.mcpPrefix
1833
+ prefix: prefix ?? metadata.mcpPrefix,
1834
+ version: version ?? metadata.version
1614
1835
  });
1615
1836
  };
1837
+ var ONE_SHOT_BOOLEANS = /* @__PURE__ */ new Map([
1838
+ ["true", true],
1839
+ ["false", false]
1840
+ ]);
1841
+ var oneShotInput = (flags) => Object.fromEntries(
1842
+ Object.entries(flags).map(([name, value]) => [name, ONE_SHOT_BOOLEANS.get(value) ?? value])
1843
+ );
1616
1844
 
1617
1845
  // src/scripts/dev-command.ts
1618
1846
  import { mkdirSync, rmSync as rmSync2 } from "fs";
@@ -1736,6 +1964,7 @@ var packageDevCommandConfig = (importMetaUrl, options) => {
1736
1964
  };
1737
1965
  export {
1738
1966
  DEFAULT_COMMANDS_DIR,
1967
+ McpProtocolError,
1739
1968
  PROGRAM_NAME_ENV_SUFFIX,
1740
1969
  PackageManager,
1741
1970
  assertToolName,
@@ -1746,6 +1975,8 @@ export {
1746
1975
  commandExportsFromModules,
1747
1976
  commandInputString,
1748
1977
  commandInputValue,
1978
+ commandMcpInput,
1979
+ commandMcpInputSchema,
1749
1980
  commandMcpRouteToResourceRoute,
1750
1981
  commandMcpRouteToTool,
1751
1982
  commandNameToMcpToolName,
@@ -1784,12 +2015,16 @@ export {
1784
2015
  loadCommandMcpRoutes,
1785
2016
  loadCommandModules,
1786
2017
  loadCommandModulesFromFiles,
2018
+ mcpServerOptionEnvName,
1787
2019
  mcpToolOutputSchema,
2020
+ negotiateMcpProtocolVersion,
1788
2021
  normalizeCommandInputAliases,
2022
+ optionInputName,
1789
2023
  packageBinEntry,
1790
2024
  packageCommandMetadata,
1791
2025
  packageEnvPrefix,
1792
2026
  packageRoot,
2027
+ parseMcpServerArgv,
1793
2028
  printProgramHelp,
1794
2029
  readPackageJson,
1795
2030
  registerCliCommandsFromDirectory,
@@ -1797,7 +2032,9 @@ export {
1797
2032
  registerCompletionCommand,
1798
2033
  registerParentCommandsFromDefinitions,
1799
2034
  registerUpdateCommand,
2035
+ resolveMcpServerOptions,
1800
2036
  resourceResult,
2037
+ runMcpCommandOnce,
1801
2038
  setProgramHelpData,
1802
2039
  shortPackageName,
1803
2040
  startCommandMcpServer,
@@ -1806,6 +2043,7 @@ export {
1806
2043
  uninstallDevCommand,
1807
2044
  uninstallPackageDevCommand,
1808
2045
  uninstallPackageDevCommands,
1809
- z4 as z
2046
+ withoutMcpServerOptionFlags,
2047
+ z5 as z
1810
2048
  };
1811
2049
  //# sourceMappingURL=index.js.map