@kubb/plugin-mcp
Generate Model Context Protocol servers that enable AI models to interact with your API.
This plugin creates an MCP server that tools like Claude or ChatGPT can use to call your API endpoints through text or voice commands.
TIP
See Setup Claude with Kubb for configuration instructions.
Installation
bun add -d @kubb/plugin-mcppnpm add -D @kubb/plugin-mcpnpm install --save-dev @kubb/plugin-mcpyarn add -D @kubb/plugin-mcpOptions
output
Specify the export location for the files and define the behavior of the output.
output.path
Path to the output folder or file that contains the generated code.
TIP
if output.path is a file, group cannot be used.
| Type: | string |
|---|---|
| Required: | true |
| Default: | 'ncp' |
output.barrelType
Specify what to export and optionally disable barrel file generation.
TIP
Using propagate will prevent a plugin from creating a barrel file, but it will still propagate, allowing output.barrelType to export the specific function or type.
| Type: | 'all' | 'named' | 'propagate' | false |
|---|---|
| Required: | false |
| Default: | 'named' |
export * from "./gen/petService.ts"export { PetService } from "./gen/petService.ts"output.banner
Add a banner comment at the top of every generated file.
| Type: | string | (oas: Oas) => string |
|---|---|
| Required: | false |
output.footer
Add a footer comment at the end of every generated file.
| Type: | string | (oas: Oas) => string |
|---|---|
| Required: | false |
output.override
Whether Kubb overrides existing external files that can be generated if they already exist.
| Type: | boolean |
|---|---|
| Required: | false |
| Default: | false |
contentType
Define which content type to use.
By default, Kubb uses the first JSON-valid media type.
| Type: | 'application/json' | (string & {}) |
|---|---|
| Required: | false |
group
Grouping combines files in a folder based on a specific type.
For example, with this configuration:
group: {
type: 'tag',
name({ group }){
return `${group}Controller`
}
}This generates the following structure:
.
├── src/
│ └── petController/
│ │ ├── addPet.ts
│ │ └── getPet.ts
│ └── storeController/
│ ├── createStore.ts
│ └── getStoreById.ts
├── petStore.yaml
├── kubb.config.ts
└── package.jsongroup.type
Specify the property to group files by.
| Type: | 'tag' |
|---|---|
| Required: | true |
'tag': Uses the first tag fromoperation.getTags().at(0)?.name
group.name
Return the name of a group based on the group name, this will be used for the file and name generation.
| Type: | (context: GroupContext) => string |
|---|---|
| Required: | false |
| Default: | (ctx) => '${ctx.group}Requests' |
paramsCasing
Transform parameter names to a specific casing format for path, query, and header parameters in generated MCP handlers.
IMPORTANT
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.
| Type: | 'camelcase' |
|---|---|
| Required: | false |
| Default: | undefined |
'camelcase'transforms parameter names to camelCase
// Handler uses camelCase parameters
export async function findPetsByStatusHandler({
stepId // ✓ camelCase
}: {
stepId: FindPetsByStatusPathParams['stepId']
}): Promise<Promise<CallToolResult>> {
// Automatically maps back to original name
const step_id = stepId
const res = await fetch({
method: 'GET',
url: `/pet/findByStatus/${step_id}`, // Uses original API name
...
})
...
}// Handler uses original API naming
export async function findPetsByStatusHandler({
step_id // Original naming
}: {
step_id: FindPetsByStatusPathParams['step_id']
}): Promise<Promise<CallToolResult>> {
const res = await fetch({
method: 'GET',
url: `/pet/findByStatus/${step_id}`,
...
})
...
}client
client.importPath
Path to the client used for API calls. Supports both relative and absolute paths.
When to use importPath
Use importPath when you want to:
- Customize the HTTP client: Provide your own client implementation with custom configurations (e.g., baseURL, headers, interceptors)
- Add authentication: Include authentication tokens or other security mechanisms in your client
- Override default behavior: Replace the default Kubb client with your own implementation
Default behavior
When importPath is not specified:
- If
bundle: false(default): Uses@kubb/plugin-client/clients/${client}where client is eitheraxiosorfetch - If
bundle: true: Bundles the client into.kubb/fetch.ts
Import structure
Generated code imports:
- Client as default import
- Types as named type imports
Example for axios client:
/**
* Generated by Kubb (https://kubb.dev/).
* Do not edit manually.
*/
import client from '${client.importPath}'
import type { RequestConfig, ResponseErrorConfig } from '${client.importPath}'
// ... rest of generated fileIMPORTANT
When using importPath with query plugins such as @kubb/plugin-react-query, @kubb/plugin-vue-query, @kubb/plugin-svelte-query, @kubb/plugin-solid-query, or @kubb/plugin-swr, the generated hooks also import type Client from the custom module:
import type { Client, RequestConfig, ResponseErrorConfig } from '@/lib/client'Your custom client module must export these three types. If any of them is missing, TypeScript will report an unresolvable import error.
export type RequestConfig<TData = unknown> = {
url?: string
method: 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE'
params?: object
data?: TData | FormData
responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
signal?: AbortSignal
headers?: HeadersInit
}
export type ResponseConfig<TData = unknown> = {
data: TData
status: number
statusText: string
}
export type ResponseErrorConfig<TError = unknown> = TError
// The Client type alias is required when using query plugins
export type Client = <TData, _TError = unknown, TVariables = unknown>(
config: RequestConfig<TVariables>
) => Promise<ResponseConfig<TData>>
export const client: Client = async (config) => { /* ... */ }
export default clientExample configuration with custom client:
import { defineConfig } from '@kubb/core'
import { pluginClient } from '@kubb/plugin-client'
export default defineConfig({
// ...
plugins: [
pluginClient({
importPath: './src/client.ts' // Path to your custom client
}),
],
})TIP
Learn more about defining a custom client here.
| Type: | string |
|---|---|
| Required: | false |
client.dataReturnType
Return type used when calling the client.
| Type: | 'data' | 'full' |
|---|---|
| Required: | false |
| Default: | 'data' |
'data'returns ResponseConfig[data].'full'returns ResponseConfig.
export async function getPetById<TData>(
petId: GetPetByIdPathParams,
): Promise<ResponseConfig<TData>["data"]> {
...
}export async function getPetById<TData>(
petId: GetPetByIdPathParams,
): Promise<ResponseConfig<TData>> {
...
}client.baseURL
Sets a custom base URL for all generated calls.
| Type: | string |
|---|---|
| Required: | false |
include
Array containing include parameters to include tags, operations, methods, paths, or content types.
| Type: | Array<Include> |
|---|---|
| Required: | false |
export type Include = {
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
pattern: string | RegExp
}exclude
Array containing exclude parameters to exclude or skip tags, operations, methods, paths, or content types.
| Type: | Array<Exclude> |
|---|---|
| Required: | false |
export type Exclude = {
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
pattern: string | RegExp
}override
Array containing override parameters to override options based on tags, operations, methods, paths, or content types.
| Type: | Array<Override> |
|---|---|
| Required: | false |
export type Override = {
type: 'tag' | 'operationId' | 'path' | 'method' | 'contentType'
pattern: string | RegExp
options: PluginOptions
}generators
See Generators for more information on how to use generators.
| Type: | Array<Generator<PluginMsw>> |
|---|---|
| Required: | false |
transformers
transformers.name
Customize the names based on the type that is provided by the plugin.
| Type: | (name: string, type?: ResolveType) => string |
|---|---|
| Required: | false |
type ResolveType = 'file' | 'function' | 'type' | 'const'Example
import { defineConfig } from '@kubb/core'
import { pluginOas } from '@kubb/plugin-oas'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginMcp } from '@kubb/plugin-mcp'
import { pluginZod } from '@kubb/plugin-zod'
export default defineConfig({
input: {
path: './petStore.yaml',
},
output: {
path: './src/gen',
},
plugins: [
pluginOas(),
pluginTs(),
pluginZod(),
pluginMcp({
output: {
path: './mcp',
barrelType: 'named',
},
client: {
baseURL: 'https://petstore.swagger.io/v2',
},
group: {
type: 'tag',
name: ({ group }) => `${group}Handlers`,
},
}),
],
})