@kubb/plugin-mcp 5.3.2 → 5.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,8 +4,7 @@ import { Const, File, Function, jsxRenderer } from "kubb/jsx";
4
4
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
5
5
  import { pluginZodName } from "@kubb/plugin-zod";
6
6
  import { pluginTsName } from "@kubb/plugin-ts";
7
- //#endregion
8
- //#region ../../internals/shared/src/operation.ts
7
+ // ../../internals/shared/src/operation.ts
9
8
  /**
10
9
  * Builds the `ResolverFileParams` every operation generator passes to
11
10
  * `resolver.file`: a file named `name`, tagged by the operation's first
@@ -127,8 +126,9 @@ function buildRequestParamsSignature(node, resolver, options = {}) {
127
126
  "body",
128
127
  "headers"
129
128
  ].filter((key) => groups[key]);
129
+ const optionsType = hasRequestContentTypeChoice(node) ? `Pick<${resolver.response.options(node)}, ${names.map((name) => `'${name}'`).join(" | ")}>` : resolver.response.options(node);
130
130
  return {
131
- signature: [names.length > 0 ? `{ ${names.join(", ")} }: ${resolver.response.options(node)}${isOptional ? " = {}" : ""}` : null, isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null].filter(Boolean).join(", "),
131
+ signature: [names.length > 0 ? `{ ${names.join(", ")} }: ${optionsType}${isOptional ? " = {}" : ""}` : null, isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null].filter(Boolean).join(", "),
132
132
  groups
133
133
  };
134
134
  }
@@ -176,6 +176,22 @@ function getOperationParameters(node) {
176
176
  operationParameterGroupsByNode.set(node, groups);
177
177
  return groups;
178
178
  }
179
+ /**
180
+ * Builds the combined `{ body, path, query, headers }` options object schema for an operation,
181
+ * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s
182
+ * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same
183
+ * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod
184
+ * printer to emit `z.object(…)` rather than a record.
185
+ */
186
+ function hasRequestContentTypeChoice(node) {
187
+ return (node.requestBody?.content ?? []).filter((entry) => entry.schema).length > 1;
188
+ }
189
+ /**
190
+ * Casts a call argument to the client's parameter type; a `'plain'` client is non-generic.
191
+ */
192
+ function castToClientOptions(callArg, clientName, returnType = "full") {
193
+ return `${callArg} as Parameters<typeof ${clientName}${returnType === "plain" ? "" : "<true>"}>[0]`;
194
+ }
179
195
  function getStatusCodeNumber(statusCode) {
180
196
  const code = Number(statusCode);
181
197
  return Number.isNaN(code) ? null : code;
@@ -193,8 +209,7 @@ function getOperationSuccessResponses(node) {
193
209
  function getPrimarySuccessResponse(node) {
194
210
  return getOperationSuccessResponses(node)[0] ?? null;
195
211
  }
196
- //#endregion
197
- //#region ../../internals/utils/src/casing.ts
212
+ // ../../internals/utils/src/casing.ts
198
213
  /**
199
214
  * Shared implementation for camelCase and PascalCase conversion.
200
215
  * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
@@ -231,8 +246,7 @@ function toCamelOrPascal(text, pascal) {
231
246
  function camelCase(text, { prefix = "", suffix = "" } = {}) {
232
247
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
233
248
  }
234
- //#endregion
235
- //#region ../../internals/utils/src/fs.ts
249
+ // ../../internals/utils/src/fs.ts
236
250
  function toSlash(p) {
237
251
  if (p.startsWith("\\\\?\\")) return p;
238
252
  return p.replaceAll("\\", "/");
@@ -251,8 +265,26 @@ function getRelativePath(rootDir, filePath) {
251
265
  const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath));
252
266
  return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
253
267
  }
254
- //#endregion
255
- //#region ../../internals/shared/src/group.ts
268
+ // ../../internals/shared/src/resolver.ts
269
+ /**
270
+ * Builds the allocation key for a declaration an operation owns. `scope` names which declaration
271
+ * it is, so two of them never share an allocation even when a custom resolver gives both the same
272
+ * name. Leave `scope` empty for the operation's own declaration.
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
277
+ * ```
278
+ */
279
+ function operationKey(node, ...scope) {
280
+ return [
281
+ "operation",
282
+ node.method,
283
+ node.path,
284
+ ...scope.map(String)
285
+ ];
286
+ }
287
+ // ../../internals/shared/src/group.ts
256
288
  /**
257
289
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
258
290
  * shared default naming so every plugin groups output consistently:
@@ -282,8 +314,7 @@ function createGroupConfig(group) {
282
314
  name: group.name ? group.name : defaultName
283
315
  };
284
316
  }
285
- //#endregion
286
- //#region src/components/McpHandler.tsx
317
+ // src/components/McpHandler.tsx
287
318
  const requestGroupOrder = [
288
319
  "path",
289
320
  "query",
@@ -298,6 +329,7 @@ function McpHandler({ name, clientName, node, resolver, returnType = "full" }) {
298
329
  "signal: ctx.mcpReq.signal",
299
330
  "throwOnError: true"
300
331
  ].join(", ")} }`;
332
+ const callArg = hasRequestContentTypeChoice(node) ? castToClientOptions(callConfig, clientName, returnType) : callConfig;
301
333
  const body = returnType === "data" ? "res" : "res.data";
302
334
  const callToolResult = `return {
303
335
  content: [
@@ -320,15 +352,14 @@ function McpHandler({ name, clientName, node, resolver, returnType = "full" }) {
320
352
  JSDoc: { comments: buildOperationComments(node) },
321
353
  returnType: "CallToolResult",
322
354
  children: [
323
- `const res = await ${clientName}(${callConfig})`,
355
+ `const res = await ${clientName}(${callArg})`,
324
356
  /* @__PURE__ */ jsx("br", {}),
325
357
  callToolResult
326
358
  ]
327
359
  })
