@kubb/plugin-mcp 5.0.0-beta.22 → 5.0.0-beta.25
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 +76 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +68 -20
- package/dist/index.js +76 -33
- package/dist/index.js.map +1 -1
- package/extension.yaml +600 -147
- package/package.json +7 -7
- package/src/components/McpHandler.tsx +7 -7
- package/src/components/Server.tsx +6 -6
- package/src/generators/mcpGenerator.tsx +11 -2
- package/src/generators/serverGenerator.tsx +9 -6
- package/src/plugin.ts +33 -1
- package/src/resolvers/resolverMcp.ts +8 -4
- package/src/types.ts +18 -12
package/dist/index.d.ts
CHANGED
|
@@ -28,44 +28,50 @@ type ResolverMcp = Resolver & {
|
|
|
28
28
|
};
|
|
29
29
|
type Options = {
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* Where the generated MCP tool handlers are written and how they are exported.
|
|
32
|
+
*
|
|
33
|
+
* @default { path: 'mcp', barrel: { type: 'named' } }
|
|
33
34
|
*/
|
|
34
35
|
output?: Output;
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
+
* HTTP client used by each MCP handler to call the underlying API. Mirrors a
|
|
38
|
+
* subset of `pluginClient` options.
|
|
37
39
|
*/
|
|
38
40
|
client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>;
|
|
39
41
|
/**
|
|
40
|
-
*
|
|
42
|
+
* Rename parameter properties in the generated handlers. The HTTP layer still
|
|
43
|
+
* uses the original spec names; Kubb writes the mapping for you.
|
|
44
|
+
*
|
|
45
|
+
* @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
|
|
41
46
|
*/
|
|
42
47
|
paramsCasing?: 'camelcase';
|
|
43
48
|
/**
|
|
44
|
-
*
|
|
49
|
+
* Split generated files into subfolders based on the operation's tag.
|
|
45
50
|
*/
|
|
46
51
|
group?: Group;
|
|
47
52
|
/**
|
|
48
|
-
*
|
|
53
|
+
* Skip operations matching at least one entry in the list.
|
|
49
54
|
*/
|
|
50
55
|
exclude?: Array<Exclude>;
|
|
51
56
|
/**
|
|
52
|
-
*
|
|
57
|
+
* Restrict generation to operations matching at least one entry in the list.
|
|
53
58
|
*/
|
|
54
59
|
include?: Array<Include>;
|
|
55
60
|
/**
|
|
56
|
-
*
|
|
61
|
+
* Apply a different options object to operations matching a pattern.
|
|
57
62
|
*/
|
|
58
63
|
override?: Array<Override<ResolvedOptions>>;
|
|
59
64
|
/**
|
|
60
|
-
* Override
|
|
65
|
+
* Override how handler names and file paths are built. Methods you omit fall
|
|
66
|
+
* back to the default `resolverMcp`.
|
|
61
67
|
*/
|
|
62
68
|
resolver?: Partial<ResolverMcp> & ThisType<ResolverMcp>;
|
|
63
69
|
/**
|
|
64
|
-
* AST visitor to
|
|
70
|
+
* AST visitor applied to each operation node before printing.
|
|
65
71
|
*/
|
|
66
72
|
transformer?: ast.Visitor;
|
|
67
73
|
/**
|
|
68
|
-
*
|
|
74
|
+
* Custom generators that run alongside the built-in MCP generators.
|
|
69
75
|
*/
|
|
70
76
|
generators?: Array<Generator<PluginMcp>>;
|
|
71
77
|
};
|
|
@@ -74,7 +80,7 @@ type ResolvedOptions = {
|
|
|
74
80
|
exclude: Array<Exclude>;
|
|
75
81
|
include: Array<Include> | undefined;
|
|
76
82
|
override: Array<Override<ResolvedOptions>>;
|
|
77
|
-
group: Group |
|
|
83
|
+
group: Group | null;
|
|
78
84
|
client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>;
|
|
79
85
|
paramsCasing: Options['paramsCasing'];
|
|
80
86
|
resolver: ResolverMcp;
|
|
@@ -170,13 +176,13 @@ type Props = {
|
|
|
170
176
|
/**
|
|
171
177
|
* Query params — individual schemas to compose into `z.object({ ... })`.
|
|
172
178
|
*/
|
|
173
|
-
queryParams?: string | Array<ZodParam
|
|
179
|
+
queryParams?: string | Array<ZodParam> | null;
|
|
174
180
|
/**
|
|
175
181
|
* Header params — individual schemas to compose into `z.object({ ... })`.
|
|
176
182
|
*/
|
|
177
|
-
headerParams?: string | Array<ZodParam
|
|
178
|
-
requestName?: string;
|
|
179
|
-
responseName?: string;
|
|
183
|
+
headerParams?: string | Array<ZodParam> | null;
|
|
184
|
+
requestName?: string | null;
|
|
185
|
+
responseName?: string | null;
|
|
180
186
|
};
|
|
181
187
|
node: ast.OperationNode;
|
|
182
188
|
}>;
|
|
@@ -190,6 +196,12 @@ declare function Server({
|
|
|
190
196
|
}: Props): KubbReactNode;
|
|
191
197
|
//#endregion
|
|
192
198
|
//#region src/generators/mcpGenerator.d.ts
|
|
199
|
+
/**
|
|
200
|
+
* Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool
|
|
201
|
+
* handler per OpenAPI operation, wiring the input Zod schema, the HTTP call,
|
|
202
|
+
* and the response shape into a single function that an MCP server can
|
|
203
|
+
* register as a callable tool.
|
|
204
|
+
*/
|
|
193
205
|
declare const mcpGenerator: _$_kubb_core0.Generator<PluginMcp, unknown>;
|
|
194
206
|
//#endregion
|
|
195
207
|
//#region src/generators/serverGenerator.d.ts
|
|
@@ -203,17 +215,53 @@ declare const mcpGenerator: _$_kubb_core0.Generator<PluginMcp, unknown>;
|
|
|
203
215
|
declare const serverGenerator: _$_kubb_core0.Generator<PluginMcp, unknown>;
|
|
204
216
|
//#endregion
|
|
205
217
|
//#region src/plugin.d.ts
|
|
218
|
+
/**
|
|
219
|
+
* Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and
|
|
220
|
+
* cross-plugin dependency references.
|
|
221
|
+
*/
|
|
206
222
|
declare const pluginMcpName = "plugin-mcp";
|
|
223
|
+
/**
|
|
224
|
+
* Generates a Model Context Protocol (MCP) server from an OpenAPI spec. Every
|
|
225
|
+
* operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude
|
|
226
|
+
* Code, MCP-compatible clients) can call directly.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* import { defineConfig } from 'kubb'
|
|
231
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
232
|
+
* import { pluginClient } from '@kubb/plugin-client'
|
|
233
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
234
|
+
* import { pluginMcp } from '@kubb/plugin-mcp'
|
|
235
|
+
*
|
|
236
|
+
* export default defineConfig({
|
|
237
|
+
* input: { path: './petStore.yaml' },
|
|
238
|
+
* output: { path: './src/gen' },
|
|
239
|
+
* plugins: [
|
|
240
|
+
* pluginTs(),
|
|
241
|
+
* pluginClient(),
|
|
242
|
+
* pluginZod(),
|
|
243
|
+
* pluginMcp({
|
|
244
|
+
* output: { path: './mcp' },
|
|
245
|
+
* client: { baseURL: 'https://petstore.swagger.io/v2' },
|
|
246
|
+
* }),
|
|
247
|
+
* ],
|
|
248
|
+
* })
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
207
251
|
declare const pluginMcp: (options?: Options | undefined) => _$_kubb_core0.Plugin<PluginMcp>;
|
|
208
252
|
//#endregion
|
|
209
253
|
//#region src/resolvers/resolverMcp.d.ts
|
|
210
254
|
/**
|
|
211
|
-
*
|
|
255
|
+
* Default resolver used by `@kubb/plugin-mcp`. Decides the names and file
|
|
256
|
+
* paths for every generated MCP tool handler. Function names get a `Handler`
|
|
257
|
+
* suffix so an operation `addPet` becomes `addPetHandler`.
|
|
212
258
|
*
|
|
213
|
-
*
|
|
259
|
+
* @example Resolve a handler name
|
|
260
|
+
* ```ts
|
|
261
|
+
* import { resolverMcp } from '@kubb/plugin-mcp'
|
|
214
262
|
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
263
|
+
* resolverMcp.default('addPet', 'function') // 'addPetHandler'
|
|
264
|
+
* ```
|
|
217
265
|
*/
|
|
218
266
|
declare const resolverMcp: ResolverMcp;
|
|
219
267
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -220,12 +220,12 @@ var URLPath = class {
|
|
|
220
220
|
get object() {
|
|
221
221
|
return this.toObject();
|
|
222
222
|
}
|
|
223
|
-
/** Returns a map of path parameter names, or `
|
|
223
|
+
/** Returns a map of path parameter names, or `null` when the path has no parameters.
|
|
224
224
|
*
|
|
225
225
|
* @example
|
|
226
226
|
* ```ts
|
|
227
227
|
* new URLPath('/pet/{petId}').params // { petId: 'petId' }
|
|
228
|
-
* new URLPath('/pet').params //
|
|
228
|
+
* new URLPath('/pet').params // null
|
|
229
229
|
* ```
|
|
230
230
|
*/
|
|
231
231
|
get params() {
|
|
@@ -288,7 +288,7 @@ var URLPath = class {
|
|
|
288
288
|
const key = replacer ? replacer(param) : param;
|
|
289
289
|
params[key] = key;
|
|
290
290
|
});
|
|
291
|
-
return Object.keys(params).length > 0 ? params :
|
|
291
|
+
return Object.keys(params).length > 0 ? params : null;
|
|
292
292
|
}
|
|
293
293
|
/** Converts the OpenAPI path to Express-style colon syntax.
|
|
294
294
|
*
|
|
@@ -304,9 +304,9 @@ var URLPath = class {
|
|
|
304
304
|
//#endregion
|
|
305
305
|
//#region ../../internals/shared/src/operation.ts
|
|
306
306
|
function getOperationLink(node, link) {
|
|
307
|
-
if (!link) return;
|
|
308
|
-
if (typeof link === "function") return link(node);
|
|
309
|
-
if (link === "urlPath") return node.path ? `{@link ${new URLPath(node.path).URL}}` :
|
|
307
|
+
if (!link) return null;
|
|
308
|
+
if (typeof link === "function") return link(node) ?? null;
|
|
309
|
+
if (link === "urlPath") return node.path ? `{@link ${new URLPath(node.path).URL}}` : null;
|
|
310
310
|
return `{@link ${node.path.replaceAll("{", ":").replaceAll("}", "")}}`;
|
|
311
311
|
}
|
|
312
312
|
function buildOperationComments(node, options = {}) {
|
|
@@ -337,15 +337,15 @@ function getOperationParameters(node, options = {}) {
|
|
|
337
337
|
}
|
|
338
338
|
function getStatusCodeNumber(statusCode) {
|
|
339
339
|
const code = Number(statusCode);
|
|
340
|
-
return Number.isNaN(code) ?
|
|
340
|
+
return Number.isNaN(code) ? null : code;
|
|
341
341
|
}
|
|
342
342
|
function isSuccessStatusCode(statusCode) {
|
|
343
343
|
const code = getStatusCodeNumber(statusCode);
|
|
344
|
-
return code !==
|
|
344
|
+
return code !== null && code >= 200 && code < 300;
|
|
345
345
|
}
|
|
346
346
|
function isErrorStatusCode(statusCode) {
|
|
347
347
|
const code = getStatusCodeNumber(statusCode);
|
|
348
|
-
return code !==
|
|
348
|
+
return code !== null && code >= 400;
|
|
349
349
|
}
|
|
350
350
|
function resolveErrorNames(node, resolver) {
|
|
351
351
|
return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
|
|
@@ -372,7 +372,7 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
|
|
|
372
372
|
...query.map((param) => resolver.resolveQueryParamsName(node, param)),
|
|
373
373
|
...header.map((param) => resolver.resolveHeaderParamsName(node, param))
|
|
374
374
|
];
|
|
375
|
-
const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
375
|
+
const bodyAndResponseNames = [node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null, resolver.resolveResponseName(node)];
|
|
376
376
|
const result = (options.order === "body-response-first" ? [
|
|
377
377
|
...bodyAndResponseNames,
|
|
378
378
|
...paramNames,
|
|
@@ -387,6 +387,7 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
|
|
|
387
387
|
}
|
|
388
388
|
function findSuccessStatusCode(responses) {
|
|
389
389
|
for (const response of responses) if (isSuccessStatusCode(response.statusCode)) return response.statusCode;
|
|
390
|
+
return null;
|
|
390
391
|
}
|
|
391
392
|
//#endregion
|
|
392
393
|
//#region ../../internals/shared/src/params.ts
|
|
@@ -398,10 +399,10 @@ function buildParamsMapping(originalParams, mappedParams) {
|
|
|
398
399
|
mapping[param.name] = mappedName;
|
|
399
400
|
if (param.name !== mappedName) hasChanged = true;
|
|
400
401
|
});
|
|
401
|
-
return hasChanged ? mapping :
|
|
402
|
+
return hasChanged ? mapping : null;
|
|
402
403
|
}
|
|
403
404
|
function buildTransformedParamsMapping(params, transformName) {
|
|
404
|
-
if (!params.length) return;
|
|
405
|
+
if (!params.length) return null;
|
|
405
406
|
return buildParamsMapping(params, params.map((param) => ({
|
|
406
407
|
...param,
|
|
407
408
|
name: transformName(param.name)
|
|
@@ -422,7 +423,7 @@ function McpHandler({ name, node, resolver, baseURL, dataReturnType, paramsCasin
|
|
|
422
423
|
const isFormData = contentType === "multipart/form-data";
|
|
423
424
|
const { query: queryParams, header: headerParams } = getOperationParameters(node, { paramsCasing });
|
|
424
425
|
const { path: originalPathParams, query: originalQueryParams, header: originalHeaderParams } = getOperationParameters(node);
|
|
425
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
426
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null;
|
|
426
427
|
const responseName = resolver.resolveResponseName(node);
|
|
427
428
|
const errorResponses = node.responses.filter((r) => Number(r.statusCode) >= 400).map((r) => resolver.resolveResponseStatusName(node, r.statusCode));
|
|
428
429
|
const generics = [
|
|
@@ -438,11 +439,11 @@ function McpHandler({ name, node, resolver, baseURL, dataReturnType, paramsCasin
|
|
|
438
439
|
});
|
|
439
440
|
const baseParamsSignature = declarationPrinter.print(paramsNode) ?? "";
|
|
440
441
|
const paramsSignature = baseParamsSignature ? `${baseParamsSignature}, request: RequestHandlerExtra<ServerRequest, ServerNotification>` : "request: RequestHandlerExtra<ServerRequest, ServerNotification>";
|
|
441
|
-
const pathParamsMapping = paramsCasing ? buildTransformedParamsMapping(originalPathParams, camelCase) :
|
|
442
|
-
const queryParamsMapping = paramsCasing ? buildTransformedParamsMapping(originalQueryParams, camelCase) :
|
|
443
|
-
const headerParamsMapping = paramsCasing ? buildTransformedParamsMapping(originalHeaderParams, camelCase) :
|
|
444
|
-
const contentTypeHeader = contentType && contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` :
|
|
445
|
-
const headers = [headerParams.length ? headerParamsMapping ? "...mappedHeaders" : "...headers" :
|
|
442
|
+
const pathParamsMapping = paramsCasing ? buildTransformedParamsMapping(originalPathParams, camelCase) : null;
|
|
443
|
+
const queryParamsMapping = paramsCasing ? buildTransformedParamsMapping(originalQueryParams, camelCase) : null;
|
|
444
|
+
const headerParamsMapping = paramsCasing ? buildTransformedParamsMapping(originalHeaderParams, camelCase) : null;
|
|
445
|
+
const contentTypeHeader = contentType && contentType !== "application/json" && contentType !== "multipart/form-data" ? `'Content-Type': '${contentType}'` : null;
|
|
446
|
+
const headers = [headerParams.length ? headerParamsMapping ? "...mappedHeaders" : "...headers" : null, contentTypeHeader].filter(Boolean);
|
|
446
447
|
const fetchConfig = [];
|
|
447
448
|
fetchConfig.push(`method: ${JSON.stringify(node.method.toUpperCase())}`);
|
|
448
449
|
fetchConfig.push(`url: ${urlPath.template}`);
|
|
@@ -585,9 +586,9 @@ function Server({ name, serverName, serverVersion, paramsCasing, operations }) {
|
|
|
585
586
|
const paramsNode = entries.length ? ast.createFunctionParameters({ params: [ast.createParameterGroup({ properties: entries.map((e) => ast.createFunctionParameter({
|
|
586
587
|
name: e.key,
|
|
587
588
|
optional: false
|
|
588
|
-
})) })] }) :
|
|
589
|
+
})) })] }) : null;
|
|
589
590
|
const destructured = paramsNode ? keysPrinter.print(paramsNode) ?? "" : "";
|
|
590
|
-
const inputSchema = entries.length ? `{ ${entries.map((e) => `${e.key}: ${e.value}`).join(", ")} }` :
|
|
591
|
+
const inputSchema = entries.length ? `{ ${entries.map((e) => `${e.key}: ${e.value}`).join(", ")} }` : null;
|
|
591
592
|
const outputSchema = zod.responseName;
|
|
592
593
|
const config = [
|
|
593
594
|
tool.title ? `title: ${JSON.stringify(tool.title)}` : null,
|
|
@@ -628,6 +629,12 @@ server.registerTool(${JSON.stringify(tool.name)}, {
|
|
|
628
629
|
}
|
|
629
630
|
//#endregion
|
|
630
631
|
//#region src/generators/mcpGenerator.tsx
|
|
632
|
+
/**
|
|
633
|
+
* Built-in operation generator for `@kubb/plugin-mcp`. Emits one MCP tool
|
|
634
|
+
* handler per OpenAPI operation, wiring the input Zod schema, the HTTP call,
|
|
635
|
+
* and the response shape into a single function that an MCP server can
|
|
636
|
+
* register as a callable tool.
|
|
637
|
+
*/
|
|
631
638
|
const mcpGenerator = defineGenerator({
|
|
632
639
|
name: "mcp",
|
|
633
640
|
renderer: jsxRendererSync,
|
|
@@ -651,7 +658,7 @@ const mcpGenerator = defineGenerator({
|
|
|
651
658
|
}, {
|
|
652
659
|
root,
|
|
653
660
|
output,
|
|
654
|
-
group
|
|
661
|
+
group: group ?? void 0
|
|
655
662
|
}),
|
|
656
663
|
fileTs: tsResolver.resolveFile({
|
|
657
664
|
name: node.operationId,
|
|
@@ -661,7 +668,7 @@ const mcpGenerator = defineGenerator({
|
|
|
661
668
|
}, {
|
|
662
669
|
root,
|
|
663
670
|
output: pluginTs.options?.output ?? output,
|
|
664
|
-
group: pluginTs.options?.group
|
|
671
|
+
group: pluginTs.options?.group ?? void 0
|
|
665
672
|
})
|
|
666
673
|
};
|
|
667
674
|
return /* @__PURE__ */ jsxs(File, {
|
|
@@ -787,7 +794,7 @@ const serverGenerator = defineGenerator({
|
|
|
787
794
|
}, {
|
|
788
795
|
root,
|
|
789
796
|
output,
|
|
790
|
-
group
|
|
797
|
+
group: group ?? void 0
|
|
791
798
|
});
|
|
792
799
|
const zodFile = zodResolver.resolveFile({
|
|
793
800
|
name: node.operationId,
|
|
@@ -797,11 +804,11 @@ const serverGenerator = defineGenerator({
|
|
|
797
804
|
}, {
|
|
798
805
|
root,
|
|
799
806
|
output: pluginZod.options?.output ?? output,
|
|
800
|
-
group: pluginZod.options?.group
|
|
807
|
+
group: pluginZod.options?.group ?? void 0
|
|
801
808
|
});
|
|
802
|
-
const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName(node) :
|
|
809
|
+
const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName(node) : null;
|
|
803
810
|
const successStatus = findSuccessStatusCode(node.responses);
|
|
804
|
-
const responseName = successStatus ? zodResolver.resolveResponseStatusName(node, successStatus) :
|
|
811
|
+
const responseName = successStatus ? zodResolver.resolveResponseStatusName(node, successStatus) : null;
|
|
805
812
|
const resolveParams = (params) => params.map((p) => ({
|
|
806
813
|
name: p.name,
|
|
807
814
|
schemaName: zodResolver.resolveParamName(node, p)
|
|
@@ -818,8 +825,8 @@ const serverGenerator = defineGenerator({
|
|
|
818
825
|
},
|
|
819
826
|
zod: {
|
|
820
827
|
pathParams: resolveParams(pathParams),
|
|
821
|
-
queryParams: queryParams.length ? resolveParams(queryParams) :
|
|
822
|
-
headerParams: headerParams.length ? resolveParams(headerParams) :
|
|
828
|
+
queryParams: queryParams.length ? resolveParams(queryParams) : null,
|
|
829
|
+
headerParams: headerParams.length ? resolveParams(headerParams) : null,
|
|
823
830
|
requestName,
|
|
824
831
|
responseName,
|
|
825
832
|
file: zodFile
|
|
@@ -904,12 +911,16 @@ const serverGenerator = defineGenerator({
|
|
|
904
911
|
//#endregion
|
|
905
912
|
//#region src/resolvers/resolverMcp.ts
|
|
906
913
|
/**
|
|
907
|
-
*
|
|
914
|
+
* Default resolver used by `@kubb/plugin-mcp`. Decides the names and file
|
|
915
|
+
* paths for every generated MCP tool handler. Function names get a `Handler`
|
|
916
|
+
* suffix so an operation `addPet` becomes `addPetHandler`.
|
|
908
917
|
*
|
|
909
|
-
*
|
|
918
|
+
* @example Resolve a handler name
|
|
919
|
+
* ```ts
|
|
920
|
+
* import { resolverMcp } from '@kubb/plugin-mcp'
|
|
910
921
|
*
|
|
911
|
-
*
|
|
912
|
-
*
|
|
922
|
+
* resolverMcp.default('addPet', 'function') // 'addPetHandler'
|
|
923
|
+
* ```
|
|
913
924
|
*/
|
|
914
925
|
const resolverMcp = defineResolver(() => ({
|
|
915
926
|
name: "default",
|
|
@@ -930,7 +941,39 @@ const resolverMcp = defineResolver(() => ({
|
|
|
930
941
|
}));
|
|
931
942
|
//#endregion
|
|
932
943
|
//#region src/plugin.ts
|
|
944
|
+
/**
|
|
945
|
+
* Canonical plugin name for `@kubb/plugin-mcp`. Used for driver lookups and
|
|
946
|
+
* cross-plugin dependency references.
|
|
947
|
+
*/
|
|
933
948
|
const pluginMcpName = "plugin-mcp";
|
|
949
|
+
/**
|
|
950
|
+
* Generates a Model Context Protocol (MCP) server from an OpenAPI spec. Every
|
|
951
|
+
* operation becomes a typed MCP tool that AI assistants (Claude Desktop, Claude
|
|
952
|
+
* Code, MCP-compatible clients) can call directly.
|
|
953
|
+
*
|
|
954
|
+
* @example
|
|
955
|
+
* ```ts
|
|
956
|
+
* import { defineConfig } from 'kubb'
|
|
957
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
958
|
+
* import { pluginClient } from '@kubb/plugin-client'
|
|
959
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
960
|
+
* import { pluginMcp } from '@kubb/plugin-mcp'
|
|
961
|
+
*
|
|
962
|
+
* export default defineConfig({
|
|
963
|
+
* input: { path: './petStore.yaml' },
|
|
964
|
+
* output: { path: './src/gen' },
|
|
965
|
+
* plugins: [
|
|
966
|
+
* pluginTs(),
|
|
967
|
+
* pluginClient(),
|
|
968
|
+
* pluginZod(),
|
|
969
|
+
* pluginMcp({
|
|
970
|
+
* output: { path: './mcp' },
|
|
971
|
+
* client: { baseURL: 'https://petstore.swagger.io/v2' },
|
|
972
|
+
* }),
|
|
973
|
+
* ],
|
|
974
|
+
* })
|
|
975
|
+
* ```
|
|
976
|
+
*/
|
|
934
977
|
const pluginMcp = definePlugin((options) => {
|
|
935
978
|
const { output = {
|
|
936
979
|
path: "mcp",
|
|
@@ -944,7 +987,7 @@ const pluginMcp = definePlugin((options) => {
|
|
|
944
987
|
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
945
988
|
return `${camelCase(ctx.group)}Requests`;
|
|
946
989
|
}
|
|
947
|
-
} :
|
|
990
|
+
} : null;
|
|
948
991
|
return {
|
|
949
992
|
name: pluginMcpName,
|
|
950
993
|
options,
|