@kubb/mcp 5.0.0-beta.2 → 5.0.0-beta.20

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,30 +1,21 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import process$1 from "node:process";
3
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
- import { z } from "zod";
2
+ import http from "node:http";
3
+ import { createRequestListener } from "@remix-run/node-fetch-server";
4
+ import { ValibotJsonSchemaAdapter } from "@tmcp/adapter-valibot";
5
+ import { HttpTransport } from "@tmcp/transport-http";
6
+ import { StdioTransport } from "@tmcp/transport-stdio";
7
+ import { McpServer } from "tmcp";
6
8
  import { EventEmitter } from "node:events";
7
- import { existsSync } from "node:fs";
9
+ import fs, { existsSync } from "node:fs";
8
10
  import path from "node:path";
9
11
  import { createKubb } from "@kubb/core";
10
- import { unrun } from "unrun";
12
+ import { defineTool } from "tmcp/tool";
13
+ import { tool } from "tmcp/utils";
14
+ import * as v from "valibot";
15
+ import { createJiti } from "jiti";
16
+ import process$1 from "node:process";
11
17
  //#region package.json
12
- var version = "5.0.0-beta.2";
13
- //#endregion
14
- //#region src/schemas/generateSchema.ts
15
- const generateSchema = z.object({
16
- config: z.string().optional().describe("Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory"),
17
- input: z.string().optional().describe("Path to OpenAPI/Swagger spec file (overrides config)"),
18
- output: z.string().optional().describe("Output directory path (overrides config)"),
19
- logLevel: z.enum([
20
- "silent",
21
- "error",
22
- "warn",
23
- "info",
24
- "verbose",
25
- "debug"
26
- ]).optional().default("info").describe("Log level for build output")
27
- });
18
+ var version = "5.0.0-beta.20";
28
19
  //#endregion
29
20
  //#region ../../internals/utils/src/errors.ts
30
21
  /**
@@ -72,9 +63,12 @@ var AsyncEventEmitter = class {
72
63
  * await emitter.emit('build', 'petstore')
73
64
  * ```
74
65
  */
