@kubb/plugin-mcp 5.3.0 → 5.3.2

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
@@ -444,6 +444,73 @@ return server`
444
444
  ] });
445
445
  }
446
446
  //#endregion
447
+ //#region ../../internals/client/src/resolveOperationTypes.ts
448
+ /**
449
+ * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
450
+ * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
451
+ */
452
+ function toZodTypeResolver(resolver) {
453
+ const type = (name) => resolver.schema.type(name);
454
+ return {
455
+ ...resolver,
456
+ file: resolver.file.bind(resolver),
457
+ param: {
458
+ name: (node, p) => type(resolver.param.name(node, p)),
459
+ path: (node, p) => type(resolver.param.path(node, p)),
460
+ query: (node, p) => type(resolver.param.query(node, p)),
461
+ headers: (node, p) => type(resolver.param.headers(node, p))
462
+ },
463
+ response: {
464
+ body: (node) => type(resolver.response.body(node)),
465
+ status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
466
+ response: (node) => type(resolver.response.response(node)),
467
+ responses: (node) => type(resolver.response.responses(node)),
468
+ options: (node) => resolver.response.options(node)
469
+ }
470
+ };
471
+ }
472
+ /**
473
+ * Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.
474
+ *
475
+ * `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`
476
+ * wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws
477
+ * `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.
478
+ *
479
+ * @example
480
+ * ```ts
481
+ * const types = resolveOperationTypes(ctx.driver, ctx.plugin.name)
482
+ * types.response.options(node) // 'GetPetByIdOptions', or 'GetPetByIdOptionsSchemaType' from zod
483
+ * ```
484
+ */
485
+ function resolveOperationTypes(driver, pluginName) {
486
+ const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
487
+ const pluginZod = driver.getPlugin(_kubb_plugin_zod.pluginZodName);
488
+ if (pluginTs && pluginZod?.options?.inferred !== "codec") {
489
+ const resolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
490
+ return {
491
+ response: resolver.response,
492
+ resolver,
493
+ output: pluginTs.options?.output,
494
+ group: pluginTs.options?.group ?? void 0
495
+ };
496
+ }
497
+ if (!pluginZod?.options?.inferred) throw new kubb_kit.Diagnostics.Error({
498
+ code: kubb_kit.Diagnostics.code.missingDependency,
499
+ severity: "error",
500
+ message: `Plugin "${pluginName}" has no source for operation types.`,
501
+ help: `Add \`pluginTs()\` before "${pluginName}", or add \`pluginZod({ inferred: true })\`.`,
502
+ location: { kind: "config" },
503
+ plugin: pluginName
504
+ });
505
+ const resolver = toZodTypeResolver(driver.getResolver(_kubb_plugin_zod.pluginZodName));
506
+ return {
507
+ response: resolver.response,
508
+ resolver,
509
+ output: pluginZod.options.output,
510
+ group: pluginZod.options.group ?? void 0
511
+ };
512
+ }
513
+ //#endregion
447
514
  //#region ../../internals/client/src/resolveClient.ts
