@kubb/mcp 5.0.0-alpha.17 → 5.0.0-alpha.19

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.cjs CHANGED
@@ -33,7 +33,7 @@ let _kubb_core = require("@kubb/core");
33
33
  let jiti = require("jiti");
34
34
  jiti = __toESM(jiti);
35
35
  //#region package.json
36
- var version = "5.0.0-alpha.17";
36
+ var version = "5.0.0-alpha.19";
37
37
  //#endregion
38
38
  //#region src/schemas/generateSchema.ts
39
39
  const generateSchema = zod.z.object({
@@ -53,8 +53,14 @@ const generateSchema = zod.z.object({
53
53
  //#region ../../internals/utils/src/errors.ts
54
54
  /**
55
55
  * Coerces an unknown thrown value to an `Error` instance.
56
- * When the value is already an `Error` it is returned as-is;
57
- * otherwise a new `Error` is created whose message is `String(value)`.
56
+ * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * try { ... } catch(err) {
61
+ * throw new BuildError('Build failed', { cause: toError(err), errors: [] })
62
+ * }
63
+ * ```
58
64
  */
59
65
  function toError(value) {
60
66
  return value instanceof Error ? value : new Error(String(value));
@@ -62,12 +68,19 @@ function toError(value) {
62
68
  //#endregion
63
69
  //#region ../../internals/utils/src/asyncEventEmitter.ts
64
70
  /**
65
- * A typed EventEmitter that awaits all async listeners before resolving.
71
+ * Typed `EventEmitter` that awaits all async listeners before resolving.
66
72
  * Wraps Node's `EventEmitter` with full TypeScript event-map inference.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
77
+ * emitter.on('build', async (name) => { console.log(name) })
78
+ * await emitter.emit('build', 'petstore') // all listeners awaited
79
+ * ```
67
80
  */
68
81
  var AsyncEventEmitter = class {
69
82
  /**
70
- * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
83
+ * Maximum number of listeners per event before Node emits a memory-leak warning.
71
84
  * @default 10
72
85
  */
73
86
  constructor(maxListener = 10) {
@@ -75,8 +88,13 @@ var AsyncEventEmitter = class {
75
88
  }
76
89
  #emitter = new node_events.EventEmitter();
77
90
  /**
78
- * Emits an event and awaits all registered listeners in parallel.
91
+ * Emits `eventName` and awaits all registered listeners in parallel.
79
92
  * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * await emitter.emit('build', 'petstore')
97
+ * ```
80
98
  */
81
99
  async emit(eventName, ...eventArgs) {
82
100
  const listeners = this.#emitter.listeners(eventName);
@@ -95,11 +113,25 @@ var AsyncEventEmitter = class {
95
113
  }
96
114
  }));
97
115
  }
98
- /** Registers a persistent listener for the given event. */
116
+ /**
117
+ * Registers a persistent listener for `eventName`.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * emitter.on('build', async (name) => { console.log(name) })
122
+ * ```
123
+ */
99
124
  on(eventName, handler) {
100
125
  this.#emitter.on(eventName, handler);
101
126
  }
102
- /** Registers a one-shot listener that removes itself after the first invocation. */
127
+ /**
128
+ * Registers a one-shot listener that removes itself after the first invocation.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * emitter.onOnce('build', async (name) => { console.log(name) })
133
+ * ```
134
+ */
103
135
  onOnce(eventName, handler) {
104
136
  const wrapper = (...args) => {
105
137
  this.off(eventName, wrapper);
@@ -107,18 +139,39 @@ var AsyncEventEmitter = class {
107
139
  };
108
140
  this.on(eventName, wrapper);
109
141
  }
110
- /** Removes a previously registered listener. */
142
+ /**
143
+ * Removes a previously registered listener.
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * emitter.off('build', handler)
148
+ * ```
149
+ */
111
150
  off(eventName, handler) {
112
151
  this.#emitter.off(eventName, handler);
113
152
  }
114
- /** Removes all listeners from every event channel. */
153
+ /**
154
+ * Removes all listeners from every event channel.
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * emitter.removeAll()
159
+ * ```
160
+ */
115
161
  removeAll() {
116
162
  this.#emitter.removeAllListeners();
117
163
  }
118
164
  };
119
165
  //#endregion
120
166
  //#region ../../internals/utils/src/promise.ts
121
- /** Returns `true` when `result` is a thenable `Promise`. */
167
+ /** Returns `true` when `result` is a thenable `Promise`.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * isPromise(Promise.resolve(1)) // true
172
+ * isPromise(42) // false
173
+ * ```
174
+ */
122
175
  function isPromise(result) {
123
176
  return result !== null && result !== void 0 && typeof result["then"] === "function";
124
177
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["z","#emitter","NodeEventEmitter","jiti","path","path","StdioServerTransport","McpServer"],"sources":["../package.json","../src/schemas/generateSchema.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/asyncEventEmitter.ts","../../../internals/utils/src/promise.ts","../src/types.ts","../src/utils/loadUserConfig.ts","../src/utils/resolveCwd.ts","../src/utils/resolveUserConfig.ts","../src/tools/generate.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","import { z } from 'zod'\n\nexport const generateSchema = z.object({\n config: z\n .string()\n .optional()\n\n .describe('Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory'),\n input: z.string().optional().describe('Path to OpenAPI/Swagger spec file (overrides config)'),\n output: z.string().optional().describe('Output directory path (overrides config)'),\n logLevel: z.enum(['silent', 'error', 'warn', 'info', 'verbose', 'debug']).optional().default('info').describe('Log level for build output'),\n})\n\n","/** Thrown when a plugin's configuration or input fails validation. */\nexport class ValidationPluginError extends Error {}\n\n/**\n * Thrown when one or more errors occur during a Kubb build.\n * Carries the full list of underlying errors on `errors`.\n */\nexport class BuildError extends Error {\n errors: Array<Error>\n\n constructor(message: string, options: { cause?: Error; errors: Array<Error> }) {\n super(message, { cause: options.cause })\n this.name = 'BuildError'\n this.errors = options.errors\n }\n}\n\n/**\n * Coerces an unknown thrown value to an `Error` instance.\n * When the value is already an `Error` it is returned as-is;\n * otherwise a new `Error` is created whose message is `String(value)`.\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Safely extracts a human-readable message from any thrown value.\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Extracts the `.cause` of an `Error` as an `Error | undefined`.\n * Returns `undefined` when the cause is absent or is not an `Error`.\n */\nexport function toCause(error: Error): Error | undefined {\n return error.cause instanceof Error ? error.cause : undefined\n}\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport { toError } from './errors.ts'\n\n/** A function that can be registered as an event listener, synchronous or async. */\ntype AsyncListener<TArgs extends unknown[]> = (...args: TArgs) => void | Promise<void>\n\n/**\n * A typed EventEmitter that awaits all async listeners before resolving.\n * Wraps Node's `EventEmitter` with full TypeScript event-map inference.\n */\nexport class AsyncEventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n /**\n * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.\n * @default 10\n */\n constructor(maxListener = 10) {\n this.#emitter.setMaxListeners(maxListener)\n }\n\n #emitter = new NodeEventEmitter()\n\n /**\n * Emits an event and awaits all registered listeners in parallel.\n * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.\n */\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<AsyncListener<TEvents[TEventName]>>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n let serializedArgs: string\n try {\n serializedArgs = JSON.stringify(eventArgs)\n } catch {\n serializedArgs = String(eventArgs)\n }\n throw new Error(`Error in async listener for \"${eventName}\" with eventArgs ${serializedArgs}`, { cause: toError(err) })\n }\n }),\n )\n }\n\n /** Registers a persistent listener for the given event. */\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.on(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /** Registers a one-shot listener that removes itself after the first invocation. */\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n const wrapper: AsyncListener<TEvents[TEventName]> = (...args) => {\n this.off(eventName, wrapper)\n return handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n /** Removes a previously registered listener. */\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.off(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /** Removes all listeners from every event channel. */\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","/** A value that may already be resolved or still pending. */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`. */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\n/** Type guard for a fulfilled `Promise.allSettled` result. */\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\n/** Type guard for a rejected `Promise.allSettled` result with a typed `reason`. */\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export const NotifyTypes = {\n INFO: 'INFO',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n WARN: 'WARN',\n PLUGIN_START: 'PLUGIN_START',\n PLUGIN_END: 'PLUGIN_END',\n FILES_START: 'FILES_START',\n FILE_UPDATE: 'FILE_UPDATE',\n FILES_END: 'FILES_END',\n GENERATION_START: 'GENERATION_START',\n GENERATION_END: 'GENERATION_END',\n CONFIG_LOADED: 'CONFIG_LOADED',\n CONFIG_ERROR: 'CONFIG_ERROR',\n CONFIG_READY: 'CONFIG_READY',\n SETUP_START: 'SETUP_START',\n SETUP_END: 'SETUP_END',\n BUILD_START: 'BUILD_START',\n BUILD_END: 'BUILD_END',\n BUILD_FAILED: 'BUILD_FAILED',\n BUILD_SUCCESS: 'BUILD_SUCCESS',\n FATAL_ERROR: 'FATAL_ERROR',\n} as const\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\nimport createJiti from 'jiti'\nimport { NotifyTypes } from '../types.ts'\n\ntype NotifyFunction = (type: string, message: string, data?: Record<string, unknown>) => Promise<void>\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\n/**\n * Load the user configuration from the specified path or current directory\n */\nexport async function loadUserConfig(configPath: string | undefined, { notify }: { notify: NotifyFunction }): Promise<{ userConfig: Config; cwd: string }> {\n let userConfig: Config | undefined\n let cwd: string\n\n if (configPath) {\n // Resolve the config path to absolute path and get its directory\n cwd = path.dirname(path.resolve(configPath))\n\n // Try to load from path\n try {\n userConfig = await jiti.import(configPath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${configPath}`)\n } catch (error) {\n await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n }\n } else {\n // Look for kubb.config in current directory with various extensions\n cwd = process.cwd()\n const configFileNames = ['kubb.config.ts', 'kubb.config.js', 'kubb.config.cjs']\n\n for (const configFileName of configFileNames) {\n try {\n const configFilePath = path.resolve(process.cwd(), configFileName)\n userConfig = await jiti.import(configFilePath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`)\n break\n } catch {\n // Continue trying next config file\n }\n }\n\n if (!userConfig) {\n await notify(NotifyTypes.CONFIG_ERROR, 'No config file found')\n\n throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(', ')}`)\n }\n }\n\n return { userConfig: userConfig!, cwd }\n}\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\n\n/**\n * Determine the root directory based on userConfig.root and resolvedConfigDir\n * 1. If userConfig.root exists and is absolute, use it as-is\n * 2. If userConfig.root exists and is relative, resolve it relative to config directory\n * 3. Otherwise, use the config directory as root\n */\nexport function resolveCwd(userConfig: Config, cwd: string): string {\n if (userConfig.root) {\n if (path.isAbsolute(userConfig.root)) {\n return userConfig.root\n }\n\n return path.resolve(cwd, userConfig.root)\n }\n\n return cwd\n}\n","import { isPromise } from '@internals/utils'\nimport type { CLIOptions, Config, UserConfig } from '@kubb/core'\n\nexport type ResolveUserConfigOptions = {\n configPath?: string\n logLevel?: string\n}\n\n/**\n * Resolve the config by handling function configs and returning the final configuration\n */\nexport async function resolveUserConfig(userConfig: UserConfig, options: ResolveUserConfigOptions): Promise<Config> {\n let kubbUserConfig = Promise.resolve(userConfig) as Promise<UserConfig>\n\n if (typeof userConfig === 'function') {\n const possiblePromise = (userConfig as any)({ logLevel: options.logLevel, config: options.configPath } as CLIOptions)\n if (isPromise(possiblePromise)) {\n kubbUserConfig = possiblePromise\n } else {\n kubbUserConfig = Promise.resolve(possiblePromise)\n }\n }\n\n return (await kubbUserConfig) as Config\n}\n","import { AsyncEventEmitter } from '@internals/utils'\nimport { type Config, type KubbEvents, safeBuild, setup } from '@kubb/core'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.d.ts'\nimport type { z } from 'zod'\nimport type { generateSchema } from '../schemas/generateSchema.ts'\nimport { NotifyTypes } from '../types.ts'\nimport { loadUserConfig } from '../utils/loadUserConfig.ts'\nimport { resolveCwd } from '../utils/resolveCwd.ts'\nimport { resolveUserConfig } from '../utils/resolveUserConfig.ts'\n\ninterface NotificationHandler {\n sendNotification(method: string, params: unknown): Promise<void>\n}\n\n/**\n * Build tool that generates code from OpenAPI specs using Kubb.\n * Sends real-time notifications of build progress and events.\n */\nexport async function generate(schema: z.infer<typeof generateSchema>, handler: NotificationHandler): Promise<CallToolResult> {\n const { config: configPath, input, output, logLevel } = schema\n\n try {\n const events = new AsyncEventEmitter<KubbEvents>()\n const messages: string[] = []\n\n // Helper to send notifications\n const notify = async (type: string, message: string, data?: Record<string, unknown>) => {\n messages.push(`${type}: ${message}`)\n\n await handler.sendNotification('kubb/progress', {\n type,\n message,\n timestamp: new Date().toISOString(),\n ...data,\n })\n }\n\n // Capture events for output and send notifications\n events.on('info', async (message: string) => {\n await notify(NotifyTypes.INFO, message)\n })\n\n events.on('success', async (message: string) => {\n await notify(NotifyTypes.SUCCESS, message)\n })\n\n events.on('error', async (error: Error) => {\n await notify(NotifyTypes.ERROR, error.message, { stack: error.stack })\n })\n\n events.on('warn', async (message: string) => {\n await notify(NotifyTypes.WARN, message)\n })\n\n // Plugin lifecycle events\n events.on('plugin:start', async ({ name }: { name: string }) => {\n await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${name}`)\n })\n\n events.on('plugin:end', async ({ name, duration }: { name: string; duration?: number }) => {\n await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${name}`, { duration })\n })\n\n // File processing events\n events.on('files:processing:start', async () => {\n await notify(NotifyTypes.FILES_START, 'Starting file processing')\n })\n\n events.on('file:processing:update', async ({ file }: { file: { name: string } }) => {\n await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`)\n })\n\n events.on('files:processing:end', async () => {\n await notify(NotifyTypes.FILES_END, 'File processing complete')\n })\n\n // Generation events\n events.on('generation:start', async () => {\n await notify(NotifyTypes.GENERATION_START, 'Generation started')\n })\n\n events.on('generation:end', async () => {\n await notify(NotifyTypes.GENERATION_END, 'Generation ended')\n })\n\n // Load and process configuration\n let userConfig: Config\n let cwd: string\n\n try {\n const configResult = await loadUserConfig(configPath, { notify })\n userConfig = configResult.userConfig\n cwd = configResult.cwd\n\n if (Array.isArray(userConfig) && userConfig.length) {\n throw new Error('Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.')\n }\n\n userConfig = await resolveUserConfig(userConfig, { configPath, logLevel })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n await notify(NotifyTypes.CONFIG_ERROR, errorMessage)\n return {\n content: [\n {\n type: 'text',\n text: errorMessage,\n },\n ],\n isError: true,\n }\n }\n\n const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)\n\n // Override config with CLI options\n const config: Config = {\n ...userConfig,\n root: resolveCwd(userConfig, cwd),\n input: inputPath\n ? {\n ...userConfig.input,\n path: inputPath,\n }\n : userConfig.input,\n output: output\n ? {\n ...userConfig.output,\n path: output,\n }\n : userConfig.output,\n }\n\n await notify(NotifyTypes.CONFIG_READY, 'Configuration ready', {\n root: config.root,\n })\n\n // Setup and build\n await notify(NotifyTypes.SETUP_START, 'Setting up Kubb')\n\n const { fabric, driver, sources } = await setup({\n config,\n events,\n })\n await notify(NotifyTypes.SETUP_END, 'Kubb setup complete')\n\n await notify(NotifyTypes.BUILD_START, 'Starting build')\n const { files, failedPlugins, error } = await safeBuild(\n {\n config,\n events,\n },\n { driver, fabric, events, sources },\n )\n await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`)\n\n if (error || failedPlugins.size > 0) {\n const allErrors: Error[] = [\n error,\n ...Array.from(failedPlugins)\n .filter((it) => it.error)\n .map((it) => it.error),\n ].filter(Boolean)\n\n await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {\n errorCount: allErrors.length,\n errors: allErrors.map((err) => err.message),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build failed:\\n${allErrors.map((err) => err.message).join('\\n')}\\n\\n${messages.join('\\n')}`,\n },\n ],\n isError: true,\n }\n }\n\n await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, {\n filesCount: files.length,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build completed successfully!\\n\\nGenerated ${files.length} files\\n\\n${messages.join('\\n')}`,\n },\n ],\n }\n } catch (caughtError) {\n const error = caughtError as Error\n\n await handler.sendNotification('kubb/progress', {\n type: NotifyTypes.FATAL_ERROR,\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString(),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build error: ${error.message}\\n${error.stack || ''}`,\n },\n ],\n isError: true,\n }\n }\n}\n","import process from 'node:process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { version } from '../package.json'\nimport { generateSchema } from './schemas/generateSchema.ts'\nimport { generate } from './tools/generate.ts'\n\n/**\n * Kubb MCP Server\n *\n * Provides tools for building OpenAPI specifications using Kubb.\n */\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n const server = new McpServer({\n name: 'Kubb',\n version,\n })\n\n // Build tool - runs Kubb build using @kubb/core\n // Wrapped to pass notification handler for real-time progress updates\n server.tool('generate', 'Generate OpenAPI spec helpers using Kubb configuration', generateSchema.shape, async (args) => {\n // Create notification handler that sends events back to the client\n const notificationHandler = {\n sendNotification: async (method: string, params: any) => {\n try {\n await transport.send({\n jsonrpc: '2.0',\n method,\n params,\n })\n } catch (error) {\n console.error('Failed to send notification:', error)\n }\n },\n }\n\n // Call build tool with notification handler\n return generate(args, notificationHandler)\n })\n\n await server.connect(transport)\n } catch (error) {\n console.error('Failed to start MCP server:', error)\n process.exit(1)\n }\n}\n","import { startServer } from './server.ts'\n\nexport async function run(_argv?: string[]): Promise<void> {\n await startServer()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["z","#emitter","NodeEventEmitter","jiti","path","path","StdioServerTransport","McpServer"],"sources":["../package.json","../src/schemas/generateSchema.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/asyncEventEmitter.ts","../../../internals/utils/src/promise.ts","../src/types.ts","../src/utils/loadUserConfig.ts","../src/utils/resolveCwd.ts","../src/utils/resolveUserConfig.ts","../src/tools/generate.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","import { z } from 'zod'\n\nexport const generateSchema = z.object({\n config: z\n .string()\n .optional()\n\n .describe('Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory'),\n input: z.string().optional().describe('Path to OpenAPI/Swagger spec file (overrides config)'),\n output: z.string().optional().describe('Output directory path (overrides config)'),\n logLevel: z.enum(['silent', 'error', 'warn', 'info', 'verbose', 'debug']).optional().default('info').describe('Log level for build output'),\n})\n\n","/** Thrown when a plugin's configuration or input fails validation.\n *\n * @example\n * ```ts\n * throw new ValidationPluginError('Invalid config: \"output.path\" is required')\n * ```\n */\nexport class ValidationPluginError extends Error {}\n\n/**\n * Thrown when one or more errors occur during a Kubb build.\n * Carries the full list of underlying errors on `errors`.\n *\n * @example\n * ```ts\n * throw new BuildError('Build failed', { errors: [err1, err2] })\n * ```\n */\nexport class BuildError extends Error {\n errors: Array<Error>\n\n constructor(message: string, options: { cause?: Error; errors: Array<Error> }) {\n super(message, { cause: options.cause })\n this.name = 'BuildError'\n this.errors = options.errors\n }\n}\n\n/**\n * Coerces an unknown thrown value to an `Error` instance.\n * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.\n *\n * @example\n * ```ts\n * try { ... } catch(err) {\n * throw new BuildError('Build failed', { cause: toError(err), errors: [] })\n * }\n * ```\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Extracts a human-readable message from any thrown value.\n *\n * @example\n * ```ts\n * getErrorMessage(new Error('oops')) // 'oops'\n * getErrorMessage('plain string') // 'plain string'\n * ```\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Extracts the `.cause` of an `Error` as an `Error`, or `undefined` when absent or not an `Error`.\n *\n * @example\n * ```ts\n * const cause = toCause(buildError) // Error | undefined\n * ```\n */\nexport function toCause(error: Error): Error | undefined {\n return error.cause instanceof Error ? error.cause : undefined\n}\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport { toError } from './errors.ts'\n\n/**\n * A function that can be registered as an event listener, synchronous or async.\n */\ntype AsyncListener<TArgs extends unknown[]> = (...args: TArgs) => void | Promise<void>\n\n/**\n * Typed `EventEmitter` that awaits all async listeners before resolving.\n * Wraps Node's `EventEmitter` with full TypeScript event-map inference.\n *\n * @example\n * ```ts\n * const emitter = new AsyncEventEmitter<{ build: [name: string] }>()\n * emitter.on('build', async (name) => { console.log(name) })\n * await emitter.emit('build', 'petstore') // all listeners awaited\n * ```\n */\nexport class AsyncEventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n /**\n * Maximum number of listeners per event before Node emits a memory-leak warning.\n * @default 10\n */\n constructor(maxListener = 10) {\n this.#emitter.setMaxListeners(maxListener)\n }\n\n #emitter = new NodeEventEmitter()\n\n /**\n * Emits `eventName` and awaits all registered listeners in parallel.\n * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.\n *\n * @example\n * ```ts\n * await emitter.emit('build', 'petstore')\n * ```\n */\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<AsyncListener<TEvents[TEventName]>>\n\n if (listeners.length === 0) {\n return\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n let serializedArgs: string\n try {\n serializedArgs = JSON.stringify(eventArgs)\n } catch {\n serializedArgs = String(eventArgs)\n }\n throw new Error(`Error in async listener for \"${eventName}\" with eventArgs ${serializedArgs}`, { cause: toError(err) })\n }\n }),\n )\n }\n\n /**\n * Registers a persistent listener for `eventName`.\n *\n * @example\n * ```ts\n * emitter.on('build', async (name) => { console.log(name) })\n * ```\n */\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.on(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /**\n * Registers a one-shot listener that removes itself after the first invocation.\n *\n * @example\n * ```ts\n * emitter.onOnce('build', async (name) => { console.log(name) })\n * ```\n */\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n const wrapper: AsyncListener<TEvents[TEventName]> = (...args) => {\n this.off(eventName, wrapper)\n return handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n /**\n * Removes a previously registered listener.\n *\n * @example\n * ```ts\n * emitter.off('build', handler)\n * ```\n */\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.off(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /**\n * Removes all listeners from every event channel.\n *\n * @example\n * ```ts\n * emitter.removeAll()\n * ```\n */\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\n/** Returns `true` when `result` is a fulfilled `Promise.allSettled` result.\n *\n * @example\n * ```ts\n * const results = await Promise.allSettled([p1, p2])\n * results.filter(isPromiseFulfilledResult).map((r) => r.value)\n * ```\n */\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\n/** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.\n *\n * @example\n * ```ts\n * const results = await Promise.allSettled([p1, p2])\n * results.filter(isPromiseRejectedResult<Error>).map((r) => r.reason.message)\n * ```\n */\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export const NotifyTypes = {\n INFO: 'INFO',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n WARN: 'WARN',\n PLUGIN_START: 'PLUGIN_START',\n PLUGIN_END: 'PLUGIN_END',\n FILES_START: 'FILES_START',\n FILE_UPDATE: 'FILE_UPDATE',\n FILES_END: 'FILES_END',\n GENERATION_START: 'GENERATION_START',\n GENERATION_END: 'GENERATION_END',\n CONFIG_LOADED: 'CONFIG_LOADED',\n CONFIG_ERROR: 'CONFIG_ERROR',\n CONFIG_READY: 'CONFIG_READY',\n SETUP_START: 'SETUP_START',\n SETUP_END: 'SETUP_END',\n BUILD_START: 'BUILD_START',\n BUILD_END: 'BUILD_END',\n BUILD_FAILED: 'BUILD_FAILED',\n BUILD_SUCCESS: 'BUILD_SUCCESS',\n FATAL_ERROR: 'FATAL_ERROR',\n} as const\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\nimport createJiti from 'jiti'\nimport { NotifyTypes } from '../types.ts'\n\ntype NotifyFunction = (type: string, message: string, data?: Record<string, unknown>) => Promise<void>\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\n/**\n * Load the user configuration from the specified path or current directory\n */\nexport async function loadUserConfig(configPath: string | undefined, { notify }: { notify: NotifyFunction }): Promise<{ userConfig: Config; cwd: string }> {\n let userConfig: Config | undefined\n let cwd: string\n\n if (configPath) {\n // Resolve the config path to absolute path and get its directory\n cwd = path.dirname(path.resolve(configPath))\n\n // Try to load from path\n try {\n userConfig = await jiti.import(configPath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${configPath}`)\n } catch (error) {\n await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n }\n } else {\n // Look for kubb.config in current directory with various extensions\n cwd = process.cwd()\n const configFileNames = ['kubb.config.ts', 'kubb.config.js', 'kubb.config.cjs']\n\n for (const configFileName of configFileNames) {\n try {\n const configFilePath = path.resolve(process.cwd(), configFileName)\n userConfig = await jiti.import(configFilePath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`)\n break\n } catch {\n // Continue trying next config file\n }\n }\n\n if (!userConfig) {\n await notify(NotifyTypes.CONFIG_ERROR, 'No config file found')\n\n throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(', ')}`)\n }\n }\n\n return { userConfig: userConfig!, cwd }\n}\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\n\n/**\n * Determine the root directory based on userConfig.root and resolvedConfigDir\n * 1. If userConfig.root exists and is absolute, use it as-is\n * 2. If userConfig.root exists and is relative, resolve it relative to config directory\n * 3. Otherwise, use the config directory as root\n */\nexport function resolveCwd(userConfig: Config, cwd: string): string {\n if (userConfig.root) {\n if (path.isAbsolute(userConfig.root)) {\n return userConfig.root\n }\n\n return path.resolve(cwd, userConfig.root)\n }\n\n return cwd\n}\n","import { isPromise } from '@internals/utils'\nimport type { CLIOptions, Config, UserConfig } from '@kubb/core'\n\nexport type ResolveUserConfigOptions = {\n configPath?: string\n logLevel?: string\n}\n\n/**\n * Resolve the config by handling function configs and returning the final configuration\n */\nexport async function resolveUserConfig(userConfig: UserConfig, options: ResolveUserConfigOptions): Promise<Config> {\n let kubbUserConfig = Promise.resolve(userConfig) as Promise<UserConfig>\n\n if (typeof userConfig === 'function') {\n const possiblePromise = (userConfig as any)({ logLevel: options.logLevel, config: options.configPath } as CLIOptions)\n if (isPromise(possiblePromise)) {\n kubbUserConfig = possiblePromise\n } else {\n kubbUserConfig = Promise.resolve(possiblePromise)\n }\n }\n\n return (await kubbUserConfig) as Config\n}\n","import { AsyncEventEmitter } from '@internals/utils'\nimport { type Config, type KubbEvents, safeBuild, setup } from '@kubb/core'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.d.ts'\nimport type { z } from 'zod'\nimport type { generateSchema } from '../schemas/generateSchema.ts'\nimport { NotifyTypes } from '../types.ts'\nimport { loadUserConfig } from '../utils/loadUserConfig.ts'\nimport { resolveCwd } from '../utils/resolveCwd.ts'\nimport { resolveUserConfig } from '../utils/resolveUserConfig.ts'\n\ninterface NotificationHandler {\n sendNotification(method: string, params: unknown): Promise<void>\n}\n\n/**\n * Build tool that generates code from OpenAPI specs using Kubb.\n * Sends real-time notifications of build progress and events.\n */\nexport async function generate(schema: z.infer<typeof generateSchema>, handler: NotificationHandler): Promise<CallToolResult> {\n const { config: configPath, input, output, logLevel } = schema\n\n try {\n const events = new AsyncEventEmitter<KubbEvents>()\n const messages: string[] = []\n\n // Helper to send notifications\n const notify = async (type: string, message: string, data?: Record<string, unknown>) => {\n messages.push(`${type}: ${message}`)\n\n await handler.sendNotification('kubb/progress', {\n type,\n message,\n timestamp: new Date().toISOString(),\n ...data,\n })\n }\n\n // Capture events for output and send notifications\n events.on('info', async (message: string) => {\n await notify(NotifyTypes.INFO, message)\n })\n\n events.on('success', async (message: string) => {\n await notify(NotifyTypes.SUCCESS, message)\n })\n\n events.on('error', async (error: Error) => {\n await notify(NotifyTypes.ERROR, error.message, { stack: error.stack })\n })\n\n events.on('warn', async (message: string) => {\n await notify(NotifyTypes.WARN, message)\n })\n\n // Plugin lifecycle events\n events.on('plugin:start', async ({ name }: { name: string }) => {\n await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${name}`)\n })\n\n events.on('plugin:end', async ({ name, duration }: { name: string; duration?: number }) => {\n await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${name}`, { duration })\n })\n\n // File processing events\n events.on('files:processing:start', async () => {\n await notify(NotifyTypes.FILES_START, 'Starting file processing')\n })\n\n events.on('file:processing:update', async ({ file }: { file: { name: string } }) => {\n await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`)\n })\n\n events.on('files:processing:end', async () => {\n await notify(NotifyTypes.FILES_END, 'File processing complete')\n })\n\n // Generation events\n events.on('generation:start', async () => {\n await notify(NotifyTypes.GENERATION_START, 'Generation started')\n })\n\n events.on('generation:end', async () => {\n await notify(NotifyTypes.GENERATION_END, 'Generation ended')\n })\n\n // Load and process configuration\n let userConfig: Config\n let cwd: string\n\n try {\n const configResult = await loadUserConfig(configPath, { notify })\n userConfig = configResult.userConfig\n cwd = configResult.cwd\n\n if (Array.isArray(userConfig) && userConfig.length) {\n throw new Error('Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.')\n }\n\n userConfig = await resolveUserConfig(userConfig, { configPath, logLevel })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n await notify(NotifyTypes.CONFIG_ERROR, errorMessage)\n return {\n content: [\n {\n type: 'text',\n text: errorMessage,\n },\n ],\n isError: true,\n }\n }\n\n const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)\n\n // Override config with CLI options\n const config: Config = {\n ...userConfig,\n root: resolveCwd(userConfig, cwd),\n input: inputPath\n ? {\n ...userConfig.input,\n path: inputPath,\n }\n : userConfig.input,\n output: output\n ? {\n ...userConfig.output,\n path: output,\n }\n : userConfig.output,\n }\n\n await notify(NotifyTypes.CONFIG_READY, 'Configuration ready', {\n root: config.root,\n })\n\n // Setup and build\n await notify(NotifyTypes.SETUP_START, 'Setting up Kubb')\n\n const { fabric, driver, sources } = await setup({\n config,\n events,\n })\n await notify(NotifyTypes.SETUP_END, 'Kubb setup complete')\n\n await notify(NotifyTypes.BUILD_START, 'Starting build')\n const { files, failedPlugins, error } = await safeBuild(\n {\n config,\n events,\n },\n { driver, fabric, events, sources },\n )\n await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`)\n\n if (error || failedPlugins.size > 0) {\n const allErrors: Error[] = [\n error,\n ...Array.from(failedPlugins)\n .filter((it) => it.error)\n .map((it) => it.error),\n ].filter(Boolean)\n\n await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {\n errorCount: allErrors.length,\n errors: allErrors.map((err) => err.message),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build failed:\\n${allErrors.map((err) => err.message).join('\\n')}\\n\\n${messages.join('\\n')}`,\n },\n ],\n isError: true,\n }\n }\n\n await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, {\n filesCount: files.length,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build completed successfully!\\n\\nGenerated ${files.length} files\\n\\n${messages.join('\\n')}`,\n },\n ],\n }\n } catch (caughtError) {\n const error = caughtError as Error\n\n await handler.sendNotification('kubb/progress', {\n type: NotifyTypes.FATAL_ERROR,\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString(),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build error: ${error.message}\\n${error.stack || ''}`,\n },\n ],\n isError: true,\n }\n }\n}\n","import process from 'node:process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { version } from '../package.json'\nimport { generateSchema } from './schemas/generateSchema.ts'\nimport { generate } from './tools/generate.ts'\n\n/**\n * Kubb MCP Server\n *\n * Provides tools for building OpenAPI specifications using Kubb.\n */\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n const server = new McpServer({\n name: 'Kubb',\n version,\n })\n\n // Build tool - runs Kubb build using @kubb/core\n // Wrapped to pass notification handler for real-time progress updates\n server.tool('generate', 'Generate OpenAPI spec helpers using Kubb configuration', generateSchema.shape, async (args) => {\n // Create notification handler that sends events back to the client\n const notificationHandler = {\n sendNotification: async (method: string, params: any) => {\n try {\n await transport.send({\n jsonrpc: '2.0',\n method,\n params,\n })\n } catch (error) {\n console.error('Failed to send notification:', error)\n }\n },\n }\n\n // Call build tool with notification handler\n return generate(args, notificationHandler)\n })\n\n await server.connect(transport)\n } catch (error) {\n console.error('Failed to start MCP server:', error)\n process.exit(1)\n }\n}\n","import { startServer } from './server.ts'\n\nexport async function run(_argv?: string[]): Promise<void> {\n await startServer()\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import path from "node:path";
8
8
  import { safeBuild, setup } from "@kubb/core";
9
9
  import createJiti from "jiti";
10
10
  //#region package.json
11
- var version = "5.0.0-alpha.17";
11
+ var version = "5.0.0-alpha.19";
12
12
  //#endregion
13
13
  //#region src/schemas/generateSchema.ts
14
14
  const generateSchema = z.object({
@@ -28,8 +28,14 @@ const generateSchema = z.object({
28
28
  //#region ../../internals/utils/src/errors.ts
29
29
  /**
30
30
  * Coerces an unknown thrown value to an `Error` instance.
31
- * When the value is already an `Error` it is returned as-is;
32
- * otherwise a new `Error` is created whose message is `String(value)`.
31
+ * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * try { ... } catch(err) {
36
+ * throw new BuildError('Build failed', { cause: toError(err), errors: [] })
37
+ * }
38
+ * ```
33
39
  */
34
40
  function toError(value) {
35
41
  return value instanceof Error ? value : new Error(String(value));
@@ -37,12 +43,19 @@ function toError(value) {
37
43
  //#endregion
38
44
  //#region ../../internals/utils/src/asyncEventEmitter.ts
39
45
  /**
40
- * A typed EventEmitter that awaits all async listeners before resolving.
46
+ * Typed `EventEmitter` that awaits all async listeners before resolving.
41
47
  * Wraps Node's `EventEmitter` with full TypeScript event-map inference.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
52
+ * emitter.on('build', async (name) => { console.log(name) })
53
+ * await emitter.emit('build', 'petstore') // all listeners awaited
54
+ * ```
42
55
  */
43
56
  var AsyncEventEmitter = class {
44
57
  /**
45
- * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.
58
+ * Maximum number of listeners per event before Node emits a memory-leak warning.
46
59
  * @default 10
47
60
  */
48
61
  constructor(maxListener = 10) {
@@ -50,8 +63,13 @@ var AsyncEventEmitter = class {
50
63
  }
51
64
  #emitter = new EventEmitter();
52
65
  /**
53
- * Emits an event and awaits all registered listeners in parallel.
66
+ * Emits `eventName` and awaits all registered listeners in parallel.
54
67
  * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * await emitter.emit('build', 'petstore')
72
+ * ```
55
73
  */
56
74
  async emit(eventName, ...eventArgs) {
57
75
  const listeners = this.#emitter.listeners(eventName);
@@ -70,11 +88,25 @@ var AsyncEventEmitter = class {
70
88
  }
71
89
  }));
72
90
  }
73
- /** Registers a persistent listener for the given event. */
91
+ /**
92
+ * Registers a persistent listener for `eventName`.
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * emitter.on('build', async (name) => { console.log(name) })
97
+ * ```
98
+ */
74
99
  on(eventName, handler) {
75
100
  this.#emitter.on(eventName, handler);
76
101
  }
77
- /** Registers a one-shot listener that removes itself after the first invocation. */
102
+ /**
103
+ * Registers a one-shot listener that removes itself after the first invocation.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * emitter.onOnce('build', async (name) => { console.log(name) })
108
+ * ```
109
+ */
78
110
  onOnce(eventName, handler) {
79
111
  const wrapper = (...args) => {
80
112
  this.off(eventName, wrapper);
@@ -82,18 +114,39 @@ var AsyncEventEmitter = class {
82
114
  };
83
115
  this.on(eventName, wrapper);
84
116
  }
85
- /** Removes a previously registered listener. */
117
+ /**
118
+ * Removes a previously registered listener.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * emitter.off('build', handler)
123
+ * ```
124
+ */
86
125
  off(eventName, handler) {
87
126
  this.#emitter.off(eventName, handler);
88
127
  }
89
- /** Removes all listeners from every event channel. */
128
+ /**
129
+ * Removes all listeners from every event channel.
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * emitter.removeAll()
134
+ * ```
135
+ */
90
136
  removeAll() {
91
137
  this.#emitter.removeAllListeners();
92
138
  }
93
139
  };
94
140
  //#endregion
95
141
  //#region ../../internals/utils/src/promise.ts
96
- /** Returns `true` when `result` is a thenable `Promise`. */
142
+ /** Returns `true` when `result` is a thenable `Promise`.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * isPromise(Promise.resolve(1)) // true
147
+ * isPromise(42) // false
148
+ * ```
149
+ */
97
150
  function isPromise(result) {
98
151
  return result !== null && result !== void 0 && typeof result["then"] === "function";
99
152
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["#emitter","NodeEventEmitter"],"sources":["../package.json","../src/schemas/generateSchema.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/asyncEventEmitter.ts","../../../internals/utils/src/promise.ts","../src/types.ts","../src/utils/loadUserConfig.ts","../src/utils/resolveCwd.ts","../src/utils/resolveUserConfig.ts","../src/tools/generate.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","import { z } from 'zod'\n\nexport const generateSchema = z.object({\n config: z\n .string()\n .optional()\n\n .describe('Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory'),\n input: z.string().optional().describe('Path to OpenAPI/Swagger spec file (overrides config)'),\n output: z.string().optional().describe('Output directory path (overrides config)'),\n logLevel: z.enum(['silent', 'error', 'warn', 'info', 'verbose', 'debug']).optional().default('info').describe('Log level for build output'),\n})\n\n","/** Thrown when a plugin's configuration or input fails validation. */\nexport class ValidationPluginError extends Error {}\n\n/**\n * Thrown when one or more errors occur during a Kubb build.\n * Carries the full list of underlying errors on `errors`.\n */\nexport class BuildError extends Error {\n errors: Array<Error>\n\n constructor(message: string, options: { cause?: Error; errors: Array<Error> }) {\n super(message, { cause: options.cause })\n this.name = 'BuildError'\n this.errors = options.errors\n }\n}\n\n/**\n * Coerces an unknown thrown value to an `Error` instance.\n * When the value is already an `Error` it is returned as-is;\n * otherwise a new `Error` is created whose message is `String(value)`.\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Safely extracts a human-readable message from any thrown value.\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Extracts the `.cause` of an `Error` as an `Error | undefined`.\n * Returns `undefined` when the cause is absent or is not an `Error`.\n */\nexport function toCause(error: Error): Error | undefined {\n return error.cause instanceof Error ? error.cause : undefined\n}\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport { toError } from './errors.ts'\n\n/** A function that can be registered as an event listener, synchronous or async. */\ntype AsyncListener<TArgs extends unknown[]> = (...args: TArgs) => void | Promise<void>\n\n/**\n * A typed EventEmitter that awaits all async listeners before resolving.\n * Wraps Node's `EventEmitter` with full TypeScript event-map inference.\n */\nexport class AsyncEventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n /**\n * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.\n * @default 10\n */\n constructor(maxListener = 10) {\n this.#emitter.setMaxListeners(maxListener)\n }\n\n #emitter = new NodeEventEmitter()\n\n /**\n * Emits an event and awaits all registered listeners in parallel.\n * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.\n */\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<AsyncListener<TEvents[TEventName]>>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n let serializedArgs: string\n try {\n serializedArgs = JSON.stringify(eventArgs)\n } catch {\n serializedArgs = String(eventArgs)\n }\n throw new Error(`Error in async listener for \"${eventName}\" with eventArgs ${serializedArgs}`, { cause: toError(err) })\n }\n }),\n )\n }\n\n /** Registers a persistent listener for the given event. */\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.on(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /** Registers a one-shot listener that removes itself after the first invocation. */\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n const wrapper: AsyncListener<TEvents[TEventName]> = (...args) => {\n this.off(eventName, wrapper)\n return handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n /** Removes a previously registered listener. */\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.off(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /** Removes all listeners from every event channel. */\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","/** A value that may already be resolved or still pending. */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`. */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\n/** Type guard for a fulfilled `Promise.allSettled` result. */\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\n/** Type guard for a rejected `Promise.allSettled` result with a typed `reason`. */\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export const NotifyTypes = {\n INFO: 'INFO',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n WARN: 'WARN',\n PLUGIN_START: 'PLUGIN_START',\n PLUGIN_END: 'PLUGIN_END',\n FILES_START: 'FILES_START',\n FILE_UPDATE: 'FILE_UPDATE',\n FILES_END: 'FILES_END',\n GENERATION_START: 'GENERATION_START',\n GENERATION_END: 'GENERATION_END',\n CONFIG_LOADED: 'CONFIG_LOADED',\n CONFIG_ERROR: 'CONFIG_ERROR',\n CONFIG_READY: 'CONFIG_READY',\n SETUP_START: 'SETUP_START',\n SETUP_END: 'SETUP_END',\n BUILD_START: 'BUILD_START',\n BUILD_END: 'BUILD_END',\n BUILD_FAILED: 'BUILD_FAILED',\n BUILD_SUCCESS: 'BUILD_SUCCESS',\n FATAL_ERROR: 'FATAL_ERROR',\n} as const\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\nimport createJiti from 'jiti'\nimport { NotifyTypes } from '../types.ts'\n\ntype NotifyFunction = (type: string, message: string, data?: Record<string, unknown>) => Promise<void>\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\n/**\n * Load the user configuration from the specified path or current directory\n */\nexport async function loadUserConfig(configPath: string | undefined, { notify }: { notify: NotifyFunction }): Promise<{ userConfig: Config; cwd: string }> {\n let userConfig: Config | undefined\n let cwd: string\n\n if (configPath) {\n // Resolve the config path to absolute path and get its directory\n cwd = path.dirname(path.resolve(configPath))\n\n // Try to load from path\n try {\n userConfig = await jiti.import(configPath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${configPath}`)\n } catch (error) {\n await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n }\n } else {\n // Look for kubb.config in current directory with various extensions\n cwd = process.cwd()\n const configFileNames = ['kubb.config.ts', 'kubb.config.js', 'kubb.config.cjs']\n\n for (const configFileName of configFileNames) {\n try {\n const configFilePath = path.resolve(process.cwd(), configFileName)\n userConfig = await jiti.import(configFilePath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`)\n break\n } catch {\n // Continue trying next config file\n }\n }\n\n if (!userConfig) {\n await notify(NotifyTypes.CONFIG_ERROR, 'No config file found')\n\n throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(', ')}`)\n }\n }\n\n return { userConfig: userConfig!, cwd }\n}\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\n\n/**\n * Determine the root directory based on userConfig.root and resolvedConfigDir\n * 1. If userConfig.root exists and is absolute, use it as-is\n * 2. If userConfig.root exists and is relative, resolve it relative to config directory\n * 3. Otherwise, use the config directory as root\n */\nexport function resolveCwd(userConfig: Config, cwd: string): string {\n if (userConfig.root) {\n if (path.isAbsolute(userConfig.root)) {\n return userConfig.root\n }\n\n return path.resolve(cwd, userConfig.root)\n }\n\n return cwd\n}\n","import { isPromise } from '@internals/utils'\nimport type { CLIOptions, Config, UserConfig } from '@kubb/core'\n\nexport type ResolveUserConfigOptions = {\n configPath?: string\n logLevel?: string\n}\n\n/**\n * Resolve the config by handling function configs and returning the final configuration\n */\nexport async function resolveUserConfig(userConfig: UserConfig, options: ResolveUserConfigOptions): Promise<Config> {\n let kubbUserConfig = Promise.resolve(userConfig) as Promise<UserConfig>\n\n if (typeof userConfig === 'function') {\n const possiblePromise = (userConfig as any)({ logLevel: options.logLevel, config: options.configPath } as CLIOptions)\n if (isPromise(possiblePromise)) {\n kubbUserConfig = possiblePromise\n } else {\n kubbUserConfig = Promise.resolve(possiblePromise)\n }\n }\n\n return (await kubbUserConfig) as Config\n}\n","import { AsyncEventEmitter } from '@internals/utils'\nimport { type Config, type KubbEvents, safeBuild, setup } from '@kubb/core'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.d.ts'\nimport type { z } from 'zod'\nimport type { generateSchema } from '../schemas/generateSchema.ts'\nimport { NotifyTypes } from '../types.ts'\nimport { loadUserConfig } from '../utils/loadUserConfig.ts'\nimport { resolveCwd } from '../utils/resolveCwd.ts'\nimport { resolveUserConfig } from '../utils/resolveUserConfig.ts'\n\ninterface NotificationHandler {\n sendNotification(method: string, params: unknown): Promise<void>\n}\n\n/**\n * Build tool that generates code from OpenAPI specs using Kubb.\n * Sends real-time notifications of build progress and events.\n */\nexport async function generate(schema: z.infer<typeof generateSchema>, handler: NotificationHandler): Promise<CallToolResult> {\n const { config: configPath, input, output, logLevel } = schema\n\n try {\n const events = new AsyncEventEmitter<KubbEvents>()\n const messages: string[] = []\n\n // Helper to send notifications\n const notify = async (type: string, message: string, data?: Record<string, unknown>) => {\n messages.push(`${type}: ${message}`)\n\n await handler.sendNotification('kubb/progress', {\n type,\n message,\n timestamp: new Date().toISOString(),\n ...data,\n })\n }\n\n // Capture events for output and send notifications\n events.on('info', async (message: string) => {\n await notify(NotifyTypes.INFO, message)\n })\n\n events.on('success', async (message: string) => {\n await notify(NotifyTypes.SUCCESS, message)\n })\n\n events.on('error', async (error: Error) => {\n await notify(NotifyTypes.ERROR, error.message, { stack: error.stack })\n })\n\n events.on('warn', async (message: string) => {\n await notify(NotifyTypes.WARN, message)\n })\n\n // Plugin lifecycle events\n events.on('plugin:start', async ({ name }: { name: string }) => {\n await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${name}`)\n })\n\n events.on('plugin:end', async ({ name, duration }: { name: string; duration?: number }) => {\n await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${name}`, { duration })\n })\n\n // File processing events\n events.on('files:processing:start', async () => {\n await notify(NotifyTypes.FILES_START, 'Starting file processing')\n })\n\n events.on('file:processing:update', async ({ file }: { file: { name: string } }) => {\n await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`)\n })\n\n events.on('files:processing:end', async () => {\n await notify(NotifyTypes.FILES_END, 'File processing complete')\n })\n\n // Generation events\n events.on('generation:start', async () => {\n await notify(NotifyTypes.GENERATION_START, 'Generation started')\n })\n\n events.on('generation:end', async () => {\n await notify(NotifyTypes.GENERATION_END, 'Generation ended')\n })\n\n // Load and process configuration\n let userConfig: Config\n let cwd: string\n\n try {\n const configResult = await loadUserConfig(configPath, { notify })\n userConfig = configResult.userConfig\n cwd = configResult.cwd\n\n if (Array.isArray(userConfig) && userConfig.length) {\n throw new Error('Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.')\n }\n\n userConfig = await resolveUserConfig(userConfig, { configPath, logLevel })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n await notify(NotifyTypes.CONFIG_ERROR, errorMessage)\n return {\n content: [\n {\n type: 'text',\n text: errorMessage,\n },\n ],\n isError: true,\n }\n }\n\n const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)\n\n // Override config with CLI options\n const config: Config = {\n ...userConfig,\n root: resolveCwd(userConfig, cwd),\n input: inputPath\n ? {\n ...userConfig.input,\n path: inputPath,\n }\n : userConfig.input,\n output: output\n ? {\n ...userConfig.output,\n path: output,\n }\n : userConfig.output,\n }\n\n await notify(NotifyTypes.CONFIG_READY, 'Configuration ready', {\n root: config.root,\n })\n\n // Setup and build\n await notify(NotifyTypes.SETUP_START, 'Setting up Kubb')\n\n const { fabric, driver, sources } = await setup({\n config,\n events,\n })\n await notify(NotifyTypes.SETUP_END, 'Kubb setup complete')\n\n await notify(NotifyTypes.BUILD_START, 'Starting build')\n const { files, failedPlugins, error } = await safeBuild(\n {\n config,\n events,\n },\n { driver, fabric, events, sources },\n )\n await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`)\n\n if (error || failedPlugins.size > 0) {\n const allErrors: Error[] = [\n error,\n ...Array.from(failedPlugins)\n .filter((it) => it.error)\n .map((it) => it.error),\n ].filter(Boolean)\n\n await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {\n errorCount: allErrors.length,\n errors: allErrors.map((err) => err.message),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build failed:\\n${allErrors.map((err) => err.message).join('\\n')}\\n\\n${messages.join('\\n')}`,\n },\n ],\n isError: true,\n }\n }\n\n await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, {\n filesCount: files.length,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build completed successfully!\\n\\nGenerated ${files.length} files\\n\\n${messages.join('\\n')}`,\n },\n ],\n }\n } catch (caughtError) {\n const error = caughtError as Error\n\n await handler.sendNotification('kubb/progress', {\n type: NotifyTypes.FATAL_ERROR,\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString(),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build error: ${error.message}\\n${error.stack || ''}`,\n },\n ],\n isError: true,\n }\n }\n}\n","import process from 'node:process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { version } from '../package.json'\nimport { generateSchema } from './schemas/generateSchema.ts'\nimport { generate } from './tools/generate.ts'\n\n/**\n * Kubb MCP Server\n *\n * Provides tools for building OpenAPI specifications using Kubb.\n */\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n const server = new McpServer({\n name: 'Kubb',\n version,\n })\n\n // Build tool - runs Kubb build using @kubb/core\n // Wrapped to pass notification handler for real-time progress updates\n server.tool('generate', 'Generate OpenAPI spec helpers using Kubb configuration', generateSchema.shape, async (args) => {\n // Create notification handler that sends events back to the client\n const notificationHandler = {\n sendNotification: async (method: string, params: any) => {\n try {\n await transport.send({\n jsonrpc: '2.0',\n method,\n params,\n })\n } catch (error) {\n console.error('Failed to send notification:', error)\n }\n },\n }\n\n // Call build tool with notification handler\n return generate(args, notificationHandler)\n })\n\n await server.connect(transport)\n } catch (error) {\n console.error('Failed to start MCP server:', error)\n process.exit(1)\n }\n}\n","import { startServer } from './server.ts'\n\nexport async function run(_argv?: string[]): Promise<void> {\n await startServer()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["#emitter","NodeEventEmitter"],"sources":["../package.json","../src/schemas/generateSchema.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/asyncEventEmitter.ts","../../../internals/utils/src/promise.ts","../src/types.ts","../src/utils/loadUserConfig.ts","../src/utils/resolveCwd.ts","../src/utils/resolveUserConfig.ts","../src/tools/generate.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","import { z } from 'zod'\n\nexport const generateSchema = z.object({\n config: z\n .string()\n .optional()\n\n .describe('Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory'),\n input: z.string().optional().describe('Path to OpenAPI/Swagger spec file (overrides config)'),\n output: z.string().optional().describe('Output directory path (overrides config)'),\n logLevel: z.enum(['silent', 'error', 'warn', 'info', 'verbose', 'debug']).optional().default('info').describe('Log level for build output'),\n})\n\n","/** Thrown when a plugin's configuration or input fails validation.\n *\n * @example\n * ```ts\n * throw new ValidationPluginError('Invalid config: \"output.path\" is required')\n * ```\n */\nexport class ValidationPluginError extends Error {}\n\n/**\n * Thrown when one or more errors occur during a Kubb build.\n * Carries the full list of underlying errors on `errors`.\n *\n * @example\n * ```ts\n * throw new BuildError('Build failed', { errors: [err1, err2] })\n * ```\n */\nexport class BuildError extends Error {\n errors: Array<Error>\n\n constructor(message: string, options: { cause?: Error; errors: Array<Error> }) {\n super(message, { cause: options.cause })\n this.name = 'BuildError'\n this.errors = options.errors\n }\n}\n\n/**\n * Coerces an unknown thrown value to an `Error` instance.\n * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.\n *\n * @example\n * ```ts\n * try { ... } catch(err) {\n * throw new BuildError('Build failed', { cause: toError(err), errors: [] })\n * }\n * ```\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Extracts a human-readable message from any thrown value.\n *\n * @example\n * ```ts\n * getErrorMessage(new Error('oops')) // 'oops'\n * getErrorMessage('plain string') // 'plain string'\n * ```\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Extracts the `.cause` of an `Error` as an `Error`, or `undefined` when absent or not an `Error`.\n *\n * @example\n * ```ts\n * const cause = toCause(buildError) // Error | undefined\n * ```\n */\nexport function toCause(error: Error): Error | undefined {\n return error.cause instanceof Error ? error.cause : undefined\n}\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport { toError } from './errors.ts'\n\n/**\n * A function that can be registered as an event listener, synchronous or async.\n */\ntype AsyncListener<TArgs extends unknown[]> = (...args: TArgs) => void | Promise<void>\n\n/**\n * Typed `EventEmitter` that awaits all async listeners before resolving.\n * Wraps Node's `EventEmitter` with full TypeScript event-map inference.\n *\n * @example\n * ```ts\n * const emitter = new AsyncEventEmitter<{ build: [name: string] }>()\n * emitter.on('build', async (name) => { console.log(name) })\n * await emitter.emit('build', 'petstore') // all listeners awaited\n * ```\n */\nexport class AsyncEventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n /**\n * Maximum number of listeners per event before Node emits a memory-leak warning.\n * @default 10\n */\n constructor(maxListener = 10) {\n this.#emitter.setMaxListeners(maxListener)\n }\n\n #emitter = new NodeEventEmitter()\n\n /**\n * Emits `eventName` and awaits all registered listeners in parallel.\n * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.\n *\n * @example\n * ```ts\n * await emitter.emit('build', 'petstore')\n * ```\n */\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<AsyncListener<TEvents[TEventName]>>\n\n if (listeners.length === 0) {\n return\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n let serializedArgs: string\n try {\n serializedArgs = JSON.stringify(eventArgs)\n } catch {\n serializedArgs = String(eventArgs)\n }\n throw new Error(`Error in async listener for \"${eventName}\" with eventArgs ${serializedArgs}`, { cause: toError(err) })\n }\n }),\n )\n }\n\n /**\n * Registers a persistent listener for `eventName`.\n *\n * @example\n * ```ts\n * emitter.on('build', async (name) => { console.log(name) })\n * ```\n */\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.on(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /**\n * Registers a one-shot listener that removes itself after the first invocation.\n *\n * @example\n * ```ts\n * emitter.onOnce('build', async (name) => { console.log(name) })\n * ```\n */\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n const wrapper: AsyncListener<TEvents[TEventName]> = (...args) => {\n this.off(eventName, wrapper)\n return handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n /**\n * Removes a previously registered listener.\n *\n * @example\n * ```ts\n * emitter.off('build', handler)\n * ```\n */\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.off(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /**\n * Removes all listeners from every event channel.\n *\n * @example\n * ```ts\n * emitter.removeAll()\n * ```\n */\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\n/** Returns `true` when `result` is a fulfilled `Promise.allSettled` result.\n *\n * @example\n * ```ts\n * const results = await Promise.allSettled([p1, p2])\n * results.filter(isPromiseFulfilledResult).map((r) => r.value)\n * ```\n */\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\n/** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.\n *\n * @example\n * ```ts\n * const results = await Promise.allSettled([p1, p2])\n * results.filter(isPromiseRejectedResult<Error>).map((r) => r.reason.message)\n * ```\n */\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export const NotifyTypes = {\n INFO: 'INFO',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n WARN: 'WARN',\n PLUGIN_START: 'PLUGIN_START',\n PLUGIN_END: 'PLUGIN_END',\n FILES_START: 'FILES_START',\n FILE_UPDATE: 'FILE_UPDATE',\n FILES_END: 'FILES_END',\n GENERATION_START: 'GENERATION_START',\n GENERATION_END: 'GENERATION_END',\n CONFIG_LOADED: 'CONFIG_LOADED',\n CONFIG_ERROR: 'CONFIG_ERROR',\n CONFIG_READY: 'CONFIG_READY',\n SETUP_START: 'SETUP_START',\n SETUP_END: 'SETUP_END',\n BUILD_START: 'BUILD_START',\n BUILD_END: 'BUILD_END',\n BUILD_FAILED: 'BUILD_FAILED',\n BUILD_SUCCESS: 'BUILD_SUCCESS',\n FATAL_ERROR: 'FATAL_ERROR',\n} as const\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\nimport createJiti from 'jiti'\nimport { NotifyTypes } from '../types.ts'\n\ntype NotifyFunction = (type: string, message: string, data?: Record<string, unknown>) => Promise<void>\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\n/**\n * Load the user configuration from the specified path or current directory\n */\nexport async function loadUserConfig(configPath: string | undefined, { notify }: { notify: NotifyFunction }): Promise<{ userConfig: Config; cwd: string }> {\n let userConfig: Config | undefined\n let cwd: string\n\n if (configPath) {\n // Resolve the config path to absolute path and get its directory\n cwd = path.dirname(path.resolve(configPath))\n\n // Try to load from path\n try {\n userConfig = await jiti.import(configPath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${configPath}`)\n } catch (error) {\n await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n }\n } else {\n // Look for kubb.config in current directory with various extensions\n cwd = process.cwd()\n const configFileNames = ['kubb.config.ts', 'kubb.config.js', 'kubb.config.cjs']\n\n for (const configFileName of configFileNames) {\n try {\n const configFilePath = path.resolve(process.cwd(), configFileName)\n userConfig = await jiti.import(configFilePath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`)\n break\n } catch {\n // Continue trying next config file\n }\n }\n\n if (!userConfig) {\n await notify(NotifyTypes.CONFIG_ERROR, 'No config file found')\n\n throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(', ')}`)\n }\n }\n\n return { userConfig: userConfig!, cwd }\n}\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\n\n/**\n * Determine the root directory based on userConfig.root and resolvedConfigDir\n * 1. If userConfig.root exists and is absolute, use it as-is\n * 2. If userConfig.root exists and is relative, resolve it relative to config directory\n * 3. Otherwise, use the config directory as root\n */\nexport function resolveCwd(userConfig: Config, cwd: string): string {\n if (userConfig.root) {\n if (path.isAbsolute(userConfig.root)) {\n return userConfig.root\n }\n\n return path.resolve(cwd, userConfig.root)\n }\n\n return cwd\n}\n","import { isPromise } from '@internals/utils'\nimport type { CLIOptions, Config, UserConfig } from '@kubb/core'\n\nexport type ResolveUserConfigOptions = {\n configPath?: string\n logLevel?: string\n}\n\n/**\n * Resolve the config by handling function configs and returning the final configuration\n */\nexport async function resolveUserConfig(userConfig: UserConfig, options: ResolveUserConfigOptions): Promise<Config> {\n let kubbUserConfig = Promise.resolve(userConfig) as Promise<UserConfig>\n\n if (typeof userConfig === 'function') {\n const possiblePromise = (userConfig as any)({ logLevel: options.logLevel, config: options.configPath } as CLIOptions)\n if (isPromise(possiblePromise)) {\n kubbUserConfig = possiblePromise\n } else {\n kubbUserConfig = Promise.resolve(possiblePromise)\n }\n }\n\n return (await kubbUserConfig) as Config\n}\n","import { AsyncEventEmitter } from '@internals/utils'\nimport { type Config, type KubbEvents, safeBuild, setup } from '@kubb/core'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.d.ts'\nimport type { z } from 'zod'\nimport type { generateSchema } from '../schemas/generateSchema.ts'\nimport { NotifyTypes } from '../types.ts'\nimport { loadUserConfig } from '../utils/loadUserConfig.ts'\nimport { resolveCwd } from '../utils/resolveCwd.ts'\nimport { resolveUserConfig } from '../utils/resolveUserConfig.ts'\n\ninterface NotificationHandler {\n sendNotification(method: string, params: unknown): Promise<void>\n}\n\n/**\n * Build tool that generates code from OpenAPI specs using Kubb.\n * Sends real-time notifications of build progress and events.\n */\nexport async function generate(schema: z.infer<typeof generateSchema>, handler: NotificationHandler): Promise<CallToolResult> {\n const { config: configPath, input, output, logLevel } = schema\n\n try {\n const events = new AsyncEventEmitter<KubbEvents>()\n const messages: string[] = []\n\n // Helper to send notifications\n const notify = async (type: string, message: string, data?: Record<string, unknown>) => {\n messages.push(`${type}: ${message}`)\n\n await handler.sendNotification('kubb/progress', {\n type,\n message,\n timestamp: new Date().toISOString(),\n ...data,\n })\n }\n\n // Capture events for output and send notifications\n events.on('info', async (message: string) => {\n await notify(NotifyTypes.INFO, message)\n })\n\n events.on('success', async (message: string) => {\n await notify(NotifyTypes.SUCCESS, message)\n })\n\n events.on('error', async (error: Error) => {\n await notify(NotifyTypes.ERROR, error.message, { stack: error.stack })\n })\n\n events.on('warn', async (message: string) => {\n await notify(NotifyTypes.WARN, message)\n })\n\n // Plugin lifecycle events\n events.on('plugin:start', async ({ name }: { name: string }) => {\n await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${name}`)\n })\n\n events.on('plugin:end', async ({ name, duration }: { name: string; duration?: number }) => {\n await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${name}`, { duration })\n })\n\n // File processing events\n events.on('files:processing:start', async () => {\n await notify(NotifyTypes.FILES_START, 'Starting file processing')\n })\n\n events.on('file:processing:update', async ({ file }: { file: { name: string } }) => {\n await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`)\n })\n\n events.on('files:processing:end', async () => {\n await notify(NotifyTypes.FILES_END, 'File processing complete')\n })\n\n // Generation events\n events.on('generation:start', async () => {\n await notify(NotifyTypes.GENERATION_START, 'Generation started')\n })\n\n events.on('generation:end', async () => {\n await notify(NotifyTypes.GENERATION_END, 'Generation ended')\n })\n\n // Load and process configuration\n let userConfig: Config\n let cwd: string\n\n try {\n const configResult = await loadUserConfig(configPath, { notify })\n userConfig = configResult.userConfig\n cwd = configResult.cwd\n\n if (Array.isArray(userConfig) && userConfig.length) {\n throw new Error('Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.')\n }\n\n userConfig = await resolveUserConfig(userConfig, { configPath, logLevel })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n await notify(NotifyTypes.CONFIG_ERROR, errorMessage)\n return {\n content: [\n {\n type: 'text',\n text: errorMessage,\n },\n ],\n isError: true,\n }\n }\n\n const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)\n\n // Override config with CLI options\n const config: Config = {\n ...userConfig,\n root: resolveCwd(userConfig, cwd),\n input: inputPath\n ? {\n ...userConfig.input,\n path: inputPath,\n }\n : userConfig.input,\n output: output\n ? {\n ...userConfig.output,\n path: output,\n }\n : userConfig.output,\n }\n\n await notify(NotifyTypes.CONFIG_READY, 'Configuration ready', {\n root: config.root,\n })\n\n // Setup and build\n await notify(NotifyTypes.SETUP_START, 'Setting up Kubb')\n\n const { fabric, driver, sources } = await setup({\n config,\n events,\n })\n await notify(NotifyTypes.SETUP_END, 'Kubb setup complete')\n\n await notify(NotifyTypes.BUILD_START, 'Starting build')\n const { files, failedPlugins, error } = await safeBuild(\n {\n config,\n events,\n },\n { driver, fabric, events, sources },\n )\n await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`)\n\n if (error || failedPlugins.size > 0) {\n const allErrors: Error[] = [\n error,\n ...Array.from(failedPlugins)\n .filter((it) => it.error)\n .map((it) => it.error),\n ].filter(Boolean)\n\n await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {\n errorCount: allErrors.length,\n errors: allErrors.map((err) => err.message),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build failed:\\n${allErrors.map((err) => err.message).join('\\n')}\\n\\n${messages.join('\\n')}`,\n },\n ],\n isError: true,\n }\n }\n\n await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, {\n filesCount: files.length,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build completed successfully!\\n\\nGenerated ${files.length} files\\n\\n${messages.join('\\n')}`,\n },\n ],\n }\n } catch (caughtError) {\n const error = caughtError as Error\n\n await handler.sendNotification('kubb/progress', {\n type: NotifyTypes.FATAL_ERROR,\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString(),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build error: ${error.message}\\n${error.stack || ''}`,\n },\n ],\n isError: true,\n }\n }\n}\n","import process from 'node:process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { version } from '../package.json'\nimport { generateSchema } from './schemas/generateSchema.ts'\nimport { generate } from './tools/generate.ts'\n\n/**\n * Kubb MCP Server\n *\n * Provides tools for building OpenAPI specifications using Kubb.\n */\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n const server = new McpServer({\n name: 'Kubb',\n version,\n })\n\n // Build tool - runs Kubb build using @kubb/core\n // Wrapped to pass notification handler for real-time progress updates\n server.tool('generate', 'Generate OpenAPI spec helpers using Kubb configuration', generateSchema.shape, async (args) => {\n // Create notification handler that sends events back to the client\n const notificationHandler = {\n sendNotification: async (method: string, params: any) => {\n try {\n await transport.send({\n jsonrpc: '2.0',\n method,\n params,\n })\n } catch (error) {\n console.error('Failed to send notification:', error)\n }\n },\n }\n\n // Call build tool with notification handler\n return generate(args, notificationHandler)\n })\n\n await server.connect(transport)\n } catch (error) {\n console.error('Failed to start MCP server:', error)\n process.exit(1)\n }\n}\n","import { startServer } from './server.ts'\n\nexport async function run(_argv?: string[]): Promise<void> {\n await startServer()\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/mcp",
3
- "version": "5.0.0-alpha.17",
3
+ "version": "5.0.0-alpha.19",
4
4
  "description": "Model Context Protocol (MCP) server for Kubb, enabling AI assistants to generate code from OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -50,16 +50,16 @@
50
50
  }
51
51
  ],
52
52
  "dependencies": {
53
- "@kubb/fabric-core": "0.14.0",
54
- "@kubb/react-fabric": "0.14.0",
53
+ "@kubb/fabric-core": "0.15.1",
54
+ "@kubb/react-fabric": "0.15.1",
55
55
  "@modelcontextprotocol/sdk": "^1.27.1",
56
56
  "jiti": "2.5.1",
57
57
  "zod": "^4.3.6",
58
- "@kubb/core": "5.0.0-alpha.17"
58
+ "@kubb/core": "5.0.0-alpha.19"
59
59
  },
60
60
  "peerDependencies": {
61
- "@kubb/fabric-core": "0.14.0",
62
- "@kubb/react-fabric": "0.14.0"
61
+ "@kubb/fabric-core": "0.15.1",
62
+ "@kubb/react-fabric": "0.15.1"
63
63
  },
64
64
  "engines": {
65
65
  "node": ">=22"