@kubb/plugin-mcp 5.0.0-alpha.9 → 5.0.0-beta.10

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
@@ -1,62 +1,88 @@
1
- import type { Group, Output, PluginFactoryOptions, ResolveNameParams } from '@kubb/core'
2
-
3
- import type { contentType, Oas } from '@kubb/oas'
1
+ import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
4
2
  import type { ClientImportPath, PluginClient } from '@kubb/plugin-client'
5
- import type { Exclude, Include, Override, ResolvePathOptions } from '@kubb/plugin-oas'
6
- import type { Generator } from '@kubb/plugin-oas/generators'
3
+
4
+ /**
5
+ * Resolver for MCP that provides naming methods for handler functions.
6
+ */
7
+ export type ResolverMcp = Resolver & {
8
+ /**
9
+ * Resolves the base handler function name for an operation.
10
+ *
11
+ * @example Resolving handler function names
12
+ * `resolver.resolveName('show pet by id') // -> 'showPetByIdHandler'`
13
+ */
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
23
+ }
7
24
 
8
25
  export type Options = {
9
26
  /**
10
- * Specify the export location for the files and define the behavior of the output
27
+ * Specify the export location for the files and define the behavior of the output.
11
28
  * @default { path: 'mcp', barrelType: 'named' }
12
29
  */
13
- output?: Output<Oas>
30
+ output?: Output
14
31
  /**
15
- * Define which contentType should be used.
16
- * By default, the first JSON valid mediaType is used
32
+ * Client configuration for HTTP request generation.
17
33
  */
18
- contentType?: contentType
19
34
  client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>
20
35
  /**
21
- * Transform parameter names to a specific casing format.
22
- * When set to 'camelcase', parameter names in path, query, and header params will be transformed to camelCase.
23
- * This should match the paramsCasing setting used in @kubb/plugin-ts.
24
- * @default undefined
36
+ * Apply casing to parameter names to match your configuration.
25
37
  */
26
38
  paramsCasing?: 'camelcase'
27
39
  /**
28
- * Group the mcp requests based on the provided name.
40
+ * Group the MCP requests based on the provided name.
29
41
  */
30
42
  group?: Group
31
43
  /**
32
- * Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
44
+ * Tags, operations, or paths to exclude from generation.
33
45
  */
34
46
  exclude?: Array<Exclude>
35
47
  /**
36
- * Array containing include parameters to include tags/operations/methods/paths.
48
+ * Tags, operations, or paths to include in generation.
37
49
  */
38
50
  include?: Array<Include>
39
51
  /**
40
- * Array containing override parameters to override `options` based on tags/operations/methods/paths.
52
+ * Override options for specific tags, operations, or paths.
41
53
  */
42
54
  override?: Array<Override<ResolvedOptions>>
43
- transformers?: {
44
- /**
45
- * Customize the names based on the type that is provided by the plugin.
46
- */
47
- name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
48
- }
49
55
  /**
50
- * Define some generators next to the Mcp generators.
56
+ * Override naming conventions for function names and types.
57
+ */
58
+ resolver?: Partial<ResolverMcp> & ThisType<ResolverMcp>
59
+ /**
60
+ * AST visitor to transform generated nodes.
61
+ */
62
+ transformer?: ast.Visitor
63
+ /**
64
+ * Additional generators alongside the default generators.
51
65
  */
52
66
  generators?: Array<Generator<PluginMcp>>
53
67
  }
54
68
 
55
69
  type ResolvedOptions = {
56
- output: Output<Oas>
57
- group: Options['group']
70
+ output: Output
71
+ exclude: Array<Exclude>
72
+ include: Array<Include> | undefined
73
+ override: Array<Override<ResolvedOptions>>
74
+ group: Group | undefined
58
75
  client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>
59
76
  paramsCasing: Options['paramsCasing']
77
+ resolver: ResolverMcp
60
78
  }
61
79
 