75
- async emit(eventName, ...eventArgs) {
66
+ emit(eventName, ...eventArgs) {
76
67
  const listeners = this.#emitter.listeners(eventName);
77
68
  if (listeners.length === 0) return;
69
+ return this.#emitAll(eventName, listeners, eventArgs);
70
+ }
71
+ async #emitAll(eventName, listeners, eventArgs) {
78
72
  for (const listener of listeners) try {
79
73
  await listener(...eventArgs);
80
74
  } catch (err) {
@@ -162,6 +156,21 @@ function isPromise(result) {
162
156
  return result !== null && result !== void 0 && typeof result["then"] === "function";
163
157
  }
164
158
  //#endregion
159
+ //#region src/schemas/generateSchema.ts
160
+ const generateSchema = v.object({
161
+ config: v.optional(v.pipe(v.string(), v.minLength(1), v.description("Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory"))),
162
+ input: v.optional(v.pipe(v.string(), v.minLength(1), v.description("Path to OpenAPI/Swagger spec file (overrides config)"))),
163
+ output: v.optional(v.pipe(v.string(), v.minLength(1), v.description("Output directory path (overrides config)"))),
164
+ logLevel: v.optional(v.pipe(v.picklist([
165
+ "silent",
166
+ "error",
167
+ "warn",
168
+ "info",
169
+ "verbose",
170
+ "debug"
171
+ ]), v.description("Log level for build output")), "info")
172
+ });
173
+ //#endregion
165
174
  //#region src/types.ts
166
175
  const NotifyTypes = {
167
176
  INFO: "INFO",
@@ -198,18 +207,23 @@ const ALLOWED_CONFIG_EXTENSIONS = new Set([
198
207
  ]);
199
208
  //#endregion
200
209
  //#region src/utils/loadUserConfig.ts
210
+ const jiti = createJiti(import.meta.url, {
211
+ jsx: {
212
+ runtime: "automatic",
213
+ importSource: "@kubb/renderer-jsx"
214
+ },
215
+ moduleCache: false
216
+ });
201
217
  const loadedModules = /* @__PURE__ */ new Map();
202
218
  async function loadModule(filePath) {
203
219
  const ext = path.extname(filePath);
204
220
  if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) throw new Error(`Invalid config file extension "${ext}". Allowed: ${[...ALLOWED_CONFIG_EXTENSIONS].join(", ")}`);
205
221
  if (loadedModules.has(filePath)) return loadedModules.get(filePath);
206
- const { module } = await unrun({ path: filePath });
207
- loadedModules.set(filePath, module);
208
- return module;
222
+ const mod = await jiti.import(filePath, { default: true });
223
+ loadedModules.set(filePath, mod);
224
+ return mod;
209
225
  }
210
226
  async function loadUserConfig(configPath, { notify }) {
211
- let userConfig;
212
- let cwd;
213
227
  if (configPath) {
214
228
  const ext = path.extname(configPath);
215
229
  if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) {
@@ -225,41 +239,44 @@ async function loadUserConfig(configPath, { notify }) {
225
239
  await notify(NotifyTypes.CONFIG_ERROR, msg);
226
240
  throw new Error(msg);
227
241
  }
228
- cwd = path.dirname(resolvedConfigPath);
242
+ const cwd = path.dirname(resolvedConfigPath);
229
243
  try {
230
- userConfig = await loadModule(resolvedConfigPath);
244
+ const userConfig = await loadModule(resolvedConfigPath);
231
245
  await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${resolvedConfigPath}`);
246
+ return {
247
+ userConfig,
248
+ cwd
249
+ };
232
250
  } catch (error) {
233
- await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
234
- throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
235
- }
236
- } else {
237
- cwd = process.cwd();
238
- const configFileNames = [
239
- "kubb.config.ts",
240
- "kubb.config.mts",
241
- "kubb.config.cts",
242
- "kubb.config.js",
243
- "kubb.config.cjs"
244
- ];
245
- for (const configFileName of configFileNames) {
246
- const configFilePath = path.resolve(process.cwd(), configFileName);
247
- if (!existsSync(configFilePath)) continue;
248
- try {
249
- userConfig = await loadModule(configFilePath);
250
- await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`);
251
- break;
252
- } catch {}
251
+ const msg = `Failed to load config: ${error instanceof Error ? error.message : String(error)}`;
252
+ await notify(NotifyTypes.CONFIG_ERROR, msg);
253
+ throw new Error(msg);
253
254
  }
254
- if (!userConfig) {
255
- await notify(NotifyTypes.CONFIG_ERROR, "No config file found");
256
- throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(", ")}`);
255
+ }
256
+ const cwd = process.cwd();
257
+ const configFileNames = [
258
+ "kubb.config.ts",
259
+ "kubb.config.mts",
260
+ "kubb.config.cts",
261
+ "kubb.config.js",
262
+ "kubb.config.cjs"
263
+ ];
264
+ for (const configFileName of configFileNames) {
265
+ const configFilePath = path.resolve(process.cwd(), configFileName);
266
+ if (!existsSync(configFilePath)) continue;
267
+ try {
268
+ const userConfig = await loadModule(configFilePath);
269
+ await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`);
270
+ return {
271
+ userConfig,
272
+ cwd
273
+ };
274
+ } catch (err) {
275
+ await notify(NotifyTypes.CONFIG_ERROR, `Failed to load ${configFileName}: ${err instanceof Error ? err.message : String(err)}`);
257
276
  }
258
277
  }