448
515
  /**
449
516
  * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
@@ -629,8 +696,8 @@ const mcpGenerator = (0, kubb_kit.defineGenerator)({
629
696
  if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
630
697
  const { resolver, driver, root, config } = ctx;
631
698
  const { output, client, group } = ctx.options;
632
- const pluginTs = ctx.requirePlugin(_kubb_plugin_ts.pluginTsName);
633
- const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
699
+ const types = resolveOperationTypes(driver, resolver.pluginName);
700
+ const tsResolver = types.resolver;
634
701
  const contractOp = resolveClientOperation({
635
702
  clientPlugin: { pluginName: client.pluginName },
636
703
  driver,
@@ -654,8 +721,8 @@ const mcpGenerator = (0, kubb_kit.defineGenerator)({
654
721
  node,
655
722
  resolver: tsResolver,
656
723
  root,
657
- output: pluginTs.options?.output ?? output,
658
- group: pluginTs.options?.group
724
+ output: types.output ?? output,
725
+ group: types.group
659
726
  })
660
727
  };
661
728
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx.File, {
@@ -888,7 +955,7 @@ var compatibility = {
888
955
  };
889
956
  //#endregion
890
957
  //#region package.json
891
- var version = "5.3.0";
958
+ var version = "5.3.2";
892
959
  //#endregion
893
960
  //#region src/resolvers/resolverMcp.ts
894
961
  /**
@@ -955,7 +1022,7 @@ const pluginMcp = (0, kubb_kit.defineExtension)({
955
1022
  compatibility
956
1023
  },
957
1024
  dependencies: {
958
- [_kubb_plugin_ts.pluginTsName]: {},
1025
+ [_kubb_plugin_ts.pluginTsName]: { optional: true },
959
1026
  [_kubb_plugin_zod.pluginZodName]: {}
960
1027
  },
961
1028
  setup(options) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Url","posix","File","Function","File","Function","Const","Diagnostics","path","defineGenerator","jsxRenderer","ast","pluginTsName","File","defineGenerator","jsxRenderer","pluginZodName","path","ast","File","createResolver","defineExtension","pluginTsName","pluginZodName","Resolver","useConfig"],"sources":["../../../internals/shared/src/operation.ts","../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/shared/src/group.ts","../src/components/McpHandler.tsx","../src/components/Server.tsx","../../../internals/client/src/resolveClient.ts","../../../internals/client/src/resolveClientOperation.ts","../src/generators/mcpGenerator.tsx","../src/generators/serverGenerator.tsx","../kubb-extension.json","../package.json","../src/resolvers/resolverMcp.ts","../src/plugin.ts"],"sourcesContent":["import { ast, type Group, type NodeCache, type Output, type Resolver, type ResolverFileParams, Url } from 'kubb/kit'\n\n/**\n * Builds the `ResolverFileParams` every operation generator passes to\n * `resolver.file`: a file named `name`, tagged by the operation's first\n * tag (or `'default'`), at the operation's path. Centralizes the entry object\n * that was repeated at dozens of call sites across the client and query plugins.\n *\n * @example\n * ```ts\n * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })\n * ```\n */\nexport function operationFileEntry(node: ast.OperationNode, name: string, extname: ResolverFileParams['extname'] = '.ts'): ResolverFileParams {\n return {\n name,\n extname,\n tag: node.tags[0] ?? 'default',\n path: node.path,\n }\n}\n\n/**\n * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the\n * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the\n * same dependency for the same operation in one pass (a query plugin's several hook generators, the\n * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.\n *\n * @example Cache `plugin-ts`'s file for the current operation\n * ```ts\n * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })\n * ```\n */\nexport function resolveDependencyOperationFile(options: {\n cache: NodeCache\n node: ast.OperationNode\n resolver: Pick<Resolver, 'file' | 'pluginName'>\n root: string\n output: Output\n group?: Group | null\n}): ast.FileNode {\n const { cache, node, resolver, root, output, group } = options\n\n return cache.ensureItem(`${resolver.pluginName}:operationFile`, () =>\n resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n )\n}\n\nexport type ContentTypeInfo = {\n contentTypes: string[]\n isMultipleContentTypes: boolean\n contentTypeUnion: string\n defaultContentType: string\n hasFormData: boolean\n}\n\nexport type RequestConfigResolver = {\n response: {\n body(node: ast.OperationNode): string\n }\n}\n\nexport type ResponseStatusNameResolver = {\n response: {\n status(node: ast.OperationNode, statusCode: ast.StatusCode): string\n }\n}\n\nexport type ResponseNameResolver = ResponseStatusNameResolver & {\n response: {\n response(node: ast.OperationNode): string\n }\n}\n\nexport type OperationTypeNameResolver = RequestConfigResolver &\n ResponseNameResolver & {\n param: {\n path(node: ast.OperationNode, param: ast.ParameterNode): string\n query(node: ast.OperationNode, param: ast.ParameterNode): string\n headers(node: ast.OperationNode, param: ast.ParameterNode): string\n }\n }\n\nexport type OperationCommentLink = 'pathTemplate' | 'urlPath' | false | ((node: ast.OperationNode) => string | undefined)\n\nexport type BuildOperationCommentsOptions = {\n link?: OperationCommentLink\n linkPosition?: 'beforeDeprecated' | 'afterDeprecated'\n splitLines?: boolean\n}\n\ntype ResponseLike = {\n statusCode: ast.StatusCode | number | string\n}\n\nexport type OperationParameterGroups = Record<ast.ParameterNode['in'], Array<ast.ParameterNode>>\n\nexport type ResolveOperationTypeNameOptions = {\n responseStatusNames?: boolean | 'error'\n exclude?: ReadonlyArray<string | undefined>\n order?: 'params-first' | 'body-response-first'\n /**\n * Include the individual `Path`/`Query`/`Headers` group type names. Set to `false` for clients\n * that reference the grouped `Options` type instead of the per-group types.\n */\n includeParams?: boolean\n}\n\nfunction getOperationLink(node: ast.OperationNode, link: OperationCommentLink): string | null {\n if (!link) {\n return null\n }\n\n if (typeof link === 'function') {\n return link(node) ?? null\n }\n\n return node.path ? `{@link ${Url.toPath(node.path)}}` : null\n}\n\n/**\n * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several\n * are present and the union, default, and form-data flags the client uses to pick one.\n */\nfunction buildContentTypeInfo(contentTypes: string[]): ContentTypeInfo {\n const isMultipleContentTypes = contentTypes.length > 1\n\n return {\n contentTypes,\n isMultipleContentTypes,\n contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(' | ') : '',\n defaultContentType: contentTypes[0] ?? 'application/json',\n hasFormData: contentTypes.some((ct) => ct === 'multipart/form-data'),\n }\n}\n\nexport function getContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? [])\n}\n\n/**\n * The request-body counterpart for the primary success response: the content types it documents and\n * whether several are present, so the client can let a caller pick which one to accept.\n */\nexport function getResponseContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [])\n}\n\nexport type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'\n\n/**\n * Reads the single base content type of an operation's primary success response, lowercased and\n * stripped of any `; charset=...` suffix. Returns `undefined` when the response declares zero or\n * more than one content type, since neither case has a single type to act on.\n */\nfunction getPrimarySuccessContentType(node: ast.OperationNode): string | undefined {\n const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? []\n if (contentTypes.length !== 1) return undefined\n return contentTypes[0]!.split(';')[0]!.trim().toLowerCase()\n}\n\n/**\n * Whether an operation streams its primary success response as Server-Sent Events\n * (`text/event-stream`). The client generator uses this to return a typed event stream instead of a\n * one-shot `RequestResult`.\n */\nexport function isEventStream(node: ast.OperationNode): boolean {\n return getPrimarySuccessContentType(node) === 'text/event-stream'\n}\n\n/**\n * Derives the default `responseType` for an operation from its primary success response.\n *\n * Returns a value only when that response declares a single non-JSON content type. `text/event-stream`\n * and other binary types (`application/octet-stream`, `application/pdf`, `image/*`, `audio/*`,\n * `video/*`) map to a stream or `'blob'`, and other `text/*` maps to `'text'`. Otherwise `undefined`,\n * leaving the runtime client's `Content-Type` auto-detection in charge.\n */\nexport function getResponseType(node: ast.OperationNode): ResponseType | undefined {\n const baseType = getPrimarySuccessContentType(node)\n if (!baseType) return undefined\n\n if (baseType === 'application/json' || baseType.endsWith('+json') || baseType === 'text/json') return undefined\n if (baseType === 'text/event-stream') return 'stream'\n if (baseType.startsWith('text/')) return 'text'\n if (baseType === 'application/octet-stream' || baseType === 'application/pdf' || /^(image|audio|video)\\//.test(baseType)) return 'blob'\n return undefined\n}\n\n/**\n * Maps a content type to the PascalCase suffix used to name per-content-type variants\n * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).\n */\nfunction getContentTypeSuffix(contentType: string): string {\n const baseType = contentType.split(';')[0]!.trim()\n if (baseType === 'application/json') return 'Json'\n if (baseType === 'multipart/form-data') return 'FormData'\n if (baseType === 'application/x-www-form-urlencoded') return 'FormUrlEncoded'\n const subtype = baseType.split('/').pop() ?? baseType\n const parts = subtype.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n if (parts.length === 0) return 'Unknown'\n return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')\n}\n\n/**\n * Appends a content-type suffix to a base name, keeping a trailing `Data` segment last\n * (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).\n */\nexport function getPerContentTypeName(baseName: string, suffix: string): string {\n if (baseName.endsWith('Data')) {\n return suffix.endsWith('Data') ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`\n }\n return baseName + suffix\n}\n\nexport type ContentVariantInput = { contentType: string; schema?: ast.SchemaNode | null; keysToOmit?: Array<string> | null }\nexport type ContentVariant = { name: string; suffix: string; schema: ast.SchemaNode; keysToOmit?: Array<string> | null; contentType: string }\n\n/**\n * Resolves per-content-type variant names for a set of content entries, deduplicating suffix\n * collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is\n * the final (possibly counter-augmented) value, so callers can derive parallel names in another\n * namespace (e.g. plugin-faker deriving the matching plugin-ts type name).\n */\nexport function resolveContentTypeVariants(entries: Array<ContentVariantInput>, baseName: string): Array<ContentVariant> {\n const usedNames = new Set<string>()\n return entries\n .filter((entry) => entry.schema)\n .map((entry) => {\n const baseSuffix = getContentTypeSuffix(entry.contentType)\n let suffix = baseSuffix\n let name = getPerContentTypeName(baseName, suffix)\n let counter = 2\n while (usedNames.has(name)) {\n suffix = `${baseSuffix}${counter++}`\n name = getPerContentTypeName(baseName, suffix)\n }\n usedNames.add(name)\n return { name, suffix, schema: entry.schema!, keysToOmit: entry.keysToOmit, contentType: entry.contentType }\n })\n}\n\n// The request groups come from the grouped params, so `config` drops the data-shape keys to stay\n// assignable to `Options`, which omits them from `RequestConfig`.\nconst requestConfigBaseType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`\n\nexport function buildRequestConfigType(node: ast.OperationNode): string {\n const request = getContentTypeInfo(node)\n const response = getResponseContentTypeInfo(node)\n\n // Only the ambiguous side is offered: a single-type side has nothing to pick, so it stays baked in\n // the generated call.\n const members = [\n request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null,\n response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null,\n ].filter(Boolean)\n\n return members.length ? `${requestConfigBaseType} & { contentType?: { ${members.join('; ')} } }` : requestConfigBaseType\n}\n\n/**\n * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,\n * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a\n * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a\n * content type for.\n */\nexport function buildClientOptionType(): string {\n return requestConfigBaseType\n}\n\nexport type RequestGroups = {\n path: boolean\n query: boolean\n body: boolean\n headers: boolean\n}\n\n/**\n * Which of the grouped request options an operation carries.\n */\nexport function getRequestGroups(node: ast.OperationNode): RequestGroups {\n const { path, query, header } = getOperationParameters(node)\n return {\n path: path.length > 0,\n query: query.length > 0,\n body: Boolean(node.requestBody?.content?.[0]?.schema),\n headers: header.length > 0,\n }\n}\n\nexport type RequestGroupOptionality = {\n groups: RequestGroups\n hasRequiredPath: boolean\n hasRequiredQuery: boolean\n hasRequiredHeader: boolean\n /**\n * Whether the grouped request parameter can default to `{}`. True only when no group carries a\n * required member, so every member is safe to omit.\n */\n isOptional: boolean\n}\n\n/**\n * Resolves which grouped request options an operation carries together with whether each group\n * holds a required member. The grouped parameter stays optional only when nothing inside it is\n * required, matching the generated `RequestConfig` type.\n */\nexport function getRequestGroupOptionality(node: ast.OperationNode): RequestGroupOptionality {\n const groups = getRequestGroups(node)\n const { path, query, header } = getOperationParameters(node)\n const hasRequiredPath = path.some((param) => param.required)\n const hasRequiredQuery = query.some((param) => param.required)\n const hasRequiredHeader = header.some((param) => param.required)\n\n return {\n groups,\n hasRequiredPath,\n hasRequiredQuery,\n hasRequiredHeader,\n isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body,\n }\n}\n\nexport type RequestOptionsNameResolver = RequestConfigResolver & {\n response: {\n options(node: ast.OperationNode): string\n }\n}\n\n/**\n * Builds the grouped `{ path, query, body, headers }` parameter for a generated client\n * function, typed from the operation's `Options` (minus `url`). Only the groups the\n * operation actually has are destructured. The trailing `config` parameter carries the\n * runtime `RequestConfig` overrides plus `client`.\n */\nexport function buildRequestParamsSignature(\n node: ast.OperationNode,\n resolver: RequestOptionsNameResolver,\n options: { isConfigurable?: boolean } = {},\n): { signature: string; groups: RequestGroups } {\n const { isConfigurable = true } = options\n const { groups, isOptional } = getRequestGroupOptionality(node)\n\n const names = (['path', 'query', 'body', 'headers'] as const).filter((key) => groups[key])\n\n const firstParam = names.length > 0 ? `{ ${names.join(', ')} }: ${resolver.response.options(node)}${isOptional ? ' = {}' : ''}` : null\n const configParam = isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null\n\n return {\n signature: [firstParam, configParam].filter(Boolean).join(', '),\n groups,\n }\n}\n\nexport function buildOperationComments(node: ast.OperationNode, options: BuildOperationCommentsOptions = {}): Array<string> {\n const { link = 'pathTemplate', linkPosition = 'afterDeprecated', splitLines = false } = options\n const linkComment = getOperationLink(node, link)\n const comments =\n linkPosition === 'beforeDeprecated'\n ? [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, linkComment, node.deprecated && '@deprecated']\n : [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, node.deprecated && '@deprecated', linkComment]\n\n const filteredComments = comments.filter((comment): comment is string => Boolean(comment))\n\n if (!splitLines) {\n return filteredComments\n }\n\n return filteredComments.flatMap((text) => text.split(/\\r?\\n/).map((line) => line.trim())).filter((comment): comment is string => Boolean(comment))\n}\n\nconst operationParameterGroupsByNode = new WeakMap<ast.OperationNode, OperationParameterGroups>()\n\n/**\n * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each\n * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance\n * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the\n * same parameters once per plugin.\n */\nexport function getOperationParameters(node: ast.OperationNode): OperationParameterGroups {\n const cached = operationParameterGroupsByNode.get(node)\n if (cached) return cached\n\n // A malformed spec can declare the same name twice within one location. Both would resolve to the\n // same output property, so emitting both would yield an object type with a duplicate member,\n // which TypeScript rejects. Keep the first.\n const group = (location: ast.ParameterNode['in']) => {\n const seen = new Set<string>()\n\n return node.parameters.filter((param) => {\n if (param.in !== location || seen.has(param.name)) return false\n seen.add(param.name)\n return true\n })\n }\n\n const groups: OperationParameterGroups = { path: group('path'), query: group('query'), header: group('header'), cookie: group('cookie') }\n\n operationParameterGroupsByNode.set(node, groups)\n return groups\n}\n\n/**\n * Builds the combined `{ body, path, query, headers }` options object schema for an operation,\n * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s\n * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same\n * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod\n * printer to emit `z.object(…)` rather than a record.\n */\nexport function buildOptionsSchema(node: ast.OperationNode, resolver: OperationTypeNameResolver): ast.SchemaNode {\n const { path, query, header } = getOperationParameters(node)\n const hasBody = Boolean(node.requestBody?.content?.[0]?.schema)\n const createNever = () => ast.factory.createSchema({ type: 'never', primitive: undefined, optional: true })\n const groups = [\n { name: 'path', params: path, resolve: resolver.param.path },\n { name: 'query', params: query, resolve: resolver.param.query },\n { name: 'headers', params: header, resolve: resolver.param.headers },\n ] as const\n\n // NOTE(v5-stable): the fields were renamed from the legacy beta shape\n // (`data`/`pathParams`/`queryParams`/`headerParams`) to `body`/`path`/`query`/`headers` so the\n // type matches the runtime client. Drop this note once v5 leaves beta.\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n deprecated: node.deprecated,\n properties: [\n ast.factory.createProperty({\n name: 'body',\n required: hasBody,\n schema: hasBody ? ast.factory.createSchema({ type: 'ref', name: resolver.response.body(node) }) : createNever(),\n }),\n ...groups.map(({ name, params, resolve }) => {\n const required = params.some((param) => param.required)\n\n return ast.factory.createProperty({\n name,\n required,\n schema:\n params.length > 0\n ? ast.factory.createSchema({ type: 'ref', name: resolve.call(resolver.param, node, params[0]!), optional: !required })\n : createNever(),\n })\n }),\n ],\n })\n}\n\n/**\n * The schema a status occupies in the `<Name>Responses` record. A status that documents several\n * content types becomes a `{ contentType; data }` union so the runtime can surface the negotiated type\n * on `result.parsed`, while the standalone `<Name>StatusNNN` alias stays the plain body union that the\n * query hooks and `result.data` use.\n */\nfunction buildResponseRecordEntry(node: ast.OperationNode, res: ast.ResponseNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n const statusName = resolver.response.status(node, res.statusCode)\n const variants = (res.content ?? []).filter((entry) => entry.schema)\n if (variants.length <= 1) {\n return ast.factory.createSchema({ type: 'ref', name: statusName })\n }\n\n return ast.factory.createSchema({\n type: 'union',\n members: resolveContentTypeVariants(variants, statusName).map((variant) =>\n ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: [\n ast.factory.createProperty({\n name: 'contentType',\n required: true,\n schema: ast.factory.createSchema({ type: 'enum', enumValues: [variant.contentType] }),\n }),\n ast.factory.createProperty({\n name: 'data',\n required: true,\n schema: ast.factory.createSchema({ type: 'ref', name: variant.name }),\n }),\n ],\n }),\n ),\n })\n}\n\n/**\n * Builds the per-status `<Name>Responses` record for an operation, referencing the already-resolved\n * `<Name>StatusNNN` names. Shared by `@kubb/plugin-ts`'s `Responses` type and `@kubb/plugin-zod`'s\n * inferred responses schema, so both emit the same shape from the same inputs.\n *\n * Always emits the keyed record, even when an operation declares no responses. An operation with no\n * responses renders as an empty object, which keeps every consumer's import (for example the axios\n * SDK's `RequestResult<XResponses>`) resolvable instead of pointing at a missing export.\n */\nexport function buildResponses(node: ast.OperationNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: node.responses.map((res) =>\n ast.factory.createProperty({\n name: String(res.statusCode),\n required: true,\n schema: buildResponseRecordEntry(node, res, resolver),\n }),\n ),\n })\n}\n\nexport function getStatusCodeNumber(statusCode: ast.StatusCode | number | string): number | null {\n const code = Number(statusCode)\n\n return Number.isNaN(code) ? null : code\n}\n\nexport function isSuccessStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 200 && code < 300\n}\n\nexport function isErrorStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 400\n}\n\nexport function getSuccessResponses<TResponse extends ResponseLike>(responses: ReadonlyArray<TResponse>): Array<TResponse> {\n return responses.filter((response) => isSuccessStatusCode(response.statusCode))\n}\n\nexport function getOperationSuccessResponses(node: ast.OperationNode): Array<ast.ResponseNode> {\n return getSuccessResponses(node.responses)\n}\n\nexport function getPrimarySuccessResponse(node: ast.OperationNode): ast.ResponseNode | null {\n return getOperationSuccessResponses(node)[0] ?? null\n}\n\nexport function resolveErrorNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveSuccessNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveStatusCodeNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.map((response) => resolver.response.status(node, response.statusCode))\n}\n\nconst typeNamesByResolver = new WeakMap<OperationTypeNameResolver, Map<string, string[]>>()\n\nexport function resolveOperationTypeNames(\n node: ast.OperationNode,\n resolver: OperationTypeNameResolver,\n options: ResolveOperationTypeNameOptions = {},\n): string[] {\n const cacheKey = `${node.operationId}\\0${options.order ?? ''}\\0${options.responseStatusNames ?? ''}\\0${options.includeParams === false ? 'noparams' : ''}\\0${(options.exclude ?? []).join(',')}`\n let byResolver = typeNamesByResolver.get(resolver)\n if (byResolver) {\n const cached = byResolver.get(cacheKey)\n if (cached) return cached\n } else {\n byResolver = new Map()\n typeNamesByResolver.set(resolver, byResolver)\n }\n\n const { path, query, header } = getOperationParameters(node)\n const responseStatusNames =\n options.responseStatusNames === 'error'\n ? resolveErrorNames(node, resolver)\n : options.responseStatusNames === false\n ? []\n : resolveStatusCodeNames(node, resolver)\n const exclude = new Set(options.exclude ?? [])\n const paramNames =\n options.includeParams === false\n ? []\n : [\n ...path.map((param) => resolver.param.path(node, param)),\n ...query.map((param) => resolver.param.query(node, param)),\n ...header.map((param) => resolver.param.headers(node, param)),\n ]\n const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)]\n const names =\n options.order === 'body-response-first'\n ? [...bodyAndResponseNames, ...paramNames, ...responseStatusNames]\n : [...paramNames, ...bodyAndResponseNames, ...responseStatusNames]\n\n const result = names.filter((name): name is string => Boolean(name) && !exclude.has(name as string))\n byResolver.set(cacheKey, result)\n return result\n}\n\nexport function resolveResponseTypes(node: ast.OperationNode, resolver: ResponseNameResolver): Array<[statusCode: number | 'default', typeName: string]> {\n const types: Array<[number | 'default', string]> = []\n\n for (const response of node.responses) {\n if (response.statusCode === 'default') {\n types.push(['default', resolver.response.response(node)])\n continue\n }\n\n const code = getStatusCodeNumber(response.statusCode)\n if (code === null) {\n continue\n }\n\n types.push([code, isSuccessStatusCode(code) ? resolver.response.response(node) : resolver.response.status(node, response.statusCode)])\n }\n\n return types\n}\n","type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction convert(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n// Plugins resolve the same names over and over (about 47,000 calls for a 1,000 schema spec), so\n// results are kept. Clearing at the limit bounds the memory a long-running process spends on it.\nconst cache = new Map<string, string>()\nconst cacheLimit = 10_000\n\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const key = `${pascal ? 'P' : 'c'}${text}`\n const cached = cache.get(key)\n if (cached !== undefined) return cached\n\n const result = convert(text, pascal)\n if (cache.size >= cacheLimit) cache.clear()\n cache.set(key, result)\n return result\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Uppercases only the first character of `text`, leaving the rest untouched.\n * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.\n *\n * @example\n * `capitalize('getPetById') // 'GetPetById'`\n */\nexport function capitalize(text: string): string {\n return `${text.charAt(0).toUpperCase()}${text.slice(1)}`\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from 'kubb/kit'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { buildOperationComments, buildRequestParamsSignature } from '@internals/shared'\nimport type { ast } from 'kubb/kit'\nimport type { ResolverTs } from '@kubb/plugin-ts'\nimport { File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype Props = {\n /**\n * Name of the handler function.\n */\n name: string\n /**\n * Name of the contract client `<op>` the handler calls.\n */\n clientName: string\n /**\n * AST operation node.\n */\n node: ast.HttpOperationNode\n /**\n * TypeScript resolver for resolving param/data/response type names.\n */\n resolver: ResolverTs\n /**\n * The registered client plugin's `returnType`, read by the caller off `resolveClientOperation`.\n */\n returnType?: 'full' | 'data' | 'plain'\n}\n\nconst requestGroupOrder = ['path', 'query', 'headers', 'body'] as const\n\nexport function McpHandler({ name, clientName, node, resolver, returnType = 'full' }: Props): KubbReactNode {\n const { signature, groups } = buildRequestParamsSignature(node, resolver, { isConfigurable: false })\n const paramsSignature = [signature, 'ctx: ServerContext'].filter(Boolean).join(', ')\n\n // Forward the grouped config and MCP cancellation signal through the contract client. `throwOnError: true`\n // pins the result shape, since `throwOnErrorDefault: false` would otherwise resolve to the full result.\n const callArgs = requestGroupOrder.filter((key) => groups[key])\n const callConfig = `{ ${[...callArgs, 'signal: ctx.mcpReq.signal', 'throwOnError: true'].join(', ')} }`\n const body = returnType === 'data' ? 'res' : 'res.data'\n\n const callToolResult = `return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(${body})\n }\n ],\n structuredContent: { data: ${body} }\n}`\n\n return (\n <File.Source name={name} isExportable isIndexable>\n <Function\n name={name}\n async\n export\n params={paramsSignature}\n JSDoc={{\n comments: buildOperationComments(node),\n }}\n returnType={'CallToolResult'}\n >\n {`const res = await ${clientName}(${callConfig})`}\n <br />\n {callToolResult}\n </Function>\n </File.Source>\n )\n}\n","import type { ast } from 'kubb/kit'\nimport { Const, File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype ZodParam = {\n name: string\n schemaName: string\n}\n\n/**\n * Composes individual param schemas into `z.object({ ... })`.\n */\nconst zodObject = (params: Array<ZodParam>) => `z.object({ ${params.map((p) => `${JSON.stringify(p.name)}: ${p.schemaName}`).join(', ')} })`\n\ntype Props = {\n /**\n * Human-readable server name passed to `new McpServer({ name })`.\n */\n serverName: string\n /**\n * Semantic version string passed to `new McpServer({ version })`.\n */\n serverVersion: string\n /**\n * Operations to register as MCP tools, each carrying its handler,\n * zod schema, and AST node metadata.\n */\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: ast.FileNode\n }\n zod: {\n pathParams: Array<ZodParam>\n /**\n * Query params — individual schemas to compose into `z.object({ ... })`.\n */\n queryParams?: Array<ZodParam> | null\n /**\n * Header params — individual schemas to compose into `z.object({ ... })`.\n */\n headerParams?: Array<ZodParam> | null\n requestName?: string | null\n responseName?: string | null\n }\n }>\n}\n\nexport function Server({ serverName, serverVersion, operations }: Props): KubbReactNode {\n const registrations = operations\n .map(({ tool, mcp, zod }) => {\n // Group params into the same `{ path, query, headers, body }` shape the contract `<op>`\n // expects, so the MCP tool input mirrors every other client consumer.\n const entries: Array<{ key: string; value: string }> = []\n\n if (zod.pathParams.length) {\n entries.push({ key: 'path', value: zodObject(zod.pathParams) })\n }\n\n if (zod.queryParams) {\n entries.push({ key: 'query', value: zodObject(zod.queryParams) })\n }\n\n if (zod.headerParams) {\n entries.push({ key: 'headers', value: zodObject(zod.headerParams) })\n }\n\n if (zod.requestName) {\n entries.push({ key: 'body', value: zod.requestName })\n }\n\n const destructured = `{ ${entries.map((e) => e.key).join(', ')} }`\n const inputSchema = entries.length ? `z.object({ ${entries.map((e) => `${e.key}: ${e.value}`).join(', ')} })` : null\n const outputSchema = zod.responseName\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: z.object({ data: ${outputSchema} })` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (inputSchema) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${inputSchema},\n}, async (${destructured}, ctx) => {\n return ${mcp.name}(${destructured}, ctx)\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async (ctx) => {\n return ${mcp.name}(ctx)\n})\n `\n })\n .filter(Boolean)\n .join('\\n')\n\n return (\n <>\n <File.Source name=\"getServer\" isExportable isIndexable>\n <Function name=\"getServer\" export>\n {`const server = new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n${registrations}\nreturn server`}\n </Function>\n </File.Source>\n\n <File.Source name=\"server\" isExportable isIndexable>\n <Const name={'server'} export>\n {'getServer()'}\n </Const>\n </File.Source>\n\n <File.Source name=\"startServer\" isExportable isIndexable>\n <Function name=\"startServer\" async export>\n {`return serveStdio(getServer, {\n onerror: (error) => console.error('MCP server error:', error),\n })`}\n </Function>\n </File.Source>\n </>\n )\n}\n","/**\n * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an\n * operation, shared so the selection rules and diagnostics stay in one place.\n *\n * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered\n * contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own\n * inline client:\n *\n * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer\n * imports and calls them.\n * - `error` — no client plugin is registered, several are registered without a selector, the\n * requested one is missing, or `client` is not a known selector.\n *\n * The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a\n * lone registered contract client plugin is picked up automatically.\n */\n\nimport { Diagnostics } from 'kubb/kit'\n\n// Canonical plugin names. They mirror the `pluginFetchName` / `pluginAxiosName` / `pluginClientName`\n// consts the plugins export, kept as literals so this internal needs no plugin install deps.\nconst pluginFetchName = 'plugin-fetch'\nconst pluginAxiosName = 'plugin-axios'\nconst pluginClientName = 'plugin-client'\n\n/**\n * The client selector accepted by a consumer's `client` option. Each calls a registered contract\n * client plugin.\n */\nexport type ClientSelector = 'fetch' | 'axios' | 'client'\n\n/**\n * The resolved client strategy stored in a consumer plugin's options: the generated code always\n * imports and calls a registered contract client plugin's `<op>`. The client runtime lives in\n * plugin-axios / plugin-fetch, so nothing is bundled by the consumer.\n */\nexport type ResolvedContractClient = { kind: 'contract'; pluginName: string }\n\n/**\n * The outcome of {@link resolveClient}.\n *\n * - `contract` names the contract client plugin whose `<op>` functions the consumer imports.\n * - `error` carries a setup diagnostic: its code, what is wrong, and how to fix it.\n */\nexport type ResolveClientResult =\n | ResolvedContractClient\n | { kind: 'error'; code: typeof Diagnostics.code.missingDependency | typeof Diagnostics.code.invalidPluginOptions; message: string; help: string }\n\nconst selectorToPlugin: Record<ClientSelector, string> = {\n fetch: pluginFetchName,\n axios: pluginAxiosName,\n client: pluginClientName,\n}\n\n// Every contract client plugin, in auto-detect priority order.\nconst contractPlugins = [pluginFetchName, pluginAxiosName, pluginClientName] as const\n\n/**\n * Applies the `client` resolution rules. See the module comment for the strategy shape.\n *\n * @example\n * ```ts\n * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })\n * // { kind: 'contract', pluginName: 'plugin-fetch' }\n * ```\n *\n * @example\n * ```ts\n * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })\n * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }\n * ```\n */\nexport function resolveClient(options: { client: ClientSelector | undefined; pluginNames: ReadonlyArray<string> }): ResolveClientResult {\n const { client, pluginNames } = options\n const has = (name: string) => pluginNames.includes(name)\n\n if (client === 'fetch' || client === 'axios' || client === 'client') {\n const pluginName = selectorToPlugin[client]\n if (!has(pluginName)) {\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: `\\`client: '${client}'\\` is set but \\`@kubb/plugin-${client}\\` is not registered in \\`plugins\\`.`,\n help: `Add \\`@kubb/plugin-${client}\\` to \\`plugins\\`, or drop \\`client\\` to use a different client plugin.`,\n }\n }\n return { kind: 'contract', pluginName }\n }\n\n // A JS config bypasses the `ClientSelector` type, so reject unknown selectors instead of auto-detecting.\n if (client !== undefined) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Option \\`client\\` is ${typeof client === 'string' ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,\n help: 'Set `client` to one of those values, or drop it to use the registered client plugin.',\n }\n }\n\n // `client` unset: auto-detect a lone registered contract client plugin.\n const registered = contractPlugins.filter(has)\n if (registered.length === 1) {\n return { kind: 'contract', pluginName: registered[0]! }\n }\n if (registered.length > 1) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Multiple client plugins are registered (${registered.map((name) => `\\`@kubb/${name}\\``).join(', ')}) and \\`client\\` is not set.`,\n help: \"Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin.\",\n }\n }\n\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: 'No client plugin is registered.',\n help: 'Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call.',\n }\n}\n\n/**\n * Resolves the contract client during a consumer plugin's setup hook.\n * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.\n * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer\n * fails fast with the same message.\n */\nexport function resolveContractClient(options: {\n plugin: string\n client: ClientSelector | undefined\n plugins?: ReadonlyArray<unknown>\n}): ResolvedContractClient {\n const { plugin, client, plugins = [] } = options\n const pluginNames = plugins.map((plugin) => (plugin as { name?: string }).name).filter((name): name is string => Boolean(name))\n const resolved = resolveClient({ client, pluginNames })\n if (resolved.kind === 'error') {\n const { code, message, help } = resolved\n throw new Diagnostics.Error({ code, severity: 'error', message, help, location: { kind: 'config' }, plugin })\n }\n return resolved\n}\n","import path from 'node:path'\nimport { operationFileEntry } from '@internals/shared'\nimport type { ast, Exclude, Group, Include, NodeCache, Output, Override, Resolver } from 'kubb/kit'\nimport type { ReturnTypeOption } from './types.ts'\n\n/**\n * The resolved contract `<op>` for one operation: the generated function name, the file it lives in,\n * the client module path (where `RequestConfig` / `ResponseErrorConfig` come from), and the\n * registered client plugin's `returnType`.\n *\n * `clientPath` is the absolute `.kubb/client.ts` path for plugin-fetch / plugin-axios, or\n * plugin-client's `importPath`: a relative one is resolved against the `<op>` file to an absolute\n * path, a package name or alias is kept verbatim. `clientPathIsFile` tells a consumer whether to\n * make it relative to the importing file.\n */\nexport type ClientOperation = { name: string; path: string; clientPath: string; clientPathIsFile: boolean; returnType: ReturnTypeOption }\n\n/**\n * The client plugin options a dependent reads, including the filters that scope them per operation.\n */\ntype ClientPluginOptions = {\n output?: Output\n group?: Group | null\n returnType?: ReturnTypeOption\n importPath?: string\n exclude?: Array<Exclude>\n include?: Array<Include>\n override?: Array<Override<Omit<ClientPluginOptions, 'override'>>>\n}\n\nfunction isRelativeImport(importPath: string): boolean {\n return importPath.startsWith('.')\n}\n\n// plugin-client resolves a relative `importPath` from its `<op>` file, so do the same here.\nfunction resolveImportPath(options: { importPath: string; operationFile: string }): string {\n const { importPath, operationFile } = options\n return isRelativeImport(importPath) ? path.resolve(path.dirname(operationFile), importPath) : importPath\n}\n\n/**\n * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up\n * the registered contract client plugin's resolver and output. Works for any contract client plugin\n * (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline\n * path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then\n * emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global\n * output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.\n * With plugin-client they come from the user's `importPath` module instead.\n *\n * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,\n * so several dependents reading the same client plugin for one operation in a single pass\n * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share\n * one computed result instead of each re-deriving the name and path.\n *\n * `returnType`, `output`, and `group` are the client plugin's options for this operation, after its\n * `override` entries, the same resolution its own generator sees. A dependent's generated call body\n * and import path therefore match the `<op>` actually emitted, even when an `override` changes it.\n */\nexport function resolveClientOperation(options: {\n clientPlugin: { pluginName: string } | null\n driver: {\n getPlugin: (name: string) => { options?: ClientPluginOptions } | undefined\n getResolver: (name: string) => Resolver\n }\n node: ast.OperationNode\n root: string\n output: Output\n cache: NodeCache\n}): ClientOperation | null {\n const { clientPlugin, driver, node, root, output, cache } = options\n if (!clientPlugin) return null\n\n return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {\n const resolver = driver.getResolver(clientPlugin.pluginName)\n const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {}\n const { exclude, include, override } = pluginOptions\n const hasOperationOptions = Boolean(exclude?.length || include?.length || override?.length)\n // Kubb's resolver always has `default`; the fallback keeps partial or custom resolvers working.\n const operationOptions =\n hasOperationOptions && resolver.default ? resolver.default.options(node, { options: pluginOptions, exclude, include, override }) : pluginOptions\n if (!operationOptions) return null\n\n const file = resolver.file({\n ...operationFileEntry(node, node.operationId),\n root,\n output: operationOptions.output ?? output,\n group: operationOptions.group ?? undefined,\n })\n\n const { importPath } = operationOptions\n\n return {\n name: resolver.name(node.operationId),\n path: file.path,\n clientPath: importPath === undefined ? path.resolve(root, '.kubb/client.ts') : resolveImportPath({ importPath, operationFile: file.path }),\n clientPathIsFile: importPath === undefined || isRelativeImport(importPath),\n returnType: operationOptions.returnType ?? 'full',\n }\n })\n}\n","import { resolveClientOperation } from '@internals/client'\nimport { operationFileEntry, resolveDependencyOperationFile } from '@internals/shared'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { McpHandler } from '../components/McpHandler.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool\n * handler per OpenAPI operation. The handler takes the grouped `{ path, query,\n * headers, body }` config and forwards it to the registered client plugin's\n * (`@kubb/plugin-axios` / `@kubb/plugin-fetch`) `<op>` function.\n */\nexport const mcpGenerator = defineGenerator<PluginMcp>({\n name: 'mcp',\n renderer: jsxRenderer,\n operation(node, ctx) {\n if (!ast.isHttpOperationNode(node)) return null\n const { resolver, driver, root, config } = ctx\n const { output, client, group } = ctx.options\n\n const pluginTs = ctx.requirePlugin(pluginTsName)\n\n const tsResolver = driver.getResolver(pluginTsName)\n\n // The registered contract client plugin owns the `<op>` the handler imports and calls.\n const contractOp = resolveClientOperation({ clientPlugin: { pluginName: client.pluginName }, driver, node, root, output, cache: ctx.cache })\n if (!contractOp) {\n return null\n }\n\n // The handler signature references the grouped `<Name>Options`.\n const optionsName = tsResolver.response.options(node)\n\n const meta = {\n name: resolver.handler.name(node),\n file: resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n fileTs: resolveDependencyOperationFile({\n cache: ctx.cache,\n node,\n resolver: tsResolver,\n root,\n output: pluginTs.options?.output ?? output,\n group: pluginTs.options?.group,\n }),\n } as const\n\n return (\n <File\n baseName={meta.file.baseName}\n path={meta.file.path}\n meta={meta.file.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n >\n {meta.fileTs && optionsName && <File.Import name={[optionsName]} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}\n <File.Import name={['CallToolResult', 'ServerContext']} path={'@modelcontextprotocol/server'} isTypeOnly />\n\n <File.Import name={[contractOp.name]} root={meta.file.path} path={contractOp.path} />\n\n <McpHandler name={meta.name} clientName={contractOp.name} node={node} resolver={tsResolver} returnType={contractOp.returnType} />\n </File>\n )\n },\n})\n","import path from 'node:path'\nimport { getOperationParameters, getPrimarySuccessResponse, operationFileEntry } from '@internals/shared'\nimport { getRelativePath } from '@internals/utils'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { Server } from '../components/Server.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default v5 server generator for `@kubb/plugin-mcp`.\n *\n * Uses individual zod schemas for each param (e.g. `createPetsPathUuidSchema`, `createPetsQueryOffsetSchema`)\n * and `resolveResponseStatusName` for per-status response schemas.\n * Query and header params are composed into `z.object({ ... })` from individual schemas.\n */\nexport const serverGenerator = defineGenerator<PluginMcp>({\n name: 'operations',\n renderer: jsxRenderer,\n operations(nodes, ctx) {\n const { config, resolver, plugin, driver, root } = ctx\n const { output, group } = ctx.options\n\n const pluginZod = ctx.requirePlugin(pluginZodName)\n\n const zodResolver = driver.getResolver(pluginZodName)\n\n const fileAt = <TName extends `${string}.${string}`>(baseName: TName) => ({\n baseName,\n path: path.resolve(root, output.path, baseName),\n meta: { pluginName: plugin.name },\n })\n const serverFile = fileAt('server.ts')\n const startFile = fileAt('start.ts')\n const jsonFile = fileAt('.mcp.json')\n\n // MCP clients spawn the command from their own working directory, usually the project root,\n // so `args` points at `start.ts` relative to `config.root` instead of the `.mcp.json` folder.\n const mcpConfig = {\n mcpServers: {\n [ctx.meta.title || 'server']: {\n type: 'stdio',\n command: 'npx',\n args: ['tsx', getRelativePath(path.resolve(config.root), startFile.path)],\n },\n },\n }\n\n const operationsMapped = nodes.filter(ast.isHttpOperationNode).map((node) => {\n const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node)\n\n const fileEntry = operationFileEntry(node, node.operationId)\n const mcpFile = resolver.file({ ...fileEntry, root, output, group: group ?? undefined })\n const zodFile = zodResolver.file({\n ...fileEntry,\n root,\n output: pluginZod.options?.output ?? output,\n group: pluginZod.options?.group ?? undefined,\n })\n\n const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null\n const successStatus = getPrimarySuccessResponse(node)?.statusCode\n const responseName = successStatus ? zodResolver.response.status(node, successStatus) : null\n\n const resolveParams = (params: typeof pathParams) => params.map((p) => ({ name: p.name, schemaName: zodResolver.param.name(node, p) }))\n\n return {\n tool: {\n name: node.operationId,\n title: node.summary || undefined,\n description: node.description || `Make a ${node.method.toUpperCase()} request to ${node.path}`,\n },\n mcp: {\n name: resolver.handler.name(node),\n file: mcpFile,\n },\n zod: {\n pathParams: resolveParams(pathParams),\n queryParams: queryParams.length ? resolveParams(queryParams) : null,\n headerParams: headerParams.length ? resolveParams(headerParams) : null,\n requestName,\n responseName,\n file: zodFile,\n },\n }\n })\n\n const imports = operationsMapped.flatMap(({ mcp, zod }) => {\n const zodNames = [\n ...zod.pathParams.map((p) => p.schemaName),\n ...(zod.queryParams ?? []).map((p) => p.schemaName),\n ...(zod.headerParams ?? []).map((p) => p.schemaName),\n zod.requestName,\n zod.responseName,\n ].filter((name): name is string => Boolean(name))\n\n const uniqueNames = [...new Set(zodNames)].sort()\n\n return [\n <File.Import key={mcp.name} name={[mcp.name]} root={serverFile.path} path={mcp.file.path} />,\n uniqueNames.length > 0 && <File.Import key={`zod-${mcp.name}`} name={uniqueNames} root={serverFile.path} path={zod.file.path} />,\n ].filter(Boolean)\n })\n\n return (\n <>\n <File\n baseName={serverFile.baseName}\n path={serverFile.path}\n meta={serverFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n >\n <File.Import name={['McpServer']} path={'@modelcontextprotocol/server'} />\n <File.Import name={['serveStdio']} path={'@modelcontextprotocol/server/stdio'} />\n <File.Import name={['z']} path={'zod'} />\n\n {imports}\n <Server serverName={ctx.meta.title ?? 'server'} serverVersion={ctx.meta.version ?? '0.0.0'} operations={operationsMapped} />\n </File>\n\n <File\n baseName={startFile.baseName}\n path={startFile.path}\n meta={startFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n >\n <File.Import name={['startServer']} root={startFile.path} path={serverFile.path} />\n {/* Not indexable: barrels must not re-export this entry, importing it starts the server. */}\n <File.Source name=\"start\">{'void startServer()'}</File.Source>\n </File>\n\n <File baseName={jsonFile.baseName} path={jsonFile.path} meta={jsonFile.meta}>\n <File.Source name=\"server\">{`${JSON.stringify(mcpConfig, null, 2)}\\n`}</File.Source>\n </File>\n </>\n )\n },\n})\n","","","import { camelCase } from '@internals/utils'\nimport { createResolver } from 'kubb/kit'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-mcp`. Decides the names and file\n * paths for every generated MCP tool handler. Function names get a `Handler`\n * suffix so an operation `addPet` becomes `addPetHandler`.\n *\n * @example Resolve a handler name\n * ```ts\n * import { resolverMcp } from '@kubb/plugin-mcp'\n *\n * resolverMcp.name('addPet') // 'addPetHandler'\n * ```\n */\nexport const resolverMcp = createResolver<PluginMcp>({\n pluginName: 'plugin-mcp',\n name(name) {\n return camelCase(name, { suffix: 'handler' })\n },\n handler: {\n name(node) {\n return this.name(node.operationId)\n },\n },\n})\n","import { createGroupConfig } from '@internals/shared'\n\nimport { resolveContractClient } from '@internals/client'\nimport { addGenerator, defineExtension, Resolver, setMacros, setResolver, useConfig } from 'kubb/kit'\nimport { compatibility } from '../kubb-extension.json'\nimport { version } from '../package.json'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { mcpGenerator } from './generators/mcpGenerator.tsx'\nimport { serverGenerator } from './generators/serverGenerator.tsx'\nimport { resolverMcp } from './resolvers/resolverMcp.ts'\nimport type { PluginMcp, ResolverMcp } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginMcpName = 'plugin-mcp' satisfies PluginMcp['name']\n\n/**\n * Generates a Model Context Protocol (MCP) server from an OpenAPI spec. Every\n * operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude\n * Code, MCP-compatible clients) can call directly. Each handler calls a contract\n * client `<op>` from a registered `@kubb/plugin-axios` or `@kubb/plugin-fetch`.\n * Next to the handlers it writes `server.ts`, a `start.ts` entry that serves the\n * tools over stdio, and a `.mcp.json` that runs `start.ts` with `tsx`.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb/config'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginZod } from '@kubb/plugin-zod'\n * import { pluginFetch } from '@kubb/plugin-fetch'\n * import { pluginMcp } from '@kubb/plugin-mcp'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginZod(),\n * pluginFetch({ baseURL: 'https://petstore.swagger.io/v2' }),\n * pluginMcp({ output: { path: 'mcp' } }),\n * ],\n * })\n * ```\n */\nexport const pluginMcp = defineExtension<PluginMcp>({\n kind: 'plugin',\n meta: { name: pluginMcpName, version, compatibility },\n dependencies: { [pluginTsName]: {}, [pluginZodName]: {} },\n setup(options) {\n const {\n output = { path: 'mcp', barrel: { type: 'named' } },\n group,\n exclude = [],\n include,\n override = [],\n client,\n resolver: userResolver,\n macros: userMacros,\n } = options\n\n const resolver = userResolver ? Resolver.merge<ResolverMcp>(resolverMcp, userResolver) : resolverMcp\n\n setResolver(resolver)\n if (userMacros?.length) {\n setMacros(userMacros)\n }\n addGenerator(mcpGenerator, serverGenerator)\n\n return {\n output,\n exclude,\n include,\n override,\n group: createGroupConfig(group),\n client: resolveContractClient({ plugin: pluginMcpName, client, plugins: useConfig().plugins }),\n resolver,\n }\n },\n})\n\nexport default pluginMcp\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,SAAgB,mBAAmB,MAAyB,MAAc,UAAyC,OAA2B;CAC5I,OAAO;EACL;EACA;EACA,KAAK,KAAK,KAAK,MAAM;EACrB,MAAM,KAAK;CACb;AACF;;;;;;;;;;;;AAaA,SAAgB,+BAA+B,SAO9B;CACf,MAAM,EAAE,OAAO,MAAM,UAAU,MAAM,QAAQ,UAAU;CAEvD,OAAO,MAAM,WAAW,GAAG,SAAS,WAAW,uBAC7C,SAAS,KAAK;EAAE,GAAG,mBAAmB,MAAM,KAAK,WAAW;EAAG;EAAM;EAAQ,OAAO,SAAS,KAAA;CAAU,CAAC,CAC1G;AACF;AA8DA,SAAS,iBAAiB,MAAyB,MAA2C;CAC5F,IAAI,CAAC,MACH,OAAO;CAGT,IAAI,OAAO,SAAS,YAClB,OAAO,KAAK,IAAI,KAAK;CAGvB,OAAO,KAAK,OAAO,UAAUA,SAAAA,IAAI,OAAO,KAAK,IAAI,EAAE,KAAK;AAC1D;;;;;AAMA,SAAS,qBAAqB,cAAyC;CACrE,MAAM,yBAAyB,aAAa,SAAS;CAErD,OAAO;EACL;EACA;EACA,kBAAkB,yBAAyB,aAAa,KAAK,OAAO,KAAK,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI;EACtG,oBAAoB,aAAa,MAAM;EACvC,aAAa,aAAa,MAAM,OAAO,OAAO,qBAAqB;CACrE;AACF;AAEA,SAAgB,mBAAmB,MAA0C;CAC3E,OAAO,qBAAqB,KAAK,aAAa,SAAS,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC,CAAC;AACxF;;;;;AAMA,SAAgB,2BAA2B,MAA0C;CACnF,OAAO,qBAAqB,0BAA0B,IAAI,CAAC,EAAE,SAAS,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC,CAAC;AACvG;AAkGA,MAAM,wBAAwB;AAE9B,SAAgB,uBAAuB,MAAiC;CACtE,MAAM,UAAU,mBAAmB,IAAI;CACvC,MAAM,WAAW,2BAA2B,IAAI;CAIhD,MAAM,UAAU,CACd,QAAQ,yBAAyB,aAAa,QAAQ,qBAAqB,MAC3E,SAAS,yBAAyB,cAAc,SAAS,qBAAqB,IAChF,CAAC,CAAC,OAAO,OAAO;CAEhB,OAAO,QAAQ,SAAS,GAAG,sBAAsB,uBAAuB,QAAQ,KAAK,IAAI,EAAE,QAAQ;AACrG;;;;AAsBA,SAAgB,iBAAiB,MAAwC;CACvE,MAAM,EAAE,MAAM,OAAO,WAAW,uBAAuB,IAAI;CAC3D,OAAO;EACL,MAAM,KAAK,SAAS;EACpB,OAAO,MAAM,SAAS;EACtB,MAAM,QAAQ,KAAK,aAAa,UAAU,EAAE,EAAE,MAAM;EACpD,SAAS,OAAO,SAAS;CAC3B;AACF;;;;;;AAmBA,SAAgB,2BAA2B,MAAkD;CAC3F,MAAM,SAAS,iBAAiB,IAAI;CACpC,MAAM,EAAE,MAAM,OAAO,WAAW,uBAAuB,IAAI;CAC3D,MAAM,kBAAkB,KAAK,MAAM,UAAU,MAAM,QAAQ;CAC3D,MAAM,mBAAmB,MAAM,MAAM,UAAU,MAAM,QAAQ;CAC7D,MAAM,oBAAoB,OAAO,MAAM,UAAU,MAAM,QAAQ;CAE/D,OAAO;EACL;EACA;EACA;EACA;EACA,YAAY,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,OAAO;CACrF;AACF;;;;;;;AAcA,SAAgB,4BACd,MACA,UACA,UAAwC,CAAC,GACK;CAC9C,MAAM,EAAE,iBAAiB,SAAS;CAClC,MAAM,EAAE,QAAQ,eAAe,2BAA2B,IAAI;CAE9D,MAAM,QAAS;EAAC;EAAQ;EAAS;EAAQ;CAAS,CAAC,CAAW,QAAQ,QAAQ,OAAO,IAAI;CAKzF,OAAO;EACL,WAAW,CAJM,MAAM,SAAS,IAAI,KAAK,MAAM,KAAK,IAAI,EAAE,MAAM,SAAS,SAAS,QAAQ,IAAI,IAAI,aAAa,UAAU,OAAO,MAC9G,iBAAiB,WAAW,uBAAuB,IAAI,EAAE,SAAS,IAGjD,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI;EAC9D;CACF;AACF;AAEA,SAAgB,uBAAuB,MAAyB,UAAyC,CAAC,GAAkB;CAC1H,MAAM,EAAE,OAAO,gBAAgB,eAAe,mBAAmB,aAAa,UAAU;CACxF,MAAM,cAAc,iBAAiB,MAAM,IAAI;CAM/C,MAAM,oBAJJ,iBAAiB,qBACb;EAAC,KAAK,eAAe,gBAAgB,KAAK;EAAe,KAAK,WAAW,YAAY,KAAK;EAAW;EAAa,KAAK,cAAc;CAAa,IAClJ;EAAC,KAAK,eAAe,gBAAgB,KAAK;EAAe,KAAK,WAAW,YAAY,KAAK;EAAW,KAAK,cAAc;EAAe;CAAW,EAAA,CAEtH,QAAQ,YAA+B,QAAQ,OAAO,CAAC;CAEzF,IAAI,CAAC,YACH,OAAO;CAGT,OAAO,iBAAiB,SAAS,SAAS,KAAK,MAAM,OAAO,CAAC,CAAC,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,YAA+B,QAAQ,OAAO,CAAC;AACnJ;AAEA,MAAM,iDAAiC,IAAI,QAAqD;;;;;;;AAQhG,SAAgB,uBAAuB,MAAmD;CACxF,MAAM,SAAS,+BAA+B,IAAI,IAAI;CACtD,IAAI,QAAQ,OAAO;CAKnB,MAAM,SAAS,aAAsC;EACnD,MAAM,uBAAO,IAAI,IAAY;EAE7B,OAAO,KAAK,WAAW,QAAQ,UAAU;GACvC,IAAI,MAAM,OAAO,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,OAAO;GAC1D,KAAK,IAAI,MAAM,IAAI;GACnB,OAAO;EACT,CAAC;CACH;CAEA,MAAM,SAAmC;EAAE,MAAM,MAAM,MAAM;EAAG,OAAO,MAAM,OAAO;EAAG,QAAQ,MAAM,QAAQ;EAAG,QAAQ,MAAM,QAAQ;CAAE;CAExI,+BAA+B,IAAI,MAAM,MAAM;CAC/C,OAAO;AACT;AA2GA,SAAgB,oBAAoB,YAA6D;CAC/F,MAAM,OAAO,OAAO,UAAU;CAE9B,OAAO,OAAO,MAAM,IAAI,IAAI,OAAO;AACrC;AAEA,SAAgB,oBAAoB,YAAuD;CACzF,MAAM,OAAO,oBAAoB,UAAU;CAE3C,OAAO,SAAS,QAAQ,QAAQ,OAAO,OAAO;AAChD;AAQA,SAAgB,oBAAoD,WAAuD;CACzH,OAAO,UAAU,QAAQ,aAAa,oBAAoB,SAAS,UAAU,CAAC;AAChF;AAEA,SAAgB,6BAA6B,MAAkD;CAC7F,OAAO,oBAAoB,KAAK,SAAS;AAC3C;AAEA,SAAgB,0BAA0B,MAAkD;CAC1F,OAAO,6BAA6B,IAAI,CAAC,CAAC,MAAM;AAClD;;;;;;;;;;ACrgBA,SAAS,QAAQ,MAAc,QAAyB;CACtD,OAAO,KACJ,KAAK,CAAC,CACN,QAAQ,qBAAqB,OAAO,CAAC,CACrC,QAAQ,yBAAyB,OAAO,CAAC,CACzC,QAAQ,gBAAgB,OAAO,CAAC,CAChC,MAAM,eAAe,CAAC,CACtB,OAAO,OAAO,CAAC,CACf,KAAK,MAAM,MAAM;EAChB,IAAI,KAAK,SAAS,KAAK,SAAS,KAAK,YAAY,GAAG,OAAO;EAE3D,QADa,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,KAC9E,KAAK,MAAM,CAAC;CAC5B,CAAC,CAAC,CACD,KAAK,EAAE,CAAC,CACR,QAAQ,iBAAiB,EAAE;AAChC;AAIA,MAAM,wBAAQ,IAAI,IAAoB;AACtC,MAAM,aAAa;AAEnB,SAAS,gBAAgB,MAAc,QAAyB;CAC9D,MAAM,MAAM,GAAG,SAAS,MAAM,MAAM;CACpC,MAAM,SAAS,MAAM,IAAI,GAAG;CAC5B,IAAI,WAAW,KAAA,GAAW,OAAO;CAEjC,MAAM,SAAS,QAAQ,MAAM,MAAM;CACnC,IAAI,MAAM,QAAQ,YAAY,MAAM,MAAM;CAC1C,MAAM,IAAI,KAAK,MAAM;CACrB,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,UAAU,MAAc,EAAE,SAAS,IAAI,SAAS,OAAgB,CAAC,GAAW;CAC1F,OAAO,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,KAAK;AAC7D;;;AC3DA,SAAS,QAAQ,GAAmB;CAClC,IAAI,EAAE,WAAW,SAAS,GAAG,OAAO;CACpC,OAAO,EAAE,WAAW,MAAM,GAAG;AAC/B;;;;;;;;;;;AAYA,SAAgB,gBAAgB,SAAiB,UAA0B;CACzE,MAAM,eAAeC,UAAAA,MAAM,SAAS,QAAQ,OAAO,GAAG,QAAQ,QAAQ,CAAC;CAEvE,OAAO,aAAa,WAAW,KAAK,IAAI,eAAe,KAAK;AAC9D;;;;;;;;;;;;;;;;;;;;;ACDA,SAAgB,kBAAkB,OAAwC;CACxE,IAAI,CAAC,OACH,OAAO;CAGT,MAAM,eAAe,QAAmC;EACtD,IAAI,MAAM,SAAS,QACjB,OAAO,GAAG,IAAI,MAAM,MAAM,GAAG,CAAC,CAAC;EAGjC,OAAO,UAAU,IAAI,KAAK;CAC5B;CAEA,OAAO;EACL,GAAG;EACH,MAAM,MAAM,OAAO,MAAM,OAAO;CAClC;AACF;;;ACTA,MAAM,oBAAoB;CAAC;CAAQ;CAAS;CAAW;AAAM;AAE7D,SAAgB,WAAW,EAAE,MAAM,YAAY,MAAM,UAAU,aAAa,UAAgC;CAC1G,MAAM,EAAE,WAAW,WAAW,4BAA4B,MAAM,UAAU,EAAE,gBAAgB,MAAM,CAAC;CACnG,MAAM,kBAAkB,CAAC,WAAW,oBAAoB,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,IAAI;CAKnF,MAAM,aAAa,KAAK;EAAC,GADR,kBAAkB,QAAQ,QAAQ,OAAO,IACvB;EAAG;EAA6B;CAAoB,CAAC,CAAC,KAAK,IAAI,EAAE;CACpG,MAAM,OAAO,eAAe,SAAS,QAAQ;CAE7C,MAAM,iBAAiB;;;;6BAII,KAAK;;;+BAGH,KAAK;;CAGlC,OACE,iBAAA,GAAA,qBAAA,IAAA,CAACC,SAAAA,KAAK,QAAN;EAAmB;EAAM,cAAA;EAAa,aAAA;EACpC,UAAA,iBAAA,GAAA,qBAAA,KAAA,CAACC,SAAAA,UAAD;GACQ;GACN,OAAA;GACA,QAAA;GACA,QAAQ;GACR,OAAO,EACL,UAAU,uBAAuB,IAAI,EACvC;GACA,YAAY;GARd,UAAA;IAUG,qBAAqB,WAAW,GAAG,WAAW;IAC/C,iBAAA,GAAA,qBAAA,IAAA,CAAC,MAAD,CAAK,CAAA;IACJ;GACO;;CACC,CAAA;AAEjB;;;;;;ACzDA,MAAM,aAAa,WAA4B,cAAc,OAAO,KAAK,MAAM,GAAG,KAAK,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,KAAK,IAAI,EAAE;AAyCxI,SAAgB,OAAO,EAAE,YAAY,eAAe,cAAoC;CACtF,MAAM,gBAAgB,WACnB,KAAK,EAAE,MAAM,KAAK,UAAU;EAG3B,MAAM,UAAiD,CAAC;EAExD,IAAI,IAAI,WAAW,QACjB,QAAQ,KAAK;GAAE,KAAK;GAAQ,OAAO,UAAU,IAAI,UAAU;EAAE,CAAC;EAGhE,IAAI,IAAI,aACN,QAAQ,KAAK;GAAE,KAAK;GAAS,OAAO,UAAU,IAAI,WAAW;EAAE,CAAC;EAGlE,IAAI,IAAI,cACN,QAAQ,KAAK;GAAE,KAAK;GAAW,OAAO,UAAU,IAAI,YAAY;EAAE,CAAC;EAGrE,IAAI,IAAI,aACN,QAAQ,KAAK;GAAE,KAAK;GAAQ,OAAO,IAAI;EAAY,CAAC;EAGtD,MAAM,eAAe,KAAK,QAAQ,KAAK,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;EAC/D,MAAM,cAAc,QAAQ,SAAS,cAAc,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,OAAO;EAChH,MAAM,eAAe,IAAI;EAEzB,MAAM,SAAS;GACb,KAAK,QAAQ,UAAU,KAAK,UAAU,KAAK,KAAK,MAAM;GACtD,gBAAgB,KAAK,UAAU,KAAK,WAAW;GAC/C,eAAe,kCAAkC,aAAa,OAAO;EACvE,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,OAAO;EAEf,IAAI,aACF,OAAO;sBACO,KAAK,UAAU,KAAK,IAAI,EAAE;IAC5C,OAAO;iBACM,YAAY;YACjB,aAAa;WACd,IAAI,KAAK,GAAG,aAAa;;;EAK9B,OAAO;sBACS,KAAK,UAAU,KAAK,IAAI,EAAE;IAC5C,OAAO;;WAEA,IAAI,KAAK;;;CAGhB,CAAC,CAAC,CACD,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;CAEZ,OACE,iBAAA,GAAA,qBAAA,KAAA,CAAA,qBAAA,UAAA,EAAA,UAAA;EACE,iBAAA,GAAA,qBAAA,IAAA,CAACC,SAAAA,KAAK,QAAN;GAAa,MAAK;GAAY,cAAA;GAAa,aAAA;GACzC,UAAA,iBAAA,GAAA,qBAAA,IAAA,CAACC,SAAAA,UAAD;IAAU,MAAK;IAAY,QAAA;IACxB,UAAA;WACA,WAAW;cACR,cAAc;;EAE1B,cAAc;;GAEE,CAAA;EACC,CAAA;EAEb,iBAAA,GAAA,qBAAA,IAAA,CAACD,SAAAA,KAAK,QAAN;GAAa,MAAK;GAAS,cAAA;GAAa,aAAA;GACtC,UAAA,iBAAA,GAAA,qBAAA,IAAA,CAACE,SAAAA,OAAD;IAAO,MAAM;IAAU,QAAA;IACpB,UAAA;GACI,CAAA;EACI,CAAA;EAEb,iBAAA,GAAA,qBAAA,IAAA,CAACF,SAAAA,KAAK,QAAN;GAAa,MAAK;GAAc,cAAA;GAAa,aAAA;GAC3C,UAAA,iBAAA,GAAA,qBAAA,IAAA,CAACC,SAAAA,UAAD;IAAU,MAAK;IAAc,OAAA;IAAM,QAAA;IAChC,UAAA;;;GAGO,CAAA;EACC,CAAA;CACb,EAAA,CAAA;AAEN;;;;;;;;;;;;;;;;;;;ACrHA,MAAM,kBAAkB;AACxB,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AAyBzB,MAAM,mBAAmD;CACvD,OAAO;CACP,OAAO;CACP,QAAQ;AACV;AAGA,MAAM,kBAAkB;CAAC;CAAiB;CAAiB;AAAgB;;;;;;;;;;;;;;;;AAiB3E,SAAgB,cAAc,SAA0G;CACtI,MAAM,EAAE,QAAQ,gBAAgB;CAChC,MAAM,OAAO,SAAiB,YAAY,SAAS,IAAI;CAEvD,IAAI,WAAW,WAAW,WAAW,WAAW,WAAW,UAAU;EACnE,MAAM,aAAa,iBAAiB;EACpC,IAAI,CAAC,IAAI,UAAU,GACjB,OAAO;GACL,MAAM;GACN,MAAME,SAAAA,YAAY,KAAK;GACvB,SAAS,cAAc,OAAO,gCAAgC,OAAO;GACrE,MAAM,sBAAsB,OAAO;EACrC;EAEF,OAAO;GAAE,MAAM;GAAY;EAAW;CACxC;CAGA,IAAI,WAAW,KAAA,GACb,OAAO;EACL,MAAM;EACN,MAAMA,SAAAA,YAAY,KAAK;EACvB,SAAS,wBAAwB,OAAO,WAAW,WAAW,IAAI,OAAO,KAAK,OAAO,MAAM,EAAE;EAC7F,MAAM;CACR;CAIF,MAAM,aAAa,gBAAgB,OAAO,GAAG;CAC7C,IAAI,WAAW,WAAW,GACxB,OAAO;EAAE,MAAM;EAAY,YAAY,WAAW;CAAI;CAExD,IAAI,WAAW,SAAS,GACtB,OAAO;EACL,MAAM;EACN,MAAMA,SAAAA,YAAY,KAAK;EACvB,SAAS,2CAA2C,WAAW,KAAK,SAAS,WAAW,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;EAC7G,MAAM;CACR;CAGF,OAAO;EACL,MAAM;EACN,MAAMA,SAAAA,YAAY,KAAK;EACvB,SAAS;EACT,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,sBAAsB,SAIX;CACzB,MAAM,EAAE,QAAQ,QAAQ,UAAU,CAAC,MAAM;CAEzC,MAAM,WAAW,cAAc;EAAE;EAAQ,aADrB,QAAQ,KAAK,WAAY,OAA6B,IAAI,CAAC,CAAC,QAAQ,SAAyB,QAAQ,IAAI,CAC1E;CAAE,CAAC;CACtD,IAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,EAAE,MAAM,SAAS,SAAS;EAChC,MAAM,IAAIA,SAAAA,YAAY,MAAM;GAAE;GAAM,UAAU;GAAS;GAAS;GAAM,UAAU,EAAE,MAAM,SAAS;GAAG;EAAO,CAAC;CAC9G;CACA,OAAO;AACT;;;AC9GA,SAAS,iBAAiB,YAA6B;CACrD,OAAO,WAAW,WAAW,GAAG;AAClC;AAGA,SAAS,kBAAkB,SAAgE;CACzF,MAAM,EAAE,YAAY,kBAAkB;CACtC,OAAO,iBAAiB,UAAU,IAAIC,UAAAA,QAAK,QAAQA,UAAAA,QAAK,QAAQ,aAAa,GAAG,UAAU,IAAI;AAChG;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,uBAAuB,SAUZ;CACzB,MAAM,EAAE,cAAc,QAAQ,MAAM,MAAM,QAAQ,UAAU;CAC5D,IAAI,CAAC,cAAc,OAAO;CAE1B,OAAO,MAAM,WAAW,GAAG,aAAa,WAAW,yBAAyB;EAC1E,MAAM,WAAW,OAAO,YAAY,aAAa,UAAU;EAC3D,MAAM,gBAAgB,OAAO,UAAU,aAAa,UAAU,CAAC,EAAE,WAAW,CAAC;EAC7E,MAAM,EAAE,SAAS,SAAS,aAAa;EAGvC,MAAM,mBAFsB,QAAQ,SAAS,UAAU,SAAS,UAAU,UAAU,MAGhE,KAAK,SAAS,UAAU,SAAS,QAAQ,QAAQ,MAAM;GAAE,SAAS;GAAe;GAAS;GAAS;EAAS,CAAC,IAAI;EACrI,IAAI,CAAC,kBAAkB,OAAO;EAE9B,MAAM,OAAO,SAAS,KAAK;GACzB,GAAG,mBAAmB,MAAM,KAAK,WAAW;GAC5C;GACA,QAAQ,iBAAiB,UAAU;GACnC,OAAO,iBAAiB,SAAS,KAAA;EACnC,CAAC;EAED,MAAM,EAAE,eAAe;EAEvB,OAAO;GACL,MAAM,SAAS,KAAK,KAAK,WAAW;GACpC,MAAM,KAAK;GACX,YAAY,eAAe,KAAA,IAAYA,UAAAA,QAAK,QAAQ,MAAM,iBAAiB,IAAI,kBAAkB;IAAE;IAAY,eAAe,KAAK;GAAK,CAAC;GACzI,kBAAkB,eAAe,KAAA,KAAa,iBAAiB,UAAU;GACzE,YAAY,iBAAiB,cAAc;EAC7C;CACF,CAAC;AACH;;;;;;;;;ACrFA,MAAa,gBAAA,GAAeC,SAAAA,gBAAAA,CAA2B;CACrD,MAAM;CACN,UAAUC,SAAAA;CACV,UAAU,MAAM,KAAK;EACnB,IAAI,CAACC,SAAAA,IAAI,oBAAoB,IAAI,GAAG,OAAO;EAC3C,MAAM,EAAE,UAAU,QAAQ,MAAM,WAAW;EAC3C,MAAM,EAAE,QAAQ,QAAQ,UAAU,IAAI;EAEtC,MAAM,WAAW,IAAI,cAAcC,gBAAAA,YAAY;EAE/C,MAAM,aAAa,OAAO,YAAYA,gBAAAA,YAAY;EAGlD,MAAM,aAAa,uBAAuB;GAAE,cAAc,EAAE,YAAY,OAAO,WAAW;GAAG;GAAQ;GAAM;GAAM;GAAQ,OAAO,IAAI;EAAM,CAAC;EAC3I,IAAI,CAAC,YACH,OAAO;EAIT,MAAM,cAAc,WAAW,SAAS,QAAQ,IAAI;EAEpD,MAAM,OAAO;GACX,MAAM,SAAS,QAAQ,KAAK,IAAI;GAChC,MAAM,SAAS,KAAK;IAAE,GAAG,mBAAmB,MAAM,KAAK,WAAW;IAAG;IAAM;IAAQ,OAAO,SAAS,KAAA;GAAU,CAAC;GAC9G,QAAQ,+BAA+B;IACrC,OAAO,IAAI;IACX;IACA,UAAU;IACV;IACA,QAAQ,SAAS,SAAS,UAAU;IACpC,OAAO,SAAS,SAAS;GAC3B,CAAC;EACH;EAEA,OACE,iBAAA,GAAA,qBAAA,KAAA,CAACC,SAAAA,MAAD;GACE,UAAU,KAAK,KAAK;GACpB,MAAM,KAAK,KAAK;GAChB,MAAM,KAAK,KAAK;GAChB,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM;IAAE;IAAQ;IAAQ,MAAM;KAAE,MAAM,KAAK,KAAK;KAAM,UAAU,KAAK,KAAK;IAAS;GAAE,CAAC;GAC1H,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM;IAAE;IAAQ;IAAQ,MAAM;KAAE,MAAM,KAAK,KAAK;KAAM,UAAU,KAAK,KAAK;IAAS;GAAE,CAAC;GAL5H,UAAA;IAOG,KAAK,UAAU,eAAe,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;KAAa,MAAM,CAAC,WAAW;KAAG,MAAM,KAAK,KAAK;KAAM,MAAM,KAAK,OAAO;KAAM,YAAA;IAAY,CAAA;IAC3H,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;KAAa,MAAM,CAAC,kBAAkB,eAAe;KAAG,MAAM;KAAgC,YAAA;IAAY,CAAA;IAE1G,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;KAAa,MAAM,CAAC,WAAW,IAAI;KAAG,MAAM,KAAK,KAAK;KAAM,MAAM,WAAW;IAAO,CAAA;IAEpF,iBAAA,GAAA,qBAAA,IAAA,CAAC,YAAD;KAAY,MAAM,KAAK;KAAM,YAAY,WAAW;KAAY;KAAM,UAAU;KAAY,YAAY,WAAW;IAAa,CAAA;GAC5H;;CAEV;AACF,CAAC;;;;;;;;;;ACjDD,MAAa,mBAAA,GAAkBC,SAAAA,gBAAAA,CAA2B;CACxD,MAAM;CACN,UAAUC,SAAAA;CACV,WAAW,OAAO,KAAK;EACrB,MAAM,EAAE,QAAQ,UAAU,QAAQ,QAAQ,SAAS;EACnD,MAAM,EAAE,QAAQ,UAAU,IAAI;EAE9B,MAAM,YAAY,IAAI,cAAcC,iBAAAA,aAAa;EAEjD,MAAM,cAAc,OAAO,YAAYA,iBAAAA,aAAa;EAEpD,MAAM,UAA+C,cAAqB;GACxE;GACA,MAAMC,UAAAA,QAAK,QAAQ,MAAM,OAAO,MAAM,QAAQ;GAC9C,MAAM,EAAE,YAAY,OAAO,KAAK;EAClC;EACA,MAAM,aAAa,OAAO,WAAW;EACrC,MAAM,YAAY,OAAO,UAAU;EACnC,MAAM,WAAW,OAAO,WAAW;EAInC,MAAM,YAAY,EAChB,YAAY,GACT,IAAI,KAAK,SAAS,WAAW;GAC5B,MAAM;GACN,SAAS;GACT,MAAM,CAAC,OAAO,gBAAgBA,UAAAA,QAAK,QAAQ,OAAO,IAAI,GAAG,UAAU,IAAI,CAAC;EAC1E,EACF,EACF;EAEA,MAAM,mBAAmB,MAAM,OAAOC,SAAAA,IAAI,mBAAmB,CAAC,CAAC,KAAK,SAAS;GAC3E,MAAM,EAAE,MAAM,YAAY,OAAO,aAAa,QAAQ,iBAAiB,uBAAuB,IAAI;GAElG,MAAM,YAAY,mBAAmB,MAAM,KAAK,WAAW;GAC3D,MAAM,UAAU,SAAS,KAAK;IAAE,GAAG;IAAW;IAAM;IAAQ,OAAO,SAAS,KAAA;GAAU,CAAC;GACvF,MAAM,UAAU,YAAY,KAAK;IAC/B,GAAG;IACH;IACA,QAAQ,UAAU,SAAS,UAAU;IACrC,OAAO,UAAU,SAAS,SAAS,KAAA;GACrC,CAAC;GAED,MAAM,cAAc,KAAK,aAAa,UAAU,EAAE,EAAE,SAAS,YAAY,SAAS,KAAK,IAAI,IAAI;GAC/F,MAAM,gBAAgB,0BAA0B,IAAI,CAAC,EAAE;GACvD,MAAM,eAAe,gBAAgB,YAAY,SAAS,OAAO,MAAM,aAAa,IAAI;GAExF,MAAM,iBAAiB,WAA8B,OAAO,KAAK,OAAO;IAAE,MAAM,EAAE;IAAM,YAAY,YAAY,MAAM,KAAK,MAAM,CAAC;GAAE,EAAE;GAEtI,OAAO;IACL,MAAM;KACJ,MAAM,KAAK;KACX,OAAO,KAAK,WAAW,KAAA;KACvB,aAAa,KAAK,eAAe,UAAU,KAAK,OAAO,YAAY,EAAE,cAAc,KAAK;IAC1F;IACA,KAAK;KACH,MAAM,SAAS,QAAQ,KAAK,IAAI;KAChC,MAAM;IACR;IACA,KAAK;KACH,YAAY,cAAc,UAAU;KACpC,aAAa,YAAY,SAAS,cAAc,WAAW,IAAI;KAC/D,cAAc,aAAa,SAAS,cAAc,YAAY,IAAI;KAClE;KACA;KACA,MAAM;IACR;GACF;EACF,CAAC;EAED,MAAM,UAAU,iBAAiB,SAAS,EAAE,KAAK,UAAU;GACzD,MAAM,WAAW;IACf,GAAG,IAAI,WAAW,KAAK,MAAM,EAAE,UAAU;IACzC,IAAI,IAAI,eAAe,CAAC,EAAA,CAAG,KAAK,MAAM,EAAE,UAAU;IAClD,IAAI,IAAI,gBAAgB,CAAC,EAAA,CAAG,KAAK,MAAM,EAAE,UAAU;IACnD,IAAI;IACJ,IAAI;GACN,CAAC,CAAC,QAAQ,SAAyB,QAAQ,IAAI,CAAC;GAEhD,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK;GAEhD,OAAO,CACL,iBAAA,GAAA,qBAAA,IAAA,CAACC,SAAAA,KAAK,QAAN;IAA4B,MAAM,CAAC,IAAI,IAAI;IAAG,MAAM,WAAW;IAAM,MAAM,IAAI,KAAK;GAAO,GAAzE,IAAI,IAAqE,GAC3F,YAAY,SAAS,KAAK,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;IAAqC,MAAM;IAAa,MAAM,WAAW;IAAM,MAAM,IAAI,KAAK;GAAO,GAAnF,OAAO,IAAI,MAAwE,CACjI,CAAC,CAAC,OAAO,OAAO;EAClB,CAAC;EAED,OACE,iBAAA,GAAA,qBAAA,KAAA,CAAA,qBAAA,UAAA,EAAA,UAAA;GACE,iBAAA,GAAA,qBAAA,KAAA,CAACA,SAAAA,MAAD;IACE,UAAU,WAAW;IACrB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM;KAAE;KAAQ;KAAQ,MAAM;MAAE,MAAM,WAAW;MAAM,UAAU,WAAW;KAAS;IAAE,CAAC;IAC5H,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM;KAAE;KAAQ;KAAQ,MAAM;MAAE,MAAM,WAAW;MAAM,UAAU,WAAW;KAAS;IAAE,CAAC;IAL9H,UAAA;KAOE,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;MAAa,MAAM,CAAC,WAAW;MAAG,MAAM;KAAiC,CAAA;KACzE,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;MAAa,MAAM,CAAC,YAAY;MAAG,MAAM;KAAuC,CAAA;KAChF,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;MAAa,MAAM,CAAC,GAAG;MAAG,MAAM;KAAQ,CAAA;KAEvC;KACD,iBAAA,GAAA,qBAAA,IAAA,CAAC,QAAD;MAAQ,YAAY,IAAI,KAAK,SAAS;MAAU,eAAe,IAAI,KAAK,WAAW;MAAS,YAAY;KAAmB,CAAA;IACvH;;GAEN,iBAAA,GAAA,qBAAA,KAAA,CAACA,SAAAA,MAAD;IACE,UAAU,UAAU;IACpB,MAAM,UAAU;IAChB,MAAM,UAAU;IAChB,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM;KAAE;KAAQ;KAAQ,MAAM;MAAE,MAAM,UAAU;MAAM,UAAU,UAAU;KAAS;IAAE,CAAC;IAC1H,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM;KAAE;KAAQ;KAAQ,MAAM;MAAE,MAAM,UAAU;MAAM,UAAU,UAAU;KAAS;IAAE,CAAC;IAL5H,UAAA,CAOE,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;KAAa,MAAM,CAAC,aAAa;KAAG,MAAM,UAAU;KAAM,MAAM,WAAW;IAAO,CAAA,GAElF,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;KAAa,MAAK;KAAS,UAAA;IAAkC,CAAA,CACzD;;GAEN,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,MAAD;IAAM,UAAU,SAAS;IAAU,MAAM,SAAS;IAAM,MAAM,SAAS;IACrE,UAAA,iBAAA,GAAA,qBAAA,IAAA,CAACA,SAAAA,KAAK,QAAN;KAAa,MAAK;KAAU,UAAA,GAAG,KAAK,UAAU,WAAW,MAAM,CAAC,EAAE;IAAiB,CAAA;GAC/E,CAAA;EACN,EAAA,CAAA;CAEN;AACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AG3HD,MAAa,eAAA,GAAcC,SAAAA,eAAAA,CAA0B;CACnD,YAAY;CACZ,KAAK,MAAM;EACT,OAAO,UAAU,MAAM,EAAE,QAAQ,UAAU,CAAC;CAC9C;CACA,SAAS,EACP,KAAK,MAAM;EACT,OAAO,KAAK,KAAK,KAAK,WAAW;CACnC,EACF;AACF,CAAC;;;;;;;ACTD,MAAa,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B7B,MAAa,aAAA,GAAYC,SAAAA,gBAAAA,CAA2B;CAClD,MAAM;CACN,MAAM;EAAE,MAAM;EAAe;EAAS;CAAc;CACpD,cAAc;GAAGC,gBAAAA,eAAe,CAAC;GAAIC,iBAAAA,gBAAgB,CAAC;CAAE;CACxD,MAAM,SAAS;EACb,MAAM,EACJ,SAAS;GAAE,MAAM;GAAO,QAAQ,EAAE,MAAM,QAAQ;EAAE,GAClD,OACA,UAAU,CAAC,GACX,SACA,WAAW,CAAC,GACZ,QACA,UAAU,cACV,QAAQ,eACN;EAEJ,MAAM,WAAW,eAAeC,SAAAA,SAAS,MAAmB,aAAa,YAAY,IAAI;EAEzF,CAAA,GAAA,SAAA,YAAA,CAAY,QAAQ;EACpB,IAAI,YAAY,QACd,CAAA,GAAA,SAAA,UAAA,CAAU,UAAU;EAEtB,CAAA,GAAA,SAAA,aAAA,CAAa,cAAc,eAAe;EAE1C,OAAO;GACL;GACA;GACA;GACA;GACA,OAAO,kBAAkB,KAAK;GAC9B,QAAQ,sBAAsB;IAAE,QAAQ;IAAe;IAAQ,UAAA,GAASC,SAAAA,UAAAA,CAAU,CAAC,CAAC;GAAQ,CAAC;GAC7F;EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"index.cjs","names":["Url","posix","File","Function","File","Function","Const","pluginTsName","pluginZodName","Diagnostics","Diagnostics","path","defineGenerator","jsxRenderer","ast","File","defineGenerator","jsxRenderer","pluginZodName","path","ast","File","createResolver","defineExtension","pluginTsName","pluginZodName","Resolver","useConfig"],"sources":["../../../internals/shared/src/operation.ts","../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/shared/src/group.ts","../src/components/McpHandler.tsx","../src/components/Server.tsx","../../../internals/client/src/resolveOperationTypes.ts","../../../internals/client/src/resolveClient.ts","../../../internals/client/src/resolveClientOperation.ts","../src/generators/mcpGenerator.tsx","../src/generators/serverGenerator.tsx","../kubb-extension.json","../package.json","../src/resolvers/resolverMcp.ts","../src/plugin.ts"],"sourcesContent":["import { ast, type Group, type NodeCache, type Output, type Resolver, type ResolverFileParams, Url } from 'kubb/kit'\n\n/**\n * Builds the `ResolverFileParams` every operation generator passes to\n * `resolver.file`: a file named `name`, tagged by the operation's first\n * tag (or `'default'`), at the operation's path. Centralizes the entry object\n * that was repeated at dozens of call sites across the client and query plugins.\n *\n * @example\n * ```ts\n * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })\n * ```\n */\nexport function operationFileEntry(node: ast.OperationNode, name: string, extname: ResolverFileParams['extname'] = '.ts'): ResolverFileParams {\n return {\n name,\n extname,\n tag: node.tags[0] ?? 'default',\n path: node.path,\n }\n}\n\n/**\n * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the\n * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the\n * same dependency for the same operation in one pass (a query plugin's several hook generators, the\n * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.\n *\n * @example Cache `plugin-ts`'s file for the current operation\n * ```ts\n * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })\n * ```\n */\nexport function resolveDependencyOperationFile(options: {\n cache: NodeCache\n node: ast.OperationNode\n resolver: Pick<Resolver, 'file' | 'pluginName'>\n root: string\n output: Output\n group?: Group | null\n}): ast.FileNode {\n const { cache, node, resolver, root, output, group } = options\n\n return cache.ensureItem(`${resolver.pluginName}:operationFile`, () =>\n resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n )\n}\n\nexport type ContentTypeInfo = {\n contentTypes: string[]\n isMultipleContentTypes: boolean\n contentTypeUnion: string\n defaultContentType: string\n hasFormData: boolean\n}\n\nexport type RequestConfigResolver = {\n response: {\n body(node: ast.OperationNode): string\n }\n}\n\nexport type ResponseStatusNameResolver = {\n response: {\n status(node: ast.OperationNode, statusCode: ast.StatusCode): string\n }\n}\n\nexport type ResponseNameResolver = ResponseStatusNameResolver & {\n response: {\n response(node: ast.OperationNode): string\n }\n}\n\nexport type OperationTypeNameResolver = RequestConfigResolver &\n ResponseNameResolver & {\n param: {\n path(node: ast.OperationNode, param: ast.ParameterNode): string\n query(node: ast.OperationNode, param: ast.ParameterNode): string\n headers(node: ast.OperationNode, param: ast.ParameterNode): string\n }\n }\n\nexport type OperationCommentLink = 'pathTemplate' | 'urlPath' | false | ((node: ast.OperationNode) => string | undefined)\n\nexport type BuildOperationCommentsOptions = {\n link?: OperationCommentLink\n linkPosition?: 'beforeDeprecated' | 'afterDeprecated'\n splitLines?: boolean\n}\n\ntype ResponseLike = {\n statusCode: ast.StatusCode | number | string\n}\n\nexport type OperationParameterGroups = Record<ast.ParameterNode['in'], Array<ast.ParameterNode>>\n\nexport type ResolveOperationTypeNameOptions = {\n responseStatusNames?: boolean | 'error'\n exclude?: ReadonlyArray<string | undefined>\n order?: 'params-first' | 'body-response-first'\n /**\n * Include the individual `Path`/`Query`/`Headers` group type names. Set to `false` for clients\n * that reference the grouped `Options` type instead of the per-group types.\n */\n includeParams?: boolean\n}\n\nfunction getOperationLink(node: ast.OperationNode, link: OperationCommentLink): string | null {\n if (!link) {\n return null\n }\n\n if (typeof link === 'function') {\n return link(node) ?? null\n }\n\n return node.path ? `{@link ${Url.toPath(node.path)}}` : null\n}\n\n/**\n * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several\n * are present and the union, default, and form-data flags the client uses to pick one.\n */\nfunction buildContentTypeInfo(contentTypes: string[]): ContentTypeInfo {\n const isMultipleContentTypes = contentTypes.length > 1\n\n return {\n contentTypes,\n isMultipleContentTypes,\n contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(' | ') : '',\n defaultContentType: contentTypes[0] ?? 'application/json',\n hasFormData: contentTypes.some((ct) => ct === 'multipart/form-data'),\n }\n}\n\nexport function getContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? [])\n}\n\n/**\n * The request-body counterpart for the primary success response: the content types it documents and\n * whether several are present, so the client can let a caller pick which one to accept.\n */\nexport function getResponseContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [])\n}\n\nexport type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'\n\n/**\n * Reads the single base content type of an operation's primary success response, lowercased and\n * stripped of any `; charset=...` suffix. Returns `undefined` when the response declares zero or\n * more than one content type, since neither case has a single type to act on.\n */\nfunction getPrimarySuccessContentType(node: ast.OperationNode): string | undefined {\n const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? []\n if (contentTypes.length !== 1) return undefined\n return contentTypes[0]!.split(';')[0]!.trim().toLowerCase()\n}\n\n/**\n * Whether an operation streams its primary success response as Server-Sent Events\n * (`text/event-stream`). The client generator uses this to return a typed event stream instead of a\n * one-shot `RequestResult`.\n */\nexport function isEventStream(node: ast.OperationNode): boolean {\n return getPrimarySuccessContentType(node) === 'text/event-stream'\n}\n\n/**\n * Derives the default `responseType` for an operation from its primary success response.\n *\n * Returns a value only when that response declares a single non-JSON content type. `text/event-stream`\n * and other binary types (`application/octet-stream`, `application/pdf`, `image/*`, `audio/*`,\n * `video/*`) map to a stream or `'blob'`, and other `text/*` maps to `'text'`. Otherwise `undefined`,\n * leaving the runtime client's `Content-Type` auto-detection in charge.\n */\nexport function getResponseType(node: ast.OperationNode): ResponseType | undefined {\n const baseType = getPrimarySuccessContentType(node)\n if (!baseType) return undefined\n\n if (baseType === 'application/json' || baseType.endsWith('+json') || baseType === 'text/json') return undefined\n if (baseType === 'text/event-stream') return 'stream'\n if (baseType.startsWith('text/')) return 'text'\n if (baseType === 'application/octet-stream' || baseType === 'application/pdf' || /^(image|audio|video)\\//.test(baseType)) return 'blob'\n return undefined\n}\n\n/**\n * Maps a content type to the PascalCase suffix used to name per-content-type variants\n * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).\n */\nfunction getContentTypeSuffix(contentType: string): string {\n const baseType = contentType.split(';')[0]!.trim()\n if (baseType === 'application/json') return 'Json'\n if (baseType === 'multipart/form-data') return 'FormData'\n if (baseType === 'application/x-www-form-urlencoded') return 'FormUrlEncoded'\n const subtype = baseType.split('/').pop() ?? baseType\n const parts = subtype.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n if (parts.length === 0) return 'Unknown'\n return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')\n}\n\n/**\n * Appends a content-type suffix to a base name, keeping a trailing `Data` segment last\n * (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).\n */\nexport function getPerContentTypeName(baseName: string, suffix: string): string {\n if (baseName.endsWith('Data')) {\n return suffix.endsWith('Data') ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`\n }\n return baseName + suffix\n}\n\nexport type ContentVariantInput = { contentType: string; schema?: ast.SchemaNode | null; keysToOmit?: Array<string> | null }\nexport type ContentVariant = { name: string; suffix: string; schema: ast.SchemaNode; keysToOmit?: Array<string> | null; contentType: string }\n\n/**\n * Resolves per-content-type variant names for a set of content entries, deduplicating suffix\n * collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is\n * the final (possibly counter-augmented) value, so callers can derive parallel names in another\n * namespace (e.g. plugin-faker deriving the matching plugin-ts type name).\n */\nexport function resolveContentTypeVariants(entries: Array<ContentVariantInput>, baseName: string): Array<ContentVariant> {\n const usedNames = new Set<string>()\n return entries\n .filter((entry) => entry.schema)\n .map((entry) => {\n const baseSuffix = getContentTypeSuffix(entry.contentType)\n let suffix = baseSuffix\n let name = getPerContentTypeName(baseName, suffix)\n let counter = 2\n while (usedNames.has(name)) {\n suffix = `${baseSuffix}${counter++}`\n name = getPerContentTypeName(baseName, suffix)\n }\n usedNames.add(name)\n return { name, suffix, schema: entry.schema!, keysToOmit: entry.keysToOmit, contentType: entry.contentType }\n })\n}\n\n// The request groups come from the grouped params, so `config` drops the data-shape keys to stay\n// assignable to `Options`, which omits them from `RequestConfig`.\nconst requestConfigBaseType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`\n\nexport function buildRequestConfigType(node: ast.OperationNode): string {\n const request = getContentTypeInfo(node)\n const response = getResponseContentTypeInfo(node)\n\n // Only the ambiguous side is offered: a single-type side has nothing to pick, so it stays baked in\n // the generated call.\n const members = [\n request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null,\n response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null,\n ].filter(Boolean)\n\n return members.length ? `${requestConfigBaseType} & { contentType?: { ${members.join('; ')} } }` : requestConfigBaseType\n}\n\n/**\n * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,\n * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a\n * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a\n * content type for.\n */\nexport function buildClientOptionType(): string {\n return requestConfigBaseType\n}\n\nexport type RequestGroups = {\n path: boolean\n query: boolean\n body: boolean\n headers: boolean\n}\n\n/**\n * Which of the grouped request options an operation carries.\n */\nexport function getRequestGroups(node: ast.OperationNode): RequestGroups {\n const { path, query, header } = getOperationParameters(node)\n return {\n path: path.length > 0,\n query: query.length > 0,\n body: Boolean(node.requestBody?.content?.[0]?.schema),\n headers: header.length > 0,\n }\n}\n\nexport type RequestGroupOptionality = {\n groups: RequestGroups\n hasRequiredPath: boolean\n hasRequiredQuery: boolean\n hasRequiredHeader: boolean\n /**\n * Whether the grouped request parameter can default to `{}`. True only when no group carries a\n * required member, so every member is safe to omit.\n */\n isOptional: boolean\n}\n\n/**\n * Resolves which grouped request options an operation carries together with whether each group\n * holds a required member. The grouped parameter stays optional only when nothing inside it is\n * required, matching the generated `RequestConfig` type.\n */\nexport function getRequestGroupOptionality(node: ast.OperationNode): RequestGroupOptionality {\n const groups = getRequestGroups(node)\n const { path, query, header } = getOperationParameters(node)\n const hasRequiredPath = path.some((param) => param.required)\n const hasRequiredQuery = query.some((param) => param.required)\n const hasRequiredHeader = header.some((param) => param.required)\n\n return {\n groups,\n hasRequiredPath,\n hasRequiredQuery,\n hasRequiredHeader,\n isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body,\n }\n}\n\nexport type RequestOptionsNameResolver = RequestConfigResolver & {\n response: {\n options(node: ast.OperationNode): string\n }\n}\n\n/**\n * Builds the grouped `{ path, query, body, headers }` parameter for a generated client\n * function, typed from the operation's `Options` (minus `url`). Only the groups the\n * operation actually has are destructured. The trailing `config` parameter carries the\n * runtime `RequestConfig` overrides plus `client`.\n */\nexport function buildRequestParamsSignature(\n node: ast.OperationNode,\n resolver: RequestOptionsNameResolver,\n options: { isConfigurable?: boolean } = {},\n): { signature: string; groups: RequestGroups } {\n const { isConfigurable = true } = options\n const { groups, isOptional } = getRequestGroupOptionality(node)\n\n const names = (['path', 'query', 'body', 'headers'] as const).filter((key) => groups[key])\n\n const firstParam = names.length > 0 ? `{ ${names.join(', ')} }: ${resolver.response.options(node)}${isOptional ? ' = {}' : ''}` : null\n const configParam = isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null\n\n return {\n signature: [firstParam, configParam].filter(Boolean).join(', '),\n groups,\n }\n}\n\nexport function buildOperationComments(node: ast.OperationNode, options: BuildOperationCommentsOptions = {}): Array<string> {\n const { link = 'pathTemplate', linkPosition = 'afterDeprecated', splitLines = false } = options\n const linkComment = getOperationLink(node, link)\n const comments =\n linkPosition === 'beforeDeprecated'\n ? [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, linkComment, node.deprecated && '@deprecated']\n : [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, node.deprecated && '@deprecated', linkComment]\n\n const filteredComments = comments.filter((comment): comment is string => Boolean(comment))\n\n if (!splitLines) {\n return filteredComments\n }\n\n return filteredComments.flatMap((text) => text.split(/\\r?\\n/).map((line) => line.trim())).filter((comment): comment is string => Boolean(comment))\n}\n\nconst operationParameterGroupsByNode = new WeakMap<ast.OperationNode, OperationParameterGroups>()\n\n/**\n * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each\n * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance\n * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the\n * same parameters once per plugin.\n */\nexport function getOperationParameters(node: ast.OperationNode): OperationParameterGroups {\n const cached = operationParameterGroupsByNode.get(node)\n if (cached) return cached\n\n // A malformed spec can declare the same name twice within one location. Both would resolve to the\n // same output property, so emitting both would yield an object type with a duplicate member,\n // which TypeScript rejects. Keep the first.\n const group = (location: ast.ParameterNode['in']) => {\n const seen = new Set<string>()\n\n return node.parameters.filter((param) => {\n if (param.in !== location || seen.has(param.name)) return false\n seen.add(param.name)\n return true\n })\n }\n\n const groups: OperationParameterGroups = { path: group('path'), query: group('query'), header: group('header'), cookie: group('cookie') }\n\n operationParameterGroupsByNode.set(node, groups)\n return groups\n}\n\n/**\n * Builds the combined `{ body, path, query, headers }` options object schema for an operation,\n * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s\n * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same\n * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod\n * printer to emit `z.object(…)` rather than a record.\n */\nexport function buildOptionsSchema(node: ast.OperationNode, resolver: OperationTypeNameResolver): ast.SchemaNode {\n const { path, query, header } = getOperationParameters(node)\n const hasBody = Boolean(node.requestBody?.content?.[0]?.schema)\n const createNever = () => ast.factory.createSchema({ type: 'never', primitive: undefined, optional: true })\n const groups = [\n { name: 'path', params: path, resolve: resolver.param.path },\n { name: 'query', params: query, resolve: resolver.param.query },\n { name: 'headers', params: header, resolve: resolver.param.headers },\n ] as const\n\n // NOTE(v5-stable): the fields were renamed from the legacy beta shape\n // (`data`/`pathParams`/`queryParams`/`headerParams`) to `body`/`path`/`query`/`headers` so the\n // type matches the runtime client. Drop this note once v5 leaves beta.\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n deprecated: node.deprecated,\n properties: [\n ast.factory.createProperty({\n name: 'body',\n required: hasBody,\n schema: hasBody ? ast.factory.createSchema({ type: 'ref', name: resolver.response.body(node) }) : createNever(),\n }),\n ...groups.map(({ name, params, resolve }) => {\n const required = params.some((param) => param.required)\n\n return ast.factory.createProperty({\n name,\n required,\n schema:\n params.length > 0\n ? ast.factory.createSchema({ type: 'ref', name: resolve.call(resolver.param, node, params[0]!), optional: !required })\n : createNever(),\n })\n }),\n ],\n })\n}\n\n/**\n * The schema a status occupies in the `<Name>Responses` record. A status that documents several\n * content types becomes a `{ contentType; data }` union so the runtime can surface the negotiated type\n * on `result.parsed`, while the standalone `<Name>StatusNNN` alias stays the plain body union that the\n * query hooks and `result.data` use.\n */\nfunction buildResponseRecordEntry(node: ast.OperationNode, res: ast.ResponseNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n const statusName = resolver.response.status(node, res.statusCode)\n const variants = (res.content ?? []).filter((entry) => entry.schema)\n if (variants.length <= 1) {\n return ast.factory.createSchema({ type: 'ref', name: statusName })\n }\n\n return ast.factory.createSchema({\n type: 'union',\n members: resolveContentTypeVariants(variants, statusName).map((variant) =>\n ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: [\n ast.factory.createProperty({\n name: 'contentType',\n required: true,\n schema: ast.factory.createSchema({ type: 'enum', enumValues: [variant.contentType] }),\n }),\n ast.factory.createProperty({\n name: 'data',\n required: true,\n schema: ast.factory.createSchema({ type: 'ref', name: variant.name }),\n }),\n ],\n }),\n ),\n })\n}\n\n/**\n * Builds the per-status `<Name>Responses` record for an operation, referencing the already-resolved\n * `<Name>StatusNNN` names. Shared by `@kubb/plugin-ts`'s `Responses` type and `@kubb/plugin-zod`'s\n * inferred responses schema, so both emit the same shape from the same inputs.\n *\n * Always emits the keyed record, even when an operation declares no responses. An operation with no\n * responses renders as an empty object, which keeps every consumer's import (for example the axios\n * SDK's `RequestResult<XResponses>`) resolvable instead of pointing at a missing export.\n */\nexport function buildResponses(node: ast.OperationNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: node.responses.map((res) =>\n ast.factory.createProperty({\n name: String(res.statusCode),\n required: true,\n schema: buildResponseRecordEntry(node, res, resolver),\n }),\n ),\n })\n}\n\nexport function getStatusCodeNumber(statusCode: ast.StatusCode | number | string): number | null {\n const code = Number(statusCode)\n\n return Number.isNaN(code) ? null : code\n}\n\nexport function isSuccessStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 200 && code < 300\n}\n\nexport function isErrorStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 400\n}\n\nexport function getSuccessResponses<TResponse extends ResponseLike>(responses: ReadonlyArray<TResponse>): Array<TResponse> {\n return responses.filter((response) => isSuccessStatusCode(response.statusCode))\n}\n\nexport function getOperationSuccessResponses(node: ast.OperationNode): Array<ast.ResponseNode> {\n return getSuccessResponses(node.responses)\n}\n\nexport function getPrimarySuccessResponse(node: ast.OperationNode): ast.ResponseNode | null {\n return getOperationSuccessResponses(node)[0] ?? null\n}\n\nexport function resolveErrorNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveSuccessNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveStatusCodeNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.map((response) => resolver.response.status(node, response.statusCode))\n}\n\nconst typeNamesByResolver = new WeakMap<OperationTypeNameResolver, Map<string, string[]>>()\n\nexport function resolveOperationTypeNames(\n node: ast.OperationNode,\n resolver: OperationTypeNameResolver,\n options: ResolveOperationTypeNameOptions = {},\n): string[] {\n const cacheKey = `${node.operationId}\\0${options.order ?? ''}\\0${options.responseStatusNames ?? ''}\\0${options.includeParams === false ? 'noparams' : ''}\\0${(options.exclude ?? []).join(',')}`\n let byResolver = typeNamesByResolver.get(resolver)\n if (byResolver) {\n const cached = byResolver.get(cacheKey)\n if (cached) return cached\n } else {\n byResolver = new Map()\n typeNamesByResolver.set(resolver, byResolver)\n }\n\n const { path, query, header } = getOperationParameters(node)\n const responseStatusNames =\n options.responseStatusNames === 'error'\n ? resolveErrorNames(node, resolver)\n : options.responseStatusNames === false\n ? []\n : resolveStatusCodeNames(node, resolver)\n const exclude = new Set(options.exclude ?? [])\n const paramNames =\n options.includeParams === false\n ? []\n : [\n ...path.map((param) => resolver.param.path(node, param)),\n ...query.map((param) => resolver.param.query(node, param)),\n ...header.map((param) => resolver.param.headers(node, param)),\n ]\n const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)]\n const names =\n options.order === 'body-response-first'\n ? [...bodyAndResponseNames, ...paramNames, ...responseStatusNames]\n : [...paramNames, ...bodyAndResponseNames, ...responseStatusNames]\n\n const result = names.filter((name): name is string => Boolean(name) && !exclude.has(name as string))\n byResolver.set(cacheKey, result)\n return result\n}\n\nexport function resolveResponseTypes(node: ast.OperationNode, resolver: ResponseNameResolver): Array<[statusCode: number | 'default', typeName: string]> {\n const types: Array<[number | 'default', string]> = []\n\n for (const response of node.responses) {\n if (response.statusCode === 'default') {\n types.push(['default', resolver.response.response(node)])\n continue\n }\n\n const code = getStatusCodeNumber(response.statusCode)\n if (code === null) {\n continue\n }\n\n types.push([code, isSuccessStatusCode(code) ? resolver.response.response(node) : resolver.response.status(node, response.statusCode)])\n }\n\n return types\n}\n","type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction convert(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n// Plugins resolve the same names over and over (about 47,000 calls for a 1,000 schema spec), so\n// results are kept. Clearing at the limit bounds the memory a long-running process spends on it.\nconst cache = new Map<string, string>()\nconst cacheLimit = 10_000\n\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const key = `${pascal ? 'P' : 'c'}${text}`\n const cached = cache.get(key)\n if (cached !== undefined) return cached\n\n const result = convert(text, pascal)\n if (cache.size >= cacheLimit) cache.clear()\n cache.set(key, result)\n return result\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Uppercases only the first character of `text`, leaving the rest untouched.\n * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.\n *\n * @example\n * `capitalize('getPetById') // 'GetPetById'`\n */\nexport function capitalize(text: string): string {\n return `${text.charAt(0).toUpperCase()}${text.slice(1)}`\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from 'kubb/kit'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { buildOperationComments, buildRequestParamsSignature } from '@internals/shared'\nimport type { ast } from 'kubb/kit'\nimport type { ResolverTs } from '@kubb/plugin-ts'\nimport { File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype Props = {\n /**\n * Name of the handler function.\n */\n name: string\n /**\n * Name of the contract client `<op>` the handler calls.\n */\n clientName: string\n /**\n * AST operation node.\n */\n node: ast.HttpOperationNode\n /**\n * TypeScript resolver for resolving param/data/response type names.\n */\n resolver: ResolverTs\n /**\n * The registered client plugin's `returnType`, read by the caller off `resolveClientOperation`.\n */\n returnType?: 'full' | 'data' | 'plain'\n}\n\nconst requestGroupOrder = ['path', 'query', 'headers', 'body'] as const\n\nexport function McpHandler({ name, clientName, node, resolver, returnType = 'full' }: Props): KubbReactNode {\n const { signature, groups } = buildRequestParamsSignature(node, resolver, { isConfigurable: false })\n const paramsSignature = [signature, 'ctx: ServerContext'].filter(Boolean).join(', ')\n\n // Forward the grouped config and MCP cancellation signal through the contract client. `throwOnError: true`\n // pins the result shape, since `throwOnErrorDefault: false` would otherwise resolve to the full result.\n const callArgs = requestGroupOrder.filter((key) => groups[key])\n const callConfig = `{ ${[...callArgs, 'signal: ctx.mcpReq.signal', 'throwOnError: true'].join(', ')} }`\n const body = returnType === 'data' ? 'res' : 'res.data'\n\n const callToolResult = `return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(${body})\n }\n ],\n structuredContent: { data: ${body} }\n}`\n\n return (\n <File.Source name={name} isExportable isIndexable>\n <Function\n name={name}\n async\n export\n params={paramsSignature}\n JSDoc={{\n comments: buildOperationComments(node),\n }}\n returnType={'CallToolResult'}\n >\n {`const res = await ${clientName}(${callConfig})`}\n <br />\n {callToolResult}\n </Function>\n </File.Source>\n )\n}\n","import type { ast } from 'kubb/kit'\nimport { Const, File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype ZodParam = {\n name: string\n schemaName: string\n}\n\n/**\n * Composes individual param schemas into `z.object({ ... })`.\n */\nconst zodObject = (params: Array<ZodParam>) => `z.object({ ${params.map((p) => `${JSON.stringify(p.name)}: ${p.schemaName}`).join(', ')} })`\n\ntype Props = {\n /**\n * Human-readable server name passed to `new McpServer({ name })`.\n */\n serverName: string\n /**\n * Semantic version string passed to `new McpServer({ version })`.\n */\n serverVersion: string\n /**\n * Operations to register as MCP tools, each carrying its handler,\n * zod schema, and AST node metadata.\n */\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: ast.FileNode\n }\n zod: {\n pathParams: Array<ZodParam>\n /**\n * Query params — individual schemas to compose into `z.object({ ... })`.\n */\n queryParams?: Array<ZodParam> | null\n /**\n * Header params — individual schemas to compose into `z.object({ ... })`.\n */\n headerParams?: Array<ZodParam> | null\n requestName?: string | null\n responseName?: string | null\n }\n }>\n}\n\nexport function Server({ serverName, serverVersion, operations }: Props): KubbReactNode {\n const registrations = operations\n .map(({ tool, mcp, zod }) => {\n // Group params into the same `{ path, query, headers, body }` shape the contract `<op>`\n // expects, so the MCP tool input mirrors every other client consumer.\n const entries: Array<{ key: string; value: string }> = []\n\n if (zod.pathParams.length) {\n entries.push({ key: 'path', value: zodObject(zod.pathParams) })\n }\n\n if (zod.queryParams) {\n entries.push({ key: 'query', value: zodObject(zod.queryParams) })\n }\n\n if (zod.headerParams) {\n entries.push({ key: 'headers', value: zodObject(zod.headerParams) })\n }\n\n if (zod.requestName) {\n entries.push({ key: 'body', value: zod.requestName })\n }\n\n const destructured = `{ ${entries.map((e) => e.key).join(', ')} }`\n const inputSchema = entries.length ? `z.object({ ${entries.map((e) => `${e.key}: ${e.value}`).join(', ')} })` : null\n const outputSchema = zod.responseName\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: z.object({ data: ${outputSchema} })` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (inputSchema) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${inputSchema},\n}, async (${destructured}, ctx) => {\n return ${mcp.name}(${destructured}, ctx)\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async (ctx) => {\n return ${mcp.name}(ctx)\n})\n `\n })\n .filter(Boolean)\n .join('\\n')\n\n return (\n <>\n <File.Source name=\"getServer\" isExportable isIndexable>\n <Function name=\"getServer\" export>\n {`const server = new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n${registrations}\nreturn server`}\n </Function>\n </File.Source>\n\n <File.Source name=\"server\" isExportable isIndexable>\n <Const name={'server'} export>\n {'getServer()'}\n </Const>\n </File.Source>\n\n <File.Source name=\"startServer\" isExportable isIndexable>\n <Function name=\"startServer\" async export>\n {`return serveStdio(getServer, {\n onerror: (error) => console.error('MCP server error:', error),\n })`}\n </Function>\n </File.Source>\n </>\n )\n}\n","import { type ast, Diagnostics, type Generator, type Group, type Output } from 'kubb/kit'\nimport { pluginTsName, type ResolverTs } from '@kubb/plugin-ts'\nimport { pluginZodName, type ResolverZod } from '@kubb/plugin-zod'\nimport type { ContractClientFactory } from './types.ts'\n\ntype GeneratorDriver = Parameters<NonNullable<Generator<ContractClientFactory>['operations']>>[1]['driver']\n\n/**\n * The two per-operation type names a generated client references: the grouped input and the\n * per-status responses record its `RequestResult` is keyed on.\n */\nexport type OperationTypeNames = {\n response: {\n /**\n * Resolves the name of the operation's grouped `{ body, path, query, headers }` input type.\n */\n options(node: ast.OperationNode): string\n /**\n * Resolves the name of the operation's per-status responses record type.\n */\n responses(node: ast.OperationNode): string\n }\n}\n\n/**\n * Where a generated client sources its operation types, plus the resolver and output the file\n * declaring them is resolved with.\n */\nexport type OperationTypeSource = OperationTypeNames & {\n /**\n * `plugin-ts` shaped resolver of the plugin supplying the names, also used to resolve the file they are exported from.\n */\n resolver: ResolverTs\n /**\n * The supplying plugin's own `output`, when it configured one.\n */\n output: Output | undefined\n /**\n * The supplying plugin's own `group`, when it configured one.\n */\n group: Group | undefined\n}\n\n/**\n * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`\n * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.\n */\nfunction toZodTypeResolver(resolver: ResolverZod): ResolverTs {\n const type = (name: string) => resolver.schema.type(name)\n\n return {\n ...resolver,\n // A class method, so a spread drops it, and it reads private fields, so it must run on `resolver`.\n file: resolver.file.bind(resolver),\n param: {\n name: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.name(node, p)),\n path: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.path(node, p)),\n query: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.query(node, p)),\n headers: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.headers(node, p)),\n },\n response: {\n body: (node: ast.OperationNode) => type(resolver.response.body(node)),\n status: (node: ast.OperationNode, statusCode: ast.StatusCode) => type(resolver.response.status(node, statusCode)),\n response: (node: ast.OperationNode) => type(resolver.response.response(node)),\n responses: (node: ast.OperationNode) => type(resolver.response.responses(node)),\n options: (node: ast.OperationNode) => resolver.response.options(node),\n },\n } as unknown as ResolverTs\n}\n\n/**\n * Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.\n *\n * `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`\n * wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws\n * `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.\n *\n * @example\n * ```ts\n * const types = resolveOperationTypes(ctx.driver, ctx.plugin.name)\n * types.response.options(node) // 'GetPetByIdOptions', or 'GetPetByIdOptionsSchemaType' from zod\n * ```\n */\nexport function resolveOperationTypes(driver: GeneratorDriver, pluginName: string): OperationTypeSource {\n const pluginTs = driver.getPlugin(pluginTsName)\n const pluginZod = driver.getPlugin(pluginZodName)\n\n if (pluginTs && pluginZod?.options?.inferred !== 'codec') {\n const resolver = driver.getResolver(pluginTsName)\n return { response: resolver.response, resolver, output: pluginTs.options?.output, group: pluginTs.options?.group ?? undefined }\n }\n\n if (!pluginZod?.options?.inferred) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.missingDependency,\n severity: 'error',\n message: `Plugin \"${pluginName}\" has no source for operation types.`,\n help: `Add \\`pluginTs()\\` before \"${pluginName}\", or add \\`pluginZod({ inferred: true })\\`.`,\n location: { kind: 'config' },\n plugin: pluginName,\n })\n }\n\n const resolver = toZodTypeResolver(driver.getResolver(pluginZodName))\n return { response: resolver.response, resolver, output: pluginZod.options.output, group: pluginZod.options.group ?? undefined }\n}\n","/**\n * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an\n * operation, shared so the selection rules and diagnostics stay in one place.\n *\n * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered\n * contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own\n * inline client:\n *\n * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer\n * imports and calls them.\n * - `error` — no client plugin is registered, several are registered without a selector, the\n * requested one is missing, or `client` is not a known selector.\n *\n * The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a\n * lone registered contract client plugin is picked up automatically.\n */\n\nimport { Diagnostics } from 'kubb/kit'\n\n// Canonical plugin names. They mirror the `pluginFetchName` / `pluginAxiosName` / `pluginClientName`\n// consts the plugins export, kept as literals so this internal needs no plugin install deps.\nconst pluginFetchName = 'plugin-fetch'\nconst pluginAxiosName = 'plugin-axios'\nconst pluginClientName = 'plugin-client'\n\n/**\n * The client selector accepted by a consumer's `client` option. Each calls a registered contract\n * client plugin.\n */\nexport type ClientSelector = 'fetch' | 'axios' | 'client'\n\n/**\n * The resolved client strategy stored in a consumer plugin's options: the generated code always\n * imports and calls a registered contract client plugin's `<op>`. The client runtime lives in\n * plugin-axios / plugin-fetch, so nothing is bundled by the consumer.\n */\nexport type ResolvedContractClient = { kind: 'contract'; pluginName: string }\n\n/**\n * The outcome of {@link resolveClient}.\n *\n * - `contract` names the contract client plugin whose `<op>` functions the consumer imports.\n * - `error` carries a setup diagnostic: its code, what is wrong, and how to fix it.\n */\nexport type ResolveClientResult =\n | ResolvedContractClient\n | { kind: 'error'; code: typeof Diagnostics.code.missingDependency | typeof Diagnostics.code.invalidPluginOptions; message: string; help: string }\n\nconst selectorToPlugin: Record<ClientSelector, string> = {\n fetch: pluginFetchName,\n axios: pluginAxiosName,\n client: pluginClientName,\n}\n\n// Every contract client plugin, in auto-detect priority order.\nconst contractPlugins = [pluginFetchName, pluginAxiosName, pluginClientName] as const\n\n/**\n * Applies the `client` resolution rules. See the module comment for the strategy shape.\n *\n * @example\n * ```ts\n * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })\n * // { kind: 'contract', pluginName: 'plugin-fetch' }\n * ```\n *\n * @example\n * ```ts\n * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })\n * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }\n * ```\n */\nexport function resolveClient(options: { client: ClientSelector | undefined; pluginNames: ReadonlyArray<string> }): ResolveClientResult {\n const { client, pluginNames } = options\n const has = (name: string) => pluginNames.includes(name)\n\n if (client === 'fetch' || client === 'axios' || client === 'client') {\n const pluginName = selectorToPlugin[client]\n if (!has(pluginName)) {\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: `\\`client: '${client}'\\` is set but \\`@kubb/plugin-${client}\\` is not registered in \\`plugins\\`.`,\n help: `Add \\`@kubb/plugin-${client}\\` to \\`plugins\\`, or drop \\`client\\` to use a different client plugin.`,\n }\n }\n return { kind: 'contract', pluginName }\n }\n\n // A JS config bypasses the `ClientSelector` type, so reject unknown selectors instead of auto-detecting.\n if (client !== undefined) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Option \\`client\\` is ${typeof client === 'string' ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,\n help: 'Set `client` to one of those values, or drop it to use the registered client plugin.',\n }\n }\n\n // `client` unset: auto-detect a lone registered contract client plugin.\n const registered = contractPlugins.filter(has)\n if (registered.length === 1) {\n return { kind: 'contract', pluginName: registered[0]! }\n }\n if (registered.length > 1) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Multiple client plugins are registered (${registered.map((name) => `\\`@kubb/${name}\\``).join(', ')}) and \\`client\\` is not set.`,\n help: \"Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin.\",\n }\n }\n\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: 'No client plugin is registered.',\n help: 'Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call.',\n }\n}\n\n/**\n * Resolves the contract client during a consumer plugin's setup hook.\n * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.\n * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer\n * fails fast with the same message.\n */\nexport function resolveContractClient(options: {\n plugin: string\n client: ClientSelector | undefined\n plugins?: ReadonlyArray<unknown>\n}): ResolvedContractClient {\n const { plugin, client, plugins = [] } = options\n const pluginNames = plugins.map((plugin) => (plugin as { name?: string }).name).filter((name): name is string => Boolean(name))\n const resolved = resolveClient({ client, pluginNames })\n if (resolved.kind === 'error') {\n const { code, message, help } = resolved\n throw new Diagnostics.Error({ code, severity: 'error', message, help, location: { kind: 'config' }, plugin })\n }\n return resolved\n}\n","import path from 'node:path'\nimport { operationFileEntry } from '@internals/shared'\nimport type { ast, Exclude, Group, Include, NodeCache, Output, Override, Resolver } from 'kubb/kit'\nimport type { ReturnTypeOption } from './types.ts'\n\n/**\n * The resolved contract `<op>` for one operation: the generated function name, the file it lives in,\n * the client module path (where `RequestConfig` / `ResponseErrorConfig` come from), and the\n * registered client plugin's `returnType`.\n *\n * `clientPath` is the absolute `.kubb/client.ts` path for plugin-fetch / plugin-axios, or\n * plugin-client's `importPath`: a relative one is resolved against the `<op>` file to an absolute\n * path, a package name or alias is kept verbatim. `clientPathIsFile` tells a consumer whether to\n * make it relative to the importing file.\n */\nexport type ClientOperation = { name: string; path: string; clientPath: string; clientPathIsFile: boolean; returnType: ReturnTypeOption }\n\n/**\n * The client plugin options a dependent reads, including the filters that scope them per operation.\n */\ntype ClientPluginOptions = {\n output?: Output\n group?: Group | null\n returnType?: ReturnTypeOption\n importPath?: string\n exclude?: Array<Exclude>\n include?: Array<Include>\n override?: Array<Override<Omit<ClientPluginOptions, 'override'>>>\n}\n\nfunction isRelativeImport(importPath: string): boolean {\n return importPath.startsWith('.')\n}\n\n// plugin-client resolves a relative `importPath` from its `<op>` file, so do the same here.\nfunction resolveImportPath(options: { importPath: string; operationFile: string }): string {\n const { importPath, operationFile } = options\n return isRelativeImport(importPath) ? path.resolve(path.dirname(operationFile), importPath) : importPath\n}\n\n/**\n * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up\n * the registered contract client plugin's resolver and output. Works for any contract client plugin\n * (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline\n * path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then\n * emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global\n * output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.\n * With plugin-client they come from the user's `importPath` module instead.\n *\n * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,\n * so several dependents reading the same client plugin for one operation in a single pass\n * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share\n * one computed result instead of each re-deriving the name and path.\n *\n * `returnType`, `output`, and `group` are the client plugin's options for this operation, after its\n * `override` entries, the same resolution its own generator sees. A dependent's generated call body\n * and import path therefore match the `<op>` actually emitted, even when an `override` changes it.\n */\nexport function resolveClientOperation(options: {\n clientPlugin: { pluginName: string } | null\n driver: {\n getPlugin: (name: string) => { options?: ClientPluginOptions } | undefined\n getResolver: (name: string) => Resolver\n }\n node: ast.OperationNode\n root: string\n output: Output\n cache: NodeCache\n}): ClientOperation | null {\n const { clientPlugin, driver, node, root, output, cache } = options\n if (!clientPlugin) return null\n\n return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {\n const resolver = driver.getResolver(clientPlugin.pluginName)\n const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {}\n const { exclude, include, override } = pluginOptions\n const hasOperationOptions = Boolean(exclude?.length || include?.length || override?.length)\n // Kubb's resolver always has `default`; the fallback keeps partial or custom resolvers working.\n const operationOptions =\n hasOperationOptions && resolver.default ? resolver.default.options(node, { options: pluginOptions, exclude, include, override }) : pluginOptions\n if (!operationOptions) return null\n\n const file = resolver.file({\n ...operationFileEntry(node, node.operationId),\n root,\n output: operationOptions.output ?? output,\n group: operationOptions.group ?? undefined,\n })\n\n const { importPath } = operationOptions\n\n return {\n name: resolver.name(node.operationId),\n path: file.path,\n clientPath: importPath === undefined ? path.resolve(root, '.kubb/client.ts') : resolveImportPath({ importPath, operationFile: file.path }),\n clientPathIsFile: importPath === undefined || isRelativeImport(importPath),\n returnType: operationOptions.returnType ?? 'full',\n }\n })\n}\n","import { resolveClientOperation, resolveOperationTypes } from '@internals/client'\nimport { operationFileEntry, resolveDependencyOperationFile } from '@internals/shared'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { McpHandler } from '../components/McpHandler.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool\n * handler per OpenAPI operation. The handler takes the grouped `{ path, query,\n * headers, body }` config and forwards it to the registered client plugin's\n * (`@kubb/plugin-axios` / `@kubb/plugin-fetch`) `<op>` function.\n */\nexport const mcpGenerator = defineGenerator<PluginMcp>({\n name: 'mcp',\n renderer: jsxRenderer,\n operation(node, ctx) {\n if (!ast.isHttpOperationNode(node)) return null\n const { resolver, driver, root, config } = ctx\n const { output, client, group } = ctx.options\n\n const types = resolveOperationTypes(driver, resolver.pluginName)\n const tsResolver = types.resolver\n\n // The registered contract client plugin owns the `<op>` the handler imports and calls.\n const contractOp = resolveClientOperation({ clientPlugin: { pluginName: client.pluginName }, driver, node, root, output, cache: ctx.cache })\n if (!contractOp) {\n return null\n }\n\n // The handler signature references the grouped `<Name>Options`.\n const optionsName = tsResolver.response.options(node)\n\n const meta = {\n name: resolver.handler.name(node),\n file: resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n fileTs: resolveDependencyOperationFile({\n cache: ctx.cache,\n node,\n resolver: tsResolver,\n root,\n output: types.output ?? output,\n group: types.group,\n }),\n } as const\n\n return (\n <File\n baseName={meta.file.baseName}\n path={meta.file.path}\n meta={meta.file.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n >\n {meta.fileTs && optionsName && <File.Import name={[optionsName]} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}\n <File.Import name={['CallToolResult', 'ServerContext']} path={'@modelcontextprotocol/server'} isTypeOnly />\n\n <File.Import name={[contractOp.name]} root={meta.file.path} path={contractOp.path} />\n\n <McpHandler name={meta.name} clientName={contractOp.name} node={node} resolver={tsResolver} returnType={contractOp.returnType} />\n </File>\n )\n },\n})\n","import path from 'node:path'\nimport { getOperationParameters, getPrimarySuccessResponse, operationFileEntry } from '@internals/shared'\nimport { getRelativePath } from '@internals/utils'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { Server } from '../components/Server.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default v5 server generator for `@kubb/plugin-mcp`.\n *\n * Uses individual zod schemas for each param (e.g. `createPetsPathUuidSchema`, `createPetsQueryOffsetSchema`)\n * and `resolveResponseStatusName` for per-status response schemas.\n * Query and header params are composed into `z.object({ ... })` from individual schemas.\n */\nexport const serverGenerator = defineGenerator<PluginMcp>({\n name: 'operations',\n renderer: jsxRenderer,\n operations(nodes, ctx) {\n const { config, resolver, plugin, driver, root } = ctx\n const { output, group } = ctx.options\n\n const pluginZod = ctx.requirePlugin(pluginZodName)\n\n const zodResolver = driver.getResolver(pluginZodName)\n\n const fileAt = <TName extends `${string}.${string}`>(baseName: TName) => ({\n baseName,\n path: path.resolve(root, output.path, baseName),\n meta: { pluginName: plugin.name },\n })\n const serverFile = fileAt('server.ts')\n const startFile = fileAt('start.ts')\n const jsonFile = fileAt('.mcp.json')\n\n // MCP clients spawn the command from their own working directory, usually the project root,\n // so `args` points at `start.ts` relative to `config.root` instead of the `.mcp.json` folder.\n const mcpConfig = {\n mcpServers: {\n [ctx.meta.title || 'server']: {\n type: 'stdio',\n command: 'npx',\n args: ['tsx', getRelativePath(path.resolve(config.root), startFile.path)],\n },\n },\n }\n\n const operationsMapped = nodes.filter(ast.isHttpOperationNode).map((node) => {\n const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node)\n\n const fileEntry = operationFileEntry(node, node.operationId)\n const mcpFile = resolver.file({ ...fileEntry, root, output, group: group ?? undefined })\n const zodFile = zodResolver.file({\n ...fileEntry,\n root,\n output: pluginZod.options?.output ?? output,\n group: pluginZod.options?.group ?? undefined,\n })\n\n const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null\n const successStatus = getPrimarySuccessResponse(node)?.statusCode\n const responseName = successStatus ? zodResolver.response.status(node, successStatus) : null\n\n const resolveParams = (params: typeof pathParams) => params.map((p) => ({ name: p.name, schemaName: zodResolver.param.name(node, p) }))\n\n return {\n tool: {\n name: node.operationId,\n title: node.summary || undefined,\n description: node.description || `Make a ${node.method.toUpperCase()} request to ${node.path}`,\n },\n mcp: {\n name: resolver.handler.name(node),\n file: mcpFile,\n },\n zod: {\n pathParams: resolveParams(pathParams),\n queryParams: queryParams.length ? resolveParams(queryParams) : null,\n headerParams: headerParams.length ? resolveParams(headerParams) : null,\n requestName,\n responseName,\n file: zodFile,\n },\n }\n })\n\n const imports = operationsMapped.flatMap(({ mcp, zod }) => {\n const zodNames = [\n ...zod.pathParams.map((p) => p.schemaName),\n ...(zod.queryParams ?? []).map((p) => p.schemaName),\n ...(zod.headerParams ?? []).map((p) => p.schemaName),\n zod.requestName,\n zod.responseName,\n ].filter((name): name is string => Boolean(name))\n\n const uniqueNames = [...new Set(zodNames)].sort()\n\n return [\n <File.Import key={mcp.name} name={[mcp.name]} root={serverFile.path} path={mcp.file.path} />,\n uniqueNames.length > 0 && <File.Import key={`zod-${mcp.name}`} name={uniqueNames} root={serverFile.path} path={zod.file.path} />,\n ].filter(Boolean)\n })\n\n return (\n <>\n <File\n baseName={serverFile.baseName}\n path={serverFile.path}\n meta={serverFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n >\n <File.Import name={['McpServer']} path={'@modelcontextprotocol/server'} />\n <File.Import name={['serveStdio']} path={'@modelcontextprotocol/server/stdio'} />\n <File.Import name={['z']} path={'zod'} />\n\n {imports}\n <Server serverName={ctx.meta.title ?? 'server'} serverVersion={ctx.meta.version ?? '0.0.0'} operations={operationsMapped} />\n </File>\n\n <File\n baseName={startFile.baseName}\n path={startFile.path}\n meta={startFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n >\n <File.Import name={['startServer']} root={startFile.path} path={serverFile.path} />\n {/* Not indexable: barrels must not re-export this entry, importing it starts the server. */}\n <File.Source name=\"start\">{'void startServer()'}</File.Source>\n </File>\n\n <File baseName={jsonFile.baseName} path={jsonFile.path} meta={jsonFile.meta}>\n <File.Source name=\"server\">{`${JSON.stringify(mcpConfig, null, 2)}\\n`}</File.Source>\n </File>\n </>\n )\n },\n})\n","","","import { camelCase } from '@internals/utils'\nimport { createResolver } from 'kubb/kit'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-mcp`. Decides the names and file\n * paths for every generated MCP tool handler. Function names get a `Handler`\n * suffix so an operation `addPet` becomes `addPetHandler`.\n *\n * @example Resolve a handler name\n * ```ts\n * import { resolverMcp } from '@kubb/plugin-mcp'\n *\n * resolverMcp.name('addPet') // 'addPetHandler'\n * ```\n */\nexport const resolverMcp = createResolver<PluginMcp>({\n pluginName: 'plugin-mcp',\n name(name) {\n return camelCase(name, { suffix: 'handler' })\n },\n handler: {\n name(node) {\n return this.name(node.operationId)\n },\n },\n})\n","import { createGroupConfig } from '@internals/shared'\n\nimport { resolveContractClient } from '@internals/client'\nimport { addGenerator, defineExtension, Resolver, setMacros, setResolver, useConfig } from 'kubb/kit'\nimport { compatibility } from '../kubb-extension.json'\nimport { version } from '../package.json'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { mcpGenerator } from './generators/mcpGenerator.tsx'\nimport { serverGenerator } from './generators/serverGenerator.tsx'\nimport { resolverMcp } from './resolvers/resolverMcp.ts'\nimport type { PluginMcp, ResolverMcp } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginMcpName = 'plugin-mcp' satisfies PluginMcp['name']\n\n/**\n * Generates a Model Context Protocol (MCP) server from an OpenAPI spec. Every\n * operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude\n * Code, MCP-compatible clients) can call directly. Each handler calls a contract\n * client `<op>` from a registered `@kubb/plugin-axios` or `@kubb/plugin-fetch`.\n * Next to the handlers it writes `server.ts`, a `start.ts` entry that serves the\n * tools over stdio, and a `.mcp.json` that runs `start.ts` with `tsx`.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb/config'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginZod } from '@kubb/plugin-zod'\n * import { pluginFetch } from '@kubb/plugin-fetch'\n * import { pluginMcp } from '@kubb/plugin-mcp'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginZod(),\n * pluginFetch({ baseURL: 'https://petstore.swagger.io/v2' }),\n * pluginMcp({ output: { path: 'mcp' } }),\n * ],\n * })\n * ```\n */\nexport const pluginMcp = defineExtension<PluginMcp>({\n kind: 'plugin',\n meta: { name: pluginMcpName, version, compatibility },\n dependencies: { [pluginTsName]: { optional: true }, [pluginZodName]: {} },\n setup(options) {\n const {\n output = { path: 'mcp', barrel: { type: 'named' } },\n group,\n exclude = [],\n include,\n override = [],\n client,\n resolver: userResolver,\n macros: userMacros,\n } = options\n\n const resolver = userResolver ? Resolver.merge<ResolverMcp>(resolverMcp, userResolver) : resolverMcp\n\n setResolver(resolver)\n if (userMacros?.length) {\n setMacros(userMacros)\n }\n addGenerator(mcpGenerator, serverGenerator)\n\n return {\n output,\n exclude,\n include,\n override,\n group: createGroupConfig(group),\n client: resolveContractClient({ plugin: pluginMcpName, client, plugins: useConfig().plugins }),\n resolver,\n }\n },\n})\n\nexport default pluginMcp\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -418,6 +418,73 @@ return server`
418
418
  ] });