62
- export type PluginMcp = PluginFactoryOptions<'plugin-mcp', Options, ResolvedOptions, never, ResolvePathOptions>
80
+ export type PluginMcp = PluginFactoryOptions<'plugin-mcp', Options, ResolvedOptions, ResolverMcp>
81
+
82
+ declare global {
83
+ namespace Kubb {
84
+ interface PluginRegistry {
85
+ 'plugin-mcp': PluginMcp
86
+ }
87
+ }
88
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type { ast } from '@kubb/core'
2
+
3
+ export type ZodParam = {
4
+ name: string
5
+ schemaName: string
6
+ }
7
+
8
+ /**
9
+ * Render a group param value — compose individual schemas into `z.object({ ... })`,
10
+ * or use a schema name string directly.
11
+ */
12
+ export function zodGroupExpr(entry: string | Array<ZodParam>): string {
13
+ if (typeof entry === 'string') {
14
+ return entry
15
+ }
16
+ const entries = entry.map((p) => `${JSON.stringify(p.name)}: ${p.schemaName}`)
17
+ return `z.object({ ${entries.join(', ')} })`
18
+ }
19
+
20
+ /**
21
+ * Convert a SchemaNode type to an inline Zod expression string.
22
+ * Used as fallback when no named zod schema is available for a path parameter.
23
+ */
24
+ export function zodExprFromSchemaNode(schema: ast.SchemaNode): string {
25
+ let expr: string
26
+ switch (schema.type) {
27
+ case 'enum': {
28
+ // namedEnumValues takes priority over enumValues
29
+ const rawValues: Array<string | number | boolean> = schema.namedEnumValues?.length
30
+ ? schema.namedEnumValues.map((v) => v.value)
31
+ : (schema.enumValues ?? []).filter((v): v is string | number | boolean => v !== null)
32
+
33
+ if (rawValues.length > 0 && rawValues.every((v) => typeof v === 'string')) {
34
+ expr = `z.enum([${rawValues.map((v) => JSON.stringify(v)).join(', ')}])`
35
+ } else if (rawValues.length > 0) {
36
+ const literals = rawValues.map((v) => `z.literal(${JSON.stringify(v)})`)
37
+ expr = literals.length === 1 ? literals[0]! : `z.union([${literals.join(', ')}])`
38
+ } else {
39
+ expr = 'z.string()'
40
+ }
41
+ break
42
+ }
43
+ case 'integer':
44
+ expr = 'z.coerce.number()'
45
+ break
46
+ case 'number':
47
+ expr = 'z.number()'
48
+ break
49
+ case 'boolean':
50
+ expr = 'z.boolean()'
51
+ break
52
+ case 'array':
53
+ expr = 'z.array(z.unknown())'
54
+ break
55
+ default:
56
+ expr = 'z.string()'
57
+ }
58
+
59
+ if (schema.nullable) {
60
+ expr = `${expr}.nullable()`
61
+ }
62
+
63
+ return expr
64
+ }
@@ -1,221 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __name = (target, value) => __defProp(target, "name", {
5
- value,
6
- configurable: true
7
- });
8
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
- var __getOwnPropNames = Object.getOwnPropertyNames;
10
- var __getProtoOf = Object.getPrototypeOf;
11
- var __hasOwnProp = Object.prototype.hasOwnProperty;
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
- key = keys[i];
15
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
- get: ((k) => from[k]).bind(null, key),
17
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
- });
19
- }
20
- return to;
21
- };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
- value: mod,
24
- enumerable: true
25
- }) : target, mod));
26
- //#endregion
27
- let _kubb_plugin_oas_utils = require("@kubb/plugin-oas/utils");
28
- let _kubb_react_fabric = require("@kubb/react-fabric");
29
- let _kubb_react_fabric_jsx_runtime = require("@kubb/react-fabric/jsx-runtime");
30
- //#region ../../internals/utils/src/casing.ts
31
- /**
32
- * Shared implementation for camelCase and PascalCase conversion.
33
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
34
- * and capitalizes each word according to `pascal`.
35
- *
36
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
37
- */
38
- function toCamelOrPascal(text, pascal) {
39
- return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
40
- if (word.length > 1 && word === word.toUpperCase()) return word;
41
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
42
- return word.charAt(0).toUpperCase() + word.slice(1);
43
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
44
- }
45
- /**
46
- * Splits `text` on `.` and applies `transformPart` to each segment.
47
- * The last segment receives `isLast = true`, all earlier segments receive `false`.
48
- * Segments are joined with `/` to form a file path.
49
- */
50
- function applyToFileParts(text, transformPart) {
51
- const parts = text.split(".");
52
- return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
53
- }
54
- /**
55
- * Converts `text` to camelCase.
56
- * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
57
- *
58
- * @example
59
- * camelCase('hello-world') // 'helloWorld'
60
- * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
61
- */
62
- function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
63
- if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
64
- prefix,
65
- suffix
66
- } : {}));
67
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
68
- }
69
- //#endregion
70
- //#region ../../internals/utils/src/reserved.ts
71
- /**
72
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
73
- */
74
- function isValidVarName(name) {
75
- try {
76
- new Function(`var ${name}`);
77
- } catch {
78
- return false;
79
- }
80
- return true;
81
- }
82
- //#endregion
83
- //#region src/components/Server.tsx
84
- function zodExprFromOasSchema(schema) {
85
- const types = Array.isArray(schema.type) ? schema.type : [schema.type];
86
- const baseType = types.find((t) => t && t !== "null");
87
- const isNullableType = types.includes("null");
88
- let expr;
89
- switch (baseType) {
90
- case "integer":
91
- expr = "z.coerce.number()";
92
- break;
93
- case "number":
94
- expr = "z.number()";
95
- break;
96
- case "boolean":
97
- expr = "z.boolean()";
98
- break;
99
- case "array":
100
- expr = "z.array(z.unknown())";
101
- break;
102
- default: expr = "z.string()";
103
- }
104
- if (isNullableType) expr = `${expr}.nullable()`;
105
- return expr;
106
- }
107
- function getParams({ schemas, paramsCasing }) {
108
- const pathParamProperties = schemas.pathParams?.schema?.properties ?? {};
109
- const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : [];
110
- const pathParamEntries = Object.entries(pathParamProperties).reduce((acc, [originalKey, propSchema]) => {
111
- const key = paramsCasing === "camelcase" || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey;
112
- acc[key] = {
113
- value: zodExprFromOasSchema(propSchema),
114
- optional: !requiredFields.includes(originalKey)
115
- };
116
- return acc;
117
- }, {});
118
- return _kubb_react_fabric.FunctionParams.factory({ data: {
119
- mode: "object",
120
- children: {
121
- ...pathParamEntries,
122
- data: schemas.request?.name ? {
123
- value: schemas.request?.name,
124
- optional: (0, _kubb_plugin_oas_utils.isOptional)(schemas.request?.schema)
125
- } : void 0,
126
- params: schemas.queryParams?.name ? {
127
- value: schemas.queryParams?.name,
128
- optional: (0, _kubb_plugin_oas_utils.isOptional)(schemas.queryParams?.schema)
129
- } : void 0,
130
- headers: schemas.headerParams?.name ? {
131
- value: schemas.headerParams?.name,
132
- optional: (0, _kubb_plugin_oas_utils.isOptional)(schemas.headerParams?.schema)
133
- } : void 0
134
- }
135
- } });
136
- }
137
- function Server({ name, serverName, serverVersion, paramsCasing, operations }) {
138
- return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File.Source, {
139
- name,
140
- isExportable: true,
141
- isIndexable: true,
142
- children: [
143
- /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Const, {
144
- name: "server",
145
- export: true,
146
- children: `
147
- new McpServer({
148
- name: '${serverName}',
149
- version: '${serverVersion}',
150
- })
151
- `
152
- }),
153
- operations.map(({ tool, mcp, zod }) => {
154
- const paramsClient = getParams({
155
- schemas: zod.schemas,
156
- paramsCasing
157
- });
158
- const outputSchema = zod.schemas.response?.name;
159
- const config = [
160
- tool.title ? `title: ${JSON.stringify(tool.title)}` : null,
161
- `description: ${JSON.stringify(tool.description)}`,
162
- outputSchema ? `outputSchema: { data: ${outputSchema} }` : null
163
- ].filter(Boolean).join(",\n ");
164
- if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) return `
165
- server.registerTool(${JSON.stringify(tool.name)}, {
166
- ${config},
167
- inputSchema: ${paramsClient.toObjectValue()},
168
- }, async (${paramsClient.toObject()}) => {
169
- return ${mcp.name}(${paramsClient.toObject()})
170
- })
171
- `;
172
- return `
173
- server.registerTool(${JSON.stringify(tool.name)}, {
174
- ${config},
175
- }, async () => {
176
- return ${mcp.name}(${paramsClient.toObject()})
177
- })
178
- `;
179
- }).filter(Boolean),
180
- `
181
- export async function startServer() {
182
- try {
183
- const transport = new StdioServerTransport()
184
- await server.connect(transport)
185
-
186
- } catch (error) {
187
- console.error('Failed to start server:', error)
188
- process.exit(1)
189
- }
190
- }
191
- `
192
- ]
193
- });
194
- }
195
- //#endregion
196
- Object.defineProperty(exports, "Server", {
197
- enumerable: true,
198
- get: function() {
199
- return Server;
200
- }
201
- });
202
- Object.defineProperty(exports, "__name", {
203
- enumerable: true,
204
- get: function() {
205
- return __name;
206
- }
207
- });
208
- Object.defineProperty(exports, "__toESM", {
209
- enumerable: true,
210
- get: function() {
211
- return __toESM;
212
- }
213
- });
214
- Object.defineProperty(exports, "camelCase", {
215
- enumerable: true,
216
- get: function() {
217
- return camelCase;
218
- }
219
- });
220
-
221
- //# sourceMappingURL=Server-DV9zFrUP.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Server-DV9zFrUP.cjs","names":["FunctionParams","File","Const"],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/reserved.ts","../src/components/Server.tsx"],"sourcesContent":["type Options = {\n /** When `true`, dot-separated segments are split on `.` and joined with `/` after casing. */\n isFile?: boolean\n /** Text prepended before casing is applied. */\n prefix?: string\n /** Text appended before casing is applied. */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const normalized = text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n\n const words = normalized.split(/[\\s\\-_./\\\\:]+/).filter(Boolean)\n\n return words\n .map((word, i) => {\n const allUpper = word.length > 1 && word === word.toUpperCase()\n if (allUpper) return word\n if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1)\n return word.charAt(0).toUpperCase() + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Splits `text` on `.` and applies `transformPart` to each segment.\n * The last segment receives `isLast = true`, all earlier segments receive `false`.\n * Segments are joined with `/` to form a file path.\n */\nfunction applyToFileParts(text: string, transformPart: (part: string, isLast: boolean) => string): string {\n const parts = text.split('.')\n return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join('/')\n}\n\n/**\n * Converts `text` to camelCase.\n * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.\n *\n * @example\n * camelCase('hello-world') // 'helloWorld'\n * camelCase('pet.petId', { isFile: true }) // 'pet/petId'\n */\nexport function camelCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? { prefix, suffix } : {}))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.\n *\n * @example\n * pascalCase('hello-world') // 'HelloWorld'\n * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'\n */\nexport function pascalCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => (isLast ? pascalCase(part, { prefix, suffix }) : camelCase(part)))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example\n * snakeCase('helloWorld') // 'hello_world'\n * snakeCase('Hello-World') // 'hello_world'\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example\n * screamingSnakeCase('helloWorld') // 'HELLO_WORLD'\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Prefixes a word with `_` when it is a reserved JavaScript/Java identifier\n * or starts with a digit.\n */\nexport function transformReservedWord(word: string): string {\n const firstChar = word.charCodeAt(0)\n if (word && (reservedWords.has(word as 'valueOf') || (firstChar >= 48 && firstChar <= 57))) {\n return `_${word}`\n }\n return word\n}\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n */\nexport function isValidVarName(name: string): boolean {\n try {\n new Function(`var ${name}`)\n } catch {\n return false\n }\n return true\n}\n","import { camelCase, isValidVarName } from '@internals/utils'\nimport type { KubbFile } from '@kubb/fabric-core/types'\nimport type { SchemaObject } from '@kubb/oas'\nimport type { OperationSchemas } from '@kubb/plugin-oas'\nimport { isOptional } from '@kubb/plugin-oas/utils'\nimport { Const, File, FunctionParams } from '@kubb/react-fabric'\nimport type { FabricReactNode } from '@kubb/react-fabric/types'\n\ntype Props = {\n name: string\n serverName: string\n serverVersion: string\n paramsCasing?: 'camelcase'\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: KubbFile.File\n }\n zod: {\n name: string\n file: KubbFile.File\n schemas: OperationSchemas\n }\n type: {\n schemas: OperationSchemas\n }\n }>\n}\n\ntype GetParamsProps = {\n schemas: OperationSchemas\n paramsCasing?: 'camelcase'\n}\n\nfunction zodExprFromOasSchema(schema: SchemaObject): string {\n const types = Array.isArray(schema.type) ? schema.type : [schema.type]\n const baseType = types.find((t) => t && t !== 'null')\n const isNullableType = types.includes('null')\n\n let expr: string\n switch (baseType) {\n case 'integer':\n expr = 'z.coerce.number()'\n break\n case 'number':\n expr = 'z.number()'\n break\n case 'boolean':\n expr = 'z.boolean()'\n break\n case 'array':\n expr = 'z.array(z.unknown())'\n break\n default:\n expr = 'z.string()'\n }\n\n if (isNullableType) {\n expr = `${expr}.nullable()`\n }\n\n return expr\n}\n\nfunction getParams({ schemas, paramsCasing }: GetParamsProps) {\n const pathParamProperties = schemas.pathParams?.schema?.properties ?? {}\n const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : []\n\n const pathParamEntries = Object.entries(pathParamProperties).reduce<Record<string, { value: string; optional: boolean }>>(\n (acc, [originalKey, propSchema]) => {\n const key = paramsCasing === 'camelcase' || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey\n acc[key] = {\n value: zodExprFromOasSchema(propSchema as SchemaObject),\n optional: !requiredFields.includes(originalKey),\n }\n return acc\n },\n {},\n )\n\n return FunctionParams.factory({\n data: {\n mode: 'object',\n children: {\n ...pathParamEntries,\n data: schemas.request?.name\n ? {\n value: schemas.request?.name,\n optional: isOptional(schemas.request?.schema),\n }\n : undefined,\n params: schemas.queryParams?.name\n ? {\n value: schemas.queryParams?.name,\n optional: isOptional(schemas.queryParams?.schema),\n }\n : undefined,\n headers: schemas.headerParams?.name\n ? {\n value: schemas.headerParams?.name,\n optional: isOptional(schemas.headerParams?.schema),\n }\n : undefined,\n },\n },\n })\n}\n\nexport function Server({ name, serverName, serverVersion, paramsCasing, operations }: Props): FabricReactNode {\n return (\n <File.Source name={name} isExportable isIndexable>\n <Const name={'server'} export>\n {`\n new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n `}\n </Const>\n\n {operations\n .map(({ tool, mcp, zod }) => {\n const paramsClient = getParams({ schemas: zod.schemas, paramsCasing })\n const outputSchema = zod.schemas.response?.name\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: { data: ${outputSchema} }` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${paramsClient.toObjectValue()},\n}, async (${paramsClient.toObject()}) => {\n return ${mcp.name}(${paramsClient.toObject()})\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async () => {\n return ${mcp.name}(${paramsClient.toObject()})\n})\n `\n })\n .filter(Boolean)}\n\n {`\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n } catch (error) {\n console.error('Failed to start server:', error)\n process.exit(1)\n }\n}\n`}\n </File.Source>\n )\n}\n"],"mappings":"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"}
@@ -1,173 +0,0 @@
1
- import "./chunk--u3MIqq1.js";
2
- import { isOptional } from "@kubb/plugin-oas/utils";
3
- import { Const, File, FunctionParams } from "@kubb/react-fabric";
4
- import { jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
5
- //#region ../../internals/utils/src/casing.ts
6
- /**
7
- * Shared implementation for camelCase and PascalCase conversion.
8
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
9
- * and capitalizes each word according to `pascal`.
10
- *
11
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
12
- */
13
- function toCamelOrPascal(text, pascal) {
14
- return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
15
- if (word.length > 1 && word === word.toUpperCase()) return word;
16
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
17
- return word.charAt(0).toUpperCase() + word.slice(1);
18
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
19
- }
20
- /**
21
- * Splits `text` on `.` and applies `transformPart` to each segment.
22
- * The last segment receives `isLast = true`, all earlier segments receive `false`.
23
- * Segments are joined with `/` to form a file path.
24
- */
25
- function applyToFileParts(text, transformPart) {
26
- const parts = text.split(".");
27
- return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
28
- }
29
- /**
30
- * Converts `text` to camelCase.
31
- * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
32
- *
33
- * @example
34
- * camelCase('hello-world') // 'helloWorld'
35
- * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
36
- */
37
- function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
38
- if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
39
- prefix,
40
- suffix
41
- } : {}));
42
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
43
- }
44
- //#endregion
45
- //#region ../../internals/utils/src/reserved.ts
46
- /**
47
- * Returns `true` when `name` is a syntactically valid JavaScript variable name.
48
- */
49
- function isValidVarName(name) {
50
- try {
51
- new Function(`var ${name}`);
52
- } catch {
53
- return false;
54
- }
55
- return true;
56
- }
57
- //#endregion
58
- //#region src/components/Server.tsx
59
- function zodExprFromOasSchema(schema) {
60
- const types = Array.isArray(schema.type) ? schema.type : [schema.type];
61
- const baseType = types.find((t) => t && t !== "null");
62
- const isNullableType = types.includes("null");
63
- let expr;
64
- switch (baseType) {
65
- case "integer":
66
- expr = "z.coerce.number()";
67
- break;
68
- case "number":
69
- expr = "z.number()";
70
- break;
71
- case "boolean":
72
- expr = "z.boolean()";
73
- break;
74
- case "array":
75
- expr = "z.array(z.unknown())";
76
- break;
77
- default: expr = "z.string()";
78
- }
79
- if (isNullableType) expr = `${expr}.nullable()`;
80
- return expr;
81
- }
82
- function getParams({ schemas, paramsCasing }) {
83
- const pathParamProperties = schemas.pathParams?.schema?.properties ?? {};
84
- const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : [];
85
- const pathParamEntries = Object.entries(pathParamProperties).reduce((acc, [originalKey, propSchema]) => {
86
- const key = paramsCasing === "camelcase" || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey;
87
- acc[key] = {
88
- value: zodExprFromOasSchema(propSchema),
89
- optional: !requiredFields.includes(originalKey)
90
- };
91
- return acc;
92
- }, {});
93
- return FunctionParams.factory({ data: {
94
- mode: "object",
95
- children: {
96
- ...pathParamEntries,
97
- data: schemas.request?.name ? {
98
- value: schemas.request?.name,
99
- optional: isOptional(schemas.request?.schema)
100
- } : void 0,
101
- params: schemas.queryParams?.name ? {
102
- value: schemas.queryParams?.name,
103
- optional: isOptional(schemas.queryParams?.schema)
104
- } : void 0,
105
- headers: schemas.headerParams?.name ? {
106
- value: schemas.headerParams?.name,
107
- optional: isOptional(schemas.headerParams?.schema)
108
- } : void 0
109
- }
110
- } });
111
- }
112
- function Server({ name, serverName, serverVersion, paramsCasing, operations }) {
113
- return /* @__PURE__ */ jsxs(File.Source, {
114
- name,
115
- isExportable: true,
116
- isIndexable: true,
117
- children: [
118
- /* @__PURE__ */ jsx(Const, {
119
- name: "server",
120
- export: true,
121
- children: `
122
- new McpServer({
123
- name: '${serverName}',
124
- version: '${serverVersion}',
125
- })
126
- `
127
- }),
128
- operations.map(({ tool, mcp, zod }) => {
129
- const paramsClient = getParams({
130
- schemas: zod.schemas,
131
- paramsCasing
132
- });
133
- const outputSchema = zod.schemas.response?.name;
134
- const config = [
135
- tool.title ? `title: ${JSON.stringify(tool.title)}` : null,
136
- `description: ${JSON.stringify(tool.description)}`,
137
- outputSchema ? `outputSchema: { data: ${outputSchema} }` : null
138
- ].filter(Boolean).join(",\n ");
139
- if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) return `
140
- server.registerTool(${JSON.stringify(tool.name)}, {
141
- ${config},
142
- inputSchema: ${paramsClient.toObjectValue()},
143
- }, async (${paramsClient.toObject()}) => {
144
- return ${mcp.name}(${paramsClient.toObject()})
145
- })
146
- `;
147
- return `
148
- server.registerTool(${JSON.stringify(tool.name)}, {
149
- ${config},
150
- }, async () => {
151
- return ${mcp.name}(${paramsClient.toObject()})
152
- })
153
- `;
154
- }).filter(Boolean),
155
- `
156
- export async function startServer() {
157
- try {
158
- const transport = new StdioServerTransport()
159
- await server.connect(transport)
160
-
161
- } catch (error) {
162
- console.error('Failed to start server:', error)
163
- process.exit(1)
164
- }
165
- }
166
- `
167
- ]
168
- });
169
- }
170
- //#endregion
171
- export { camelCase as n, Server as t };
172
-
173
- //# sourceMappingURL=Server-KWLMg0Lm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Server-KWLMg0Lm.js","names":[],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/reserved.ts","../src/components/Server.tsx"],"sourcesContent":["type Options = {\n /** When `true`, dot-separated segments are split on `.` and joined with `/` after casing. */\n isFile?: boolean\n /** Text prepended before casing is applied. */\n prefix?: string\n /** Text appended before casing is applied. */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const normalized = text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n\n const words = normalized.split(/[\\s\\-_./\\\\:]+/).filter(Boolean)\n\n return words\n .map((word, i) => {\n const allUpper = word.length > 1 && word === word.toUpperCase()\n if (allUpper) return word\n if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1)\n return word.charAt(0).toUpperCase() + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Splits `text` on `.` and applies `transformPart` to each segment.\n * The last segment receives `isLast = true`, all earlier segments receive `false`.\n * Segments are joined with `/` to form a file path.\n */\nfunction applyToFileParts(text: string, transformPart: (part: string, isLast: boolean) => string): string {\n const parts = text.split('.')\n return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join('/')\n}\n\n/**\n * Converts `text` to camelCase.\n * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.\n *\n * @example\n * camelCase('hello-world') // 'helloWorld'\n * camelCase('pet.petId', { isFile: true }) // 'pet/petId'\n */\nexport function camelCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? { prefix, suffix } : {}))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.\n *\n * @example\n * pascalCase('hello-world') // 'HelloWorld'\n * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'\n */\nexport function pascalCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => (isLast ? pascalCase(part, { prefix, suffix }) : camelCase(part)))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example\n * snakeCase('helloWorld') // 'hello_world'\n * snakeCase('Hello-World') // 'hello_world'\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example\n * screamingSnakeCase('helloWorld') // 'HELLO_WORLD'\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Prefixes a word with `_` when it is a reserved JavaScript/Java identifier\n * or starts with a digit.\n */\nexport function transformReservedWord(word: string): string {\n const firstChar = word.charCodeAt(0)\n if (word && (reservedWords.has(word as 'valueOf') || (firstChar >= 48 && firstChar <= 57))) {\n return `_${word}`\n }\n return word\n}\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n */\nexport function isValidVarName(name: string): boolean {\n try {\n new Function(`var ${name}`)\n } catch {\n return false\n }\n return true\n}\n","import { camelCase, isValidVarName } from '@internals/utils'\nimport type { KubbFile } from '@kubb/fabric-core/types'\nimport type { SchemaObject } from '@kubb/oas'\nimport type { OperationSchemas } from '@kubb/plugin-oas'\nimport { isOptional } from '@kubb/plugin-oas/utils'\nimport { Const, File, FunctionParams } from '@kubb/react-fabric'\nimport type { FabricReactNode } from '@kubb/react-fabric/types'\n\ntype Props = {\n name: string\n serverName: string\n serverVersion: string\n paramsCasing?: 'camelcase'\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: KubbFile.File\n }\n zod: {\n name: string\n file: KubbFile.File\n schemas: OperationSchemas\n }\n type: {\n schemas: OperationSchemas\n }\n }>\n}\n\ntype GetParamsProps = {\n schemas: OperationSchemas\n paramsCasing?: 'camelcase'\n}\n\nfunction zodExprFromOasSchema(schema: SchemaObject): string {\n const types = Array.isArray(schema.type) ? schema.type : [schema.type]\n const baseType = types.find((t) => t && t !== 'null')\n const isNullableType = types.includes('null')\n\n let expr: string\n switch (baseType) {\n case 'integer':\n expr = 'z.coerce.number()'\n break\n case 'number':\n expr = 'z.number()'\n break\n case 'boolean':\n expr = 'z.boolean()'\n break\n case 'array':\n expr = 'z.array(z.unknown())'\n break\n default:\n expr = 'z.string()'\n }\n\n if (isNullableType) {\n expr = `${expr}.nullable()`\n }\n\n return expr\n}\n\nfunction getParams({ schemas, paramsCasing }: GetParamsProps) {\n const pathParamProperties = schemas.pathParams?.schema?.properties ?? {}\n const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : []\n\n const pathParamEntries = Object.entries(pathParamProperties).reduce<Record<string, { value: string; optional: boolean }>>(\n (acc, [originalKey, propSchema]) => {\n const key = paramsCasing === 'camelcase' || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey\n acc[key] = {\n value: zodExprFromOasSchema(propSchema as SchemaObject),\n optional: !requiredFields.includes(originalKey),\n }\n return acc\n },\n {},\n )\n\n return FunctionParams.factory({\n data: {\n mode: 'object',\n children: {\n ...pathParamEntries,\n data: schemas.request?.name\n ? {\n value: schemas.request?.name,\n optional: isOptional(schemas.request?.schema),\n }\n : undefined,\n params: schemas.queryParams?.name\n ? {\n value: schemas.queryParams?.name,\n optional: isOptional(schemas.queryParams?.schema),\n }\n : undefined,\n headers: schemas.headerParams?.name\n ? {\n value: schemas.headerParams?.name,\n optional: isOptional(schemas.headerParams?.schema),\n }\n : undefined,\n },\n },\n })\n}\n\nexport function Server({ name, serverName, serverVersion, paramsCasing, operations }: Props): FabricReactNode {\n return (\n <File.Source name={name} isExportable isIndexable>\n <Const name={'server'} export>\n {`\n new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n `}\n </Const>\n\n {operations\n .map(({ tool, mcp, zod }) => {\n const paramsClient = getParams({ schemas: zod.schemas, paramsCasing })\n const outputSchema = zod.schemas.response?.name\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: { data: ${outputSchema} }` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${paramsClient.toObjectValue()},\n}, async (${paramsClient.toObject()}) => {\n return ${mcp.name}(${paramsClient.toObject()})\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async () => {\n return ${mcp.name}(${paramsClient.toObject()})\n})\n `\n })\n .filter(Boolean)}\n\n {`\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n } catch (error) {\n console.error('Failed to start server:', error)\n process.exit(1)\n }\n}\n`}\n </File.Source>\n )\n}\n"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_Server = require("./Server-DV9zFrUP.cjs");
3
- exports.Server = require_Server.Server;