MCP
Officialv5.1.2@kubb/plugin-mcp
Run an MCP server
Generate and start an MCP server with typed tools and an HTTP client.
Generate the server
Register TypeScript types, Zod schemas, and an Axios or Fetch client alongside pluginMcp. A single registered client is detected automatically.
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' },
plugins: [
pluginTs({ output: { path: 'types', mode: 'directory' } }),
pluginZod(),
pluginAxios({ baseURL: 'https://petstore.swagger.io/v2' }),
pluginMcp({ output: { path: 'mcp', mode: 'directory' } }),
],
})Run kubb generate. The plugin writes tool handlers, server.ts, start.ts, and .mcp.json. Each generated handler calls its HTTP operation, forwards the cancellation signal, and throws for non-2xx responses. Tool results include text content and structured response data. server.ts registers tools with Zod input and output schemas, and start.ts calls its startServer() to serve them over stdio.
Start the server
Install the generated server's runtime dependencies and a TypeScript runner:
npm install @modelcontextprotocol/server@^2 zod@^4.2 axios@^1.20.0
npm install -D tsxRun the generated entry from the project root:
npx tsx src/gen/mcp/start.tsThe server reads MCP messages from stdin, prints nothing on startup, and logs transport errors to stderr. Press Ctrl+C to stop it.
Connect a client
The generated .mcp.json runs the same command:
{
"mcpServers": {
"Swagger Petstore": {
"type": "stdio",
"command": "npx",
"args": ["tsx", "./src/gen/mcp/start.ts"]
}
}
}The server name comes from info.title in your OpenAPI spec. MCP clients start the command from their own working directory, so the args path is relative to the Kubb root, not to the .mcp.json folder. Claude Code reads .mcp.json from the project root, so copy the entry under mcpServers into that file. For a client that starts in another folder, such as Claude Desktop, use an absolute path to start.ts.
Use your own entry file
To run setup code first, such as loading environment variables, import startServer from the generated server.ts in your own entry file and point args at that file instead of start.ts.
import { startServer } from './src/gen/mcp/server'
startServer()Select a client
When both HTTP plugins are registered, set client explicitly. Give each client a different output directory so their generated files do not overwrite each other.
import { pluginAxios } from '@kubb/plugin-axios'
import { pluginFetch } from '@kubb/plugin-fetch'
import { pluginMcp } from '@kubb/plugin-mcp'
const clients = [
pluginAxios({ output: { path: 'clients-axios', mode: 'directory' } }),
pluginFetch({ output: { path: 'clients-fetch', mode: 'directory' } }),
pluginMcp({ output: { path: 'mcp', mode: 'directory' }, client: 'axios' }),
]Add these entries alongside pluginTs and pluginZod in defineConfig.plugins. The handlers import operations from clients-axios.