328
360
  });
329
361
  }
330
- //#endregion
331
- //#region src/components/Server.tsx
362
+ // src/components/Server.tsx
332
363
  /**
333
364
  * Composes individual param schemas into `z.object({ ... })`.
334
365
  */
@@ -417,8 +448,7 @@ return server`
417
448
  })
418
449
  ] });
419
450
  }
420
- //#endregion
421
- //#region ../../internals/client/src/resolveOperationTypes.ts
451
+ // ../../internals/client/src/resolveOperationTypes.ts
422
452
  /**
423
453
  * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
424
454
  * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
@@ -484,8 +514,7 @@ function resolveOperationTypes(driver, pluginName) {
484
514
  group: pluginZod.options.group ?? void 0
485
515
  };
486
516
  }
487
- //#endregion
488
- //#region ../../internals/client/src/resolveClient.ts
517
+ // ../../internals/client/src/resolveClient.ts
489
518
  /**
490
519
  * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
491
520
  * operation, shared so the selection rules and diagnostics stay in one place.
@@ -595,8 +624,7 @@ function resolveContractClient(options) {
595
624
  }
596
625
  return resolved;
597
626
  }
598
- //#endregion
599
- //#region ../../internals/client/src/resolveClientOperation.ts
627
+ // ../../internals/client/src/resolveClientOperation.ts
600
628
  function isRelativeImport(importPath) {
601
629
  return importPath.startsWith(".");
602
630
  }
@@ -643,8 +671,12 @@ function resolveClientOperation(options) {
643
671
  group: operationOptions.group ?? void 0
644
672
  });
645
673
  const { importPath } = operationOptions;
674
+ const name = resolver.name(node.operationId);
646
675
  return {
647
- name: resolver.name(node.operationId),
676
+ name: resolver.resolveName({
677
+ key: operationKey(node),
678
+ name
679
+ }),
648
680
  path: file.path,
649
681
  clientPath: importPath === void 0 ? path.resolve(root, ".kubb/client.ts") : resolveImportPath({
650
682
  importPath,
@@ -655,8 +687,7 @@ function resolveClientOperation(options) {
655
687
  };
656
688
  });
657
689
  }
658
- //#endregion
659
- //#region src/generators/mcpGenerator.tsx
690
+ // src/generators/mcpGenerator.tsx
660
691
  /**
661
692
  * Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool
662
693
  * handler per OpenAPI operation. The handler takes the grouped `{ path, query,
@@ -747,8 +778,7 @@ const mcpGenerator = defineGenerator({
747
778
  });
748
779
  }
749
780
  });
750
- //#endregion
751
- //#region src/generators/serverGenerator.tsx
781
+ // src/generators/serverGenerator.tsx
752
782
  /**
753
783
  * Default v5 server generator for `@kubb/plugin-mcp`.
754
784
  *
@@ -921,17 +951,14 @@ const serverGenerator = defineGenerator({
921
951
  ] });
922
952
  }
923
953
  });
924
- //#endregion
925
- //#region kubb-extension.json
954
+ // kubb-extension.json
926
955
  var compatibility = {
927
- "kubb": ">=5.8.3",
956
+ "kubb": ">=5.14.6",
928
957
  "node": ">=22.22"
929
958
  };
930
- //#endregion
931
- //#region package.json
932
- var version = "5.3.2";
933
- //#endregion
934
- //#region src/resolvers/resolverMcp.ts
959
+ // package.json
960
+ var version = "5.3.3";
961
+ // src/resolvers/resolverMcp.ts
935
962
  /**
936
963
  * Default resolver used by `@kubb/plugin-mcp`. Decides the names and file
937
964
  * paths for every generated MCP tool handler. Function names get a `Handler`
@@ -950,11 +977,14 @@ const resolverMcp = createResolver({
950
977
  return camelCase(name, { suffix: "handler" });
951
978
  },
952
979
  handler: { name(node) {
953
- return this.name(node.operationId);
980
+ const name = this.name(node.operationId);
981
+ return this.resolveName({
982
+ key: operationKey(node, "handler", "name"),
983
+ name
984
+ });
954
985
  } }
955
986
  });
956
- //#endregion
957
- //#region src/plugin.ts
987
+ // src/plugin.ts
958
988
  /**
959
989
  * Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and
960
990
  * cross-plugin dependency references.
@@ -1023,7 +1053,6 @@ const pluginMcp = defineExtension({
1023
1053
  };
1024
1054
  }
1025
1055
  });
1026
- //#endregion
1027
1056
  export { McpHandler, Server, pluginMcp as default, pluginMcp, mcpGenerator, pluginMcpName, resolverMcp, serverGenerator };
1028
1057
 
1029
1058
  //# sourceMappingURL=index.js.map