419
419
  }
420
420
  //#endregion
421
+ //#region ../../internals/client/src/resolveOperationTypes.ts
422
+ /**
423
+ * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
424
+ * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
425
+ */
426
+ function toZodTypeResolver(resolver) {
427
+ const type = (name) => resolver.schema.type(name);
428
+ return {
429
+ ...resolver,
430
+ file: resolver.file.bind(resolver),
431
+ param: {
432
+ name: (node, p) => type(resolver.param.name(node, p)),
433
+ path: (node, p) => type(resolver.param.path(node, p)),
434
+ query: (node, p) => type(resolver.param.query(node, p)),
435
+ headers: (node, p) => type(resolver.param.headers(node, p))
436
+ },
437
+ response: {
438
+ body: (node) => type(resolver.response.body(node)),
439
+ status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
440
+ response: (node) => type(resolver.response.response(node)),
441
+ responses: (node) => type(resolver.response.responses(node)),
442
+ options: (node) => resolver.response.options(node)
443
+ }
444
+ };
445
+ }
446
+ /**
447
+ * Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.
448
+ *
449
+ * `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`
450
+ * wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws
451
+ * `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.
452
+ *
453
+ * @example
454
+ * ```ts
455
+ * const types = resolveOperationTypes(ctx.driver, ctx.plugin.name)
456
+ * types.response.options(node) // 'GetPetByIdOptions', or 'GetPetByIdOptionsSchemaType' from zod
457
+ * ```
458
+ */
459
+ function resolveOperationTypes(driver, pluginName) {
460
+ const pluginTs = driver.getPlugin(pluginTsName);
461
+ const pluginZod = driver.getPlugin(pluginZodName);
462
+ if (pluginTs && pluginZod?.options?.inferred !== "codec") {
463
+ const resolver = driver.getResolver(pluginTsName);
464
+ return {
465
+ response: resolver.response,
466
+ resolver,
467
+ output: pluginTs.options?.output,
468
+ group: pluginTs.options?.group ?? void 0
469
+ };
470
+ }
471
+ if (!pluginZod?.options?.inferred) throw new Diagnostics.Error({
472
+ code: Diagnostics.code.missingDependency,
473
+ severity: "error",
474
+ message: `Plugin "${pluginName}" has no source for operation types.`,
475
+ help: `Add \`pluginTs()\` before "${pluginName}", or add \`pluginZod({ inferred: true })\`.`,
476
+ location: { kind: "config" },
477
+ plugin: pluginName
478
+ });
479
+ const resolver = toZodTypeResolver(driver.getResolver(pluginZodName));
480
+ return {
481
+ response: resolver.response,
482
+ resolver,
483
+ output: pluginZod.options.output,
484
+ group: pluginZod.options.group ?? void 0
485
+ };
486
+ }
487
+ //#endregion
421
488
  //#region ../../internals/client/src/resolveClient.ts
