A working MCP server from a spec
Register pluginTs(), pluginZod(), and one client plugin alongside pluginMcp(), so the handlers get their types, validation schemas, and an HTTP client. With a single client registered the plugin detects it, so output is the only thing left to tune.
typescript
import { defineConfig } from 'kubb/config'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginZod } from '@kubb/plugin-zod'
import { pluginAxios } from '@kubb/plugin-axios'
import { pluginMcp } from '@kubb/plugin-mcp'
export default defineConfig({
input: './petStore.yaml',
output: { path: './src/gen', clean: true },
plugins: [
pluginTs(),
pluginZod(),
pluginAxios({ baseURL: 'https://petstore.swagger.io/v2' }),
pluginMcp(),
],
})Output example
typescript
import type { GetPetByIdOptions } from '../types/GetPetById'
import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol'
import type { CallToolResult, ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types'
import { getPetById } from '../clients/getPetById'
export async function getPetByIdHandler({ path }: GetPetByIdOptions, request: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<Promise<CallToolResult>> {
const res = await getPetById({ path })
return {
content: [{ type: 'text', text: JSON.stringify(res.data) }],
structuredContent: { data: res.data },
}
}The handler calls getPetById from the Axios client the plugin auto-detected, and server.ts registers a matching tool with Zod input and output schemas, so the same file also exports a ready-to-run server.
typescript
import { startServer } from './src/gen/mcp/server'
await startServer()