259
- return {
260
- userConfig,
261
- cwd
262
- };
278
+ await notify(NotifyTypes.CONFIG_ERROR, "No config file found");
279
+ throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(", ")}`);
263
280
  }
264
281
  //#endregion
265
282
  //#region src/utils/resolveCwd.ts
@@ -278,40 +295,27 @@ function resolveCwd(userConfig, cwd) {
278
295
  }
279
296
  //#endregion
280
297
  //#region src/utils/resolveUserConfig.ts
281
- /**
282
- * Resolve the config by handling function configs and returning the final configuration
283
- */
284
298
  async function resolveUserConfig(config, options) {
285
- let kubbUserConfig = Promise.resolve(config);
286
- if (typeof config === "function") {
287
- const possiblePromise = config({
288
- logLevel: options.logLevel,
289
- config: options.configPath
290
- });
291
- if (isPromise(possiblePromise)) kubbUserConfig = possiblePromise;
292
- else kubbUserConfig = Promise.resolve(possiblePromise);
293
- }
294
- return await kubbUserConfig;
299
+ const result = typeof config === "function" ? config({
300
+ logLevel: options.logLevel,
301
+ config: options.configPath
302
+ }) : config;
303
+ const resolved = isPromise(result) ? await result : result;
304
+ return Array.isArray(resolved) ? resolved[0] : resolved;
295
305
  }
296
306
  //#endregion
297
307
  //#region src/tools/generate.ts
298
- /**
299
- * Build tool that generates code from OpenAPI specs using Kubb.
300
- * Sends real-time notifications of build progress and events.
301
- */
302
- async function generate(schema, handler) {
308
+ const generateTool = defineTool({
309
+ name: "generate",
310
+ description: "Generate OpenAPI spec helpers using Kubb configuration",
311
+ schema: generateSchema
312
+ }, async function generate(schema) {
303
313
  const { config: configPath, input, output, logLevel } = schema;
304
314
  try {
305
315
  const hooks = new AsyncEventEmitter();
306
316
  const messages = [];
307
- const notify = async (type, message, data) => {
317
+ const notify = async (type, message, _data) => {
308
318
  messages.push(`${type}: ${message}`);
309
- await handler.sendNotification("kubb/progress", {
310
- type,
311
- message,
312
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
313
- ...data
314
- });
315
319
  };
316
320
  hooks.on("kubb:info", async ({ message }) => {
317
321
  await notify(NotifyTypes.INFO, message);
@@ -320,7 +324,7 @@ async function generate(schema, handler) {
320
324
  await notify(NotifyTypes.SUCCESS, message);
321
325
  });
322
326
  hooks.on("kubb:error", async ({ error }) => {
323
- await notify(NotifyTypes.ERROR, error.message, { stack: error.stack });
327
+ await notify(NotifyTypes.ERROR, error.message);
324
328
  });
325
329
  hooks.on("kubb:warn", async ({ message }) => {
326
330
  await notify(NotifyTypes.WARN, message);
@@ -352,7 +356,7 @@ async function generate(schema, handler) {
352
356
  const configResult = await loadUserConfig(configPath, { notify });
353
357
  userConfig = configResult.userConfig;
354
358
  cwd = configResult.cwd;
355
- if (Array.isArray(userConfig) && userConfig.length) throw new Error("Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.");
359
+ if (Array.isArray(userConfig)) throw new Error("Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.");
356
360
  userConfig = await resolveUserConfig(userConfig, {
357
361
  configPath,
358
362
  logLevel
@@ -360,15 +364,9 @@ async function generate(schema, handler) {
360
364
  } catch (error) {
361
365
  const errorMessage = error instanceof Error ? error.message : String(error);
362
366
  await notify(NotifyTypes.CONFIG_ERROR, errorMessage);
363
- return {
364
- content: [{
365
- type: "text",
366
- text: errorMessage
367
- }],
368
- isError: true
369
- };
367
+ return tool.error(errorMessage);
370
368
  }
371
- const inputPath = input ?? ("path" in userConfig.input ? userConfig.input.path : void 0);
369
+ const inputPath = input ?? (userConfig.input && "path" in userConfig.input ? userConfig.input.path : void 0);
372
370
  const config = {
373
371
  ...userConfig,
374
372
  root: resolveCwd(userConfig, cwd),
@@ -381,7 +379,7 @@ async function generate(schema, handler) {
381
379
  path: output
382
380
  } : userConfig.output
383
381
  };
384
- await notify(NotifyTypes.CONFIG_READY, "Configuration ready", { root: config.root });
382
+ await notify(NotifyTypes.CONFIG_READY, "Configuration ready");
385
383
  await notify(NotifyTypes.SETUP_START, "Setting up Kubb");
386
384
  const kubb = createKubb(config, { hooks });
387
385
  await kubb.setup();
@@ -391,79 +389,242 @@ async function generate(schema, handler) {
391
389
  await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`);