422
489
  /**
423
490
  * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
@@ -603,8 +670,8 @@ const mcpGenerator = defineGenerator({
603
670
  if (!ast.isHttpOperationNode(node)) return null;
604
671
  const { resolver, driver, root, config } = ctx;
605
672
  const { output, client, group } = ctx.options;
606
- const pluginTs = ctx.requirePlugin(pluginTsName);
607
- const tsResolver = driver.getResolver(pluginTsName);
673
+ const types = resolveOperationTypes(driver, resolver.pluginName);
674
+ const tsResolver = types.resolver;
608
675
  const contractOp = resolveClientOperation({
609
676
  clientPlugin: { pluginName: client.pluginName },
610
677
  driver,
@@ -628,8 +695,8 @@ const mcpGenerator = defineGenerator({
628
695
  node,
629
696
  resolver: tsResolver,
630
697
  root,
631
- output: pluginTs.options?.output ?? output,
632
- group: pluginTs.options?.group
698
+ output: types.output ?? output,
699
+ group: types.group
633
700
  })
634
701
  };
635
702
  return /* @__PURE__ */ jsxs(File, {
@@ -862,7 +929,7 @@ var compatibility = {
862
929
  };
863
930
  //#endregion
864
931
  //#region package.json
865
- var version = "5.3.0";
932
+ var version = "5.3.2";
866
933
  //#endregion
867
934
  //#region src/resolvers/resolverMcp.ts
868
935
  /**
@@ -929,7 +996,7 @@ const pluginMcp = defineExtension({
929
996
  compatibility
930
997
  },
931
998
  dependencies: {
932
- [pluginTsName]: {},
999
+ [pluginTsName]: { optional: true },
933
1000
  [pluginZodName]: {}
934
1001
  },
935
1002
  setup(options) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../internals/shared/src/operation.ts","../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/shared/src/group.ts","../src/components/McpHandler.tsx","../src/components/Server.tsx","../../../internals/client/src/resolveClient.ts","../../../internals/client/src/resolveClientOperation.ts","../src/generators/mcpGenerator.tsx","../src/generators/serverGenerator.tsx","../kubb-extension.json","../package.json","../src/resolvers/resolverMcp.ts","../src/plugin.ts"],"sourcesContent":["import { ast, type Group, type NodeCache, type Output, type Resolver, type ResolverFileParams, Url } from 'kubb/kit'\n\n/**\n * Builds the `ResolverFileParams` every operation generator passes to\n * `resolver.file`: a file named `name`, tagged by the operation's first\n * tag (or `'default'`), at the operation's path. Centralizes the entry object\n * that was repeated at dozens of call sites across the client and query plugins.\n *\n * @example\n * ```ts\n * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })\n * ```\n */\nexport function operationFileEntry(node: ast.OperationNode, name: string, extname: ResolverFileParams['extname'] = '.ts'): ResolverFileParams {\n return {\n name,\n extname,\n tag: node.tags[0] ?? 'default',\n path: node.path,\n }\n}\n\n/**\n * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the\n * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the\n * same dependency for the same operation in one pass (a query plugin's several hook generators, the\n * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.\n *\n * @example Cache `plugin-ts`'s file for the current operation\n * ```ts\n * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })\n * ```\n */\nexport function resolveDependencyOperationFile(options: {\n cache: NodeCache\n node: ast.OperationNode\n resolver: Pick<Resolver, 'file' | 'pluginName'>\n root: string\n output: Output\n group?: Group | null\n}): ast.FileNode {\n const { cache, node, resolver, root, output, group } = options\n\n return cache.ensureItem(`${resolver.pluginName}:operationFile`, () =>\n resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n )\n}\n\nexport type ContentTypeInfo = {\n contentTypes: string[]\n isMultipleContentTypes: boolean\n contentTypeUnion: string\n defaultContentType: string\n hasFormData: boolean\n}\n\nexport type RequestConfigResolver = {\n response: {\n body(node: ast.OperationNode): string\n }\n}\n\nexport type ResponseStatusNameResolver = {\n response: {\n status(node: ast.OperationNode, statusCode: ast.StatusCode): string\n }\n}\n\nexport type ResponseNameResolver = ResponseStatusNameResolver & {\n response: {\n response(node: ast.OperationNode): string\n }\n}\n\nexport type OperationTypeNameResolver = RequestConfigResolver &\n ResponseNameResolver & {\n param: {\n path(node: ast.OperationNode, param: ast.ParameterNode): string\n query(node: ast.OperationNode, param: ast.ParameterNode): string\n headers(node: ast.OperationNode, param: ast.ParameterNode): string\n }\n }\n\nexport type OperationCommentLink = 'pathTemplate' | 'urlPath' | false | ((node: ast.OperationNode) => string | undefined)\n\nexport type BuildOperationCommentsOptions = {\n link?: OperationCommentLink\n linkPosition?: 'beforeDeprecated' | 'afterDeprecated'\n splitLines?: boolean\n}\n\ntype ResponseLike = {\n statusCode: ast.StatusCode | number | string\n}\n\nexport type OperationParameterGroups = Record<ast.ParameterNode['in'], Array<ast.ParameterNode>>\n\nexport type ResolveOperationTypeNameOptions = {\n responseStatusNames?: boolean | 'error'\n exclude?: ReadonlyArray<string | undefined>\n order?: 'params-first' | 'body-response-first'\n /**\n * Include the individual `Path`/`Query`/`Headers` group type names. Set to `false` for clients\n * that reference the grouped `Options` type instead of the per-group types.\n */\n includeParams?: boolean\n}\n\nfunction getOperationLink(node: ast.OperationNode, link: OperationCommentLink): string | null {\n if (!link) {\n return null\n }\n\n if (typeof link === 'function') {\n return link(node) ?? null\n }\n\n return node.path ? `{@link ${Url.toPath(node.path)}}` : null\n}\n\n/**\n * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several\n * are present and the union, default, and form-data flags the client uses to pick one.\n */\nfunction buildContentTypeInfo(contentTypes: string[]): ContentTypeInfo {\n const isMultipleContentTypes = contentTypes.length > 1\n\n return {\n contentTypes,\n isMultipleContentTypes,\n contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(' | ') : '',\n defaultContentType: contentTypes[0] ?? 'application/json',\n hasFormData: contentTypes.some((ct) => ct === 'multipart/form-data'),\n }\n}\n\nexport function getContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? [])\n}\n\n/**\n * The request-body counterpart for the primary success response: the content types it documents and\n * whether several are present, so the client can let a caller pick which one to accept.\n */\nexport function getResponseContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [])\n}\n\nexport type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'\n\n/**\n * Reads the single base content type of an operation's primary success response, lowercased and\n * stripped of any `; charset=...` suffix. Returns `undefined` when the response declares zero or\n * more than one content type, since neither case has a single type to act on.\n */\nfunction getPrimarySuccessContentType(node: ast.OperationNode): string | undefined {\n const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? []\n if (contentTypes.length !== 1) return undefined\n return contentTypes[0]!.split(';')[0]!.trim().toLowerCase()\n}\n\n/**\n * Whether an operation streams its primary success response as Server-Sent Events\n * (`text/event-stream`). The client generator uses this to return a typed event stream instead of a\n * one-shot `RequestResult`.\n */\nexport function isEventStream(node: ast.OperationNode): boolean {\n return getPrimarySuccessContentType(node) === 'text/event-stream'\n}\n\n/**\n * Derives the default `responseType` for an operation from its primary success response.\n *\n * Returns a value only when that response declares a single non-JSON content type. `text/event-stream`\n * and other binary types (`application/octet-stream`, `application/pdf`, `image/*`, `audio/*`,\n * `video/*`) map to a stream or `'blob'`, and other `text/*` maps to `'text'`. Otherwise `undefined`,\n * leaving the runtime client's `Content-Type` auto-detection in charge.\n */\nexport function getResponseType(node: ast.OperationNode): ResponseType | undefined {\n const baseType = getPrimarySuccessContentType(node)\n if (!baseType) return undefined\n\n if (baseType === 'application/json' || baseType.endsWith('+json') || baseType === 'text/json') return undefined\n if (baseType === 'text/event-stream') return 'stream'\n if (baseType.startsWith('text/')) return 'text'\n if (baseType === 'application/octet-stream' || baseType === 'application/pdf' || /^(image|audio|video)\\//.test(baseType)) return 'blob'\n return undefined\n}\n\n/**\n * Maps a content type to the PascalCase suffix used to name per-content-type variants\n * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).\n */\nfunction getContentTypeSuffix(contentType: string): string {\n const baseType = contentType.split(';')[0]!.trim()\n if (baseType === 'application/json') return 'Json'\n if (baseType === 'multipart/form-data') return 'FormData'\n if (baseType === 'application/x-www-form-urlencoded') return 'FormUrlEncoded'\n const subtype = baseType.split('/').pop() ?? baseType\n const parts = subtype.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n if (parts.length === 0) return 'Unknown'\n return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')\n}\n\n/**\n * Appends a content-type suffix to a base name, keeping a trailing `Data` segment last\n * (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).\n */\nexport function getPerContentTypeName(baseName: string, suffix: string): string {\n if (baseName.endsWith('Data')) {\n return suffix.endsWith('Data') ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`\n }\n return baseName + suffix\n}\n\nexport type ContentVariantInput = { contentType: string; schema?: ast.SchemaNode | null; keysToOmit?: Array<string> | null }\nexport type ContentVariant = { name: string; suffix: string; schema: ast.SchemaNode; keysToOmit?: Array<string> | null; contentType: string }\n\n/**\n * Resolves per-content-type variant names for a set of content entries, deduplicating suffix\n * collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is\n * the final (possibly counter-augmented) value, so callers can derive parallel names in another\n * namespace (e.g. plugin-faker deriving the matching plugin-ts type name).\n */\nexport function resolveContentTypeVariants(entries: Array<ContentVariantInput>, baseName: string): Array<ContentVariant> {\n const usedNames = new Set<string>()\n return entries\n .filter((entry) => entry.schema)\n .map((entry) => {\n const baseSuffix = getContentTypeSuffix(entry.contentType)\n let suffix = baseSuffix\n let name = getPerContentTypeName(baseName, suffix)\n let counter = 2\n while (usedNames.has(name)) {\n suffix = `${baseSuffix}${counter++}`\n name = getPerContentTypeName(baseName, suffix)\n }\n usedNames.add(name)\n return { name, suffix, schema: entry.schema!, keysToOmit: entry.keysToOmit, contentType: entry.contentType }\n })\n}\n\n// The request groups come from the grouped params, so `config` drops the data-shape keys to stay\n// assignable to `Options`, which omits them from `RequestConfig`.\nconst requestConfigBaseType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`\n\nexport function buildRequestConfigType(node: ast.OperationNode): string {\n const request = getContentTypeInfo(node)\n const response = getResponseContentTypeInfo(node)\n\n // Only the ambiguous side is offered: a single-type side has nothing to pick, so it stays baked in\n // the generated call.\n const members = [\n request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null,\n response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null,\n ].filter(Boolean)\n\n return members.length ? `${requestConfigBaseType} & { contentType?: { ${members.join('; ')} } }` : requestConfigBaseType\n}\n\n/**\n * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,\n * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a\n * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a\n * content type for.\n */\nexport function buildClientOptionType(): string {\n return requestConfigBaseType\n}\n\nexport type RequestGroups = {\n path: boolean\n query: boolean\n body: boolean\n headers: boolean\n}\n\n/**\n * Which of the grouped request options an operation carries.\n */\nexport function getRequestGroups(node: ast.OperationNode): RequestGroups {\n const { path, query, header } = getOperationParameters(node)\n return {\n path: path.length > 0,\n query: query.length > 0,\n body: Boolean(node.requestBody?.content?.[0]?.schema),\n headers: header.length > 0,\n }\n}\n\nexport type RequestGroupOptionality = {\n groups: RequestGroups\n hasRequiredPath: boolean\n hasRequiredQuery: boolean\n hasRequiredHeader: boolean\n /**\n * Whether the grouped request parameter can default to `{}`. True only when no group carries a\n * required member, so every member is safe to omit.\n */\n isOptional: boolean\n}\n\n/**\n * Resolves which grouped request options an operation carries together with whether each group\n * holds a required member. The grouped parameter stays optional only when nothing inside it is\n * required, matching the generated `RequestConfig` type.\n */\nexport function getRequestGroupOptionality(node: ast.OperationNode): RequestGroupOptionality {\n const groups = getRequestGroups(node)\n const { path, query, header } = getOperationParameters(node)\n const hasRequiredPath = path.some((param) => param.required)\n const hasRequiredQuery = query.some((param) => param.required)\n const hasRequiredHeader = header.some((param) => param.required)\n\n return {\n groups,\n hasRequiredPath,\n hasRequiredQuery,\n hasRequiredHeader,\n isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body,\n }\n}\n\nexport type RequestOptionsNameResolver = RequestConfigResolver & {\n response: {\n options(node: ast.OperationNode): string\n }\n}\n\n/**\n * Builds the grouped `{ path, query, body, headers }` parameter for a generated client\n * function, typed from the operation's `Options` (minus `url`). Only the groups the\n * operation actually has are destructured. The trailing `config` parameter carries the\n * runtime `RequestConfig` overrides plus `client`.\n */\nexport function buildRequestParamsSignature(\n node: ast.OperationNode,\n resolver: RequestOptionsNameResolver,\n options: { isConfigurable?: boolean } = {},\n): { signature: string; groups: RequestGroups } {\n const { isConfigurable = true } = options\n const { groups, isOptional } = getRequestGroupOptionality(node)\n\n const names = (['path', 'query', 'body', 'headers'] as const).filter((key) => groups[key])\n\n const firstParam = names.length > 0 ? `{ ${names.join(', ')} }: ${resolver.response.options(node)}${isOptional ? ' = {}' : ''}` : null\n const configParam = isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null\n\n return {\n signature: [firstParam, configParam].filter(Boolean).join(', '),\n groups,\n }\n}\n\nexport function buildOperationComments(node: ast.OperationNode, options: BuildOperationCommentsOptions = {}): Array<string> {\n const { link = 'pathTemplate', linkPosition = 'afterDeprecated', splitLines = false } = options\n const linkComment = getOperationLink(node, link)\n const comments =\n linkPosition === 'beforeDeprecated'\n ? [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, linkComment, node.deprecated && '@deprecated']\n : [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, node.deprecated && '@deprecated', linkComment]\n\n const filteredComments = comments.filter((comment): comment is string => Boolean(comment))\n\n if (!splitLines) {\n return filteredComments\n }\n\n return filteredComments.flatMap((text) => text.split(/\\r?\\n/).map((line) => line.trim())).filter((comment): comment is string => Boolean(comment))\n}\n\nconst operationParameterGroupsByNode = new WeakMap<ast.OperationNode, OperationParameterGroups>()\n\n/**\n * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each\n * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance\n * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the\n * same parameters once per plugin.\n */\nexport function getOperationParameters(node: ast.OperationNode): OperationParameterGroups {\n const cached = operationParameterGroupsByNode.get(node)\n if (cached) return cached\n\n // A malformed spec can declare the same name twice within one location. Both would resolve to the\n // same output property, so emitting both would yield an object type with a duplicate member,\n // which TypeScript rejects. Keep the first.\n const group = (location: ast.ParameterNode['in']) => {\n const seen = new Set<string>()\n\n return node.parameters.filter((param) => {\n if (param.in !== location || seen.has(param.name)) return false\n seen.add(param.name)\n return true\n })\n }\n\n const groups: OperationParameterGroups = { path: group('path'), query: group('query'), header: group('header'), cookie: group('cookie') }\n\n operationParameterGroupsByNode.set(node, groups)\n return groups\n}\n\n/**\n * Builds the combined `{ body, path, query, headers }` options object schema for an operation,\n * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s\n * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same\n * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod\n * printer to emit `z.object(…)` rather than a record.\n */\nexport function buildOptionsSchema(node: ast.OperationNode, resolver: OperationTypeNameResolver): ast.SchemaNode {\n const { path, query, header } = getOperationParameters(node)\n const hasBody = Boolean(node.requestBody?.content?.[0]?.schema)\n const createNever = () => ast.factory.createSchema({ type: 'never', primitive: undefined, optional: true })\n const groups = [\n { name: 'path', params: path, resolve: resolver.param.path },\n { name: 'query', params: query, resolve: resolver.param.query },\n { name: 'headers', params: header, resolve: resolver.param.headers },\n ] as const\n\n // NOTE(v5-stable): the fields were renamed from the legacy beta shape\n // (`data`/`pathParams`/`queryParams`/`headerParams`) to `body`/`path`/`query`/`headers` so the\n // type matches the runtime client. Drop this note once v5 leaves beta.\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n deprecated: node.deprecated,\n properties: [\n ast.factory.createProperty({\n name: 'body',\n required: hasBody,\n schema: hasBody ? ast.factory.createSchema({ type: 'ref', name: resolver.response.body(node) }) : createNever(),\n }),\n ...groups.map(({ name, params, resolve }) => {\n const required = params.some((param) => param.required)\n\n return ast.factory.createProperty({\n name,\n required,\n schema:\n params.length > 0\n ? ast.factory.createSchema({ type: 'ref', name: resolve.call(resolver.param, node, params[0]!), optional: !required })\n : createNever(),\n })\n }),\n ],\n })\n}\n\n/**\n * The schema a status occupies in the `<Name>Responses` record. A status that documents several\n * content types becomes a `{ contentType; data }` union so the runtime can surface the negotiated type\n * on `result.parsed`, while the standalone `<Name>StatusNNN` alias stays the plain body union that the\n * query hooks and `result.data` use.\n */\nfunction buildResponseRecordEntry(node: ast.OperationNode, res: ast.ResponseNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n const statusName = resolver.response.status(node, res.statusCode)\n const variants = (res.content ?? []).filter((entry) => entry.schema)\n if (variants.length <= 1) {\n return ast.factory.createSchema({ type: 'ref', name: statusName })\n }\n\n return ast.factory.createSchema({\n type: 'union',\n members: resolveContentTypeVariants(variants, statusName).map((variant) =>\n ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: [\n ast.factory.createProperty({\n name: 'contentType',\n required: true,\n schema: ast.factory.createSchema({ type: 'enum', enumValues: [variant.contentType] }),\n }),\n ast.factory.createProperty({\n name: 'data',\n required: true,\n schema: ast.factory.createSchema({ type: 'ref', name: variant.name }),\n }),\n ],\n }),\n ),\n })\n}\n\n/**\n * Builds the per-status `<Name>Responses` record for an operation, referencing the already-resolved\n * `<Name>StatusNNN` names. Shared by `@kubb/plugin-ts`'s `Responses` type and `@kubb/plugin-zod`'s\n * inferred responses schema, so both emit the same shape from the same inputs.\n *\n * Always emits the keyed record, even when an operation declares no responses. An operation with no\n * responses renders as an empty object, which keeps every consumer's import (for example the axios\n * SDK's `RequestResult<XResponses>`) resolvable instead of pointing at a missing export.\n */\nexport function buildResponses(node: ast.OperationNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: node.responses.map((res) =>\n ast.factory.createProperty({\n name: String(res.statusCode),\n required: true,\n schema: buildResponseRecordEntry(node, res, resolver),\n }),\n ),\n })\n}\n\nexport function getStatusCodeNumber(statusCode: ast.StatusCode | number | string): number | null {\n const code = Number(statusCode)\n\n return Number.isNaN(code) ? null : code\n}\n\nexport function isSuccessStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 200 && code < 300\n}\n\nexport function isErrorStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 400\n}\n\nexport function getSuccessResponses<TResponse extends ResponseLike>(responses: ReadonlyArray<TResponse>): Array<TResponse> {\n return responses.filter((response) => isSuccessStatusCode(response.statusCode))\n}\n\nexport function getOperationSuccessResponses(node: ast.OperationNode): Array<ast.ResponseNode> {\n return getSuccessResponses(node.responses)\n}\n\nexport function getPrimarySuccessResponse(node: ast.OperationNode): ast.ResponseNode | null {\n return getOperationSuccessResponses(node)[0] ?? null\n}\n\nexport function resolveErrorNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveSuccessNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveStatusCodeNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.map((response) => resolver.response.status(node, response.statusCode))\n}\n\nconst typeNamesByResolver = new WeakMap<OperationTypeNameResolver, Map<string, string[]>>()\n\nexport function resolveOperationTypeNames(\n node: ast.OperationNode,\n resolver: OperationTypeNameResolver,\n options: ResolveOperationTypeNameOptions = {},\n): string[] {\n const cacheKey = `${node.operationId}\\0${options.order ?? ''}\\0${options.responseStatusNames ?? ''}\\0${options.includeParams === false ? 'noparams' : ''}\\0${(options.exclude ?? []).join(',')}`\n let byResolver = typeNamesByResolver.get(resolver)\n if (byResolver) {\n const cached = byResolver.get(cacheKey)\n if (cached) return cached\n } else {\n byResolver = new Map()\n typeNamesByResolver.set(resolver, byResolver)\n }\n\n const { path, query, header } = getOperationParameters(node)\n const responseStatusNames =\n options.responseStatusNames === 'error'\n ? resolveErrorNames(node, resolver)\n : options.responseStatusNames === false\n ? []\n : resolveStatusCodeNames(node, resolver)\n const exclude = new Set(options.exclude ?? [])\n const paramNames =\n options.includeParams === false\n ? []\n : [\n ...path.map((param) => resolver.param.path(node, param)),\n ...query.map((param) => resolver.param.query(node, param)),\n ...header.map((param) => resolver.param.headers(node, param)),\n ]\n const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)]\n const names =\n options.order === 'body-response-first'\n ? [...bodyAndResponseNames, ...paramNames, ...responseStatusNames]\n : [...paramNames, ...bodyAndResponseNames, ...responseStatusNames]\n\n const result = names.filter((name): name is string => Boolean(name) && !exclude.has(name as string))\n byResolver.set(cacheKey, result)\n return result\n}\n\nexport function resolveResponseTypes(node: ast.OperationNode, resolver: ResponseNameResolver): Array<[statusCode: number | 'default', typeName: string]> {\n const types: Array<[number | 'default', string]> = []\n\n for (const response of node.responses) {\n if (response.statusCode === 'default') {\n types.push(['default', resolver.response.response(node)])\n continue\n }\n\n const code = getStatusCodeNumber(response.statusCode)\n if (code === null) {\n continue\n }\n\n types.push([code, isSuccessStatusCode(code) ? resolver.response.response(node) : resolver.response.status(node, response.statusCode)])\n }\n\n return types\n}\n","type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction convert(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n// Plugins resolve the same names over and over (about 47,000 calls for a 1,000 schema spec), so\n// results are kept. Clearing at the limit bounds the memory a long-running process spends on it.\nconst cache = new Map<string, string>()\nconst cacheLimit = 10_000\n\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const key = `${pascal ? 'P' : 'c'}${text}`\n const cached = cache.get(key)\n if (cached !== undefined) return cached\n\n const result = convert(text, pascal)\n if (cache.size >= cacheLimit) cache.clear()\n cache.set(key, result)\n return result\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Uppercases only the first character of `text`, leaving the rest untouched.\n * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.\n *\n * @example\n * `capitalize('getPetById') // 'GetPetById'`\n */\nexport function capitalize(text: string): string {\n return `${text.charAt(0).toUpperCase()}${text.slice(1)}`\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from 'kubb/kit'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { buildOperationComments, buildRequestParamsSignature } from '@internals/shared'\nimport type { ast } from 'kubb/kit'\nimport type { ResolverTs } from '@kubb/plugin-ts'\nimport { File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype Props = {\n /**\n * Name of the handler function.\n */\n name: string\n /**\n * Name of the contract client `<op>` the handler calls.\n */\n clientName: string\n /**\n * AST operation node.\n */\n node: ast.HttpOperationNode\n /**\n * TypeScript resolver for resolving param/data/response type names.\n */\n resolver: ResolverTs\n /**\n * The registered client plugin's `returnType`, read by the caller off `resolveClientOperation`.\n */\n returnType?: 'full' | 'data' | 'plain'\n}\n\nconst requestGroupOrder = ['path', 'query', 'headers', 'body'] as const\n\nexport function McpHandler({ name, clientName, node, resolver, returnType = 'full' }: Props): KubbReactNode {\n const { signature, groups } = buildRequestParamsSignature(node, resolver, { isConfigurable: false })\n const paramsSignature = [signature, 'ctx: ServerContext'].filter(Boolean).join(', ')\n\n // Forward the grouped config and MCP cancellation signal through the contract client. `throwOnError: true`\n // pins the result shape, since `throwOnErrorDefault: false` would otherwise resolve to the full result.\n const callArgs = requestGroupOrder.filter((key) => groups[key])\n const callConfig = `{ ${[...callArgs, 'signal: ctx.mcpReq.signal', 'throwOnError: true'].join(', ')} }`\n const body = returnType === 'data' ? 'res' : 'res.data'\n\n const callToolResult = `return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(${body})\n }\n ],\n structuredContent: { data: ${body} }\n}`\n\n return (\n <File.Source name={name} isExportable isIndexable>\n <Function\n name={name}\n async\n export\n params={paramsSignature}\n JSDoc={{\n comments: buildOperationComments(node),\n }}\n returnType={'CallToolResult'}\n >\n {`const res = await ${clientName}(${callConfig})`}\n <br />\n {callToolResult}\n </Function>\n </File.Source>\n )\n}\n","import type { ast } from 'kubb/kit'\nimport { Const, File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype ZodParam = {\n name: string\n schemaName: string\n}\n\n/**\n * Composes individual param schemas into `z.object({ ... })`.\n */\nconst zodObject = (params: Array<ZodParam>) => `z.object({ ${params.map((p) => `${JSON.stringify(p.name)}: ${p.schemaName}`).join(', ')} })`\n\ntype Props = {\n /**\n * Human-readable server name passed to `new McpServer({ name })`.\n */\n serverName: string\n /**\n * Semantic version string passed to `new McpServer({ version })`.\n */\n serverVersion: string\n /**\n * Operations to register as MCP tools, each carrying its handler,\n * zod schema, and AST node metadata.\n */\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: ast.FileNode\n }\n zod: {\n pathParams: Array<ZodParam>\n /**\n * Query params — individual schemas to compose into `z.object({ ... })`.\n */\n queryParams?: Array<ZodParam> | null\n /**\n * Header params — individual schemas to compose into `z.object({ ... })`.\n */\n headerParams?: Array<ZodParam> | null\n requestName?: string | null\n responseName?: string | null\n }\n }>\n}\n\nexport function Server({ serverName, serverVersion, operations }: Props): KubbReactNode {\n const registrations = operations\n .map(({ tool, mcp, zod }) => {\n // Group params into the same `{ path, query, headers, body }` shape the contract `<op>`\n // expects, so the MCP tool input mirrors every other client consumer.\n const entries: Array<{ key: string; value: string }> = []\n\n if (zod.pathParams.length) {\n entries.push({ key: 'path', value: zodObject(zod.pathParams) })\n }\n\n if (zod.queryParams) {\n entries.push({ key: 'query', value: zodObject(zod.queryParams) })\n }\n\n if (zod.headerParams) {\n entries.push({ key: 'headers', value: zodObject(zod.headerParams) })\n }\n\n if (zod.requestName) {\n entries.push({ key: 'body', value: zod.requestName })\n }\n\n const destructured = `{ ${entries.map((e) => e.key).join(', ')} }`\n const inputSchema = entries.length ? `z.object({ ${entries.map((e) => `${e.key}: ${e.value}`).join(', ')} })` : null\n const outputSchema = zod.responseName\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: z.object({ data: ${outputSchema} })` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (inputSchema) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${inputSchema},\n}, async (${destructured}, ctx) => {\n return ${mcp.name}(${destructured}, ctx)\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async (ctx) => {\n return ${mcp.name}(ctx)\n})\n `\n })\n .filter(Boolean)\n .join('\\n')\n\n return (\n <>\n <File.Source name=\"getServer\" isExportable isIndexable>\n <Function name=\"getServer\" export>\n {`const server = new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n${registrations}\nreturn server`}\n </Function>\n </File.Source>\n\n <File.Source name=\"server\" isExportable isIndexable>\n <Const name={'server'} export>\n {'getServer()'}\n </Const>\n </File.Source>\n\n <File.Source name=\"startServer\" isExportable isIndexable>\n <Function name=\"startServer\" async export>\n {`return serveStdio(getServer, {\n onerror: (error) => console.error('MCP server error:', error),\n })`}\n </Function>\n </File.Source>\n </>\n )\n}\n","/**\n * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an\n * operation, shared so the selection rules and diagnostics stay in one place.\n *\n * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered\n * contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own\n * inline client:\n *\n * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer\n * imports and calls them.\n * - `error` — no client plugin is registered, several are registered without a selector, the\n * requested one is missing, or `client` is not a known selector.\n *\n * The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a\n * lone registered contract client plugin is picked up automatically.\n */\n\nimport { Diagnostics } from 'kubb/kit'\n\n// Canonical plugin names. They mirror the `pluginFetchName` / `pluginAxiosName` / `pluginClientName`\n// consts the plugins export, kept as literals so this internal needs no plugin install deps.\nconst pluginFetchName = 'plugin-fetch'\nconst pluginAxiosName = 'plugin-axios'\nconst pluginClientName = 'plugin-client'\n\n/**\n * The client selector accepted by a consumer's `client` option. Each calls a registered contract\n * client plugin.\n */\nexport type ClientSelector = 'fetch' | 'axios' | 'client'\n\n/**\n * The resolved client strategy stored in a consumer plugin's options: the generated code always\n * imports and calls a registered contract client plugin's `<op>`. The client runtime lives in\n * plugin-axios / plugin-fetch, so nothing is bundled by the consumer.\n */\nexport type ResolvedContractClient = { kind: 'contract'; pluginName: string }\n\n/**\n * The outcome of {@link resolveClient}.\n *\n * - `contract` names the contract client plugin whose `<op>` functions the consumer imports.\n * - `error` carries a setup diagnostic: its code, what is wrong, and how to fix it.\n */\nexport type ResolveClientResult =\n | ResolvedContractClient\n | { kind: 'error'; code: typeof Diagnostics.code.missingDependency | typeof Diagnostics.code.invalidPluginOptions; message: string; help: string }\n\nconst selectorToPlugin: Record<ClientSelector, string> = {\n fetch: pluginFetchName,\n axios: pluginAxiosName,\n client: pluginClientName,\n}\n\n// Every contract client plugin, in auto-detect priority order.\nconst contractPlugins = [pluginFetchName, pluginAxiosName, pluginClientName] as const\n\n/**\n * Applies the `client` resolution rules. See the module comment for the strategy shape.\n *\n * @example\n * ```ts\n * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })\n * // { kind: 'contract', pluginName: 'plugin-fetch' }\n * ```\n *\n * @example\n * ```ts\n * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })\n * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }\n * ```\n */\nexport function resolveClient(options: { client: ClientSelector | undefined; pluginNames: ReadonlyArray<string> }): ResolveClientResult {\n const { client, pluginNames } = options\n const has = (name: string) => pluginNames.includes(name)\n\n if (client === 'fetch' || client === 'axios' || client === 'client') {\n const pluginName = selectorToPlugin[client]\n if (!has(pluginName)) {\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: `\\`client: '${client}'\\` is set but \\`@kubb/plugin-${client}\\` is not registered in \\`plugins\\`.`,\n help: `Add \\`@kubb/plugin-${client}\\` to \\`plugins\\`, or drop \\`client\\` to use a different client plugin.`,\n }\n }\n return { kind: 'contract', pluginName }\n }\n\n // A JS config bypasses the `ClientSelector` type, so reject unknown selectors instead of auto-detecting.\n if (client !== undefined) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Option \\`client\\` is ${typeof client === 'string' ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,\n help: 'Set `client` to one of those values, or drop it to use the registered client plugin.',\n }\n }\n\n // `client` unset: auto-detect a lone registered contract client plugin.\n const registered = contractPlugins.filter(has)\n if (registered.length === 1) {\n return { kind: 'contract', pluginName: registered[0]! }\n }\n if (registered.length > 1) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Multiple client plugins are registered (${registered.map((name) => `\\`@kubb/${name}\\``).join(', ')}) and \\`client\\` is not set.`,\n help: \"Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin.\",\n }\n }\n\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: 'No client plugin is registered.',\n help: 'Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call.',\n }\n}\n\n/**\n * Resolves the contract client during a consumer plugin's setup hook.\n * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.\n * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer\n * fails fast with the same message.\n */\nexport function resolveContractClient(options: {\n plugin: string\n client: ClientSelector | undefined\n plugins?: ReadonlyArray<unknown>\n}): ResolvedContractClient {\n const { plugin, client, plugins = [] } = options\n const pluginNames = plugins.map((plugin) => (plugin as { name?: string }).name).filter((name): name is string => Boolean(name))\n const resolved = resolveClient({ client, pluginNames })\n if (resolved.kind === 'error') {\n const { code, message, help } = resolved\n throw new Diagnostics.Error({ code, severity: 'error', message, help, location: { kind: 'config' }, plugin })\n }\n return resolved\n}\n","import path from 'node:path'\nimport { operationFileEntry } from '@internals/shared'\nimport type { ast, Exclude, Group, Include, NodeCache, Output, Override, Resolver } from 'kubb/kit'\nimport type { ReturnTypeOption } from './types.ts'\n\n/**\n * The resolved contract `<op>` for one operation: the generated function name, the file it lives in,\n * the client module path (where `RequestConfig` / `ResponseErrorConfig` come from), and the\n * registered client plugin's `returnType`.\n *\n * `clientPath` is the absolute `.kubb/client.ts` path for plugin-fetch / plugin-axios, or\n * plugin-client's `importPath`: a relative one is resolved against the `<op>` file to an absolute\n * path, a package name or alias is kept verbatim. `clientPathIsFile` tells a consumer whether to\n * make it relative to the importing file.\n */\nexport type ClientOperation = { name: string; path: string; clientPath: string; clientPathIsFile: boolean; returnType: ReturnTypeOption }\n\n/**\n * The client plugin options a dependent reads, including the filters that scope them per operation.\n */\ntype ClientPluginOptions = {\n output?: Output\n group?: Group | null\n returnType?: ReturnTypeOption\n importPath?: string\n exclude?: Array<Exclude>\n include?: Array<Include>\n override?: Array<Override<Omit<ClientPluginOptions, 'override'>>>\n}\n\nfunction isRelativeImport(importPath: string): boolean {\n return importPath.startsWith('.')\n}\n\n// plugin-client resolves a relative `importPath` from its `<op>` file, so do the same here.\nfunction resolveImportPath(options: { importPath: string; operationFile: string }): string {\n const { importPath, operationFile } = options\n return isRelativeImport(importPath) ? path.resolve(path.dirname(operationFile), importPath) : importPath\n}\n\n/**\n * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up\n * the registered contract client plugin's resolver and output. Works for any contract client plugin\n * (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline\n * path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then\n * emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global\n * output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.\n * With plugin-client they come from the user's `importPath` module instead.\n *\n * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,\n * so several dependents reading the same client plugin for one operation in a single pass\n * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share\n * one computed result instead of each re-deriving the name and path.\n *\n * `returnType`, `output`, and `group` are the client plugin's options for this operation, after its\n * `override` entries, the same resolution its own generator sees. A dependent's generated call body\n * and import path therefore match the `<op>` actually emitted, even when an `override` changes it.\n */\nexport function resolveClientOperation(options: {\n clientPlugin: { pluginName: string } | null\n driver: {\n getPlugin: (name: string) => { options?: ClientPluginOptions } | undefined\n getResolver: (name: string) => Resolver\n }\n node: ast.OperationNode\n root: string\n output: Output\n cache: NodeCache\n}): ClientOperation | null {\n const { clientPlugin, driver, node, root, output, cache } = options\n if (!clientPlugin) return null\n\n return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {\n const resolver = driver.getResolver(clientPlugin.pluginName)\n const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {}\n const { exclude, include, override } = pluginOptions\n const hasOperationOptions = Boolean(exclude?.length || include?.length || override?.length)\n // Kubb's resolver always has `default`; the fallback keeps partial or custom resolvers working.\n const operationOptions =\n hasOperationOptions && resolver.default ? resolver.default.options(node, { options: pluginOptions, exclude, include, override }) : pluginOptions\n if (!operationOptions) return null\n\n const file = resolver.file({\n ...operationFileEntry(node, node.operationId),\n root,\n output: operationOptions.output ?? output,\n group: operationOptions.group ?? undefined,\n })\n\n const { importPath } = operationOptions\n\n return {\n name: resolver.name(node.operationId),\n path: file.path,\n clientPath: importPath === undefined ? path.resolve(root, '.kubb/client.ts') : resolveImportPath({ importPath, operationFile: file.path }),\n clientPathIsFile: importPath === undefined || isRelativeImport(importPath),\n returnType: operationOptions.returnType ?? 'full',\n }\n })\n}\n","import { resolveClientOperation } from '@internals/client'\nimport { operationFileEntry, resolveDependencyOperationFile } from '@internals/shared'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { McpHandler } from '../components/McpHandler.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool\n * handler per OpenAPI operation. The handler takes the grouped `{ path, query,\n * headers, body }` config and forwards it to the registered client plugin's\n * (`@kubb/plugin-axios` / `@kubb/plugin-fetch`) `<op>` function.\n */\nexport const mcpGenerator = defineGenerator<PluginMcp>({\n name: 'mcp',\n renderer: jsxRenderer,\n operation(node, ctx) {\n if (!ast.isHttpOperationNode(node)) return null\n const { resolver, driver, root, config } = ctx\n const { output, client, group } = ctx.options\n\n const pluginTs = ctx.requirePlugin(pluginTsName)\n\n const tsResolver = driver.getResolver(pluginTsName)\n\n // The registered contract client plugin owns the `<op>` the handler imports and calls.\n const contractOp = resolveClientOperation({ clientPlugin: { pluginName: client.pluginName }, driver, node, root, output, cache: ctx.cache })\n if (!contractOp) {\n return null\n }\n\n // The handler signature references the grouped `<Name>Options`.\n const optionsName = tsResolver.response.options(node)\n\n const meta = {\n name: resolver.handler.name(node),\n file: resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n fileTs: resolveDependencyOperationFile({\n cache: ctx.cache,\n node,\n resolver: tsResolver,\n root,\n output: pluginTs.options?.output ?? output,\n group: pluginTs.options?.group,\n }),\n } as const\n\n return (\n <File\n baseName={meta.file.baseName}\n path={meta.file.path}\n meta={meta.file.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n >\n {meta.fileTs && optionsName && <File.Import name={[optionsName]} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}\n <File.Import name={['CallToolResult', 'ServerContext']} path={'@modelcontextprotocol/server'} isTypeOnly />\n\n <File.Import name={[contractOp.name]} root={meta.file.path} path={contractOp.path} />\n\n <McpHandler name={meta.name} clientName={contractOp.name} node={node} resolver={tsResolver} returnType={contractOp.returnType} />\n </File>\n )\n },\n})\n","import path from 'node:path'\nimport { getOperationParameters, getPrimarySuccessResponse, operationFileEntry } from '@internals/shared'\nimport { getRelativePath } from '@internals/utils'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { Server } from '../components/Server.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default v5 server generator for `@kubb/plugin-mcp`.\n *\n * Uses individual zod schemas for each param (e.g. `createPetsPathUuidSchema`, `createPetsQueryOffsetSchema`)\n * and `resolveResponseStatusName` for per-status response schemas.\n * Query and header params are composed into `z.object({ ... })` from individual schemas.\n */\nexport const serverGenerator = defineGenerator<PluginMcp>({\n name: 'operations',\n renderer: jsxRenderer,\n operations(nodes, ctx) {\n const { config, resolver, plugin, driver, root } = ctx\n const { output, group } = ctx.options\n\n const pluginZod = ctx.requirePlugin(pluginZodName)\n\n const zodResolver = driver.getResolver(pluginZodName)\n\n const fileAt = <TName extends `${string}.${string}`>(baseName: TName) => ({\n baseName,\n path: path.resolve(root, output.path, baseName),\n meta: { pluginName: plugin.name },\n })\n const serverFile = fileAt('server.ts')\n const startFile = fileAt('start.ts')\n const jsonFile = fileAt('.mcp.json')\n\n // MCP clients spawn the command from their own working directory, usually the project root,\n // so `args` points at `start.ts` relative to `config.root` instead of the `.mcp.json` folder.\n const mcpConfig = {\n mcpServers: {\n [ctx.meta.title || 'server']: {\n type: 'stdio',\n command: 'npx',\n args: ['tsx', getRelativePath(path.resolve(config.root), startFile.path)],\n },\n },\n }\n\n const operationsMapped = nodes.filter(ast.isHttpOperationNode).map((node) => {\n const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node)\n\n const fileEntry = operationFileEntry(node, node.operationId)\n const mcpFile = resolver.file({ ...fileEntry, root, output, group: group ?? undefined })\n const zodFile = zodResolver.file({\n ...fileEntry,\n root,\n output: pluginZod.options?.output ?? output,\n group: pluginZod.options?.group ?? undefined,\n })\n\n const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null\n const successStatus = getPrimarySuccessResponse(node)?.statusCode\n const responseName = successStatus ? zodResolver.response.status(node, successStatus) : null\n\n const resolveParams = (params: typeof pathParams) => params.map((p) => ({ name: p.name, schemaName: zodResolver.param.name(node, p) }))\n\n return {\n tool: {\n name: node.operationId,\n title: node.summary || undefined,\n description: node.description || `Make a ${node.method.toUpperCase()} request to ${node.path}`,\n },\n mcp: {\n name: resolver.handler.name(node),\n file: mcpFile,\n },\n zod: {\n pathParams: resolveParams(pathParams),\n queryParams: queryParams.length ? resolveParams(queryParams) : null,\n headerParams: headerParams.length ? resolveParams(headerParams) : null,\n requestName,\n responseName,\n file: zodFile,\n },\n }\n })\n\n const imports = operationsMapped.flatMap(({ mcp, zod }) => {\n const zodNames = [\n ...zod.pathParams.map((p) => p.schemaName),\n ...(zod.queryParams ?? []).map((p) => p.schemaName),\n ...(zod.headerParams ?? []).map((p) => p.schemaName),\n zod.requestName,\n zod.responseName,\n ].filter((name): name is string => Boolean(name))\n\n const uniqueNames = [...new Set(zodNames)].sort()\n\n return [\n <File.Import key={mcp.name} name={[mcp.name]} root={serverFile.path} path={mcp.file.path} />,\n uniqueNames.length > 0 && <File.Import key={`zod-${mcp.name}`} name={uniqueNames} root={serverFile.path} path={zod.file.path} />,\n ].filter(Boolean)\n })\n\n return (\n <>\n <File\n baseName={serverFile.baseName}\n path={serverFile.path}\n meta={serverFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n >\n <File.Import name={['McpServer']} path={'@modelcontextprotocol/server'} />\n <File.Import name={['serveStdio']} path={'@modelcontextprotocol/server/stdio'} />\n <File.Import name={['z']} path={'zod'} />\n\n {imports}\n <Server serverName={ctx.meta.title ?? 'server'} serverVersion={ctx.meta.version ?? '0.0.0'} operations={operationsMapped} />\n </File>\n\n <File\n baseName={startFile.baseName}\n path={startFile.path}\n meta={startFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n >\n <File.Import name={['startServer']} root={startFile.path} path={serverFile.path} />\n {/* Not indexable: barrels must not re-export this entry, importing it starts the server. */}\n <File.Source name=\"start\">{'void startServer()'}</File.Source>\n </File>\n\n <File baseName={jsonFile.baseName} path={jsonFile.path} meta={jsonFile.meta}>\n <File.Source name=\"server\">{`${JSON.stringify(mcpConfig, null, 2)}\\n`}</File.Source>\n </File>\n </>\n )\n },\n})\n","","","import { camelCase } from '@internals/utils'\nimport { createResolver } from 'kubb/kit'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-mcp`. Decides the names and file\n * paths for every generated MCP tool handler. Function names get a `Handler`\n * suffix so an operation `addPet` becomes `addPetHandler`.\n *\n * @example Resolve a handler name\n * ```ts\n * import { resolverMcp } from '@kubb/plugin-mcp'\n *\n * resolverMcp.name('addPet') // 'addPetHandler'\n * ```\n */\nexport const resolverMcp = createResolver<PluginMcp>({\n pluginName: 'plugin-mcp',\n name(name) {\n return camelCase(name, { suffix: 'handler' })\n },\n handler: {\n name(node) {\n return this.name(node.operationId)\n },\n },\n})\n","import { createGroupConfig } from '@internals/shared'\n\nimport { resolveContractClient } from '@internals/client'\nimport { addGenerator, defineExtension, Resolver, setMacros, setResolver, useConfig } from 'kubb/kit'\nimport { compatibility } from '../kubb-extension.json'\nimport { version } from '../package.json'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { mcpGenerator } from './generators/mcpGenerator.tsx'\nimport { serverGenerator } from './generators/serverGenerator.tsx'\nimport { resolverMcp } from './resolvers/resolverMcp.ts'\nimport type { PluginMcp, ResolverMcp } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginMcpName = 'plugin-mcp' satisfies PluginMcp['name']\n\n/**\n * Generates a Model Context Protocol (MCP) server from an OpenAPI spec. Every\n * operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude\n * Code, MCP-compatible clients) can call directly. Each handler calls a contract\n * client `<op>` from a registered `@kubb/plugin-axios` or `@kubb/plugin-fetch`.\n * Next to the handlers it writes `server.ts`, a `start.ts` entry that serves the\n * tools over stdio, and a `.mcp.json` that runs `start.ts` with `tsx`.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb/config'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginZod } from '@kubb/plugin-zod'\n * import { pluginFetch } from '@kubb/plugin-fetch'\n * import { pluginMcp } from '@kubb/plugin-mcp'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginZod(),\n * pluginFetch({ baseURL: 'https://petstore.swagger.io/v2' }),\n * pluginMcp({ output: { path: 'mcp' } }),\n * ],\n * })\n * ```\n */\nexport const pluginMcp = defineExtension<PluginMcp>({\n kind: 'plugin',\n meta: { name: pluginMcpName, version, compatibility },\n dependencies: { [pluginTsName]: {}, [pluginZodName]: {} },\n setup(options) {\n const {\n output = { path: 'mcp', barrel: { type: 'named' } },\n group,\n exclude = [],\n include,\n override = [],\n client,\n resolver: userResolver,\n macros: userMacros,\n } = options\n\n const resolver = userResolver ? Resolver.merge<ResolverMcp>(resolverMcp, userResolver) : resolverMcp\n\n setResolver(resolver)\n if (userMacros?.length) {\n setMacros(userMacros)\n }\n addGenerator(mcpGenerator, serverGenerator)\n\n return {\n output,\n exclude,\n include,\n override,\n group: createGroupConfig(group),\n client: resolveContractClient({ plugin: pluginMcpName, client, plugins: useConfig().plugins }),\n resolver,\n }\n },\n})\n\nexport default pluginMcp\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../internals/shared/src/operation.ts","../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/shared/src/group.ts","../src/components/McpHandler.tsx","../src/components/Server.tsx","../../../internals/client/src/resolveOperationTypes.ts","../../../internals/client/src/resolveClient.ts","../../../internals/client/src/resolveClientOperation.ts","../src/generators/mcpGenerator.tsx","../src/generators/serverGenerator.tsx","../kubb-extension.json","../package.json","../src/resolvers/resolverMcp.ts","../src/plugin.ts"],"sourcesContent":["import { ast, type Group, type NodeCache, type Output, type Resolver, type ResolverFileParams, Url } from 'kubb/kit'\n\n/**\n * Builds the `ResolverFileParams` every operation generator passes to\n * `resolver.file`: a file named `name`, tagged by the operation's first\n * tag (or `'default'`), at the operation's path. Centralizes the entry object\n * that was repeated at dozens of call sites across the client and query plugins.\n *\n * @example\n * ```ts\n * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })\n * ```\n */\nexport function operationFileEntry(node: ast.OperationNode, name: string, extname: ResolverFileParams['extname'] = '.ts'): ResolverFileParams {\n return {\n name,\n extname,\n tag: node.tags[0] ?? 'default',\n path: node.path,\n }\n}\n\n/**\n * Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the\n * current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the\n * same dependency for the same operation in one pass (a query plugin's several hook generators, the\n * MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.\n *\n * @example Cache `plugin-ts`'s file for the current operation\n * ```ts\n * const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })\n * ```\n */\nexport function resolveDependencyOperationFile(options: {\n cache: NodeCache\n node: ast.OperationNode\n resolver: Pick<Resolver, 'file' | 'pluginName'>\n root: string\n output: Output\n group?: Group | null\n}): ast.FileNode {\n const { cache, node, resolver, root, output, group } = options\n\n return cache.ensureItem(`${resolver.pluginName}:operationFile`, () =>\n resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n )\n}\n\nexport type ContentTypeInfo = {\n contentTypes: string[]\n isMultipleContentTypes: boolean\n contentTypeUnion: string\n defaultContentType: string\n hasFormData: boolean\n}\n\nexport type RequestConfigResolver = {\n response: {\n body(node: ast.OperationNode): string\n }\n}\n\nexport type ResponseStatusNameResolver = {\n response: {\n status(node: ast.OperationNode, statusCode: ast.StatusCode): string\n }\n}\n\nexport type ResponseNameResolver = ResponseStatusNameResolver & {\n response: {\n response(node: ast.OperationNode): string\n }\n}\n\nexport type OperationTypeNameResolver = RequestConfigResolver &\n ResponseNameResolver & {\n param: {\n path(node: ast.OperationNode, param: ast.ParameterNode): string\n query(node: ast.OperationNode, param: ast.ParameterNode): string\n headers(node: ast.OperationNode, param: ast.ParameterNode): string\n }\n }\n\nexport type OperationCommentLink = 'pathTemplate' | 'urlPath' | false | ((node: ast.OperationNode) => string | undefined)\n\nexport type BuildOperationCommentsOptions = {\n link?: OperationCommentLink\n linkPosition?: 'beforeDeprecated' | 'afterDeprecated'\n splitLines?: boolean\n}\n\ntype ResponseLike = {\n statusCode: ast.StatusCode | number | string\n}\n\nexport type OperationParameterGroups = Record<ast.ParameterNode['in'], Array<ast.ParameterNode>>\n\nexport type ResolveOperationTypeNameOptions = {\n responseStatusNames?: boolean | 'error'\n exclude?: ReadonlyArray<string | undefined>\n order?: 'params-first' | 'body-response-first'\n /**\n * Include the individual `Path`/`Query`/`Headers` group type names. Set to `false` for clients\n * that reference the grouped `Options` type instead of the per-group types.\n */\n includeParams?: boolean\n}\n\nfunction getOperationLink(node: ast.OperationNode, link: OperationCommentLink): string | null {\n if (!link) {\n return null\n }\n\n if (typeof link === 'function') {\n return link(node) ?? null\n }\n\n return node.path ? `{@link ${Url.toPath(node.path)}}` : null\n}\n\n/**\n * Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several\n * are present and the union, default, and form-data flags the client uses to pick one.\n */\nfunction buildContentTypeInfo(contentTypes: string[]): ContentTypeInfo {\n const isMultipleContentTypes = contentTypes.length > 1\n\n return {\n contentTypes,\n isMultipleContentTypes,\n contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(' | ') : '',\n defaultContentType: contentTypes[0] ?? 'application/json',\n hasFormData: contentTypes.some((ct) => ct === 'multipart/form-data'),\n }\n}\n\nexport function getContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(node.requestBody?.content?.map((e) => e.contentType) ?? [])\n}\n\n/**\n * The request-body counterpart for the primary success response: the content types it documents and\n * whether several are present, so the client can let a caller pick which one to accept.\n */\nexport function getResponseContentTypeInfo(node: ast.OperationNode): ContentTypeInfo {\n return buildContentTypeInfo(getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [])\n}\n\nexport type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'\n\n/**\n * Reads the single base content type of an operation's primary success response, lowercased and\n * stripped of any `; charset=...` suffix. Returns `undefined` when the response declares zero or\n * more than one content type, since neither case has a single type to act on.\n */\nfunction getPrimarySuccessContentType(node: ast.OperationNode): string | undefined {\n const contentTypes = getPrimarySuccessResponse(node)?.content?.map((entry) => entry.contentType) ?? []\n if (contentTypes.length !== 1) return undefined\n return contentTypes[0]!.split(';')[0]!.trim().toLowerCase()\n}\n\n/**\n * Whether an operation streams its primary success response as Server-Sent Events\n * (`text/event-stream`). The client generator uses this to return a typed event stream instead of a\n * one-shot `RequestResult`.\n */\nexport function isEventStream(node: ast.OperationNode): boolean {\n return getPrimarySuccessContentType(node) === 'text/event-stream'\n}\n\n/**\n * Derives the default `responseType` for an operation from its primary success response.\n *\n * Returns a value only when that response declares a single non-JSON content type. `text/event-stream`\n * and other binary types (`application/octet-stream`, `application/pdf`, `image/*`, `audio/*`,\n * `video/*`) map to a stream or `'blob'`, and other `text/*` maps to `'text'`. Otherwise `undefined`,\n * leaving the runtime client's `Content-Type` auto-detection in charge.\n */\nexport function getResponseType(node: ast.OperationNode): ResponseType | undefined {\n const baseType = getPrimarySuccessContentType(node)\n if (!baseType) return undefined\n\n if (baseType === 'application/json' || baseType.endsWith('+json') || baseType === 'text/json') return undefined\n if (baseType === 'text/event-stream') return 'stream'\n if (baseType.startsWith('text/')) return 'text'\n if (baseType === 'application/octet-stream' || baseType === 'application/pdf' || /^(image|audio|video)\\//.test(baseType)) return 'blob'\n return undefined\n}\n\n/**\n * Maps a content type to the PascalCase suffix used to name per-content-type variants\n * (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).\n */\nfunction getContentTypeSuffix(contentType: string): string {\n const baseType = contentType.split(';')[0]!.trim()\n if (baseType === 'application/json') return 'Json'\n if (baseType === 'multipart/form-data') return 'FormData'\n if (baseType === 'application/x-www-form-urlencoded') return 'FormUrlEncoded'\n const subtype = baseType.split('/').pop() ?? baseType\n const parts = subtype.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n if (parts.length === 0) return 'Unknown'\n return parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('')\n}\n\n/**\n * Appends a content-type suffix to a base name, keeping a trailing `Data` segment last\n * (e.g. `AddPetData` + `Json` → `AddPetJsonData`, `AddPetStatus200` + `Xml` → `AddPetStatus200Xml`).\n */\nexport function getPerContentTypeName(baseName: string, suffix: string): string {\n if (baseName.endsWith('Data')) {\n return suffix.endsWith('Data') ? baseName.slice(0, -4) + suffix : `${baseName.slice(0, -4)}${suffix}Data`\n }\n return baseName + suffix\n}\n\nexport type ContentVariantInput = { contentType: string; schema?: ast.SchemaNode | null; keysToOmit?: Array<string> | null }\nexport type ContentVariant = { name: string; suffix: string; schema: ast.SchemaNode; keysToOmit?: Array<string> | null; contentType: string }\n\n/**\n * Resolves per-content-type variant names for a set of content entries, deduplicating suffix\n * collisions with a numeric counter. Entries without a schema are skipped. The returned `suffix` is\n * the final (possibly counter-augmented) value, so callers can derive parallel names in another\n * namespace (e.g. plugin-faker deriving the matching plugin-ts type name).\n */\nexport function resolveContentTypeVariants(entries: Array<ContentVariantInput>, baseName: string): Array<ContentVariant> {\n const usedNames = new Set<string>()\n return entries\n .filter((entry) => entry.schema)\n .map((entry) => {\n const baseSuffix = getContentTypeSuffix(entry.contentType)\n let suffix = baseSuffix\n let name = getPerContentTypeName(baseName, suffix)\n let counter = 2\n while (usedNames.has(name)) {\n suffix = `${baseSuffix}${counter++}`\n name = getPerContentTypeName(baseName, suffix)\n }\n usedNames.add(name)\n return { name, suffix, schema: entry.schema!, keysToOmit: entry.keysToOmit, contentType: entry.contentType }\n })\n}\n\n// The request groups come from the grouped params, so `config` drops the data-shape keys to stay\n// assignable to `Options`, which omits them from `RequestConfig`.\nconst requestConfigBaseType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`\n\nexport function buildRequestConfigType(node: ast.OperationNode): string {\n const request = getContentTypeInfo(node)\n const response = getResponseContentTypeInfo(node)\n\n // Only the ambiguous side is offered: a single-type side has nothing to pick, so it stays baked in\n // the generated call.\n const members = [\n request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null,\n response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null,\n ].filter(Boolean)\n\n return members.length ? `${requestConfigBaseType} & { contentType?: { ${members.join('; ')} } }` : requestConfigBaseType\n}\n\n/**\n * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,\n * `useInfiniteQuery`, `useSWR`, ...). Unlike {@link buildRequestConfigType}, it never adds a\n * `contentType?:` member: query hooks wrap GET operations, which carry no request body to select a\n * content type for.\n */\nexport function buildClientOptionType(): string {\n return requestConfigBaseType\n}\n\nexport type RequestGroups = {\n path: boolean\n query: boolean\n body: boolean\n headers: boolean\n}\n\n/**\n * Which of the grouped request options an operation carries.\n */\nexport function getRequestGroups(node: ast.OperationNode): RequestGroups {\n const { path, query, header } = getOperationParameters(node)\n return {\n path: path.length > 0,\n query: query.length > 0,\n body: Boolean(node.requestBody?.content?.[0]?.schema),\n headers: header.length > 0,\n }\n}\n\nexport type RequestGroupOptionality = {\n groups: RequestGroups\n hasRequiredPath: boolean\n hasRequiredQuery: boolean\n hasRequiredHeader: boolean\n /**\n * Whether the grouped request parameter can default to `{}`. True only when no group carries a\n * required member, so every member is safe to omit.\n */\n isOptional: boolean\n}\n\n/**\n * Resolves which grouped request options an operation carries together with whether each group\n * holds a required member. The grouped parameter stays optional only when nothing inside it is\n * required, matching the generated `RequestConfig` type.\n */\nexport function getRequestGroupOptionality(node: ast.OperationNode): RequestGroupOptionality {\n const groups = getRequestGroups(node)\n const { path, query, header } = getOperationParameters(node)\n const hasRequiredPath = path.some((param) => param.required)\n const hasRequiredQuery = query.some((param) => param.required)\n const hasRequiredHeader = header.some((param) => param.required)\n\n return {\n groups,\n hasRequiredPath,\n hasRequiredQuery,\n hasRequiredHeader,\n isOptional: !hasRequiredPath && !hasRequiredQuery && !hasRequiredHeader && !groups.body,\n }\n}\n\nexport type RequestOptionsNameResolver = RequestConfigResolver & {\n response: {\n options(node: ast.OperationNode): string\n }\n}\n\n/**\n * Builds the grouped `{ path, query, body, headers }` parameter for a generated client\n * function, typed from the operation's `Options` (minus `url`). Only the groups the\n * operation actually has are destructured. The trailing `config` parameter carries the\n * runtime `RequestConfig` overrides plus `client`.\n */\nexport function buildRequestParamsSignature(\n node: ast.OperationNode,\n resolver: RequestOptionsNameResolver,\n options: { isConfigurable?: boolean } = {},\n): { signature: string; groups: RequestGroups } {\n const { isConfigurable = true } = options\n const { groups, isOptional } = getRequestGroupOptionality(node)\n\n const names = (['path', 'query', 'body', 'headers'] as const).filter((key) => groups[key])\n\n const firstParam = names.length > 0 ? `{ ${names.join(', ')} }: ${resolver.response.options(node)}${isOptional ? ' = {}' : ''}` : null\n const configParam = isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null\n\n return {\n signature: [firstParam, configParam].filter(Boolean).join(', '),\n groups,\n }\n}\n\nexport function buildOperationComments(node: ast.OperationNode, options: BuildOperationCommentsOptions = {}): Array<string> {\n const { link = 'pathTemplate', linkPosition = 'afterDeprecated', splitLines = false } = options\n const linkComment = getOperationLink(node, link)\n const comments =\n linkPosition === 'beforeDeprecated'\n ? [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, linkComment, node.deprecated && '@deprecated']\n : [node.description && `@description ${node.description}`, node.summary && `@summary ${node.summary}`, node.deprecated && '@deprecated', linkComment]\n\n const filteredComments = comments.filter((comment): comment is string => Boolean(comment))\n\n if (!splitLines) {\n return filteredComments\n }\n\n return filteredComments.flatMap((text) => text.split(/\\r?\\n/).map((line) => line.trim())).filter((comment): comment is string => Boolean(comment))\n}\n\nconst operationParameterGroupsByNode = new WeakMap<ast.OperationNode, OperationParameterGroups>()\n\n/**\n * Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each\n * group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance\n * (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the\n * same parameters once per plugin.\n */\nexport function getOperationParameters(node: ast.OperationNode): OperationParameterGroups {\n const cached = operationParameterGroupsByNode.get(node)\n if (cached) return cached\n\n // A malformed spec can declare the same name twice within one location. Both would resolve to the\n // same output property, so emitting both would yield an object type with a duplicate member,\n // which TypeScript rejects. Keep the first.\n const group = (location: ast.ParameterNode['in']) => {\n const seen = new Set<string>()\n\n return node.parameters.filter((param) => {\n if (param.in !== location || seen.has(param.name)) return false\n seen.add(param.name)\n return true\n })\n }\n\n const groups: OperationParameterGroups = { path: group('path'), query: group('query'), header: group('header'), cookie: group('cookie') }\n\n operationParameterGroupsByNode.set(node, groups)\n return groups\n}\n\n/**\n * Builds the combined `{ body, path, query, headers }` options object schema for an operation,\n * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s\n * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same\n * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod\n * printer to emit `z.object(…)` rather than a record.\n */\nexport function buildOptionsSchema(node: ast.OperationNode, resolver: OperationTypeNameResolver): ast.SchemaNode {\n const { path, query, header } = getOperationParameters(node)\n const hasBody = Boolean(node.requestBody?.content?.[0]?.schema)\n const createNever = () => ast.factory.createSchema({ type: 'never', primitive: undefined, optional: true })\n const groups = [\n { name: 'path', params: path, resolve: resolver.param.path },\n { name: 'query', params: query, resolve: resolver.param.query },\n { name: 'headers', params: header, resolve: resolver.param.headers },\n ] as const\n\n // NOTE(v5-stable): the fields were renamed from the legacy beta shape\n // (`data`/`pathParams`/`queryParams`/`headerParams`) to `body`/`path`/`query`/`headers` so the\n // type matches the runtime client. Drop this note once v5 leaves beta.\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n deprecated: node.deprecated,\n properties: [\n ast.factory.createProperty({\n name: 'body',\n required: hasBody,\n schema: hasBody ? ast.factory.createSchema({ type: 'ref', name: resolver.response.body(node) }) : createNever(),\n }),\n ...groups.map(({ name, params, resolve }) => {\n const required = params.some((param) => param.required)\n\n return ast.factory.createProperty({\n name,\n required,\n schema:\n params.length > 0\n ? ast.factory.createSchema({ type: 'ref', name: resolve.call(resolver.param, node, params[0]!), optional: !required })\n : createNever(),\n })\n }),\n ],\n })\n}\n\n/**\n * The schema a status occupies in the `<Name>Responses` record. A status that documents several\n * content types becomes a `{ contentType; data }` union so the runtime can surface the negotiated type\n * on `result.parsed`, while the standalone `<Name>StatusNNN` alias stays the plain body union that the\n * query hooks and `result.data` use.\n */\nfunction buildResponseRecordEntry(node: ast.OperationNode, res: ast.ResponseNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n const statusName = resolver.response.status(node, res.statusCode)\n const variants = (res.content ?? []).filter((entry) => entry.schema)\n if (variants.length <= 1) {\n return ast.factory.createSchema({ type: 'ref', name: statusName })\n }\n\n return ast.factory.createSchema({\n type: 'union',\n members: resolveContentTypeVariants(variants, statusName).map((variant) =>\n ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: [\n ast.factory.createProperty({\n name: 'contentType',\n required: true,\n schema: ast.factory.createSchema({ type: 'enum', enumValues: [variant.contentType] }),\n }),\n ast.factory.createProperty({\n name: 'data',\n required: true,\n schema: ast.factory.createSchema({ type: 'ref', name: variant.name }),\n }),\n ],\n }),\n ),\n })\n}\n\n/**\n * Builds the per-status `<Name>Responses` record for an operation, referencing the already-resolved\n * `<Name>StatusNNN` names. Shared by `@kubb/plugin-ts`'s `Responses` type and `@kubb/plugin-zod`'s\n * inferred responses schema, so both emit the same shape from the same inputs.\n *\n * Always emits the keyed record, even when an operation declares no responses. An operation with no\n * responses renders as an empty object, which keeps every consumer's import (for example the axios\n * SDK's `RequestResult<XResponses>`) resolvable instead of pointing at a missing export.\n */\nexport function buildResponses(node: ast.OperationNode, resolver: ResponseStatusNameResolver): ast.SchemaNode {\n return ast.factory.createSchema({\n type: 'object',\n primitive: 'object',\n properties: node.responses.map((res) =>\n ast.factory.createProperty({\n name: String(res.statusCode),\n required: true,\n schema: buildResponseRecordEntry(node, res, resolver),\n }),\n ),\n })\n}\n\nexport function getStatusCodeNumber(statusCode: ast.StatusCode | number | string): number | null {\n const code = Number(statusCode)\n\n return Number.isNaN(code) ? null : code\n}\n\nexport function isSuccessStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 200 && code < 300\n}\n\nexport function isErrorStatusCode(statusCode: ast.StatusCode | number | string): boolean {\n const code = getStatusCodeNumber(statusCode)\n\n return code !== null && code >= 400\n}\n\nexport function getSuccessResponses<TResponse extends ResponseLike>(responses: ReadonlyArray<TResponse>): Array<TResponse> {\n return responses.filter((response) => isSuccessStatusCode(response.statusCode))\n}\n\nexport function getOperationSuccessResponses(node: ast.OperationNode): Array<ast.ResponseNode> {\n return getSuccessResponses(node.responses)\n}\n\nexport function getPrimarySuccessResponse(node: ast.OperationNode): ast.ResponseNode | null {\n return getOperationSuccessResponses(node)[0] ?? null\n}\n\nexport function resolveErrorNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveSuccessNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.filter((response) => isSuccessStatusCode(response.statusCode)).map((response) => resolver.response.status(node, response.statusCode))\n}\n\nexport function resolveStatusCodeNames(node: ast.OperationNode, resolver: ResponseStatusNameResolver): string[] {\n return node.responses.map((response) => resolver.response.status(node, response.statusCode))\n}\n\nconst typeNamesByResolver = new WeakMap<OperationTypeNameResolver, Map<string, string[]>>()\n\nexport function resolveOperationTypeNames(\n node: ast.OperationNode,\n resolver: OperationTypeNameResolver,\n options: ResolveOperationTypeNameOptions = {},\n): string[] {\n const cacheKey = `${node.operationId}\\0${options.order ?? ''}\\0${options.responseStatusNames ?? ''}\\0${options.includeParams === false ? 'noparams' : ''}\\0${(options.exclude ?? []).join(',')}`\n let byResolver = typeNamesByResolver.get(resolver)\n if (byResolver) {\n const cached = byResolver.get(cacheKey)\n if (cached) return cached\n } else {\n byResolver = new Map()\n typeNamesByResolver.set(resolver, byResolver)\n }\n\n const { path, query, header } = getOperationParameters(node)\n const responseStatusNames =\n options.responseStatusNames === 'error'\n ? resolveErrorNames(node, resolver)\n : options.responseStatusNames === false\n ? []\n : resolveStatusCodeNames(node, resolver)\n const exclude = new Set(options.exclude ?? [])\n const paramNames =\n options.includeParams === false\n ? []\n : [\n ...path.map((param) => resolver.param.path(node, param)),\n ...query.map((param) => resolver.param.query(node, param)),\n ...header.map((param) => resolver.param.headers(node, param)),\n ]\n const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.response.body(node) : null, resolver.response.response(node)]\n const names =\n options.order === 'body-response-first'\n ? [...bodyAndResponseNames, ...paramNames, ...responseStatusNames]\n : [...paramNames, ...bodyAndResponseNames, ...responseStatusNames]\n\n const result = names.filter((name): name is string => Boolean(name) && !exclude.has(name as string))\n byResolver.set(cacheKey, result)\n return result\n}\n\nexport function resolveResponseTypes(node: ast.OperationNode, resolver: ResponseNameResolver): Array<[statusCode: number | 'default', typeName: string]> {\n const types: Array<[number | 'default', string]> = []\n\n for (const response of node.responses) {\n if (response.statusCode === 'default') {\n types.push(['default', resolver.response.response(node)])\n continue\n }\n\n const code = getStatusCodeNumber(response.statusCode)\n if (code === null) {\n continue\n }\n\n types.push([code, isSuccessStatusCode(code) ? resolver.response.response(node) : resolver.response.status(node, response.statusCode)])\n }\n\n return types\n}\n","type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction convert(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n// Plugins resolve the same names over and over (about 47,000 calls for a 1,000 schema spec), so\n// results are kept. Clearing at the limit bounds the memory a long-running process spends on it.\nconst cache = new Map<string, string>()\nconst cacheLimit = 10_000\n\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const key = `${pascal ? 'P' : 'c'}${text}`\n const cached = cache.get(key)\n if (cached !== undefined) return cached\n\n const result = convert(text, pascal)\n if (cache.size >= cacheLimit) cache.clear()\n cache.set(key, result)\n return result\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Uppercases only the first character of `text`, leaving the rest untouched.\n * Unlike {@link pascalCase} it never re-splits word boundaries or strips characters.\n *\n * @example\n * `capitalize('getPetById') // 'GetPetById'`\n */\nexport function capitalize(text: string): string {\n return `${text.charAt(0).toUpperCase()}${text.slice(1)}`\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir: string, filePath: string): string {\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from 'kubb/kit'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { buildOperationComments, buildRequestParamsSignature } from '@internals/shared'\nimport type { ast } from 'kubb/kit'\nimport type { ResolverTs } from '@kubb/plugin-ts'\nimport { File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype Props = {\n /**\n * Name of the handler function.\n */\n name: string\n /**\n * Name of the contract client `<op>` the handler calls.\n */\n clientName: string\n /**\n * AST operation node.\n */\n node: ast.HttpOperationNode\n /**\n * TypeScript resolver for resolving param/data/response type names.\n */\n resolver: ResolverTs\n /**\n * The registered client plugin's `returnType`, read by the caller off `resolveClientOperation`.\n */\n returnType?: 'full' | 'data' | 'plain'\n}\n\nconst requestGroupOrder = ['path', 'query', 'headers', 'body'] as const\n\nexport function McpHandler({ name, clientName, node, resolver, returnType = 'full' }: Props): KubbReactNode {\n const { signature, groups } = buildRequestParamsSignature(node, resolver, { isConfigurable: false })\n const paramsSignature = [signature, 'ctx: ServerContext'].filter(Boolean).join(', ')\n\n // Forward the grouped config and MCP cancellation signal through the contract client. `throwOnError: true`\n // pins the result shape, since `throwOnErrorDefault: false` would otherwise resolve to the full result.\n const callArgs = requestGroupOrder.filter((key) => groups[key])\n const callConfig = `{ ${[...callArgs, 'signal: ctx.mcpReq.signal', 'throwOnError: true'].join(', ')} }`\n const body = returnType === 'data' ? 'res' : 'res.data'\n\n const callToolResult = `return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(${body})\n }\n ],\n structuredContent: { data: ${body} }\n}`\n\n return (\n <File.Source name={name} isExportable isIndexable>\n <Function\n name={name}\n async\n export\n params={paramsSignature}\n JSDoc={{\n comments: buildOperationComments(node),\n }}\n returnType={'CallToolResult'}\n >\n {`const res = await ${clientName}(${callConfig})`}\n <br />\n {callToolResult}\n </Function>\n </File.Source>\n )\n}\n","import type { ast } from 'kubb/kit'\nimport { Const, File, Function } from 'kubb/jsx'\nimport type { KubbReactNode } from 'kubb/jsx'\n\ntype ZodParam = {\n name: string\n schemaName: string\n}\n\n/**\n * Composes individual param schemas into `z.object({ ... })`.\n */\nconst zodObject = (params: Array<ZodParam>) => `z.object({ ${params.map((p) => `${JSON.stringify(p.name)}: ${p.schemaName}`).join(', ')} })`\n\ntype Props = {\n /**\n * Human-readable server name passed to `new McpServer({ name })`.\n */\n serverName: string\n /**\n * Semantic version string passed to `new McpServer({ version })`.\n */\n serverVersion: string\n /**\n * Operations to register as MCP tools, each carrying its handler,\n * zod schema, and AST node metadata.\n */\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: ast.FileNode\n }\n zod: {\n pathParams: Array<ZodParam>\n /**\n * Query params — individual schemas to compose into `z.object({ ... })`.\n */\n queryParams?: Array<ZodParam> | null\n /**\n * Header params — individual schemas to compose into `z.object({ ... })`.\n */\n headerParams?: Array<ZodParam> | null\n requestName?: string | null\n responseName?: string | null\n }\n }>\n}\n\nexport function Server({ serverName, serverVersion, operations }: Props): KubbReactNode {\n const registrations = operations\n .map(({ tool, mcp, zod }) => {\n // Group params into the same `{ path, query, headers, body }` shape the contract `<op>`\n // expects, so the MCP tool input mirrors every other client consumer.\n const entries: Array<{ key: string; value: string }> = []\n\n if (zod.pathParams.length) {\n entries.push({ key: 'path', value: zodObject(zod.pathParams) })\n }\n\n if (zod.queryParams) {\n entries.push({ key: 'query', value: zodObject(zod.queryParams) })\n }\n\n if (zod.headerParams) {\n entries.push({ key: 'headers', value: zodObject(zod.headerParams) })\n }\n\n if (zod.requestName) {\n entries.push({ key: 'body', value: zod.requestName })\n }\n\n const destructured = `{ ${entries.map((e) => e.key).join(', ')} }`\n const inputSchema = entries.length ? `z.object({ ${entries.map((e) => `${e.key}: ${e.value}`).join(', ')} })` : null\n const outputSchema = zod.responseName\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: z.object({ data: ${outputSchema} })` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (inputSchema) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${inputSchema},\n}, async (${destructured}, ctx) => {\n return ${mcp.name}(${destructured}, ctx)\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async (ctx) => {\n return ${mcp.name}(ctx)\n})\n `\n })\n .filter(Boolean)\n .join('\\n')\n\n return (\n <>\n <File.Source name=\"getServer\" isExportable isIndexable>\n <Function name=\"getServer\" export>\n {`const server = new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n${registrations}\nreturn server`}\n </Function>\n </File.Source>\n\n <File.Source name=\"server\" isExportable isIndexable>\n <Const name={'server'} export>\n {'getServer()'}\n </Const>\n </File.Source>\n\n <File.Source name=\"startServer\" isExportable isIndexable>\n <Function name=\"startServer\" async export>\n {`return serveStdio(getServer, {\n onerror: (error) => console.error('MCP server error:', error),\n })`}\n </Function>\n </File.Source>\n </>\n )\n}\n","import { type ast, Diagnostics, type Generator, type Group, type Output } from 'kubb/kit'\nimport { pluginTsName, type ResolverTs } from '@kubb/plugin-ts'\nimport { pluginZodName, type ResolverZod } from '@kubb/plugin-zod'\nimport type { ContractClientFactory } from './types.ts'\n\ntype GeneratorDriver = Parameters<NonNullable<Generator<ContractClientFactory>['operations']>>[1]['driver']\n\n/**\n * The two per-operation type names a generated client references: the grouped input and the\n * per-status responses record its `RequestResult` is keyed on.\n */\nexport type OperationTypeNames = {\n response: {\n /**\n * Resolves the name of the operation's grouped `{ body, path, query, headers }` input type.\n */\n options(node: ast.OperationNode): string\n /**\n * Resolves the name of the operation's per-status responses record type.\n */\n responses(node: ast.OperationNode): string\n }\n}\n\n/**\n * Where a generated client sources its operation types, plus the resolver and output the file\n * declaring them is resolved with.\n */\nexport type OperationTypeSource = OperationTypeNames & {\n /**\n * `plugin-ts` shaped resolver of the plugin supplying the names, also used to resolve the file they are exported from.\n */\n resolver: ResolverTs\n /**\n * The supplying plugin's own `output`, when it configured one.\n */\n output: Output | undefined\n /**\n * The supplying plugin's own `group`, when it configured one.\n */\n group: Group | undefined\n}\n\n/**\n * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`\n * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.\n */\nfunction toZodTypeResolver(resolver: ResolverZod): ResolverTs {\n const type = (name: string) => resolver.schema.type(name)\n\n return {\n ...resolver,\n // A class method, so a spread drops it, and it reads private fields, so it must run on `resolver`.\n file: resolver.file.bind(resolver),\n param: {\n name: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.name(node, p)),\n path: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.path(node, p)),\n query: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.query(node, p)),\n headers: (node: ast.OperationNode, p: ast.ParameterNode) => type(resolver.param.headers(node, p)),\n },\n response: {\n body: (node: ast.OperationNode) => type(resolver.response.body(node)),\n status: (node: ast.OperationNode, statusCode: ast.StatusCode) => type(resolver.response.status(node, statusCode)),\n response: (node: ast.OperationNode) => type(resolver.response.response(node)),\n responses: (node: ast.OperationNode) => type(resolver.response.responses(node)),\n options: (node: ast.OperationNode) => resolver.response.options(node),\n },\n } as unknown as ResolverTs\n}\n\n/**\n * Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.\n *\n * `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`\n * wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws\n * `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.\n *\n * @example\n * ```ts\n * const types = resolveOperationTypes(ctx.driver, ctx.plugin.name)\n * types.response.options(node) // 'GetPetByIdOptions', or 'GetPetByIdOptionsSchemaType' from zod\n * ```\n */\nexport function resolveOperationTypes(driver: GeneratorDriver, pluginName: string): OperationTypeSource {\n const pluginTs = driver.getPlugin(pluginTsName)\n const pluginZod = driver.getPlugin(pluginZodName)\n\n if (pluginTs && pluginZod?.options?.inferred !== 'codec') {\n const resolver = driver.getResolver(pluginTsName)\n return { response: resolver.response, resolver, output: pluginTs.options?.output, group: pluginTs.options?.group ?? undefined }\n }\n\n if (!pluginZod?.options?.inferred) {\n throw new Diagnostics.Error({\n code: Diagnostics.code.missingDependency,\n severity: 'error',\n message: `Plugin \"${pluginName}\" has no source for operation types.`,\n help: `Add \\`pluginTs()\\` before \"${pluginName}\", or add \\`pluginZod({ inferred: true })\\`.`,\n location: { kind: 'config' },\n plugin: pluginName,\n })\n }\n\n const resolver = toZodTypeResolver(driver.getResolver(pluginZodName))\n return { response: resolver.response, resolver, output: pluginZod.options.output, group: pluginZod.options.group ?? undefined }\n}\n","/**\n * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an\n * operation, shared so the selection rules and diagnostics stay in one place.\n *\n * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered\n * contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own\n * inline client:\n *\n * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer\n * imports and calls them.\n * - `error` — no client plugin is registered, several are registered without a selector, the\n * requested one is missing, or `client` is not a known selector.\n *\n * The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a\n * lone registered contract client plugin is picked up automatically.\n */\n\nimport { Diagnostics } from 'kubb/kit'\n\n// Canonical plugin names. They mirror the `pluginFetchName` / `pluginAxiosName` / `pluginClientName`\n// consts the plugins export, kept as literals so this internal needs no plugin install deps.\nconst pluginFetchName = 'plugin-fetch'\nconst pluginAxiosName = 'plugin-axios'\nconst pluginClientName = 'plugin-client'\n\n/**\n * The client selector accepted by a consumer's `client` option. Each calls a registered contract\n * client plugin.\n */\nexport type ClientSelector = 'fetch' | 'axios' | 'client'\n\n/**\n * The resolved client strategy stored in a consumer plugin's options: the generated code always\n * imports and calls a registered contract client plugin's `<op>`. The client runtime lives in\n * plugin-axios / plugin-fetch, so nothing is bundled by the consumer.\n */\nexport type ResolvedContractClient = { kind: 'contract'; pluginName: string }\n\n/**\n * The outcome of {@link resolveClient}.\n *\n * - `contract` names the contract client plugin whose `<op>` functions the consumer imports.\n * - `error` carries a setup diagnostic: its code, what is wrong, and how to fix it.\n */\nexport type ResolveClientResult =\n | ResolvedContractClient\n | { kind: 'error'; code: typeof Diagnostics.code.missingDependency | typeof Diagnostics.code.invalidPluginOptions; message: string; help: string }\n\nconst selectorToPlugin: Record<ClientSelector, string> = {\n fetch: pluginFetchName,\n axios: pluginAxiosName,\n client: pluginClientName,\n}\n\n// Every contract client plugin, in auto-detect priority order.\nconst contractPlugins = [pluginFetchName, pluginAxiosName, pluginClientName] as const\n\n/**\n * Applies the `client` resolution rules. See the module comment for the strategy shape.\n *\n * @example\n * ```ts\n * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })\n * // { kind: 'contract', pluginName: 'plugin-fetch' }\n * ```\n *\n * @example\n * ```ts\n * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })\n * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }\n * ```\n */\nexport function resolveClient(options: { client: ClientSelector | undefined; pluginNames: ReadonlyArray<string> }): ResolveClientResult {\n const { client, pluginNames } = options\n const has = (name: string) => pluginNames.includes(name)\n\n if (client === 'fetch' || client === 'axios' || client === 'client') {\n const pluginName = selectorToPlugin[client]\n if (!has(pluginName)) {\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: `\\`client: '${client}'\\` is set but \\`@kubb/plugin-${client}\\` is not registered in \\`plugins\\`.`,\n help: `Add \\`@kubb/plugin-${client}\\` to \\`plugins\\`, or drop \\`client\\` to use a different client plugin.`,\n }\n }\n return { kind: 'contract', pluginName }\n }\n\n // A JS config bypasses the `ClientSelector` type, so reject unknown selectors instead of auto-detecting.\n if (client !== undefined) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Option \\`client\\` is ${typeof client === 'string' ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,\n help: 'Set `client` to one of those values, or drop it to use the registered client plugin.',\n }\n }\n\n // `client` unset: auto-detect a lone registered contract client plugin.\n const registered = contractPlugins.filter(has)\n if (registered.length === 1) {\n return { kind: 'contract', pluginName: registered[0]! }\n }\n if (registered.length > 1) {\n return {\n kind: 'error',\n code: Diagnostics.code.invalidPluginOptions,\n message: `Multiple client plugins are registered (${registered.map((name) => `\\`@kubb/${name}\\``).join(', ')}) and \\`client\\` is not set.`,\n help: \"Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin.\",\n }\n }\n\n return {\n kind: 'error',\n code: Diagnostics.code.missingDependency,\n message: 'No client plugin is registered.',\n help: 'Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call.',\n }\n}\n\n/**\n * Resolves the contract client during a consumer plugin's setup hook.\n * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.\n * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer\n * fails fast with the same message.\n */\nexport function resolveContractClient(options: {\n plugin: string\n client: ClientSelector | undefined\n plugins?: ReadonlyArray<unknown>\n}): ResolvedContractClient {\n const { plugin, client, plugins = [] } = options\n const pluginNames = plugins.map((plugin) => (plugin as { name?: string }).name).filter((name): name is string => Boolean(name))\n const resolved = resolveClient({ client, pluginNames })\n if (resolved.kind === 'error') {\n const { code, message, help } = resolved\n throw new Diagnostics.Error({ code, severity: 'error', message, help, location: { kind: 'config' }, plugin })\n }\n return resolved\n}\n","import path from 'node:path'\nimport { operationFileEntry } from '@internals/shared'\nimport type { ast, Exclude, Group, Include, NodeCache, Output, Override, Resolver } from 'kubb/kit'\nimport type { ReturnTypeOption } from './types.ts'\n\n/**\n * The resolved contract `<op>` for one operation: the generated function name, the file it lives in,\n * the client module path (where `RequestConfig` / `ResponseErrorConfig` come from), and the\n * registered client plugin's `returnType`.\n *\n * `clientPath` is the absolute `.kubb/client.ts` path for plugin-fetch / plugin-axios, or\n * plugin-client's `importPath`: a relative one is resolved against the `<op>` file to an absolute\n * path, a package name or alias is kept verbatim. `clientPathIsFile` tells a consumer whether to\n * make it relative to the importing file.\n */\nexport type ClientOperation = { name: string; path: string; clientPath: string; clientPathIsFile: boolean; returnType: ReturnTypeOption }\n\n/**\n * The client plugin options a dependent reads, including the filters that scope them per operation.\n */\ntype ClientPluginOptions = {\n output?: Output\n group?: Group | null\n returnType?: ReturnTypeOption\n importPath?: string\n exclude?: Array<Exclude>\n include?: Array<Include>\n override?: Array<Override<Omit<ClientPluginOptions, 'override'>>>\n}\n\nfunction isRelativeImport(importPath: string): boolean {\n return importPath.startsWith('.')\n}\n\n// plugin-client resolves a relative `importPath` from its `<op>` file, so do the same here.\nfunction resolveImportPath(options: { importPath: string; operationFile: string }): string {\n const { importPath, operationFile } = options\n return isRelativeImport(importPath) ? path.resolve(path.dirname(operationFile), importPath) : importPath\n}\n\n/**\n * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up\n * the registered contract client plugin's resolver and output. Works for any contract client plugin\n * (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline\n * path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then\n * emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global\n * output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.\n * With plugin-client they come from the user's `importPath` module instead.\n *\n * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,\n * so several dependents reading the same client plugin for one operation in a single pass\n * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share\n * one computed result instead of each re-deriving the name and path.\n *\n * `returnType`, `output`, and `group` are the client plugin's options for this operation, after its\n * `override` entries, the same resolution its own generator sees. A dependent's generated call body\n * and import path therefore match the `<op>` actually emitted, even when an `override` changes it.\n */\nexport function resolveClientOperation(options: {\n clientPlugin: { pluginName: string } | null\n driver: {\n getPlugin: (name: string) => { options?: ClientPluginOptions } | undefined\n getResolver: (name: string) => Resolver\n }\n node: ast.OperationNode\n root: string\n output: Output\n cache: NodeCache\n}): ClientOperation | null {\n const { clientPlugin, driver, node, root, output, cache } = options\n if (!clientPlugin) return null\n\n return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {\n const resolver = driver.getResolver(clientPlugin.pluginName)\n const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {}\n const { exclude, include, override } = pluginOptions\n const hasOperationOptions = Boolean(exclude?.length || include?.length || override?.length)\n // Kubb's resolver always has `default`; the fallback keeps partial or custom resolvers working.\n const operationOptions =\n hasOperationOptions && resolver.default ? resolver.default.options(node, { options: pluginOptions, exclude, include, override }) : pluginOptions\n if (!operationOptions) return null\n\n const file = resolver.file({\n ...operationFileEntry(node, node.operationId),\n root,\n output: operationOptions.output ?? output,\n group: operationOptions.group ?? undefined,\n })\n\n const { importPath } = operationOptions\n\n return {\n name: resolver.name(node.operationId),\n path: file.path,\n clientPath: importPath === undefined ? path.resolve(root, '.kubb/client.ts') : resolveImportPath({ importPath, operationFile: file.path }),\n clientPathIsFile: importPath === undefined || isRelativeImport(importPath),\n returnType: operationOptions.returnType ?? 'full',\n }\n })\n}\n","import { resolveClientOperation, resolveOperationTypes } from '@internals/client'\nimport { operationFileEntry, resolveDependencyOperationFile } from '@internals/shared'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { McpHandler } from '../components/McpHandler.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool\n * handler per OpenAPI operation. The handler takes the grouped `{ path, query,\n * headers, body }` config and forwards it to the registered client plugin's\n * (`@kubb/plugin-axios` / `@kubb/plugin-fetch`) `<op>` function.\n */\nexport const mcpGenerator = defineGenerator<PluginMcp>({\n name: 'mcp',\n renderer: jsxRenderer,\n operation(node, ctx) {\n if (!ast.isHttpOperationNode(node)) return null\n const { resolver, driver, root, config } = ctx\n const { output, client, group } = ctx.options\n\n const types = resolveOperationTypes(driver, resolver.pluginName)\n const tsResolver = types.resolver\n\n // The registered contract client plugin owns the `<op>` the handler imports and calls.\n const contractOp = resolveClientOperation({ clientPlugin: { pluginName: client.pluginName }, driver, node, root, output, cache: ctx.cache })\n if (!contractOp) {\n return null\n }\n\n // The handler signature references the grouped `<Name>Options`.\n const optionsName = tsResolver.response.options(node)\n\n const meta = {\n name: resolver.handler.name(node),\n file: resolver.file({ ...operationFileEntry(node, node.operationId), root, output, group: group ?? undefined }),\n fileTs: resolveDependencyOperationFile({\n cache: ctx.cache,\n node,\n resolver: tsResolver,\n root,\n output: types.output ?? output,\n group: types.group,\n }),\n } as const\n\n return (\n <File\n baseName={meta.file.baseName}\n path={meta.file.path}\n meta={meta.file.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}\n >\n {meta.fileTs && optionsName && <File.Import name={[optionsName]} root={meta.file.path} path={meta.fileTs.path} isTypeOnly />}\n <File.Import name={['CallToolResult', 'ServerContext']} path={'@modelcontextprotocol/server'} isTypeOnly />\n\n <File.Import name={[contractOp.name]} root={meta.file.path} path={contractOp.path} />\n\n <McpHandler name={meta.name} clientName={contractOp.name} node={node} resolver={tsResolver} returnType={contractOp.returnType} />\n </File>\n )\n },\n})\n","import path from 'node:path'\nimport { getOperationParameters, getPrimarySuccessResponse, operationFileEntry } from '@internals/shared'\nimport { getRelativePath } from '@internals/utils'\nimport { ast, defineGenerator } from 'kubb/kit'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { File, jsxRenderer } from 'kubb/jsx'\nimport { Server } from '../components/Server.tsx'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default v5 server generator for `@kubb/plugin-mcp`.\n *\n * Uses individual zod schemas for each param (e.g. `createPetsPathUuidSchema`, `createPetsQueryOffsetSchema`)\n * and `resolveResponseStatusName` for per-status response schemas.\n * Query and header params are composed into `z.object({ ... })` from individual schemas.\n */\nexport const serverGenerator = defineGenerator<PluginMcp>({\n name: 'operations',\n renderer: jsxRenderer,\n operations(nodes, ctx) {\n const { config, resolver, plugin, driver, root } = ctx\n const { output, group } = ctx.options\n\n const pluginZod = ctx.requirePlugin(pluginZodName)\n\n const zodResolver = driver.getResolver(pluginZodName)\n\n const fileAt = <TName extends `${string}.${string}`>(baseName: TName) => ({\n baseName,\n path: path.resolve(root, output.path, baseName),\n meta: { pluginName: plugin.name },\n })\n const serverFile = fileAt('server.ts')\n const startFile = fileAt('start.ts')\n const jsonFile = fileAt('.mcp.json')\n\n // MCP clients spawn the command from their own working directory, usually the project root,\n // so `args` points at `start.ts` relative to `config.root` instead of the `.mcp.json` folder.\n const mcpConfig = {\n mcpServers: {\n [ctx.meta.title || 'server']: {\n type: 'stdio',\n command: 'npx',\n args: ['tsx', getRelativePath(path.resolve(config.root), startFile.path)],\n },\n },\n }\n\n const operationsMapped = nodes.filter(ast.isHttpOperationNode).map((node) => {\n const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node)\n\n const fileEntry = operationFileEntry(node, node.operationId)\n const mcpFile = resolver.file({ ...fileEntry, root, output, group: group ?? undefined })\n const zodFile = zodResolver.file({\n ...fileEntry,\n root,\n output: pluginZod.options?.output ?? output,\n group: pluginZod.options?.group ?? undefined,\n })\n\n const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null\n const successStatus = getPrimarySuccessResponse(node)?.statusCode\n const responseName = successStatus ? zodResolver.response.status(node, successStatus) : null\n\n const resolveParams = (params: typeof pathParams) => params.map((p) => ({ name: p.name, schemaName: zodResolver.param.name(node, p) }))\n\n return {\n tool: {\n name: node.operationId,\n title: node.summary || undefined,\n description: node.description || `Make a ${node.method.toUpperCase()} request to ${node.path}`,\n },\n mcp: {\n name: resolver.handler.name(node),\n file: mcpFile,\n },\n zod: {\n pathParams: resolveParams(pathParams),\n queryParams: queryParams.length ? resolveParams(queryParams) : null,\n headerParams: headerParams.length ? resolveParams(headerParams) : null,\n requestName,\n responseName,\n file: zodFile,\n },\n }\n })\n\n const imports = operationsMapped.flatMap(({ mcp, zod }) => {\n const zodNames = [\n ...zod.pathParams.map((p) => p.schemaName),\n ...(zod.queryParams ?? []).map((p) => p.schemaName),\n ...(zod.headerParams ?? []).map((p) => p.schemaName),\n zod.requestName,\n zod.responseName,\n ].filter((name): name is string => Boolean(name))\n\n const uniqueNames = [...new Set(zodNames)].sort()\n\n return [\n <File.Import key={mcp.name} name={[mcp.name]} root={serverFile.path} path={mcp.file.path} />,\n uniqueNames.length > 0 && <File.Import key={`zod-${mcp.name}`} name={uniqueNames} root={serverFile.path} path={zod.file.path} />,\n ].filter(Boolean)\n })\n\n return (\n <>\n <File\n baseName={serverFile.baseName}\n path={serverFile.path}\n meta={serverFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: serverFile.path, baseName: serverFile.baseName } })}\n >\n <File.Import name={['McpServer']} path={'@modelcontextprotocol/server'} />\n <File.Import name={['serveStdio']} path={'@modelcontextprotocol/server/stdio'} />\n <File.Import name={['z']} path={'zod'} />\n\n {imports}\n <Server serverName={ctx.meta.title ?? 'server'} serverVersion={ctx.meta.version ?? '0.0.0'} operations={operationsMapped} />\n </File>\n\n <File\n baseName={startFile.baseName}\n path={startFile.path}\n meta={startFile.meta}\n banner={resolver.default.banner(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n footer={resolver.default.footer(ctx.meta, { output, config, file: { path: startFile.path, baseName: startFile.baseName } })}\n >\n <File.Import name={['startServer']} root={startFile.path} path={serverFile.path} />\n {/* Not indexable: barrels must not re-export this entry, importing it starts the server. */}\n <File.Source name=\"start\">{'void startServer()'}</File.Source>\n </File>\n\n <File baseName={jsonFile.baseName} path={jsonFile.path} meta={jsonFile.meta}>\n <File.Source name=\"server\">{`${JSON.stringify(mcpConfig, null, 2)}\\n`}</File.Source>\n </File>\n </>\n )\n },\n})\n","","","import { camelCase } from '@internals/utils'\nimport { createResolver } from 'kubb/kit'\nimport type { PluginMcp } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-mcp`. Decides the names and file\n * paths for every generated MCP tool handler. Function names get a `Handler`\n * suffix so an operation `addPet` becomes `addPetHandler`.\n *\n * @example Resolve a handler name\n * ```ts\n * import { resolverMcp } from '@kubb/plugin-mcp'\n *\n * resolverMcp.name('addPet') // 'addPetHandler'\n * ```\n */\nexport const resolverMcp = createResolver<PluginMcp>({\n pluginName: 'plugin-mcp',\n name(name) {\n return camelCase(name, { suffix: 'handler' })\n },\n handler: {\n name(node) {\n return this.name(node.operationId)\n },\n },\n})\n","import { createGroupConfig } from '@internals/shared'\n\nimport { resolveContractClient } from '@internals/client'\nimport { addGenerator, defineExtension, Resolver, setMacros, setResolver, useConfig } from 'kubb/kit'\nimport { compatibility } from '../kubb-extension.json'\nimport { version } from '../package.json'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { pluginZodName } from '@kubb/plugin-zod'\nimport { mcpGenerator } from './generators/mcpGenerator.tsx'\nimport { serverGenerator } from './generators/serverGenerator.tsx'\nimport { resolverMcp } from './resolvers/resolverMcp.ts'\nimport type { PluginMcp, ResolverMcp } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginMcpName = 'plugin-mcp' satisfies PluginMcp['name']\n\n/**\n * Generates a Model Context Protocol (MCP) server from an OpenAPI spec. Every\n * operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude\n * Code, MCP-compatible clients) can call directly. Each handler calls a contract\n * client `<op>` from a registered `@kubb/plugin-axios` or `@kubb/plugin-fetch`.\n * Next to the handlers it writes `server.ts`, a `start.ts` entry that serves the\n * tools over stdio, and a `.mcp.json` that runs `start.ts` with `tsx`.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb/config'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginZod } from '@kubb/plugin-zod'\n * import { pluginFetch } from '@kubb/plugin-fetch'\n * import { pluginMcp } from '@kubb/plugin-mcp'\n *\n * export default defineConfig({\n * input: './petStore.yaml',\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginZod(),\n * pluginFetch({ baseURL: 'https://petstore.swagger.io/v2' }),\n * pluginMcp({ output: { path: 'mcp' } }),\n * ],\n * })\n * ```\n */\nexport const pluginMcp = defineExtension<PluginMcp>({\n kind: 'plugin',\n meta: { name: pluginMcpName, version, compatibility },\n dependencies: { [pluginTsName]: { optional: true }, [pluginZodName]: {} },\n setup(options) {\n const {\n output = { path: 'mcp', barrel: { type: 'named' } },\n group,\n exclude = [],\n include,\n override = [],\n client,\n resolver: userResolver,\n macros: userMacros,\n } = options\n\n const resolver = userResolver ? Resolver.merge<ResolverMcp>(resolverMcp, userResolver) : resolverMcp\n\n setResolver(resolver)\n if (userMacros?.length) {\n setMacros(userMacros)\n }\n addGenerator(mcpGenerator, serverGenerator)\n\n return {\n output,\n exclude,\n include,\n override,\n group: createGroupConfig(group),\n client: resolveContractClient({ plugin: pluginMcpName, client, plugins: useConfig().plugins }),\n resolver,\n }\n },\n})\n\nexport default pluginMcp\n"],"mappings":"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"}
package/docs/overview.md CHANGED
@@ -6,7 +6,7 @@ Each tool handler calls the function a client plugin generates for that operatio
6
6
 
7
7
  ## Setup
8
8
 
9
- - Add `@kubb/plugin-ts`, `@kubb/plugin-zod`, and a client plugin: `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client`. Leave `sdk` unset on the client plugin.
9
+ - Add `@kubb/plugin-zod`, `@kubb/plugin-ts` (optional with `pluginZod({ inferred: 'codec' })`), and a client plugin: `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client`. Leave `sdk` unset on the client plugin.
10
10
  - Install `@modelcontextprotocol/server` v2 and `zod` 4.2 or a later v4 release in the app that runs the server. Add `axios` too when you use `@kubb/plugin-axios`.
11
11
  - Install a TypeScript runner such as `tsx`. The generated `.mcp.json` runs `npx tsx`, which downloads `tsx` from npm when it is missing.
12
12
  - Copy the server entry from the generated `.mcp.json` into the `.mcp.json` your MCP client reads, such as the one at the project root for Claude Code.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-mcp",
3
- "version": "5.3.0",
3
+ "version": "5.3.2",
4
4
  "description": "Generate Model Context Protocol (MCP) tool definitions with Kubb. Expose your REST APIs as AI-callable tools for LLMs, Claude, ChatGPT, and other AI assistants.",
5
5
  "keywords": [
6
6
  "ai",
@@ -68,20 +68,20 @@
68
68
  "registry": "https://registry.npmjs.org/"
69
69
  },
70
70
  "dependencies": {
71
- "@kubb/plugin-ts": "^5.1.0",
72
- "@kubb/plugin-zod": "^5.6.0"
71
+ "@kubb/plugin-ts": "^5.2.0",
72
+ "@kubb/plugin-zod": "^5.7.2"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@internals/client": "0.0.0",
76
76
  "@internals/shared": "0.0.0",
77
77
  "@internals/utils": "0.0.0",
78
78
  "@modelcontextprotocol/server": "^2.3.1",
79
- "kubb": "^5.13.0",
79
+ "kubb": "^5.14.0",
80
80
  "zod": "^4.6.7"
81
81
  },
82
82
  "peerDependencies": {
83
83
  "@modelcontextprotocol/server": "^2.0.0",
84
- "kubb": "^5.13.0",
84
+ "kubb": "^5.14.0",
85
85
  "zod": "^4.2.0"
86
86
  },
87
87
  "peerDependenciesMeta": {