Kubb Plugin Fastmcp
Kubb plugin to generate FastMCP servers and tools from OpenAPI specifications
Ask AI about Kubb Plugin Fastmcp
Powered by Claude Β· Grounded in docs
I know everything about Kubb Plugin Fastmcp. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
@beshkenadze/kubb-plugin-fastmcp
Swagger/OpenAPI integration to create FastMCP servers and tools.
Features
- Generate FastMCP tool handlers from OpenAPI operations
- Create FastMCP server setup with automatic tool registration
- Group handlers by OpenAPI tags
- TypeScript and Zod schema integration
- Customizable output paths and client configuration
Installation
bun add -D @beshkenadze/kubb-plugin-fastmcp
Quick Start
1. Configure Kubb
Create kubb.config.ts:
import { defineConfig } from '@kubb/core'
import { pluginOas } from '@kubb/plugin-oas'
import { pluginTs } from '@kubb/plugin-ts'
import { pluginZod } from '@kubb/plugin-zod'
import { pluginFastMCP } from '@beshkenadze/kubb-plugin-fastmcp'
export default defineConfig({
input: {
path: './petstore.yaml',
},
output: {
path: './src/gen',
},
plugins: [
pluginOas(),
pluginTs(),
pluginZod(),
pluginFastMCP({
output: {
path: './fastmcp',
barrelType: 'named',
},
client: {
baseURL: 'https://petstore.swagger.io/v2',
},
group: {
type: 'tag',
name: ({ group }) => `${group}Handlers`,
},
}),
],
})
2. Generate Code
kubb generate
This will generate:
- TypeScript types and Zod schemas
- FastMCP handler functions for each API operation
- FastMCP server setup with all tools registered
- Grouped handler files by OpenAPI tags
3. Generated Output
The plugin generates:
src/gen/fastmcp/server.ts
export const server: FastMCPServer = new FastMCPServer({
name: "OpenAPI Petstore",
version: "3.0.0",
tools: [
{ name: "addPet", description: "Add a new pet to the store", handler: addPetHandler },
{ name: "getPetById", description: "Find pet by ID", handler: getPetByIdHandler },
// ... more operations
],
})
server.start({ transportType: "httpStream", httpStream: { port: 8080 } })
src/gen/fastmcp/petHandlers/addPet.ts
import { CallToolResult } from 'fastmcp/types'
import { client } from 'fastmcp/client'
export const addPetHandler = async (params: AddPetRequest): Promise<CallToolResult> => {
const res = await client<AddPet200Response>('/pet', {
method: 'POST',
params,
// ... generated client code
})
return {
content: [
{
type: 'text',
text: JSON.stringify(res.data)
}
]
}
}
tsconfig.json Integration
The plugin integrates with your project's tsconfig.json to provide intelligent import path resolution and extension handling for generated code. This ensures compatibility with your TypeScript configuration and bundler setup.
Features
- Path Alias Resolution: Automatically resolves
@/*and other path mappings fromcompilerOptions.paths - Import Style Detection: Detects whether to append
.jsor.tsextensions based on your module system (ESM vs CJS) - Dynamic Extension Handling: Generated imports adapt to your configuration (bundler mode, Node.js ESM, etc.)
- Fallback Detection: Uses file existence checks when automatic detection is ambiguous
How It Works
- tsconfig Loading: The plugin uses get-tsconfig to load and parse your
tsconfig.json - Import Style Detection: Based on your
compilerOptions:moduleResolution: "node16" | "nodenext"+module: "node16" | "nodenext"β'needs-js-extension'(ESM requires.jsextensions)allowImportingTsExtensions: trueβ'ts-extensions-allowed'(allows.tsimports for bundlers)- Default bundler mode β
'no-extension-ok'(extensions optional for Webpack/Vite/esbuild)
- Path Resolution: Uses
createPathsMatcherto resolve aliases like@utilsβ./src/utils - Extension Appending: The
resolveImportPathutility appends appropriate extensions based on detected style - Plugin Option Override: You can manually set
importStyleto override automatic detection
Example tsconfig.json Configurations
1. ESM with Extensions (Node.js 16+)
{
"compilerOptions": {
"module": "node16",
"moduleResolution": "node16",
"verbatimModuleSyntax": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Generated imports:
// @utils β ./src/utils.js (needs-js-extension)
import { helper } from '@utils';
// ./local β ./local.js
import { localFn } from './local';
2. Bundler Mode with TS Extensions
{
"compilerOptions": {
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@components/*": ["./src/components/*"]
}
}
}
Generated imports:
// @components/Button β ./src/components/Button.ts (ts-extensions-allowed)
import { Button } from '@components/Button';
// ./utils β ./utils.ts
import { utilFn } from './utils';
// ./Componentx β ./Componentx.tsx (React JSX detection)
import { Componentx } from './Componentx';
3. CommonJS / Legacy Mode
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"baseUrl": "."
}
}
Generated imports:
// No extensions appended (no-extension-ok)
import { helper } from '@utils';
import { localFn } from './local';
Plugin Configuration
You can override automatic detection with the importStyle option:
pluginFastMCP({
importStyle: 'ts-extensions-allowed', // Force .ts extensions
// or
importStyle: 'no-extension-ok', // No extensions for bundler
output: { path: './fastmcp' },
})
Available values:
'auto'(default): Detect from tsconfig.json'needs-js-extension': Always append.js(Node.js ESM)'ts-extensions-allowed': Append.ts/.tsx(bundler with TS extensions)'no-extension-ok': No extensions (CommonJS/bundler)
Testing the Integration
The plugin includes tests for different tsconfig configurations. Run tests to verify:
bun test
Tests cover:
- Alias resolution with paths mapping
- Extension appending for ESM vs CJS
- React JSX (.tsx) detection
- File existence fallback
Troubleshooting
- Path aliases not resolving: Ensure
baseUrlandpathsare defined in compilerOptions - Extension errors at runtime: Check your bundler configuration matches the detected importStyle
- No tsconfig.json found: The plugin falls back to relative paths without extensions
- Testing with path mappings: Use
vite-tsconfig-pathsin your Vitest config for test resolution
For more details, see the get-tsconfig documentation and TypeScript module resolution docs.
Configuration Options
Basic Configuration
pluginFastMCP({
output: {
path: './fastmcp', // Output directory
barrelType: 'named', // 'named', 'all', or false
},
})
Advanced Configuration
pluginFastMCP({
output: {
path: './fastmcp',
barrelType: 'named',
banner: '/* Generated FastMCP Server */',
},
client: {
baseURL: 'https://api.example.com',
dataReturnType: 'data', // 'data' or 'full'
importPath: 'fastmcp/client',
},
group: {
type: 'tag',
name: ({ group }) => `${group}Service`,
},
exclude: [
{ type: 'tag', pattern: 'internal' },
],
include: [
{ type: 'operationId', pattern: 'public*' },
],
transformers: {
name: (name, type) => `${name}FastMCP`,
},
})
Grouping Options
- By Tag (default): Groups handlers by OpenAPI tags
- By Path: Groups by path segments
- Custom: Use custom grouping logic
group: {
type: 'tag',
output: './handlers/{{tag}}', // For file grouping
name: ({ group }) => `${group}API`, // For service names
}
Demo
1. Setup
Clone the repo and install dependencies:
git clone https://github.com/beshkenadze/kubb-plugin-fastmcp
cd kubb-plugin-fastmcp
bun install
2. Download Petstore API
curl -o petstore.yaml https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml
3. Generate FastMCP Server
kubb generate --config kubb.config.ts
4. Run the Server
The generated src/gen/fastmcp/server.ts can be run directly:
cd src/gen/fastmcp
npx tsx server.ts
This starts a FastMCP server on port 8080 with tools for all Petstore API operations.
Integration with FastMCP Clients
The generated handlers use the FastMCP client pattern:
import { FastMCPClient } from 'fastmcp/client'
import { server } from './server'
const client = new FastMCPClient({
server: server,
tools: ['addPet', 'getPetById', 'placeOrder']
})
const result = await client.callTool('addPet', {
// pet data
})
Troubleshooting
Module Resolution Errors
Ensure all Kubb packages are compatible versions:
bun add -D @kubb/core@3.18.3 @kubb/plugin-oas@3.18.3 @kubb/plugin-ts@3.18.3 @kubb/plugin-zod@3.18.3
Testing with Path Mappings
For advanced testing with tsconfig path mappings, add jonaskello/tsconfig-paths:
bun add -D jonaskello/tsconfig-paths
Update vitest.config.ts:
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react(), tsconfigPaths()],
test: {
environment: 'node',
globals: true,
include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],
extension: ['.ts', '.tsx'],
},
})
This enables automatic .js/.ts extension resolution based on your tsconfig.json settings.
Generation Errors
- Check OpenAPI spec validity with
kubb validate - Ensure all required plugins are included (OAS, TS, Zod)
- Verify output paths exist and are writable
Custom FastMCP SDK
If using a custom FastMCP implementation, update the import paths:
pluginFastMCP({
client: {
importPath: 'your-fastmcp/client',
},
})
Contributing
- Fork the repo
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
MIT
