Skip to content

Migration: @kubb/plugin-mcp

Part of the v4 → v5 migration guide. For the full option reference, see @kubb/plugin-mcp.

resolver.name replaces transformers.name, and the generators option is gone.

client selects a registered client plugin

In v4, client was an object that configured a bundled client (clientType, dataReturnType, baseURL, bundle, importPath, paramsCasing). In v5 it is a string that names a registered client plugin. See Query and MCP plugins select a client for the shared rules, then register @kubb/plugin-axios or @kubb/plugin-fetch in plugins and set baseURL there instead of on pluginMcp.

pluginMcp also depends on @kubb/plugin-ts and @kubb/plugin-zod, so register both alongside the client plugin.

typescript
import { defineConfig } from '@kubb/core'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginZod } from '@kubb/plugin-zod'
import { pluginMcp } from '@kubb/plugin-mcp'

export default defineConfig({
  input: './petStore.yaml',
  output: { path: './src/gen' },
  plugins: [
    pluginTs(),
    pluginZod(),
    pluginMcp({
      client: {
        client: 'fetch',
        baseURL: 'https://petstore.swagger.io/v2',
      },
    }),
  ],
})
typescript
import { 
defineConfig
} from 'kubb/config'
import {
pluginTs
} from '@kubb/plugin-ts'
import {
pluginZod
} from '@kubb/plugin-zod'
import {
pluginFetch
} from '@kubb/plugin-fetch'
import {
pluginMcp
} from '@kubb/plugin-mcp'
export default
defineConfig
({
input
: './petStore.yaml',
output
: {
path
: './src/gen' },
plugins
: [
pluginTs
(),
pluginZod
(),
pluginFetch
({
baseURL
: 'https://petstore.swagger.io/v2' }),
pluginMcp
({
client
: 'fetch' }),
], })

Removed: paramsCasing

v4 kubb.config.ts
typescript
pluginMcp({ paramsCasing: 'camelcase' })

Parameter properties in the generated handlers come from the @kubb/plugin-ts *Options type, so they match the names in your OpenAPI document. The client.paramsCasing sub-option is gone too, so drop both.

Generated output

Each handler now takes a second argument, the MCP RequestHandlerExtra object, so it can read the request context. The handler no longer builds the request inline. Instead it calls the named operation from the registered client plugin (addPet here) with a single grouped { path, query, headers, body } config object, and reads res.data.

Generated output
diff
import type { CallToolResult } from '@modelcontextprotocol/sdk/types'
import type { CallToolResult, ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types'
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol'
import { addPet } from './clients/addPet'

export async function addPetHandler({ data }: { data: AddPetMutationRequest }): Promise<CallToolResult> {
export async function addPetHandler(
  { body }: AddPetOptions,
  request: RequestHandlerExtra<ServerRequest, ServerNotification>,
): Promise<CallToolResult> {
  const res = await fetch<AddPetMutationResponse, ResponseErrorConfig<AddPet405>, AddPetMutationRequest>({
    method: 'POST',
    url: '/pet',
    baseURL: 'https://petstore.swagger.io/v2',
    data,
  })
  const res = await addPet({ body })
  ...
}