@kubb/plugin-mcp 5.0.0-beta.4 → 5.0.0-beta.42

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/src/types.ts CHANGED
@@ -6,54 +6,68 @@ import type { ClientImportPath, PluginClient } from '@kubb/plugin-client'
6
6
  */
7
7
  export type ResolverMcp = Resolver & {
8
8
  /**
9
- * Resolves the handler function name for an operation.
9
+ * Resolves the base handler function name for an operation.
10
10
  *
11
11
  * @example Resolving handler function names
12
12
  * `resolver.resolveName('show pet by id') // -> 'showPetByIdHandler'`
13
13
  */
14
14
  resolveName(this: ResolverMcp, name: string): string
15
+ /**
16
+ * Resolves the output file name for an MCP module.
17
+ */
18
+ resolvePathName(this: ResolverMcp, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
19
+ /**
20
+ * Resolves the handler function name for an operation.
21
+ */
22
+ resolveHandlerName(this: ResolverMcp, node: ast.OperationNode): string
15
23
  }
16
24
 
17
25
  export type Options = {
18
26
  /**
19
- * Specify the export location for the files and define the behavior of the output.
20
- * @default { path: 'mcp', barrelType: 'named' }
27
+ * Where the generated MCP tool handlers are written and how they are exported.
28
+ *
29
+ * @default { path: 'mcp', barrel: { type: 'named' } }
21
30
  */
22
31
  output?: Output
23
32
  /**
24
- * Client configuration for HTTP request generation.
33
+ * HTTP client used by each MCP handler to call the underlying API. Mirrors a
34
+ * subset of `pluginClient` options.
25
35
  */
26
36
  client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>
27
37
  /**
28
- * Apply casing to parameter names to match your configuration.
38
+ * Rename parameter properties in the generated handlers. The HTTP layer still
39
+ * uses the original spec names; Kubb writes the mapping for you.
40
+ *
41
+ * @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
29
42
  */
30
43
  paramsCasing?: 'camelcase'
31
44
  /**
32
- * Group the MCP requests based on the provided name.
45
+ * Split generated files into subfolders based on the operation's tag.
33
46
  */
34
47
  group?: Group
35
48
  /**
36
- * Tags, operations, or paths to exclude from generation.
49
+ * Skip operations matching at least one entry in the list.
37
50
  */
38
51
  exclude?: Array<Exclude>
39
52
  /**
40
- * Tags, operations, or paths to include in generation.
53
+ * Restrict generation to operations matching at least one entry in the list.
41
54
  */
42
55
  include?: Array<Include>
43
56
  /**
44
- * Override options for specific tags, operations, or paths.
57
+ * Apply a different options object to operations matching a pattern.
45
58
  */
46
59
  override?: Array<Override<ResolvedOptions>>
47
60
  /**
48
- * Override naming conventions for function names and types.
61
+ * Override how handler names and file paths are built. Methods you omit fall
62
+ * back to the default `resolverMcp`.
49
63
  */
50
64
  resolver?: Partial<ResolverMcp> & ThisType<ResolverMcp>
51
65
  /**
52
- * AST visitor to transform generated nodes.
66
+ * AST visitor applied to each operation node before printing.
53
67
  */
54
68
  transformer?: ast.Visitor
55
69
  /**
56
- * Additional generators alongside the default generators.
70
+ * Custom generators that run alongside the built-in MCP generators.
57
71
  */
58
72
  generators?: Array<Generator<PluginMcp>>
59
73
  }
@@ -63,7 +77,7 @@ type ResolvedOptions = {
63
77
  exclude: Array<Exclude>
64
78
  include: Array<Include> | undefined
65
79
  override: Array<Override<ResolvedOptions>>
66
- group: Group | undefined
80
+ group: Group | null
67
81
  client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>
68
82
  paramsCasing: Options['paramsCasing']
69
83
  resolver: ResolverMcp
package/src/utils.ts CHANGED
@@ -1,19 +1,5 @@
1
- import { camelCase } from '@internals/utils'
2
1
  import type { ast } from '@kubb/core'
3
2
 
4
- /**
5
- * Find the first 2xx response status code from an operation's responses.
6
- */
7
- export function findSuccessStatusCode(responses: Array<{ statusCode: number | string }>): ast.StatusCode | undefined {
8
- for (const res of responses) {
9
- const code = Number(res.statusCode)
10
- if (code >= 200 && code < 300) {
11
- return res.statusCode as ast.StatusCode
12
- }
13
- }
14
- return undefined
15
- }
16
-
17
3
  export type ZodParam = {
18
4
  name: string
19
5
  schemaName: string
@@ -31,83 +17,32 @@ export function zodGroupExpr(entry: string | Array<ZodParam>): string {
31
17
  return `z.object({ ${entries.join(', ')} })`
32
18
  }
33
19
 
34
- /**
35
- * Build JSDoc comment lines from an OperationNode.
36
- */
37
- export function getComments(node: ast.OperationNode): Array<string> {
38
- return [
39
- node.description && `@description ${node.description}`,
40
- node.summary && `@summary ${node.summary}`,
41
- node.deprecated && '@deprecated',
42
- `{@link ${node.path.replaceAll('{', ':').replaceAll('}', '')}}`,
43
- ].filter((x): x is string => Boolean(x))
44
- }
45
-
46
- /**
47
- * Build a mapping of original param names → camelCase names.
48
- * Returns `undefined` when no names actually change (no remapping needed).
49
- */
50
- export function getParamsMapping(params: Array<{ name: string }>): Record<string, string> | undefined {
51
- if (!params.length) {
52
- return undefined
53
- }
54
-
55
- const mapping: Record<string, string> = {}
56
- let hasDifference = false
57
-
58
- for (const p of params) {
59
- const camelName = camelCase(p.name)
60
- mapping[p.name] = camelName
61
- if (p.name !== camelName) {
62
- hasDifference = true
63
- }
64
- }
65
-
66
- return hasDifference ? mapping : undefined
67
- }
68
-
69
20
  /**
70
21
  * Convert a SchemaNode type to an inline Zod expression string.
71
22
  * Used as fallback when no named zod schema is available for a path parameter.
72
23
  */
73
24
  export function zodExprFromSchemaNode(schema: ast.SchemaNode): string {
74
- let expr: string
75
- switch (schema.type) {
76
- case 'enum': {
77
- // namedEnumValues takes priority over enumValues
25
+ const baseExpr = (() => {
26
+ if (schema.type === 'enum') {
78
27
  const rawValues: Array<string | number | boolean> = schema.namedEnumValues?.length
79
28
  ? schema.namedEnumValues.map((v) => v.value)
80
29
  : (schema.enumValues ?? []).filter((v): v is string | number | boolean => v !== null)
81
30
 
82
31
  if (rawValues.length > 0 && rawValues.every((v) => typeof v === 'string')) {
83
- expr = `z.enum([${rawValues.map((v) => JSON.stringify(v)).join(', ')}])`
84
- } else if (rawValues.length > 0) {
32
+ return `z.enum([${rawValues.map((v) => JSON.stringify(v)).join(', ')}])`
33
+ }
34
+ if (rawValues.length > 0) {
85
35
  const literals = rawValues.map((v) => `z.literal(${JSON.stringify(v)})`)
86
- expr = literals.length === 1 ? literals[0]! : `z.union([${literals.join(', ')}])`
87
- } else {
88
- expr = 'z.string()'
36
+ return literals.length === 1 ? literals[0]! : `z.union([${literals.join(', ')}])`
89
37
  }
90
- break
38
+ return 'z.string()'
91
39
  }
92
- case 'integer':
93
- expr = 'z.coerce.number()'
94
- break
95
- case 'number':
96
- expr = 'z.number()'
97
- break
98
- case 'boolean':
99
- expr = 'z.boolean()'
100
- break
101
- case 'array':
102
- expr = 'z.array(z.unknown())'
103
- break
104
- default:
105
- expr = 'z.string()'
106
- }
107
-
108
- if (schema.nullable) {
109
- expr = `${expr}.nullable()`
110
- }
111
-
112
- return expr
40
+ if (schema.type === 'integer') return 'z.coerce.number()'
41
+ if (schema.type === 'number') return 'z.number()'
42
+ if (schema.type === 'boolean') return 'z.boolean()'
43
+ if (schema.type === 'array') return 'z.array(z.unknown())'
44
+ return 'z.string()'
45
+ })()
46
+
47
+ return schema.nullable ? `${baseExpr}.nullable()` : baseExpr
113
48
  }
File without changes