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

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.
Files changed (2) hide show
  1. package/extension.yaml +470 -0
  2. package/package.json +8 -8
package/extension.yaml ADDED
@@ -0,0 +1,470 @@
1
+ $schema: https://kubb.dev/schemas/extension.json
2
+ kind: plugin
3
+ id: plugin-mcp
4
+ name: MCP
5
+ description: Generate Model Context Protocol (MCP) servers from OpenAPI specifications for AI assistants to call your API.
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 [Model Context Protocol](https://modelcontextprotocol.io/introduction) servers from your OpenAPI schema. AI assistants like Claude can now call your API through conversational interfaces.
43
+
44
+ ```mermaid
45
+ graph TD
46
+ A[Kubb<br/>Generates code from OpenAPI] --> B[MCP Server<br/>Handles tool calls]
47
+ B --> C[Claude<br/>Conversational AI]
48
+ C -->|Sends tool request| B
49
+ B -->|Uses generated code| A
50
+ ```
51
+ notes:
52
+ - type: tip
53
+ body: |
54
+ See [Setup Claude with Kubb](https://modelcontextprotocol.io/docs/tools/claude-desktop) for configuration instructions.
55
+ options:
56
+ - name: output
57
+ type: Output
58
+ required: false
59
+ default: "{ path: 'mcp', barrelType: 'named' }"
60
+ description: Specify the export location for the files and define the behavior of the output.
61
+ properties:
62
+ - name: path
63
+ type: string
64
+ required: true
65
+ description: Output directory or file for the generated code, relative to the global `output.path`.
66
+ tip: |
67
+ if `output.path` is a file, `group` cannot be used.
68
+ default: "'mcp'"
69
+ - name: barrelType
70
+ type: "'all' | 'named' | 'propagate' | false"
71
+ required: false
72
+ default: "'named'"
73
+ description: Specify what to export and optionally disable barrel-file generation.
74
+ tip: |
75
+ Using `propagate` will prevent a plugin from creating a barrel file, but it will still propagate, allowing [`output.barrelType`](https://kubb.dev/docs/5.x/configuration#output-barreltype) to export the specific function or type.
76
+ examples:
77
+ - name: all
78
+ files:
79
+ - lang: typescript
80
+ code: |
81
+ export * from './gen/petService.ts'
82
+ twoslash: false
83
+ - name: named
84
+ files:
85
+ - lang: typescript
86
+ code: |
87
+ export { PetService } from './gen/petService.ts'
88
+ twoslash: false
89
+ - name: propagate
90
+ files:
91
+ - lang: typescript
92
+ code: ""
93
+ twoslash: false
94
+ - name: "false"
95
+ files:
96
+ - lang: typescript
97
+ code: ""
98
+ twoslash: false
99
+ - name: banner
100
+ type: "string | ((node: RootNode) => string)"
101
+ required: false
102
+ description: Add a banner comment at the top of every generated file. Accepts a static string or a function that receives the `RootNode` and returns a string.
103
+ - name: footer
104
+ type: "string | ((node: RootNode) => string)"
105
+ required: false
106
+ description: Add a footer comment at the end of every generated file. Accepts a static string or a function that receives the `RootNode` and returns a string.
107
+ - name: override
108
+ type: boolean
109
+ required: false
110
+ default: "false"
111
+ description: Whether Kubb overrides existing external files that can be generated if they already exist.
112
+ - name: resolver
113
+ type: Partial<ResolverMcp> & ThisType<ResolverMcp>
114
+ required: false
115
+ description: |
116
+ A single resolver that overrides the naming and path-resolution conventions. Each method you provide replaces the corresponding built-in one. When a method returns `null` or `undefined`, the resolver's result is used as the fallback, so you only need to supply the methods you want to change.
117
+
118
+ `this` inside each method is bound to the **full** resolver, so you can call other resolver methods (e.g. `this.default(name, 'function')`) without losing context.
119
+ body: |
120
+ Each plugin ships a built-in resolver:
121
+
122
+ | Plugin | Default resolver |
123
+ | --- | --- |
124
+ | `@kubb/plugin-ts` | `resolverTs` |
125
+ | `@kubb/plugin-zod` | `resolverZod` |
126
+ | `@kubb/plugin-cypress` | `resolverCypress` |
127
+ | `@kubb/plugin-mcp` | `resolverMcp` |
128
+ codeBlock:
129
+ lang: typescript
130
+ title: Custom resolver (plugin-mcp example)
131
+ code: |
132
+ import { pluginMcp } from '@kubb/plugin-mcp'
133
+
134
+ pluginMcp({
135
+ resolver: {
136
+ resolveName(name) {
137
+ return `Mcp${this.default(name, 'function')}`
138
+ },
139
+ },
140
+ })
141
+ tip: |
142
+ Use `resolver` for fine-grained control over naming conventions.
143
+ - name: group
144
+ type: Group
145
+ required: false
146
+ description: |
147
+ Grouping combines files in a folder based on a specific `type`.
148
+ examples:
149
+ - name: kubb.config.ts
150
+ files:
151
+ - lang: typescript
152
+ code: |
153
+ group: {
154
+ type: 'tag',
155
+ name({ group }) {
156
+ return `${group}Controller`
157
+ }
158
+ }
159
+ twoslash: false
160
+ body: |
161
+ With the configuration above, the generator emits:
162
+
163
+ ```text
164
+ .
165
+ ├── src/
166
+ │ └── petController/
167
+ │ │ ├── addPet.ts
168
+ │ │ └── getPet.ts
169
+ │ └── storeController/
170
+ │ ├── createStore.ts
171
+ │ └── getStoreById.ts
172
+ ├── petStore.yaml
173
+ ├── kubb.config.ts
174
+ └── package.json
175
+ ```
176
+ properties:
177
+ - name: type
178
+ type: "'tag'"
179
+ required: true
180
+ description: Specify the property to group files by. Required when `group` is defined.
181
+ note: |
182
+ `Required: true*` means this is required only when the `group` option is used. The `group` option itself is optional.
183
+ body: |
184
+ - `'tag'`: Uses the first tag from `operation.getTags().at(0)?.name`
185
+ - name: name
186
+ type: "(context: GroupContext) => string"
187
+ required: false
188
+ default: (ctx) => `${ctx.group}Requests`
189
+ description: Return the name of a group based on the group name. This is used for file and identifier generation.
190
+ - name: paramsCasing
191
+ type: "'camelcase'"
192
+ required: false
193
+ description: Transform parameter names to camelCase in generated MCP handlers.
194
+ important: |
195
+ When using `paramsCasing`, ensure that `@kubb/plugin-ts` also has the same `paramsCasing` setting. This option automatically maps transformed parameter names back to their original API names in HTTP requests.
196
+ body: |
197
+ - `'camelcase'` transforms parameter names to camelCase.
198
+ examples:
199
+ - name: With paramsCasing camelcase
200
+ files:
201
+ - lang: typescript
202
+ code: |
203
+ // Handler uses camelCase parameters
204
+ export async function findPetsByStatusHandler({
205
+ stepId // ✓ camelCase
206
+ }: {
207
+ stepId: FindPetsByStatusPathParams['stepId']
208
+ }): Promise<Promise<CallToolResult>> {
209
+ // Automatically maps back to original name
210
+ const step_id = stepId
211
+
212
+ const res = await fetch({
213
+ method: 'GET',
214
+ url: `/pet/findByStatus/${step_id}`, // Uses original API name
215
+ ...
216
+ })
217
+ ...
218
+ }
219
+ twoslash: false
220
+ - name: Without paramsCasing
221
+ files:
222
+ - lang: typescript
223
+ code: |
224
+ // Handler uses original API naming
225
+ export async function findPetsByStatusHandler({
226
+ step_id // Original naming
227
+ }: {
228
+ step_id: FindPetsByStatusPathParams['step_id']
229
+ }): Promise<Promise<CallToolResult>> {
230
+ const res = await fetch({
231
+ method: 'GET',
232
+ url: `/pet/findByStatus/${step_id}`,
233
+ ...
234
+ })
235
+ ...
236
+ }
237
+ twoslash: false
238
+ - name: client
239
+ type: ClientImportPath & { clientType?, dataReturnType?, baseURL?, bundle?, paramsCasing? }
240
+ required: false
241
+ description: Client configuration for HTTP request generation, including client type, data return type, base URL, and bundling options.
242
+ properties:
243
+ - name: importPath
244
+ type: string
245
+ required: false
246
+ description: Path to the client used for API calls. Supports both relative and absolute paths.
247
+ details:
248
+ - title: When to use `importPath`
249
+ body: |
250
+ Use `importPath` when you want to:
251
+
252
+ - **Customize the HTTP client**: Provide your own client implementation with custom configurations (e.g., baseURL, headers, interceptors)
253
+ - **Add authentication**: Include authentication tokens or other security mechanisms in your client
254
+ - **Override default behavior**: Replace the default Kubb client with your own implementation
255
+ - title: Default behavior
256
+ body: |
257
+ When `importPath` is not specified:
258
+
259
+ - If `bundle: false` (default): Uses `@kubb/plugin-client/clients/${client}` where client is either `axios` or `fetch`.
260
+ - If `bundle: true`: Bundles the client into `.kubb/fetch.ts`.
261
+ - title: Import structure
262
+ body: "Generated code imports the client as a default import and the runtime types as named type imports:"
263
+ codeBlock:
264
+ lang: typescript
265
+ code: |-
266
+ /**
267
+ * Generated by Kubb (https://kubb.dev/).
268
+ * Do not edit manually.
269
+ */
270
+ import client from '${client.importPath}'
271
+ import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
272
+ // ... rest of generated file
273
+ important: |
274
+ When using `importPath` with query plugins such as `@kubb/plugin-react-query` or `@kubb/plugin-vue-query`, the generated hooks also import a `Client` type alongside `RequestConfig` and `ResponseErrorConfig` from the custom module. Your custom client module **must** export all three types — if any is missing, TypeScript will report an unresolvable import error.
275
+ codeBlock:
276
+ lang: typescript
277
+ title: client.ts
278
+ code: |
279
+ export type RequestConfig<TData = unknown> = {
280
+ url?: string
281
+ method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
282
+ params?: object
283
+ data?: TData | FormData
284
+ responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
285
+ signal?: AbortSignal
286
+ headers?: HeadersInit
287
+ }
288
+
289
+ export type ResponseConfig<TData = unknown> = {
290
+ data: TData
291
+ status: number
292
+ statusText: string
293
+ }
294
+
295
+ export type ResponseErrorConfig<TError = unknown> = TError
296
+
297
+ // The Client type alias is required when using query plugins
298
+ export type Client = <TData, _TError = unknown, TVariables = unknown>(
299
+ config: RequestConfig<TVariables>
300
+ ) => Promise<ResponseConfig<TData>>
301
+
302
+ export const client: Client = async (config) => { /* ... */ }
303
+ export default client
304
+ examples:
305
+ - name: kubb.config.ts
306
+ files:
307
+ - lang: typescript
308
+ code: |
309
+ import { defineConfig } from 'kubb'
310
+ import { pluginClient } from '@kubb/plugin-client'
311
+
312
+ export default defineConfig({
313
+ // ...
314
+ plugins: [
315
+ pluginClient({
316
+ importPath: './src/client.ts', // Path to your custom client
317
+ }),
318
+ ],
319
+ })
320
+ twoslash: false
321
+ tip: |
322
+ Learn more about defining a custom client [here](https://kubb.dev/plugins/plugin-client#importpath).
323
+ - name: dataReturnType
324
+ type: "'data' | 'full'"
325
+ required: false
326
+ default: "'data'"
327
+ description: |
328
+ Return type used when calling the client.
329
+
330
+ - `'data'` returns `ResponseConfig['data']`.
331
+ - `'full'` returns the full `ResponseConfig`.
332
+ examples:
333
+ - name: data
334
+ files:
335
+ - lang: typescript
336
+ code: |
337
+ export async function getPetById<TData>(
338
+ petId: GetPetByIdPathParams,
339
+ ): Promise<ResponseConfig<TData>['data']> {
340
+ ...
341
+ }
342
+ twoslash: false
343
+ - name: full
344
+ files:
345
+ - lang: typescript
346
+ code: |
347
+ export async function getPetById<TData>(
348
+ petId: GetPetByIdPathParams,
349
+ ): Promise<ResponseConfig<TData>> {
350
+ ...
351
+ }
352
+ twoslash: false
353
+ - name: baseURL
354
+ type: string
355
+ required: false
356
+ description: Sets a custom base URL for all generated calls. When not set, the base URL is automatically taken from the OAS spec via the adapter (e.g. the `servers[0].url` field).
357
+ - name: include
358
+ type: Array<Include>
359
+ required: false
360
+ description: Array containing include parameters to include tags, operations, methods, paths, or content types.
361
+ codeBlock:
362
+ lang: typescript
363
+ title: Include
364
+ code: |
365
+ export type Include = {
366
+ type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
367
+ pattern: string | RegExp
368
+ }
369
+ - name: exclude
370
+ type: Array<Exclude>
371
+ required: false
372
+ description: Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.
373
+ codeBlock:
374
+ lang: typescript
375
+ title: Exclude
376
+ code: |
377
+ export type Exclude = {
378
+ type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
379
+ pattern: string | RegExp
380
+ }
381
+ - name: override
382
+ type: Array<Override>
383
+ required: false
384
+ description: Array containing override parameters to override `options` based on tags, operations, methods, paths, or content types.
385
+ codeBlock:
386
+ lang: typescript
387
+ title: Override
388
+ code: |
389
+ export type Override = {
390
+ type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
391
+ pattern: string | RegExp
392
+ options: PluginOptions
393
+ }
394
+ - name: generators
395
+ type: Array<Generator<PluginMcp>>
396
+ required: false
397
+ experimental: true
398
+ description: |
399
+ Define additional generators next to the built-in generators.
400
+
401
+ See [Generators](https://kubb.dev/docs/5.x/guides/creating-plugins) for more information on how to use generators.
402
+ - name: transformer
403
+ type: Visitor
404
+ required: false
405
+ description: |
406
+ A single AST visitor applied to every node before code is printed. Each method you provide replaces the corresponding built-in one. When a method returns `null` or `undefined`, the preset transformer's result is used as the fallback — so you only need to supply the methods you want to change.
407
+
408
+ Visitor methods receive the node and a context object. Return a modified node to replace it, or return `undefined`/`void` to leave it unchanged.
409
+ examples:
410
+ - name: Strip descriptions before printing
411
+ files:
412
+ - lang: typescript
413
+ code: |
414
+ import { pluginTs } from '@kubb/plugin-ts'
415
+
416
+ pluginTs({
417
+ transformer: {
418
+ schema(node) {
419
+ return { ...node, description: undefined }
420
+ },
421
+ },
422
+ })
423
+ twoslash: false
424
+ - name: Prefix every operationId
425
+ files:
426
+ - lang: typescript
427
+ code: |
428
+ import { pluginTs } from '@kubb/plugin-ts'
429
+
430
+ pluginTs({
431
+ transformer: {
432
+ operation(node) {
433
+ return { ...node, operationId: `api_${node.operationId}` }
434
+ },
435
+ },
436
+ })
437
+ twoslash: false
438
+ tip: |
439
+ Use `transformer` to rewrite node properties before printing. For output naming customization, use `resolver` instead.
440
+ examples:
441
+ - name: kubb.config.ts
442
+ files:
443
+ - lang: typescript
444
+ code: |
445
+ import { defineConfig } from 'kubb'
446
+ import { pluginTs } from '@kubb/plugin-ts'
447
+ import { pluginClient } from '@kubb/plugin-client'
448
+ import { pluginZod } from '@kubb/plugin-zod'
449
+ import { pluginMcp } from '@kubb/plugin-mcp'
450
+
451
+ export default defineConfig({
452
+ input: { path: './petStore.yaml' },
453
+ output: { path: './src/gen' },
454
+ plugins: [
455
+ pluginTs(),
456
+ pluginClient(),
457
+ pluginZod(),
458
+ pluginMcp({
459
+ output: { path: 'mcp', barrelType: 'named' },
460
+ client: {
461
+ baseURL: 'https://petstore.swagger.io/v2',
462
+ },
463
+ group: {
464
+ type: 'tag',
465
+ name: ({ group }) => `${group}Handlers`,
466
+ },
467
+ }),
468
+ ],
469
+ })
470
+ twoslash: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-mcp",
3
- "version": "5.0.0-beta.3",
3
+ "version": "5.0.0-beta.4",
4
4
  "description": "Model Context Protocol (MCP) plugin for Kubb, generating MCP-compatible tools and schemas from OpenAPI specifications for AI assistants.",
5
5
  "keywords": [
6
6
  "ai",
@@ -27,7 +27,7 @@
27
27
  "files": [
28
28
  "src",
29
29
  "dist",
30
- "plugin.json",
30
+ "extension.yaml",
31
31
  "!/**/**.test.**",
32
32
  "!/**/__tests__/**",
33
33
  "!/**/__snapshots__/**"
@@ -49,17 +49,17 @@
49
49
  "registry": "https://registry.npmjs.org/"
50
50
  },
51
51
  "dependencies": {
52
- "@kubb/core": "5.0.0-beta.3",
53
- "@kubb/renderer-jsx": "5.0.0-beta.3",
54
- "@kubb/plugin-client": "5.0.0-beta.3",
55
- "@kubb/plugin-ts": "5.0.0-beta.3",
56
- "@kubb/plugin-zod": "5.0.0-beta.3"
52
+ "@kubb/core": "5.0.0-beta.4",
53
+ "@kubb/renderer-jsx": "5.0.0-beta.4",
54
+ "@kubb/plugin-client": "5.0.0-beta.4",
55
+ "@kubb/plugin-ts": "5.0.0-beta.4",
56
+ "@kubb/plugin-zod": "5.0.0-beta.4"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@internals/utils": "0.0.0"
60
60
  },
61
61
  "peerDependencies": {
62
- "@kubb/renderer-jsx": "5.0.0-beta.3"
62
+ "@kubb/renderer-jsx": "5.0.0-beta.4"
63
63
  },
64
64
  "size-limit": [
65
65
  {