@kubb/plugin-mcp 5.0.0-alpha.9 → 5.0.0-beta.100
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/LICENSE +17 -10
- package/README.md +37 -23
- package/dist/index.cjs +860 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +254 -6
- package/dist/index.js +830 -105
- package/dist/index.js.map +1 -1
- package/package.json +38 -74
- package/dist/Server-DV9zFrUP.cjs +0 -221
- package/dist/Server-DV9zFrUP.cjs.map +0 -1
- package/dist/Server-KWLMg0Lm.js +0 -173
- package/dist/Server-KWLMg0Lm.js.map +0 -1
- package/dist/components.cjs +0 -3
- package/dist/components.d.ts +0 -41
- package/dist/components.js +0 -2
- package/dist/generators-CWAFnA94.cjs +0 -285
- package/dist/generators-CWAFnA94.cjs.map +0 -1
- package/dist/generators-TtEOkDB1.js +0 -274
- package/dist/generators-TtEOkDB1.js.map +0 -1
- package/dist/generators.cjs +0 -4
- package/dist/generators.d.ts +0 -508
- package/dist/generators.js +0 -2
- package/dist/types-DXZDZ3vf.d.ts +0 -64
- package/src/components/Server.tsx +0 -174
- package/src/components/index.ts +0 -1
- package/src/generators/index.ts +0 -2
- package/src/generators/mcpGenerator.tsx +0 -110
- package/src/generators/serverGenerator.tsx +0 -112
- package/src/index.ts +0 -2
- package/src/plugin.ts +0 -170
- package/src/types.ts +0 -62
- /package/dist/{chunk--u3MIqq1.js → rolldown-runtime-C0LytTxp.js} +0 -0
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { camelCase, isValidVarName } from '@internals/utils'
|
|
2
|
-
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
3
|
-
import type { SchemaObject } from '@kubb/oas'
|
|
4
|
-
import type { OperationSchemas } from '@kubb/plugin-oas'
|
|
5
|
-
import { isOptional } from '@kubb/plugin-oas/utils'
|
|
6
|
-
import { Const, File, FunctionParams } from '@kubb/react-fabric'
|
|
7
|
-
import type { FabricReactNode } from '@kubb/react-fabric/types'
|
|
8
|
-
|
|
9
|
-
type Props = {
|
|
10
|
-
name: string
|
|
11
|
-
serverName: string
|
|
12
|
-
serverVersion: string
|
|
13
|
-
paramsCasing?: 'camelcase'
|
|
14
|
-
operations: Array<{
|
|
15
|
-
tool: {
|
|
16
|
-
name: string
|
|
17
|
-
title?: string
|
|
18
|
-
description: string
|
|
19
|
-
}
|
|
20
|
-
mcp: {
|
|
21
|
-
name: string
|
|
22
|
-
file: KubbFile.File
|
|
23
|
-
}
|
|
24
|
-
zod: {
|
|
25
|
-
name: string
|
|
26
|
-
file: KubbFile.File
|
|
27
|
-
schemas: OperationSchemas
|
|
28
|
-
}
|
|
29
|
-
type: {
|
|
30
|
-
schemas: OperationSchemas
|
|
31
|
-
}
|
|
32
|
-
}>
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
type GetParamsProps = {
|
|
36
|
-
schemas: OperationSchemas
|
|
37
|
-
paramsCasing?: 'camelcase'
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function zodExprFromOasSchema(schema: SchemaObject): string {
|
|
41
|
-
const types = Array.isArray(schema.type) ? schema.type : [schema.type]
|
|
42
|
-
const baseType = types.find((t) => t && t !== 'null')
|
|
43
|
-
const isNullableType = types.includes('null')
|
|
44
|
-
|
|
45
|
-
let expr: string
|
|
46
|
-
switch (baseType) {
|
|
47
|
-
case 'integer':
|
|
48
|
-
expr = 'z.coerce.number()'
|
|
49
|
-
break
|
|
50
|
-
case 'number':
|
|
51
|
-
expr = 'z.number()'
|
|
52
|
-
break
|
|
53
|
-
case 'boolean':
|
|
54
|
-
expr = 'z.boolean()'
|
|
55
|
-
break
|
|
56
|
-
case 'array':
|
|
57
|
-
expr = 'z.array(z.unknown())'
|
|
58
|
-
break
|
|
59
|
-
default:
|
|
60
|
-
expr = 'z.string()'
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (isNullableType) {
|
|
64
|
-
expr = `${expr}.nullable()`
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return expr
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getParams({ schemas, paramsCasing }: GetParamsProps) {
|
|
71
|
-
const pathParamProperties = schemas.pathParams?.schema?.properties ?? {}
|
|
72
|
-
const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : []
|
|
73
|
-
|
|
74
|
-
const pathParamEntries = Object.entries(pathParamProperties).reduce<Record<string, { value: string; optional: boolean }>>(
|
|
75
|
-
(acc, [originalKey, propSchema]) => {
|
|
76
|
-
const key = paramsCasing === 'camelcase' || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey
|
|
77
|
-
acc[key] = {
|
|
78
|
-
value: zodExprFromOasSchema(propSchema as SchemaObject),
|
|
79
|
-
optional: !requiredFields.includes(originalKey),
|
|
80
|
-
}
|
|
81
|
-
return acc
|
|
82
|
-
},
|
|
83
|
-
{},
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
return FunctionParams.factory({
|
|
87
|
-
data: {
|
|
88
|
-
mode: 'object',
|
|
89
|
-
children: {
|
|
90
|
-
...pathParamEntries,
|
|
91
|
-
data: schemas.request?.name
|
|
92
|
-
? {
|
|
93
|
-
value: schemas.request?.name,
|
|
94
|
-
optional: isOptional(schemas.request?.schema),
|
|
95
|
-
}
|
|
96
|
-
: undefined,
|
|
97
|
-
params: schemas.queryParams?.name
|
|
98
|
-
? {
|
|
99
|
-
value: schemas.queryParams?.name,
|
|
100
|
-
optional: isOptional(schemas.queryParams?.schema),
|
|
101
|
-
}
|
|
102
|
-
: undefined,
|
|
103
|
-
headers: schemas.headerParams?.name
|
|
104
|
-
? {
|
|
105
|
-
value: schemas.headerParams?.name,
|
|
106
|
-
optional: isOptional(schemas.headerParams?.schema),
|
|
107
|
-
}
|
|
108
|
-
: undefined,
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function Server({ name, serverName, serverVersion, paramsCasing, operations }: Props): FabricReactNode {
|
|
115
|
-
return (
|
|
116
|
-
<File.Source name={name} isExportable isIndexable>
|
|
117
|
-
<Const name={'server'} export>
|
|
118
|
-
{`
|
|
119
|
-
new McpServer({
|
|
120
|
-
name: '${serverName}',
|
|
121
|
-
version: '${serverVersion}',
|
|
122
|
-
})
|
|
123
|
-
`}
|
|
124
|
-
</Const>
|
|
125
|
-
|
|
126
|
-
{operations
|
|
127
|
-
.map(({ tool, mcp, zod }) => {
|
|
128
|
-
const paramsClient = getParams({ schemas: zod.schemas, paramsCasing })
|
|
129
|
-
const outputSchema = zod.schemas.response?.name
|
|
130
|
-
|
|
131
|
-
const config = [
|
|
132
|
-
tool.title ? `title: ${JSON.stringify(tool.title)}` : null,
|
|
133
|
-
`description: ${JSON.stringify(tool.description)}`,
|
|
134
|
-
outputSchema ? `outputSchema: { data: ${outputSchema} }` : null,
|
|
135
|
-
]
|
|
136
|
-
.filter(Boolean)
|
|
137
|
-
.join(',\n ')
|
|
138
|
-
|
|
139
|
-
if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) {
|
|
140
|
-
return `
|
|
141
|
-
server.registerTool(${JSON.stringify(tool.name)}, {
|
|
142
|
-
${config},
|
|
143
|
-
inputSchema: ${paramsClient.toObjectValue()},
|
|
144
|
-
}, async (${paramsClient.toObject()}) => {
|
|
145
|
-
return ${mcp.name}(${paramsClient.toObject()})
|
|
146
|
-
})
|
|
147
|
-
`
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return `
|
|
151
|
-
server.registerTool(${JSON.stringify(tool.name)}, {
|
|
152
|
-
${config},
|
|
153
|
-
}, async () => {
|
|
154
|
-
return ${mcp.name}(${paramsClient.toObject()})
|
|
155
|
-
})
|
|
156
|
-
`
|
|
157
|
-
})
|
|
158
|
-
.filter(Boolean)}
|
|
159
|
-
|
|
160
|
-
{`
|
|
161
|
-
export async function startServer() {
|
|
162
|
-
try {
|
|
163
|
-
const transport = new StdioServerTransport()
|
|
164
|
-
await server.connect(transport)
|
|
165
|
-
|
|
166
|
-
} catch (error) {
|
|
167
|
-
console.error('Failed to start server:', error)
|
|
168
|
-
process.exit(1)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
`}
|
|
172
|
-
</File.Source>
|
|
173
|
-
)
|
|
174
|
-
}
|
package/src/components/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Server } from './Server.tsx'
|
package/src/generators/index.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { Client } from '@kubb/plugin-client/components'
|
|
3
|
-
import { createReactGenerator } from '@kubb/plugin-oas/generators'
|
|
4
|
-
import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
5
|
-
import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
|
|
6
|
-
import { pluginTsName } from '@kubb/plugin-ts'
|
|
7
|
-
import { File } from '@kubb/react-fabric'
|
|
8
|
-
import type { PluginMcp } from '../types'
|
|
9
|
-
|
|
10
|
-
export const mcpGenerator = createReactGenerator<PluginMcp>({
|
|
11
|
-
name: 'mcp',
|
|
12
|
-
Operation({ config, operation, generator, plugin }) {
|
|
13
|
-
const { options } = plugin
|
|
14
|
-
const oas = useOas()
|
|
15
|
-
|
|
16
|
-
const { getSchemas, getName, getFile } = useOperationManager(generator)
|
|
17
|
-
|
|
18
|
-
const mcp = {
|
|
19
|
-
name: getName(operation, { type: 'function', suffix: 'handler' }),
|
|
20
|
-
file: getFile(operation),
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const type = {
|
|
24
|
-
file: getFile(operation, { pluginName: pluginTsName }),
|
|
25
|
-
schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<File
|
|
30
|
-
baseName={mcp.file.baseName}
|
|
31
|
-
path={mcp.file.path}
|
|
32
|
-
meta={mcp.file.meta}
|
|
33
|
-
banner={getBanner({ oas, output: options.output })}
|
|
34
|
-
footer={getFooter({ oas, output: options.output })}
|
|
35
|
-
>
|
|
36
|
-
{options.client.importPath ? (
|
|
37
|
-
<>
|
|
38
|
-
<File.Import name={'fetch'} path={options.client.importPath} />
|
|
39
|
-
<File.Import name={['Client', 'RequestConfig', 'ResponseErrorConfig']} path={options.client.importPath} isTypeOnly />
|
|
40
|
-
{options.client.dataReturnType === 'full' && <File.Import name={['ResponseConfig']} path={options.client.importPath} isTypeOnly />}
|
|
41
|
-
</>
|
|
42
|
-
) : (
|
|
43
|
-
<>
|
|
44
|
-
<File.Import name={['fetch']} root={mcp.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} />
|
|
45
|
-
<File.Import
|
|
46
|
-
name={['Client', 'RequestConfig', 'ResponseErrorConfig']}
|
|
47
|
-
root={mcp.file.path}
|
|
48
|
-
path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')}
|
|
49
|
-
isTypeOnly
|
|
50
|
-
/>
|
|
51
|
-
{options.client.dataReturnType === 'full' && (
|
|
52
|
-
<File.Import name={['ResponseConfig']} root={mcp.file.path} path={path.resolve(config.root, config.output.path, '.kubb/fetch.ts')} isTypeOnly />
|
|
53
|
-
)}
|
|
54
|
-
</>
|
|
55
|
-
)}
|
|
56
|
-
<File.Import name={['buildFormData']} root={mcp.file.path} path={path.resolve(config.root, config.output.path, '.kubb/config.ts')} />
|
|
57
|
-
<File.Import name={['CallToolResult']} path={'@modelcontextprotocol/sdk/types'} isTypeOnly />
|
|
58
|
-
<File.Import
|
|
59
|
-
name={[
|
|
60
|
-
type.schemas.request?.name,
|
|
61
|
-
type.schemas.response.name,
|
|
62
|
-
type.schemas.pathParams?.name,
|
|
63
|
-
type.schemas.queryParams?.name,
|
|
64
|
-
type.schemas.headerParams?.name,
|
|
65
|
-
...(type.schemas.statusCodes?.map((item) => item.name) || []),
|
|
66
|
-
].filter(Boolean)}
|
|
67
|
-
root={mcp.file.path}
|
|
68
|
-
path={type.file.path}
|
|
69
|
-
isTypeOnly
|
|
70
|
-
/>
|
|
71
|
-
|
|
72
|
-
<Client
|
|
73
|
-
name={mcp.name}
|
|
74
|
-
isConfigurable={false}
|
|
75
|
-
returnType={'Promise<CallToolResult>'}
|
|
76
|
-
baseURL={options.client.baseURL}
|
|
77
|
-
operation={operation}
|
|
78
|
-
typeSchemas={type.schemas}
|
|
79
|
-
zodSchemas={undefined}
|
|
80
|
-
dataReturnType={options.client.dataReturnType || 'data'}
|
|
81
|
-
paramsType={'object'}
|
|
82
|
-
paramsCasing={options.client?.paramsCasing || options.paramsCasing}
|
|
83
|
-
pathParamsType={'object'}
|
|
84
|
-
parser={'client'}
|
|
85
|
-
>
|
|
86
|
-
{options.client.dataReturnType === 'data' &&
|
|
87
|
-
`return {
|
|
88
|
-
content: [
|
|
89
|
-
{
|
|
90
|
-
type: 'text',
|
|
91
|
-
text: JSON.stringify(res.data)
|
|
92
|
-
}
|
|
93
|
-
],
|
|
94
|
-
structuredContent: { data: res.data }
|
|
95
|
-
}`}
|
|
96
|
-
{options.client.dataReturnType === 'full' &&
|
|
97
|
-
`return {
|
|
98
|
-
content: [
|
|
99
|
-
{
|
|
100
|
-
type: 'text',
|
|
101
|
-
text: JSON.stringify(res)
|
|
102
|
-
}
|
|
103
|
-
],
|
|
104
|
-
structuredContent: { data: res.data }
|
|
105
|
-
}`}
|
|
106
|
-
</Client>
|
|
107
|
-
</File>
|
|
108
|
-
)
|
|
109
|
-
},
|
|
110
|
-
})
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { usePluginDriver } from '@kubb/core/hooks'
|
|
2
|
-
import { createReactGenerator } from '@kubb/plugin-oas/generators'
|
|
3
|
-
import { useOas, useOperationManager } from '@kubb/plugin-oas/hooks'
|
|
4
|
-
import { getBanner, getFooter } from '@kubb/plugin-oas/utils'
|
|
5
|
-
import { pluginTsName } from '@kubb/plugin-ts'
|
|
6
|
-
import { pluginZodName } from '@kubb/plugin-zod'
|
|
7
|
-
import { File } from '@kubb/react-fabric'
|
|
8
|
-
import { Server } from '../components/Server'
|
|
9
|
-
import type { PluginMcp } from '../types'
|
|
10
|
-
|
|
11
|
-
export const serverGenerator = createReactGenerator<PluginMcp>({
|
|
12
|
-
name: 'operations',
|
|
13
|
-
Operations({ operations, generator, plugin }) {
|
|
14
|
-
const driver = usePluginDriver()
|
|
15
|
-
const { options } = plugin
|
|
16
|
-
|
|
17
|
-
const oas = useOas()
|
|
18
|
-
const { getFile, getName, getSchemas } = useOperationManager(generator)
|
|
19
|
-
|
|
20
|
-
const name = 'server'
|
|
21
|
-
const file = driver.getFile({ name, extname: '.ts', pluginName: plugin.name })
|
|
22
|
-
|
|
23
|
-
const jsonFile = driver.getFile({ name: '.mcp', extname: '.json', pluginName: plugin.name })
|
|
24
|
-
|
|
25
|
-
const operationsMapped = operations.map((operation) => {
|
|
26
|
-
return {
|
|
27
|
-
tool: {
|
|
28
|
-
name: operation.getOperationId() || operation.getSummary() || `${operation.method.toUpperCase()} ${operation.path}`,
|
|
29
|
-
title: operation.getSummary() || undefined,
|
|
30
|
-
description: operation.getDescription() || `Make a ${operation.method.toUpperCase()} request to ${operation.path}`,
|
|
31
|
-
},
|
|
32
|
-
mcp: {
|
|
33
|
-
name: getName(operation, {
|
|
34
|
-
type: 'function',
|
|
35
|
-
suffix: 'handler',
|
|
36
|
-
}),
|
|
37
|
-
file: getFile(operation),
|
|
38
|
-
},
|
|
39
|
-
zod: {
|
|
40
|
-
name: getName(operation, {
|
|
41
|
-
type: 'function',
|
|
42
|
-
pluginName: pluginZodName,
|
|
43
|
-
}),
|
|
44
|
-
schemas: getSchemas(operation, { pluginName: pluginZodName, type: 'function' }),
|
|
45
|
-
file: getFile(operation, { pluginName: pluginZodName }),
|
|
46
|
-
},
|
|
47
|
-
type: {
|
|
48
|
-
schemas: getSchemas(operation, { pluginName: pluginTsName, type: 'type' }),
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const imports = operationsMapped.flatMap(({ mcp, zod }) => {
|
|
54
|
-
return [
|
|
55
|
-
<File.Import key={mcp.name} name={[mcp.name]} root={file.path} path={mcp.file.path} />,
|
|
56
|
-
<File.Import
|
|
57
|
-
key={zod.name}
|
|
58
|
-
name={[
|
|
59
|
-
zod.schemas.request?.name,
|
|
60
|
-
zod.schemas.pathParams?.name,
|
|
61
|
-
zod.schemas.queryParams?.name,
|
|
62
|
-
zod.schemas.headerParams?.name,
|
|
63
|
-
zod.schemas.response?.name,
|
|
64
|
-
].filter(Boolean)}
|
|
65
|
-
root={file.path}
|
|
66
|
-
path={zod.file.path}
|
|
67
|
-
/>,
|
|
68
|
-
]
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<>
|
|
73
|
-
<File
|
|
74
|
-
baseName={file.baseName}
|
|
75
|
-
path={file.path}
|
|
76
|
-
meta={file.meta}
|
|
77
|
-
banner={getBanner({ oas, output: options.output, config: driver.config })}
|
|
78
|
-
footer={getFooter({ oas, output: options.output })}
|
|
79
|
-
>
|
|
80
|
-
<File.Import name={['McpServer']} path={'@modelcontextprotocol/sdk/server/mcp'} />
|
|
81
|
-
<File.Import name={['z']} path={'zod'} />
|
|
82
|
-
<File.Import name={['StdioServerTransport']} path={'@modelcontextprotocol/sdk/server/stdio'} />
|
|
83
|
-
|
|
84
|
-
{imports}
|
|
85
|
-
<Server
|
|
86
|
-
name={name}
|
|
87
|
-
serverName={oas.api.info?.title}
|
|
88
|
-
serverVersion={oas.getVersion()}
|
|
89
|
-
paramsCasing={options.paramsCasing}
|
|
90
|
-
operations={operationsMapped}
|
|
91
|
-
/>
|
|
92
|
-
</File>
|
|
93
|
-
|
|
94
|
-
<File baseName={jsonFile.baseName} path={jsonFile.path} meta={jsonFile.meta}>
|
|
95
|
-
<File.Source name={name}>
|
|
96
|
-
{`
|
|
97
|
-
{
|
|
98
|
-
"mcpServers": {
|
|
99
|
-
"${oas.api.info?.title || 'server'}": {
|
|
100
|
-
"type": "stdio",
|
|
101
|
-
"command": "npx",
|
|
102
|
-
"args": ["tsx", "${file.path}"]
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
`}
|
|
107
|
-
</File.Source>
|
|
108
|
-
</File>
|
|
109
|
-
</>
|
|
110
|
-
)
|
|
111
|
-
},
|
|
112
|
-
})
|
package/src/index.ts
DELETED
package/src/plugin.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { camelCase } from '@internals/utils'
|
|
3
|
-
import { createPlugin, type Group, getBarrelFiles, getMode } from '@kubb/core'
|
|
4
|
-
import { pluginClientName } from '@kubb/plugin-client'
|
|
5
|
-
import { source as axiosClientSource } from '@kubb/plugin-client/templates/clients/axios.source'
|
|
6
|
-
import { source as fetchClientSource } from '@kubb/plugin-client/templates/clients/fetch.source'
|
|
7
|
-
import { source as configSource } from '@kubb/plugin-client/templates/config.source'
|
|
8
|
-
import { OperationGenerator, pluginOasName } from '@kubb/plugin-oas'
|
|
9
|
-
import { pluginTsName } from '@kubb/plugin-ts'
|
|
10
|
-
import { pluginZodName } from '@kubb/plugin-zod'
|
|
11
|
-
import { mcpGenerator, serverGenerator } from './generators'
|
|
12
|
-
import type { PluginMcp } from './types.ts'
|
|
13
|
-
|
|
14
|
-
export const pluginMcpName = 'plugin-mcp' satisfies PluginMcp['name']
|
|
15
|
-
|
|
16
|
-
export const pluginMcp = createPlugin<PluginMcp>((options) => {
|
|
17
|
-
const {
|
|
18
|
-
output = { path: 'mcp', barrelType: 'named' },
|
|
19
|
-
group,
|
|
20
|
-
exclude = [],
|
|
21
|
-
include,
|
|
22
|
-
override = [],
|
|
23
|
-
transformers = {},
|
|
24
|
-
generators = [mcpGenerator, serverGenerator].filter(Boolean),
|
|
25
|
-
contentType,
|
|
26
|
-
paramsCasing,
|
|
27
|
-
client,
|
|
28
|
-
} = options
|
|
29
|
-
|
|
30
|
-
const clientName = client?.client ?? 'axios'
|
|
31
|
-
const clientImportPath = client?.importPath ?? (!client?.bundle ? `@kubb/plugin-client/clients/${clientName}` : undefined)
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
name: pluginMcpName,
|
|
35
|
-
options: {
|
|
36
|
-
output,
|
|
37
|
-
group,
|
|
38
|
-
paramsCasing,
|
|
39
|
-
client: {
|
|
40
|
-
client: clientName,
|
|
41
|
-
clientType: client?.clientType ?? 'function',
|
|
42
|
-
importPath: clientImportPath,
|
|
43
|
-
dataReturnType: client?.dataReturnType ?? 'data',
|
|
44
|
-
bundle: client?.bundle,
|
|
45
|
-
baseURL: client?.baseURL,
|
|
46
|
-
paramsCasing: client?.paramsCasing,
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
pre: [pluginOasName, pluginTsName, pluginZodName].filter(Boolean),
|
|
50
|
-
resolvePath(baseName, pathMode, options) {
|
|
51
|
-
const root = path.resolve(this.config.root, this.config.output.path)
|
|
52
|
-
const mode = pathMode ?? getMode(path.resolve(root, output.path))
|
|
53
|
-
|
|
54
|
-
if (mode === 'single') {
|
|
55
|
-
/**
|
|
56
|
-
* when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
|
|
57
|
-
* Other plugins then need to call addOrAppend instead of just add from the fileManager class
|
|
58
|
-
*/
|
|
59
|
-
return path.resolve(root, output.path)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (group && (options?.group?.path || options?.group?.tag)) {
|
|
63
|
-
const groupName: Group['name'] = group?.name
|
|
64
|
-
? group.name
|
|
65
|
-
: (ctx) => {
|
|
66
|
-
if (group?.type === 'path') {
|
|
67
|
-
return `${ctx.group.split('/')[1]}`
|
|
68
|
-
}
|
|
69
|
-
return `${camelCase(ctx.group)}Requests`
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return path.resolve(
|
|
73
|
-
root,
|
|
74
|
-
output.path,
|
|
75
|
-
groupName({
|
|
76
|
-
group: group.type === 'path' ? options.group.path! : options.group.tag!,
|
|
77
|
-
}),
|
|
78
|
-
baseName,
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return path.resolve(root, output.path, baseName)
|
|
83
|
-
},
|
|
84
|
-
resolveName(name, type) {
|
|
85
|
-
const resolvedName = camelCase(name, {
|
|
86
|
-
isFile: type === 'file',
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
if (type) {
|
|
90
|
-
return transformers?.name?.(resolvedName, type) || resolvedName
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return resolvedName
|
|
94
|
-
},
|
|
95
|
-
async install() {
|
|
96
|
-
const root = path.resolve(this.config.root, this.config.output.path)
|
|
97
|
-
const mode = getMode(path.resolve(root, output.path))
|
|
98
|
-
const oas = await this.getOas()
|
|
99
|
-
const baseURL = await this.getBaseURL()
|
|
100
|
-
|
|
101
|
-
if (baseURL) {
|
|
102
|
-
this.plugin.options.client.baseURL = baseURL
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const hasClientPlugin = !!this.driver.getPluginByName(pluginClientName)
|
|
106
|
-
|
|
107
|
-
if (this.plugin.options.client.bundle && !hasClientPlugin && !this.plugin.options.client.importPath) {
|
|
108
|
-
// pre add bundled fetch
|
|
109
|
-
await this.addFile({
|
|
110
|
-
baseName: 'fetch.ts',
|
|
111
|
-
path: path.resolve(root, '.kubb/fetch.ts'),
|
|
112
|
-
sources: [
|
|
113
|
-
{
|
|
114
|
-
name: 'fetch',
|
|
115
|
-
value: this.plugin.options.client.client === 'fetch' ? fetchClientSource : axiosClientSource,
|
|
116
|
-
isExportable: true,
|
|
117
|
-
isIndexable: true,
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
imports: [],
|
|
121
|
-
exports: [],
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!hasClientPlugin) {
|
|
126
|
-
await this.addFile({
|
|
127
|
-
baseName: 'config.ts',
|
|
128
|
-
path: path.resolve(root, '.kubb/config.ts'),
|
|
129
|
-
sources: [
|
|
130
|
-
{
|
|
131
|
-
name: 'config',
|
|
132
|
-
value: configSource,
|
|
133
|
-
isExportable: false,
|
|
134
|
-
isIndexable: false,
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
imports: [],
|
|
138
|
-
exports: [],
|
|
139
|
-
})
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const operationGenerator = new OperationGenerator(this.plugin.options, {
|
|
143
|
-
fabric: this.fabric,
|
|
144
|
-
oas,
|
|
145
|
-
driver: this.driver,
|
|
146
|
-
events: this.events,
|
|
147
|
-
plugin: this.plugin,
|
|
148
|
-
contentType,
|
|
149
|
-
exclude,
|
|
150
|
-
include,
|
|
151
|
-
override,
|
|
152
|
-
mode,
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
const files = await operationGenerator.build(...generators)
|
|
156
|
-
await this.upsertFile(...files)
|
|
157
|
-
|
|
158
|
-
const barrelFiles = await getBarrelFiles(this.fabric.files, {
|
|
159
|
-
type: output.barrelType ?? 'named',
|
|
160
|
-
root,
|
|
161
|
-
output,
|
|
162
|
-
meta: {
|
|
163
|
-
pluginName: this.plugin.name,
|
|
164
|
-
},
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
await this.upsertFile(...barrelFiles)
|
|
168
|
-
},
|
|
169
|
-
}
|
|
170
|
-
})
|
package/src/types.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { Group, Output, PluginFactoryOptions, ResolveNameParams } from '@kubb/core'
|
|
2
|
-
|
|
3
|
-
import type { contentType, Oas } from '@kubb/oas'
|
|
4
|
-
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'
|
|
7
|
-
|
|
8
|
-
export type Options = {
|
|
9
|
-
/**
|
|
10
|
-
* Specify the export location for the files and define the behavior of the output
|
|
11
|
-
* @default { path: 'mcp', barrelType: 'named' }
|
|
12
|
-
*/
|
|
13
|
-
output?: Output<Oas>
|
|
14
|
-
/**
|
|
15
|
-
* Define which contentType should be used.
|
|
16
|
-
* By default, the first JSON valid mediaType is used
|
|
17
|
-
*/
|
|
18
|
-
contentType?: contentType
|
|
19
|
-
client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>
|
|
20
|
-
/**
|
|
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
|
|
25
|
-
*/
|
|
26
|
-
paramsCasing?: 'camelcase'
|
|
27
|
-
/**
|
|
28
|
-
* Group the mcp requests based on the provided name.
|
|
29
|
-
*/
|
|
30
|
-
group?: Group
|
|
31
|
-
/**
|
|
32
|
-
* Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
|
|
33
|
-
*/
|
|
34
|
-
exclude?: Array<Exclude>
|
|
35
|
-
/**
|
|
36
|
-
* Array containing include parameters to include tags/operations/methods/paths.
|
|
37
|
-
*/
|
|
38
|
-
include?: Array<Include>
|
|
39
|
-
/**
|
|
40
|
-
* Array containing override parameters to override `options` based on tags/operations/methods/paths.
|
|
41
|
-
*/
|
|
42
|
-
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
|
-
/**
|
|
50
|
-
* Define some generators next to the Mcp generators.
|
|
51
|
-
*/
|
|
52
|
-
generators?: Array<Generator<PluginMcp>>
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
type ResolvedOptions = {
|
|
56
|
-
output: Output<Oas>
|
|
57
|
-
group: Options['group']
|
|
58
|
-
client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>
|
|
59
|
-
paramsCasing: Options['paramsCasing']
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export type PluginMcp = PluginFactoryOptions<'plugin-mcp', Options, ResolvedOptions, never, ResolvePathOptions>
|
|
File without changes
|