@kubb/plugin-mcp 5.0.0-beta.3 → 5.0.0-beta.31

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/extension.yaml ADDED
@@ -0,0 +1,926 @@
1
+ $schema: https://kubb.dev/schemas/extension.json
2
+ kind: plugin
3
+ id: plugin-mcp
4
+ name: MCP
5
+ description: Generate a Model Context Protocol (MCP) server from OpenAPI so AI assistants like Claude can call your API as tools.
6
+ category: ai
7
+ type: official
8
+ npmPackage: '@kubb/plugin-mcp'
9
+ docsPath: /plugins/plugin-mcp
10
+ repo: https://github.com/kubb-labs/plugins
11
+ maintainers:
12
+ - name: Stijn Van Hulle
13
+ github: stijnvanhulle
14
+ compatibility:
15
+ kubb: '>=5.0.0'
16
+ node: '>=22'
17
+ tags:
18
+ - mcp
19
+ - model-context-protocol
20
+ - ai
21
+ - claude
22
+ - llm
23
+ - codegen
24
+ - openapi
25
+ dependencies:
26
+ - plugin-ts
27
+ - plugin-client
28
+ - plugin-zod
29
+ resources:
30
+ documentation: https://kubb.dev/plugins/plugin-mcp
31
+ repository: https://github.com/kubb-labs/plugins
32
+ issues: https://github.com/kubb-labs/plugins/issues
33
+ changelog: https://github.com/kubb-labs/plugins/blob/main/packages/plugin-mcp/CHANGELOG.md
34
+ codesandbox: https://codesandbox.io/p/github/kubb-labs/plugins/main/examples/mcp
35
+ featured: false
36
+ icon:
37
+ light: https://kubb.dev/feature/mcp-light.svg
38
+ dark: https://kubb.dev/feature/mcp-dark.svg
39
+ intro: |
40
+ # @kubb/plugin-mcp
41
+
42
+ Generate a [Model Context Protocol](https://modelcontextprotocol.io/introduction) server straight from your OpenAPI spec. Every operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude Code, MCP-compatible clients) can call directly.
43
+
44
+ The plugin emits the tool definitions, the request handlers, and the Zod schemas they validate against. Plug the generated server into Claude with one config file.
45
+
46
+ ```mermaid
47
+ graph TD
48
+ A[OpenAPI spec] --> B[Kubb<br/>code generation]
49
+ B --> C[MCP server<br/>tool registry]
50
+ C --> D[Claude / MCP client]
51
+ D -->|Tool call| C
52
+ C -->|HTTP request| E[Your API]
53
+ ```
54
+ notes:
55
+ - type: tip
56
+ body: |
57
+ See [Connect Claude to a remote MCP server](https://modelcontextprotocol.io/docs/tools/claude-desktop) for connecting the generated server.
58
+ options:
59
+ - name: output
60
+ type: Output
61
+ required: false
62
+ default: "{ path: 'mcp', barrel: { type: 'named' } }"
63
+ description: Where the generated MCP tool handlers are written and how they are exported.
64
+ properties:
65
+ - name: path
66
+ type: string
67
+ required: true
68
+ description: |
69
+ Folder (or single file) where the plugin writes its generated code. The path is resolved against the global `output.path` set on `defineConfig`.
70
+
71
+ Use a folder to keep each generator's output isolated (`'types'`, `'clients'`, `'hooks'`). Use a single file when you want everything in one place, for example `'api.ts'`.
72
+ tip: |
73
+ When `output.path` points to a single file, the `group` option cannot be used because every operation ends up in the same file.
74
+ examples:
75
+ - name: kubb.config.ts
76
+ files:
77
+ - lang: typescript
78
+ twoslash: false
79
+ code: |
80
+ import { defineConfig } from 'kubb'
81
+ import { pluginTs } from '@kubb/plugin-ts'
82
+
83
+ export default defineConfig({
84
+ input: { path: './petStore.yaml' },
85
+ output: { path: './src/gen' },
86
+ plugins: [
87
+ pluginTs({
88
+ output: { path: './types' },
89
+ }),
90
+ ],
91
+ })
92
+ - name: Resulting tree
93
+ files:
94
+ - lang: text
95
+ twoslash: false
96
+ code: |
97
+ src/
98
+ └── gen/
99
+ └── types/
100
+ ├── Pet.ts
101
+ └── Store.ts
102
+ default: "'mcp'"
103
+ - name: barrel
104
+ type: "{ type: 'named' | 'all', nested?: boolean } | false"
105
+ required: false
106
+ default: "{ type: 'named' }"
107
+ description: |
108
+ Controls how the generated `index.ts` (barrel) file re-exports the plugin's output.
109
+
110
+ - `{ type: 'named' }` re-exports each symbol by name. Best for tree-shaking and explicit imports.
111
+ - `{ type: 'all' }` uses `export *`. Smaller barrel file, but exports everything.
112
+ - `{ nested: true }` creates a barrel in every subdirectory, so callers can import from any depth.
113
+ - `false` skips the barrel entirely. The plugin's files are also excluded from the root `index.ts`.
114
+ tip: |
115
+ Pick `'named'` when consumers care about which symbols they import (better tree-shaking, friendlier auto-import). Pick `'all'` when the file count is small and you want a one-line barrel.
116
+ examples:
117
+ - name: "'named' (default)"
118
+ files:
119
+ - name: kubb.config.ts
120
+ lang: typescript
121
+ twoslash: false
122
+ code: |
123
+ import { defineConfig } from 'kubb'
124
+ import { pluginTs } from '@kubb/plugin-ts'
125
+
126
+ export default defineConfig({
127
+ input: { path: './petStore.yaml' },
128
+ output: { path: './src/gen' },
129
+ plugins: [
130
+ pluginTs({
131
+ output: { barrel: { type: 'named' } },
132
+ }),
133
+ ],
134
+ })
135
+ - name: src/gen/types/index.ts
136
+ lang: typescript
137
+ twoslash: false
138
+ code: |
139
+ export { Pet, PetStatus } from './Pet'
140
+ export { Store } from './Store'
141
+ - name: "'all'"
142
+ files:
143
+ - name: kubb.config.ts
144
+ lang: typescript
145
+ twoslash: false
146
+ code: |
147
+ import { defineConfig } from 'kubb'
148
+ import { pluginTs } from '@kubb/plugin-ts'
149
+
150
+ export default defineConfig({
151
+ input: { path: './petStore.yaml' },
152
+ output: { path: './src/gen' },
153
+ plugins: [
154
+ pluginTs({
155
+ output: { barrel: { type: 'all' } },
156
+ }),
157
+ ],
158
+ })
159
+ - name: src/gen/types/index.ts
160
+ lang: typescript
161
+ twoslash: false
162
+ code: |
163
+ export * from './Pet'
164
+ export * from './Store'
165
+ - name: nested
166
+ files:
167
+ - name: kubb.config.ts
168
+ lang: typescript
169
+ twoslash: false
170
+ code: |
171
+ import { defineConfig } from 'kubb'
172
+ import { pluginTs } from '@kubb/plugin-ts'
173
+
174
+ export default defineConfig({
175
+ input: { path: './petStore.yaml' },
176
+ output: { path: './src/gen' },
177
+ plugins: [
178
+ pluginTs({
179
+ output: { barrel: { type: 'named', nested: true } },
180
+ }),
181
+ ],
182
+ })
183
+ - name: Generated tree
184
+ lang: text
185
+ twoslash: false
186
+ code: |
187
+ src/gen/types/
188
+ ├── index.ts # re-exports ./petController and ./storeController
189
+ ├── petController/
190
+ │ ├── index.ts # re-exports Pet, Store, ...
191
+ │ └── Pet.ts
192
+ └── storeController/
193
+ ├── index.ts
194
+ └── Store.ts
195
+ - name: 'false'
196
+ files:
197
+ - name: kubb.config.ts
198
+ lang: typescript
199
+ twoslash: false
200
+ code: |
201
+ import { defineConfig } from 'kubb'
202
+ import { pluginTs } from '@kubb/plugin-ts'
203
+
204
+ export default defineConfig({
205
+ input: { path: './petStore.yaml' },
206
+ output: { path: './src/gen' },
207
+ plugins: [
208
+ pluginTs({
209
+ output: { barrel: false },
210
+ }),
211
+ ],
212
+ })
213
+ - name: Result
214
+ lang: text
215
+ twoslash: false
216
+ code: |
217
+ # No index.ts is generated for this plugin.
218
+ # Its files are also excluded from the root index.ts.
219
+ - name: banner
220
+ type: 'string | ((node: RootNode) => string)'
221
+ required: false
222
+ description: |
223
+ Text prepended to every generated file. Useful for license headers, lint disables, or `@ts-nocheck` directives.
224
+
225
+ Pass a string for a static banner. Pass a function to compute the banner from each file's `RootNode` (the AST root containing path, schema, and operation context).
226
+ examples:
227
+ - name: Static banner
228
+ files:
229
+ - name: kubb.config.ts
230
+ lang: typescript
231
+ twoslash: false
232
+ code: |
233
+ import { defineConfig } from 'kubb'
234
+ import { pluginTs } from '@kubb/plugin-ts'
235
+
236
+ export default defineConfig({
237
+ input: { path: './petStore.yaml' },
238
+ output: { path: './src/gen' },
239
+ plugins: [
240
+ pluginTs({
241
+ output: {
242
+ banner: '/* eslint-disable */\n// @ts-nocheck',
243
+ },
244
+ }),
245
+ ],
246
+ })
247
+ - name: Generated file
248
+ lang: typescript
249
+ twoslash: false
250
+ code: |
251
+ /* eslint-disable */
252
+ // @ts-nocheck
253
+ export type Pet = {
254
+ id: number
255
+ name: string
256
+ }
257
+ - name: Dynamic banner
258
+ files:
259
+ - name: kubb.config.ts
260
+ lang: typescript
261
+ twoslash: false
262
+ code: |
263
+ import { defineConfig } from 'kubb'
264
+ import { pluginTs } from '@kubb/plugin-ts'
265
+
266
+ export default defineConfig({
267
+ input: { path: './petStore.yaml' },
268
+ output: { path: './src/gen' },
269
+ plugins: [
270
+ pluginTs({
271
+ output: {
272
+ banner: (node) => `// Source: ${node.path}\n// Generated at ${new Date().toISOString()}`,
273
+ },
274
+ }),
275
+ ],
276
+ })
277
+ - name: footer
278
+ type: 'string | ((node: RootNode) => string)'
279
+ required: false
280
+ description: |
281
+ Text appended at the end of every generated file. The mirror of `banner` — use it for closing comments, re-enabling lint rules, or marker lines.
282
+
283
+ Pass a string for a static footer, or a function that receives the file's `RootNode` and returns the footer text.
284
+ examples:
285
+ - name: Re-enable lint after a banner disable
286
+ files:
287
+ - name: kubb.config.ts
288
+ lang: typescript
289
+ twoslash: false
290
+ code: |
291
+ import { defineConfig } from 'kubb'
292
+ import { pluginTs } from '@kubb/plugin-ts'
293
+
294
+ export default defineConfig({
295
+ input: { path: './petStore.yaml' },
296
+ output: { path: './src/gen' },
297
+ plugins: [
298
+ pluginTs({
299
+ output: {
300
+ banner: '/* eslint-disable */',
301
+ footer: '/* eslint-enable */',
302
+ },
303
+ }),
304
+ ],
305
+ })
306
+ - name: override
307
+ type: boolean
308
+ required: false
309
+ default: 'false'
310
+ description: |
311
+ Allows the plugin to overwrite hand-written files that share a name with a generated file.
312
+
313
+ - `false` (default): Kubb skips a file if it already exists and is not marked as generated. This protects manual edits.
314
+ - `true`: Kubb overwrites any file at the target path, including hand-written ones.
315
+ warning: |
316
+ Enable this only when you are sure the target folder contains nothing you need to keep. Local edits are lost on the next generation.
317
+ examples:
318
+ - name: kubb.config.ts
319
+ files:
320
+ - lang: typescript
321
+ twoslash: false
322
+ code: |
323
+ import { defineConfig } from 'kubb'
324
+ import { pluginTs } from '@kubb/plugin-ts'
325
+
326
+ export default defineConfig({
327
+ input: { path: './petStore.yaml' },
328
+ output: { path: './src/gen' },
329
+ plugins: [
330
+ pluginTs({
331
+ output: { override: true },
332
+ }),
333
+ ],
334
+ })
335
+ - name: resolver
336
+ type: Partial<ResolverMcp> & ThisType<ResolverMcp>
337
+ required: false
338
+ description: |
339
+ Overrides how the plugin builds names and paths for generated files and symbols. Use this to add prefixes, suffixes, or to swap the casing strategy without forking the plugin.
340
+
341
+ Only override the methods you want to change. Anything you omit falls back to the plugin's default resolver. A method that returns `null` or `undefined` also falls back.
342
+
343
+ Inside each method, `this` is bound to the full resolver, so you can call `this.default(name, 'function')` to delegate to the built-in implementation.
344
+ body: |
345
+ Each plugin ships with a default resolver:
346
+
347
+ | Plugin | Default resolver |
348
+ | --- | --- |
349
+ | `@kubb/plugin-ts` | `resolverTs` |
350
+ | `@kubb/plugin-zod` | `resolverZod` |
351
+ | `@kubb/plugin-cypress` | `resolverCypress` |
352
+ | `@kubb/plugin-mcp` | `resolverMcp` |
353
+ | `@kubb/plugin-client` | `resolverClient` |
354
+ codeBlock:
355
+ lang: typescript
356
+ title: Prefix every tool name with "Mcp"
357
+ code: |
358
+ import { defineConfig } from 'kubb'
359
+ import { pluginMcp } from '@kubb/plugin-mcp'
360
+
361
+ export default defineConfig({
362
+ input: { path: './petStore.yaml' },
363
+ output: { path: './src/gen' },
364
+ plugins: [
365
+ pluginMcp({
366
+ resolver: {
367
+ resolveName(name) {
368
+ return `Mcp${this.default(name, 'function')}`
369
+ },
370
+ },
371
+ }),
372
+ ],
373
+ })
374
+ tip: |
375
+ Use `resolver` for naming and file-location tweaks. For changing the AST nodes themselves (e.g. stripping descriptions), use `transformer` instead.
376
+ - name: group
377
+ type: Group
378
+ required: false
379
+ description: |
380
+ Splits generated files into subfolders based on the operation's tag, so each tag in your OpenAPI spec gets its own directory.
381
+
382
+ Without `group`, every file lands in the plugin's `output.path` folder. With `group`, files are bucketed under `{output.path}/{groupName}/`, where `groupName` is derived from the operation's first tag.
383
+ tip: |
384
+ Use `group` to mirror your API's domain structure (pet, store, user) in the generated code. Combine it with `output.barrel: { type: 'named', nested: true }` to get per-tag barrel files.
385
+ examples:
386
+ - name: kubb.config.ts
387
+ files:
388
+ - lang: typescript
389
+ twoslash: false
390
+ code: |
391
+ import { defineConfig } from 'kubb'
392
+ import { pluginTs } from '@kubb/plugin-ts'
393
+
394
+ export default defineConfig({
395
+ input: { path: './petStore.yaml' },
396
+ output: { path: './src/gen' },
397
+ plugins: [
398
+ pluginTs({
399
+ group: {
400
+ type: 'tag',
401
+ name: ({ group }) => `${group}Controller`,
402
+ },
403
+ }),
404
+ ],
405
+ })
406
+ body: |
407
+ With the configuration above, the generator emits:
408
+
409
+ ```text
410
+ src/gen/
411
+ ├── petController/
412
+ │ ├── AddPet.ts
413
+ │ └── GetPet.ts
414
+ └── storeController/
415
+ ├── CreateStore.ts
416
+ └── GetStoreById.ts
417
+ ```
418
+ properties:
419
+ - name: type
420
+ type: "'tag'"
421
+ required: true
422
+ description: |
423
+ Property used to assign each operation to a group. Required whenever `group` is set.
424
+
425
+ Today only `'tag'` is supported: Kubb reads the first tag on the operation (`operation.getTags().at(0)?.name`) and uses it as the group key. Operations without a tag are placed in a default group.
426
+ note: |
427
+ `Required: true*` is conditional — only required when the parent `group` option is used. `group` itself stays optional.
428
+ - name: name
429
+ type: '(context: GroupContext) => string'
430
+ required: false
431
+ default: (ctx) => `${ctx.group}Requests`
432
+ description: Function that builds the folder/identifier name from a group key (the operation's first tag).
433
+ - name: paramsCasing
434
+ type: "'camelcase'"
435
+ required: false
436
+ description: |
437
+ Renames parameter properties in the generated MCP handlers. The HTTP layer still uses the original spec names — Kubb adds the mapping for you.
438
+ important: |
439
+ Set the same `paramsCasing` here as on `@kubb/plugin-ts` so the handlers' parameter types line up with the generated request types.
440
+ examples:
441
+ - name: "With `paramsCasing: 'camelcase'`"
442
+ files:
443
+ - lang: typescript
444
+ twoslash: false
445
+ code: |
446
+ // Handler signature uses camelCase
447
+ export async function findPetsByStatusHandler({
448
+ stepId,
449
+ }: {
450
+ stepId: FindPetsByStatusPathParams['stepId']
451
+ }): Promise<CallToolResult> {
452
+ const step_id = stepId
453
+
454
+ const res = await fetch({
455
+ method: 'GET',
456
+ url: `/pet/findByStatus/${step_id}`,
457
+ })
458
+ // ...
459
+ }
460
+ - name: Without `paramsCasing`
461
+ files:
462
+ - lang: typescript
463
+ twoslash: false
464
+ code: |
465
+ export async function findPetsByStatusHandler({
466
+ step_id,
467
+ }: {
468
+ step_id: FindPetsByStatusPathParams['step_id']
469
+ }): Promise<CallToolResult> {
470
+ const res = await fetch({
471
+ method: 'GET',
472
+ url: `/pet/findByStatus/${step_id}`,
473
+ })
474
+ // ...
475
+ }
476
+ - name: client
477
+ type: ClientImportPath & { clientType?, dataReturnType?, baseURL?, bundle?, paramsCasing? }
478
+ required: false
479
+ description: |
480
+ HTTP client used by each MCP handler to call the underlying API. Mirrors a subset of `pluginClient` options.
481
+ properties:
482
+ - name: importPath
483
+ type: string
484
+ required: false
485
+ description: |
486
+ Path or module specifier of a custom client module. Generated code imports its HTTP runtime from here instead of `@kubb/plugin-client/clients/{client}`.
487
+
488
+ Use this when you need to inject auth headers, add interceptors, change the base URL at runtime, or wrap a different HTTP library (ky, ofetch, ...). Both relative paths (`./src/client.ts`) and bare specifiers (`@my-org/api-client`) work.
489
+ details:
490
+ - title: When to use `importPath`
491
+ body: |
492
+ Reach for a custom client when you need to:
493
+
494
+ - Add an auth token to every request.
495
+ - Plug in interceptors, retries, or logging.
496
+ - Configure `baseURL` and headers from environment variables.
497
+ - Wrap a library other than `axios`/`fetch`.
498
+ - title: Default behavior
499
+ body: |
500
+ Without `importPath`:
501
+
502
+ - `bundle: false` (default) — generated code imports from `@kubb/plugin-client/clients/{axios|fetch}`.
503
+ - `bundle: true` — Kubb writes `.kubb/client.ts` and generated code imports from there.
504
+ - title: Required exports
505
+ body: |
506
+ The module pointed to by `importPath` must satisfy the same shape as the built-in client. At minimum:
507
+
508
+ - A default export of the `client` function.
509
+ - A `RequestConfig` type.
510
+ - A `ResponseErrorConfig` type.
511
+
512
+ When used together with a query plugin (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`), it must also export a `Client` type alias.
513
+ - title: How generated files import it
514
+ body: |
515
+ Generated code imports the client as a default import (bound to the local name `client`) and the runtime types as named type imports:
516
+ codeBlock:
517
+ lang: typescript
518
+ code: |
519
+ import client from '${client.importPath}'
520
+ import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
521
+ // ... rest of the generated file
522
+ important: |
523
+ When used with query plugins (`@kubb/plugin-react-query`, `@kubb/plugin-vue-query`), generated hooks also import a `Client` type alias. Your module **must** export `Client`, `RequestConfig`, and `ResponseErrorConfig` — TypeScript will fail the import otherwise.
524
+ codeBlock:
525
+ lang: typescript
526
+ title: src/client.ts
527
+ code: |
528
+ import axios from 'axios'
529
+
530
+ export type RequestConfig<TData = unknown> = {
531
+ url?: string
532
+ method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
533
+ params?: object
534
+ data?: TData | FormData
535
+ responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
536
+ signal?: AbortSignal
537
+ headers?: HeadersInit
538
+ }
539
+
540
+ export type ResponseConfig<TData = unknown> = {
541
+ data: TData
542
+ status: number
543
+ statusText: string
544
+ }
545
+
546
+ export type ResponseErrorConfig<TError = unknown> = TError
547
+
548
+ // Required when used with @kubb/plugin-react-query or @kubb/plugin-vue-query
549
+ export type Client = <TData, _TError = unknown, TVariables = unknown>(
550
+ config: RequestConfig<TVariables>,
551
+ ) => Promise<ResponseConfig<TData>>
552
+
553
+ const client: Client = async (config) => {
554
+ const response = await axios.request<TData>({
555
+ ...config,
556
+ headers: {
557
+ Authorization: `Bearer ${process.env.API_TOKEN}`,
558
+ ...config.headers,
559
+ },
560
+ })
561
+
562
+ return response
563
+ }
564
+
565
+ export default client
566
+ examples:
567
+ - name: Wire up a custom client
568
+ files:
569
+ - name: kubb.config.ts
570
+ lang: typescript
571
+ twoslash: false
572
+ code: |
573
+ import { defineConfig } from 'kubb'
574
+ import { pluginClient } from '@kubb/plugin-client'
575
+
576
+ export default defineConfig({
577
+ input: { path: './petStore.yaml' },
578
+ output: { path: './src/gen' },
579
+ plugins: [
580
+ pluginClient({
581
+ importPath: './src/client.ts',
582
+ }),
583
+ ],
584
+ })
585
+ tip: |
586
+ See the [custom client guide](https://kubb.dev/plugins/plugin-client#importpath) for a worked example.
587
+ - name: dataReturnType
588
+ type: "'data' | 'full'"
589
+ required: false
590
+ default: "'data'"
591
+ description: |
592
+ Shape of the value returned from each generated client function.
593
+
594
+ - `'data'` returns only the response body (`response.data`). Concise and matches what most apps need.
595
+ - `'full'` returns the full response config — body, status code, headers, and the original request. Use this when callers need to inspect headers or status.
596
+ examples:
597
+ - name: "'data' (default)"
598
+ files:
599
+ - name: getPetById.ts
600
+ lang: typescript
601
+ twoslash: false
602
+ code: |
603
+ export async function getPetById<TData>(
604
+ petId: GetPetByIdPathParams,
605
+ ): Promise<ResponseConfig<TData>['data']> {
606
+ // ...
607
+ }
608
+ - name: usage.ts
609
+ lang: typescript
610
+ twoslash: false
611
+ code: |
612
+ const pet = await getPetById(1)
613
+ // ^? Pet
614
+ - name: "'full'"
615
+ files:
616
+ - name: getPetById.ts
617
+ lang: typescript
618
+ twoslash: false
619
+ code: |
620
+ export async function getPetById<TData>(
621
+ petId: GetPetByIdPathParams,
622
+ ): Promise<ResponseConfig<TData>> {
623
+ // ...
624
+ }
625
+ - name: usage.ts
626
+ lang: typescript
627
+ twoslash: false
628
+ code: |
629
+ const response = await getPetById(1)
630
+ // ^? ResponseConfig<Pet>
631
+ console.log(response.status, response.headers)
632
+ const pet = response.data
633
+ - name: baseURL
634
+ type: string
635
+ required: false
636
+ description: |
637
+ Base URL prepended to every request URL in the generated client. When omitted, the URL comes from the OpenAPI spec's `servers[0].url` (or whichever index the adapter is configured to read).
638
+
639
+ Set this when the generated client should point at a different environment (staging, production) than the one written in the spec.
640
+ examples:
641
+ - name: Override the spec's server URL
642
+ files:
643
+ - lang: typescript
644
+ twoslash: false
645
+ code: |
646
+ import { defineConfig } from 'kubb'
647
+ import { pluginClient } from '@kubb/plugin-client'
648
+
649
+ export default defineConfig({
650
+ input: { path: './petStore.yaml' },
651
+ output: { path: './src/gen' },
652
+ plugins: [
653
+ pluginClient({
654
+ baseURL: 'https://petstore.swagger.io/v2',
655
+ }),
656
+ ],
657
+ })
658
+ - name: include
659
+ type: Array<Include>
660
+ required: false
661
+ description: |
662
+ Restricts generation to operations that match at least one entry in the list. Anything not matched is skipped.
663
+
664
+ Each entry filters by one of:
665
+
666
+ - `tag` — the operation's first tag in the OpenAPI spec.
667
+ - `operationId` — the operation's `operationId`.
668
+ - `path` — the URL pattern (`'/pet/{petId}'`).
669
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
670
+ - `contentType` — the media type of the request body.
671
+
672
+ `pattern` accepts either a string (exact match) or a `RegExp` for fuzzy matches.
673
+ codeBlock:
674
+ lang: typescript
675
+ title: Type definition
676
+ code: |
677
+ export type Include = {
678
+ type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
679
+ pattern: string | RegExp
680
+ }
681
+ examples:
682
+ - name: Only the pet tag
683
+ files:
684
+ - name: kubb.config.ts
685
+ lang: typescript
686
+ twoslash: false
687
+ code: |
688
+ import { defineConfig } from 'kubb'
689
+ import { pluginTs } from '@kubb/plugin-ts'
690
+
691
+ export default defineConfig({
692
+ input: { path: './petStore.yaml' },
693
+ output: { path: './src/gen' },
694
+ plugins: [
695
+ pluginTs({
696
+ include: [
697
+ { type: 'tag', pattern: 'pet' },
698
+ ],
699
+ }),
700
+ ],
701
+ })
702
+ - name: Only GET operations under /pet
703
+ files:
704
+ - name: kubb.config.ts
705
+ lang: typescript
706
+ twoslash: false
707
+ code: |
708
+ import { defineConfig } from 'kubb'
709
+ import { pluginTs } from '@kubb/plugin-ts'
710
+
711
+ export default defineConfig({
712
+ input: { path: './petStore.yaml' },
713
+ output: { path: './src/gen' },
714
+ plugins: [
715
+ pluginTs({
716
+ include: [
717
+ { type: 'method', pattern: 'get' },
718
+ { type: 'path', pattern: /^\/pet/ },
719
+ ],
720
+ }),
721
+ ],
722
+ })
723
+ - name: exclude
724
+ type: Array<Exclude>
725
+ required: false
726
+ description: |
727
+ Skips any operation that matches at least one entry in the list. The opposite of `include`.
728
+
729
+ Each entry filters by one of:
730
+
731
+ - `tag` — the operation's first tag.
732
+ - `operationId` — the operation's `operationId`.
733
+ - `path` — the URL pattern (`'/pet/{petId}'`).
734
+ - `method` — HTTP method (`'get'`, `'post'`, ...).
735
+ - `contentType` — the media type of the request body.
736
+
737
+ `pattern` accepts a plain string or a `RegExp`. When both `include` and `exclude` are set, `exclude` wins.
738
+ codeBlock:
739
+ lang: typescript
740
+ title: Type definition
741
+ code: |
742
+ export type Exclude = {
743
+ type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
744
+ pattern: string | RegExp
745
+ }
746
+ examples:
747
+ - name: Skip everything under the store tag
748
+ files:
749
+ - name: kubb.config.ts
750
+ lang: typescript
751
+ twoslash: false
752
+ code: |
753
+ import { defineConfig } from 'kubb'
754
+ import { pluginTs } from '@kubb/plugin-ts'
755
+
756
+ export default defineConfig({
757
+ input: { path: './petStore.yaml' },
758
+ output: { path: './src/gen' },
759
+ plugins: [
760
+ pluginTs({
761
+ exclude: [
762
+ { type: 'tag', pattern: 'store' },
763
+ ],
764
+ }),
765
+ ],
766
+ })
767
+ - name: Skip a specific operation and all delete methods
768
+ files:
769
+ - name: kubb.config.ts
770
+ lang: typescript
771
+ twoslash: false
772
+ code: |
773
+ import { defineConfig } from 'kubb'
774
+ import { pluginTs } from '@kubb/plugin-ts'
775
+
776
+ export default defineConfig({
777
+ input: { path: './petStore.yaml' },
778
+ output: { path: './src/gen' },
779
+ plugins: [
780
+ pluginTs({
781
+ exclude: [
782
+ { type: 'operationId', pattern: 'deletePet' },
783
+ { type: 'method', pattern: 'delete' },
784
+ ],
785
+ }),
786
+ ],
787
+ })
788
+ - name: override
789
+ type: Array<Override>
790
+ required: false
791
+ description: |
792
+ Applies a different set of plugin options to operations that match a pattern. Use this when most of your API should follow the global config, but a handful of endpoints need different treatment.
793
+
794
+ Each entry has the same `type` and `pattern` shape as `include`/`exclude`, plus an `options` object that overrides the plugin's options for matched operations.
795
+
796
+ Entries are evaluated top to bottom. The first matching entry's `options` is merged onto the plugin defaults; later entries do not stack.
797
+ codeBlock:
798
+ lang: typescript
799
+ title: Type definition
800
+ code: |
801
+ export type Override = {
802
+ type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
803
+ pattern: string | RegExp
804
+ options: PluginOptions
805
+ }
806
+ examples:
807
+ - name: Use a different enum style for the user tag
808
+ files:
809
+ - name: kubb.config.ts
810
+ lang: typescript
811
+ twoslash: false
812
+ code: |
813
+ import { defineConfig } from 'kubb'
814
+ import { pluginTs } from '@kubb/plugin-ts'
815
+
816
+ export default defineConfig({
817
+ input: { path: './petStore.yaml' },
818
+ output: { path: './src/gen' },
819
+ plugins: [
820
+ pluginTs({
821
+ enumType: 'asConst',
822
+ override: [
823
+ {
824
+ type: 'tag',
825
+ pattern: 'user',
826
+ options: { enumType: 'literal' },
827
+ },
828
+ ],
829
+ }),
830
+ ],
831
+ })
832
+ - name: generators
833
+ type: Array<Generator<PluginMcp>>
834
+ required: false
835
+ experimental: true
836
+ description: |
837
+ Adds custom generators that run alongside the plugin's built-in generators. Each generator can emit additional files or post-process existing ones using the plugin's AST and options.
838
+
839
+ Use this when you need output the plugin does not produce out of the box (a custom client wrapper, an extra index, a metadata file). For end-to-end guidance, see [Creating plugins](https://kubb.dev/docs/5.x/guides/creating-plugins).
840
+ warning: |
841
+ Generators are an experimental, low-level API. The signature may change between minor releases.
842
+ - name: transformer
843
+ type: Visitor
844
+ required: false
845
+ description: |
846
+ Modifies AST nodes before they are printed to source code. Use this when you need to rewrite operation IDs, drop descriptions, or change schema metadata without forking the generator.
847
+
848
+ Each visitor method (e.g. `schema`, `operation`) receives the node and a context object. Return a new node to replace it, or return `undefined` to leave it untouched. Methods you omit keep the plugin's default behavior.
849
+ examples:
850
+ - name: Strip descriptions before printing
851
+ files:
852
+ - name: kubb.config.ts
853
+ lang: typescript
854
+ twoslash: false
855
+ code: |
856
+ import { defineConfig } from 'kubb'
857
+ import { pluginTs } from '@kubb/plugin-ts'
858
+
859
+ export default defineConfig({
860
+ input: { path: './petStore.yaml' },
861
+ output: { path: './src/gen' },
862
+ plugins: [
863
+ pluginTs({
864
+ transformer: {
865
+ schema(node) {
866
+ return { ...node, description: undefined }
867
+ },
868
+ },
869
+ }),
870
+ ],
871
+ })
872
+ - name: Prefix every operationId
873
+ files:
874
+ - name: kubb.config.ts
875
+ lang: typescript
876
+ twoslash: false
877
+ code: |
878
+ import { defineConfig } from 'kubb'
879
+ import { pluginTs } from '@kubb/plugin-ts'
880
+
881
+ export default defineConfig({
882
+ input: { path: './petStore.yaml' },
883
+ output: { path: './src/gen' },
884
+ plugins: [
885
+ pluginTs({
886
+ transformer: {
887
+ operation(node) {
888
+ return { ...node, operationId: `api_${node.operationId}` }
889
+ },
890
+ },
891
+ }),
892
+ ],
893
+ })
894
+ tip: |
895
+ Use `transformer` to rewrite node properties before printing. For changing the names of generated symbols and files, use `resolver` instead.
896
+ examples:
897
+ - name: kubb.config.ts
898
+ files:
899
+ - lang: typescript
900
+ twoslash: false
901
+ code: |
902
+ import { defineConfig } from 'kubb'
903
+ import { pluginTs } from '@kubb/plugin-ts'
904
+ import { pluginClient } from '@kubb/plugin-client'
905
+ import { pluginZod } from '@kubb/plugin-zod'
906
+ import { pluginMcp } from '@kubb/plugin-mcp'
907
+
908
+ export default defineConfig({
909
+ input: { path: './petStore.yaml' },
910
+ output: { path: './src/gen' },
911
+ plugins: [
912
+ pluginTs(),
913
+ pluginClient(),
914
+ pluginZod(),
915
+ pluginMcp({
916
+ output: { path: 'mcp', barrel: { type: 'named' } },
917
+ client: {
918
+ baseURL: 'https://petstore.swagger.io/v2',
919
+ },
920
+ group: {
921
+ type: 'tag',
922
+ name: ({ group }) => `${group}Handlers`,
923
+ },
924
+ }),
925
+ ],
926
+ })