392
390
  if (error || failedPlugins.size > 0) {
393
391
  const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
394
- await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {
395
- errorCount: allErrors.length,
396
- errors: allErrors.map((err) => err.message)
397
- });
398
- return {
399
- content: [{
400
- type: "text",
401
- text: `Build failed:\n${allErrors.map((err) => err.message).join("\n")}\n\n${messages.join("\n")}`
402
- }],
403
- isError: true
404
- };
392
+ await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`);
393
+ return tool.error(`Build failed:\n${allErrors.map((err) => err.message).join("\n")}\n\n${messages.join("\n")}`);
405
394
  }
406
- await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, { filesCount: files.length });
407
- return { content: [{
408
- type: "text",
409
- text: `Build completed successfully!\n\nGenerated ${files.length} files\n\n${messages.join("\n")}`
410
- }] };
395
+ await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`);
396
+ return tool.text(`Build completed successfully!\n\nGenerated ${files.length} files\n\n${messages.join("\n")}`);
411
397
  } catch (caughtError) {
412
- const error = caughtError;
413
- await handler.sendNotification("kubb/progress", {
414
- type: NotifyTypes.FATAL_ERROR,
415
- message: error.message,
416
- stack: error.stack,
417
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
418
- });
419
- return {
420
- content: [{
421
- type: "text",
422
- text: `Build error: ${error.message}\n${error.stack || ""}`
423
- }],
424
- isError: true
425
- };
398
+ const error = toError(caughtError);
399
+ return tool.error(`Build error: ${error.message}\n${error.stack ?? ""}`);
400
+ }
401
+ });
402
+ //#endregion
403
+ //#region ../../internals/shared/src/constants.ts
404
+ const KUBB_CONFIG_FILENAME = "kubb.config.ts";
405
+ const availablePlugins = [
406
+ {
407
+ value: "plugin-ts",
408
+ label: "TypeScript",
409
+ hint: "Recommended",
410
+ packageName: "@kubb/plugin-ts",
411
+ importName: "pluginTs",
412
+ category: "types"
413
+ },
414
+ {
415
+ value: "plugin-client",
416
+ label: "Client (Fetch/Axios)",
417
+ packageName: "@kubb/plugin-client",
418
+ importName: "pluginClient",
419
+ category: "client"
420
+ },
421
+ {
422
+ value: "plugin-react-query",
423
+ label: "React Query / TanStack Query",
424
+ packageName: "@kubb/plugin-react-query",
425
+ importName: "pluginReactQuery",
426
+ category: "framework"
427
+ },
428
+ {
429
+ value: "plugin-vue-query",
430
+ label: "Vue Query",
431
+ packageName: "@kubb/plugin-vue-query",
432
+ importName: "pluginVueQuery",
433
+ category: "framework"
434
+ },
435
+ {
436
+ value: "plugin-zod",
437
+ label: "Zod Schemas",
438
+ packageName: "@kubb/plugin-zod",
439
+ importName: "pluginZod",
440
+ category: "validation"
441
+ },
442
+ {
443
+ value: "plugin-faker",
444
+ label: "Faker.js Mocks",
445
+ packageName: "@kubb/plugin-faker",
446
+ importName: "pluginFaker",
447
+ category: "mocks"
448
+ },
449
+ {
450
+ value: "plugin-msw",
451
+ label: "MSW Handlers",
452
+ packageName: "@kubb/plugin-msw",
453
+ importName: "pluginMsw",
454
+ category: "mocks"
455
+ },
456
+ {
457
+ value: "plugin-cypress",
458
+ label: "Cypress Tests",
459
+ packageName: "@kubb/plugin-cypress",
460
+ importName: "pluginCypress",
461
+ category: "testing"
462
+ },
463
+ {
464
+ value: "plugin-mcp",
465
+ label: "MCP Server (AI / Model Context Protocol)",
466
+ packageName: "@kubb/plugin-mcp",
467
+ importName: "pluginMcp",
468
+ category: "ai"
469
+ },
470
+ {
471
+ value: "plugin-redoc",
472
+ label: "ReDoc Documentation",
473
+ packageName: "@kubb/plugin-redoc",
474
+ importName: "pluginRedoc",
475
+ category: "documentation"
426
476
  }
477
+ ];
478
+ const pluginDefaultConfigs = {
479
+ "plugin-ts": `pluginTs({
480
+ output: { path: 'models' },
481
+ })`,
482
+ "plugin-client": `pluginClient({
483
+ output: { path: 'clients' },
484
+ })`,
485
+ "plugin-react-query": `pluginReactQuery({
486
+ output: { path: 'hooks' },
487
+ })`,
488
+ "plugin-vue-query": `pluginVueQuery({
489
+ output: { path: 'hooks' },
490
+ })`,
491
+ "plugin-zod": `pluginZod({
492
+ output: { path: 'zod' },
493
+ })`,
494
+ "plugin-faker": `pluginFaker({
495
+ output: { path: 'mocks' },
496
+ })`,
497
+ "plugin-msw": `pluginMsw({
498
+ output: { path: 'msw' },
499
+ })`,
500
+ "plugin-cypress": `pluginCypress({
501
+ output: { path: 'cypress' },
502
+ })`,
503
+ "plugin-mcp": `pluginMcp({
504
+ output: { path: 'mcp' },
505
+ })`,
506
+ "plugin-redoc": `pluginRedoc({
507
+ output: { path: 'redoc' },
508
+ })`
509
+ };
510
+ //#endregion
511
+ //#region ../../internals/shared/src/init.ts
512
+ function generateConfigFile({ selectedPlugins, inputPath, outputPath }) {
513
+ return `import { defineConfig } from 'kubb'
514
+ ${selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`).join("\n")}
515
+
516
+ export default defineConfig({
517
+ root: '.',
518
+ input: {
519
+ path: '${inputPath}',
520
+ },
521
+ output: {
522
+ path: '${outputPath}',
523
+ clean: true,
524
+ },
525
+ plugins: [
526
+ ${selectedPlugins.map((plugin) => {
527
+ return ` ${pluginDefaultConfigs[plugin.value] ?? `${plugin.importName}()`},`;
528
+ }).join("\n")}
529
+ ],
530
+ })
531
+ `;
427
532
  }
428
533
  //#endregion
429
- //#region src/server.ts
430
- /**
431
- * Kubb MCP Server
432
- *
433
- * Provides tools for building OpenAPI specifications using Kubb.
434
- */
435
- async function startServer() {
534
+ //#region src/schemas/initSchema.ts
535
+ const initSchema = v.object({
536
+ input: v.optional(v.pipe(v.string(), v.minLength(1), v.description("Path to OpenAPI spec (default: ./openapi.yaml)"))),
537
+ output: v.optional(v.pipe(v.string(), v.minLength(1), v.description("Output directory (default: ./src/gen)"))),
538
+ plugins: v.optional(v.pipe(v.string(), v.minLength(1), v.description("Comma-separated list of plugins: plugin-ts,plugin-zod,...")))
539
+ });
540
+ //#endregion
541
+ //#region src/tools/init.ts
542
+ function resolvePlugins(pluginsFlag) {
543
+ if (!pluginsFlag) return [];
544
+ const requested = pluginsFlag.split(",").map((v) => v.trim()).filter(Boolean);
545
+ return availablePlugins.filter((p) => requested.includes(p.value));
546
+ }
547
+ const initTool = defineTool({
548
+ name: "init",
549
+ description: "Scaffold a kubb.config.ts in the current directory (non-interactive). Does not install packages.",
550
+ schema: initSchema
551
+ }, async ({ input = "./openapi.yaml", output = "./src/gen", plugins }) => {
552
+ const selected = resolvePlugins(plugins);
553
+ const content = generateConfigFile({
554
+ selectedPlugins: selected,
555
+ inputPath: input,
556
+ outputPath: output
557
+ });
558
+ const dest = path.join(process$1.cwd(), KUBB_CONFIG_FILENAME);
559
+ if (fs.existsSync(dest)) return tool.error(`${KUBB_CONFIG_FILENAME} already exists at ${dest}. Delete it first before running init again.`);
560
+ fs.writeFileSync(dest, content, "utf-8");
561
+ const packageList = ["kubb", ...selected.map((p) => p.packageName)].join(" ");
562
+ return tool.text(`Created kubb.config.ts\n\nInstall packages:\n npm install ${packageList}\n\nThen run:\n npx kubb generate`);
563
+ });
564
+ //#endregion
565
+ //#region src/tools/validate.ts
566
+ const validateTool = defineTool({
567
+ name: "validate",
568
+ description: "Validate an OpenAPI/Swagger specification file or URL",
569
+ schema: v.object({ input: v.pipe(v.string(), v.minLength(1), v.description("Path or URL to the OpenAPI/Swagger specification")) })
570
+ }, async ({ input }) => {
571
+ let mod;
436
572
  try {
437
- const transport = new StdioServerTransport();
438
- const server = new McpServer({
439
- name: "Kubb",
440
- version
441
- });
442
- server.tool("generate", "Generate OpenAPI spec helpers using Kubb configuration", generateSchema.shape, async (args) => {
443
- return generate(args, { sendNotification: async (method, params) => {
444
- try {
445
- await transport.send({
446
- jsonrpc: "2.0",
447
- method,
448
- params
449
- });
450
- } catch (error) {
451
- console.error("Failed to send notification:", error);
452
- }
453
- } });
454
- });
455
- await server.connect(transport);
456
- } catch (error) {
457
- console.error("Failed to start MCP server:", error);
458
- process$1.exit(1);
573
+ mod = await import("@kubb/adapter-oas");
574
+ } catch {
575
+ return tool.error("The validate tool requires @kubb/adapter-oas.\nInstall: npm install @kubb/adapter-oas");
576
+ }
577
+ try {
578
+ await mod.adapterOas().validate(input, { throwOnError: true });
579
+ return tool.text(`Validation successful: ${input}`);
580
+ } catch (err) {
581
+ return tool.error(`Validation failed:\n${err instanceof Error ? err.message : String(err)}`);
582
+ }
583
+ });
584
+ //#endregion
585
+ //#region src/server.ts
586
+ function createMcpServer() {
587
+ const server = new McpServer({
588
+ name: "Kubb",
589
+ version
590
+ }, {
591
+ adapter: new ValibotJsonSchemaAdapter(),
592
+ capabilities: { tools: {} }
593
+ });
594
+ server.tools([
595
+ generateTool,
596
+ validateTool,
597
+ initTool
598
+ ]);
599
+ return server;
600
+ }
601
+ async function startServer({ port, host = "localhost" } = {}) {
602
+ const server = createMcpServer();
603
+ if (port === void 0) {
604
+ new StdioTransport(server).listen();
605
+ return;
459
606
  }
607
+ const transport = new HttpTransport(server, { path: "/mcp" });
608
+ const httpServer = http.createServer(createRequestListener(async (request) => {
609
+ return await transport.respond(request) ?? new Response("Not Found", { status: 404 });
610
+ }));
611
+ httpServer.listen(port, host, () => {
612
+ console.log(`Kubb MCP server on http://${host}:${port}`);
613
+ });
614
+ const closeServer = () => httpServer.close();
615
+ process.once("SIGINT", closeServer);
616
+ process.once("SIGTERM", closeServer);
617
+ httpServer.once("close", () => {
618
+ process.off("SIGINT", closeServer);
619
+ process.off("SIGTERM", closeServer);
620
+ });
460
621
  }
461
622
  //#endregion
462
623
  //#region src/index.ts
463
- async function run(_argv) {
464
- await startServer();
624
+ async function run(_argv, options) {
625
+ await startServer(options);
465
626
  }
466
627
  //#endregion
467
- export { run };
628
+ export { createMcpServer, run };
468
629
 
469
630
  //# sourceMappingURL=index.js.map