{"_id":"@beshkenadze/kubb-plugin-fastmcp","name":"@beshkenadze/kubb-plugin-fastmcp","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@beshkenadze/kubb-plugin-fastmcp","version":"0.1.0","description":"Kubb plugin to generate FastMCP servers and tools from OpenAPI specifications","keywords":["typescript","plugins","kubb","codegen","fastmcp","mcp","ai","openapi"],"repository":{"type":"git","url":"git+https://github.com/beshkenadze/kubb-plugin-fastmcp.git"},"license":"MIT","author":{"name":"Aleksandr Beshkenadze","email":"beshkenadze@gmail.com"},"sideEffects":false,"type":"module","exports":{".":{"import":"./dist/index.js","require":"./dist/index.cjs"},"./components":{"import":"./dist/components.js","require":"./dist/components.cjs"},"./generators":{"import":"./dist/generators.js","require":"./dist/generators.cjs"},"./package.json":"./package.json"},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.cts","typesVersions":{"*":{"utils":["./dist/utils.d.ts"],"hooks":["./dist/hooks.d.ts"],"components":["./dist/components.d.ts"],"generators":["./dist/generators.d.ts"]}},"scripts":{"build":"tsdown","clean":"npx rimraf ./dist","clean:test":"rm -rf test/generated","generate":"bun x kubb generate","generate:test":"bun x kubb generate --config kubb.config.test.ts","lint":"bun biome lint .","lint:fix":"bun biome lint --fix --unsafe .","pretest:integration":"bun run clean:test","release":"pnpm publish --no-git-check","release:canary":"bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check","start":"tsdown --watch","test":"bun run generate && bun test test/server.test.ts","test:server":"bun test test/server.test.ts","test:integration":"bun test test/integration","test:all":"bun test && bun run generate:test && bun run test:integration","typecheck":"tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false"},"dependencies":{"@kubb/core":"^3.18.3","@kubb/oas":"^3.18.3","@kubb/plugin-client":"^3.18.3","@kubb/plugin-oas":"^3.18.3","@kubb/plugin-ts":"^3.18.3","@kubb/plugin-zod":"^3.18.3","@kubb/react":"^3.18.3","axios":"^1.7.0","fastmcp":"^3.17.0","get-tsconfig":"^4.10.1"},"devDependencies":{"@kubb/config-ts":"^3.18.3","@types/react":"^19.1.13","react":"^19.1.1","tsdown":"^0.15.1","typescript":"^5.0.0","vitest":"^3.2.4","@types/node":"^24.5.0","@vitejs/plugin-react":"^5.0.2","jsdom":"^27.0.0"},"peerDependencies":{"@kubb/react":"^3.0.0","typescript":"^5.0.0"},"engines":{"node":">=20"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_id":"@beshkenadze/kubb-plugin-fastmcp@0.1.0","gitHead":"773889fd3bb9b00ddecf20912a82a7923ffbe6ee","bugs":{"url":"https://github.com/beshkenadze/kubb-plugin-fastmcp/issues"},"homepage":"https://github.com/beshkenadze/kubb-plugin-fastmcp#readme","_nodeVersion":"24.7.0","_npmVersion":"11.5.1","dist":{"integrity":"sha512-kHKzXp2pSe8y2rWChzKcAmAA40ep5Nn3GfrLyDVUT4ZEaRxL8FnuB1h28lgx3bHBxvxFZPjXTwxyQ2K5tnlk6g==","shasum":"ef7924e13db716798cee9129236699cab808b90c","tarball":"https://registry.npmjs.org/@beshkenadze/kubb-plugin-fastmcp/-/kubb-plugin-fastmcp-0.1.0.tgz","fileCount":15,"unpackedSize":125611,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICoBY51UK7I4k3hO4HfRMZ0qZw35nTmeUowrSluJUVNdAiEA1P0kS9pl0UwZ8Rugs1dB4MLRJldTZg2tvC4Hd3KF3vk="}]},"_npmUser":{"name":"beshkenadze","email":"beshkenadze@gmail.com"},"directories":{},"maintainers":[{"name":"beshkenadze","email":"beshkenadze@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kubb-plugin-fastmcp_0.1.0_1758042518985_0.11620645244887262"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-16T17:08:38.877Z","0.1.0":"2025-09-16T17:08:39.187Z","modified":"2025-09-16T17:08:39.460Z"},"maintainers":[{"name":"beshkenadze","email":"beshkenadze@gmail.com"}],"description":"Kubb plugin to generate FastMCP servers and tools from OpenAPI specifications","homepage":"https://github.com/beshkenadze/kubb-plugin-fastmcp#readme","keywords":["typescript","plugins","kubb","codegen","fastmcp","mcp","ai","openapi"],"repository":{"type":"git","url":"git+https://github.com/beshkenadze/kubb-plugin-fastmcp.git"},"author":{"name":"Aleksandr Beshkenadze","email":"beshkenadze@gmail.com"},"bugs":{"url":"https://github.com/beshkenadze/kubb-plugin-fastmcp/issues"},"license":"MIT","readme":"# @beshkenadze/kubb-plugin-fastmcp\n\nSwagger/OpenAPI integration to create FastMCP servers and tools.\n\n[![npm version](https://img.shields.io/npm/v/@beshkenadze/kubb-plugin-fastmcp?flat&colorA=18181B&colorB=f58517)](https://npmjs.com/package/@beshkenadze/kubb-plugin-fastmcp)\n[![npm downloads](https://img.shields.io/npm/dm/@beshkenadze/kubb-plugin-fastmcp?flat&colorA=18181B&colorB=f58517)](https://npmjs.com/package/@beshkenadze/kubb-plugin-fastmcp)\n[![License](https://img.shields.io/github/license/beshkenadze/kubb-plugin-fastmcp.svg?flat&colorA=18181B&colorB=f58517)](https://github.com/beshkenadze/kubb-plugin-fastmcp/blob/main/LICENSE)\n\n## Features\n\n- Generate FastMCP tool handlers from OpenAPI operations\n- Create FastMCP server setup with automatic tool registration\n- Group handlers by OpenAPI tags\n- TypeScript and Zod schema integration\n- Customizable output paths and client configuration\n\n## Installation\n\n```bash\nbun add -D @beshkenadze/kubb-plugin-fastmcp\n```\n\n## Quick Start\n\n### 1. Configure Kubb\n\nCreate `kubb.config.ts`:\n\n```typescript\nimport { defineConfig } from '@kubb/core'\nimport { pluginOas } from '@kubb/plugin-oas'\nimport { pluginTs } from '@kubb/plugin-ts'\nimport { pluginZod } from '@kubb/plugin-zod'\nimport { pluginFastMCP } from '@beshkenadze/kubb-plugin-fastmcp'\n\nexport default defineConfig({\n  input: {\n    path: './petstore.yaml',\n  },\n  output: {\n    path: './src/gen',\n  },\n  plugins: [\n    pluginOas(),\n    pluginTs(),\n    pluginZod(),\n    pluginFastMCP({\n      output: {\n        path: './fastmcp',\n        barrelType: 'named',\n      },\n      client: {\n        baseURL: 'https://petstore.swagger.io/v2',\n      },\n      group: {\n        type: 'tag',\n        name: ({ group }) => `${group}Handlers`,\n      },\n    }),\n  ],\n})\n```\n\n### 2. Generate Code\n\n```bash\nkubb generate\n```\n\nThis will generate:\n- TypeScript types and Zod schemas\n- FastMCP handler functions for each API operation\n- FastMCP server setup with all tools registered\n- Grouped handler files by OpenAPI tags\n\n### 3. Generated Output\n\nThe plugin generates:\n\n**src/gen/fastmcp/server.ts**\n```typescript\nexport const server: FastMCPServer = new FastMCPServer({\n  name: \"OpenAPI Petstore\",\n  version: \"3.0.0\",\n  tools: [\n    { name: \"addPet\", description: \"Add a new pet to the store\", handler: addPetHandler },\n    { name: \"getPetById\", description: \"Find pet by ID\", handler: getPetByIdHandler },\n    // ... more operations\n  ],\n})\n\nserver.start({ transportType: \"httpStream\", httpStream: { port: 8080 } })\n```\n\n**src/gen/fastmcp/petHandlers/addPet.ts**\n```typescript\nimport { CallToolResult } from 'fastmcp/types'\nimport fetch from 'fastmcp/client'\n\nexport const addPetHandler = async (params: AddPetRequest): Promise<CallToolResult> => {\n  const res = await fetch<AddPet200Response>('/pet', {\n    method: 'POST',\n    params,\n    // ... generated client code\n  })\n  \n  return {\n    content: [\n      {\n        type: 'text',\n        text: JSON.stringify(res.data)\n      }\n    ]\n  }\n}\n```\n\n## tsconfig.json Integration\n\nThe 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.\n\n### Features\n\n- **Path Alias Resolution**: Automatically resolves `@/*` and other path mappings from `compilerOptions.paths`\n- **Import Style Detection**: Detects whether to append `.js` or `.ts` extensions based on your module system (ESM vs CJS)\n- **Dynamic Extension Handling**: Generated imports adapt to your configuration (bundler mode, Node.js ESM, etc.)\n- **Fallback Detection**: Uses file existence checks when automatic detection is ambiguous\n\n### How It Works\n\n1. **tsconfig Loading**: The plugin uses [get-tsconfig](https://github.com/privatenumber/get-tsconfig) to load and parse your `tsconfig.json`\n2. **Import Style Detection**: Based on your `compilerOptions`:\n   - `moduleResolution: \"node16\" | \"nodenext\"` + `module: \"node16\" | \"nodenext\"` → `'needs-js-extension'` (ESM requires `.js` extensions)\n   - `allowImportingTsExtensions: true` → `'ts-extensions-allowed'` (allows `.ts` imports for bundlers)\n   - Default bundler mode → `'no-extension-ok'` (extensions optional for Webpack/Vite/esbuild)\n3. **Path Resolution**: Uses `createPathsMatcher` to resolve aliases like `@utils` → `./src/utils`\n4. **Extension Appending**: The `resolveImportPath` utility appends appropriate extensions based on detected style\n5. **Plugin Option Override**: You can manually set `importStyle` to override automatic detection\n\n### Example tsconfig.json Configurations\n\n#### 1. ESM with Extensions (Node.js 16+)\n\n```json\n{\n  \"compilerOptions\": {\n    \"module\": \"node16\",\n    \"moduleResolution\": \"node16\",\n    \"verbatimModuleSyntax\": true,\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    }\n  }\n}\n```\n\nGenerated imports:\n```typescript\n// @utils → ./src/utils.js (needs-js-extension)\nimport { helper } from '@utils';\n// ./local → ./local.js\nimport { localFn } from './local';\n```\n\n#### 2. Bundler Mode with TS Extensions\n\n```json\n{\n  \"compilerOptions\": {\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"jsx\": \"react-jsx\",\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@components/*\": [\"./src/components/*\"]\n    }\n  }\n}\n```\n\nGenerated imports:\n```typescript\n// @components/Button → ./src/components/Button.ts (ts-extensions-allowed)\nimport { Button } from '@components/Button';\n// ./utils → ./utils.ts\nimport { utilFn } from './utils';\n// ./Componentx → ./Componentx.tsx (React JSX detection)\nimport { Componentx } from './Componentx';\n```\n\n#### 3. CommonJS / Legacy Mode\n\n```json\n{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"baseUrl\": \".\"\n  }\n}\n```\n\nGenerated imports:\n```typescript\n// No extensions appended (no-extension-ok)\nimport { helper } from '@utils';\nimport { localFn } from './local';\n```\n\n### Plugin Configuration\n\nYou can override automatic detection with the `importStyle` option:\n\n```typescript\npluginFastMCP({\n  importStyle: 'ts-extensions-allowed', // Force .ts extensions\n  // or\n  importStyle: 'no-extension-ok', // No extensions for bundler\n  output: { path: './fastmcp' },\n})\n```\n\nAvailable values:\n- `'auto'` (default): Detect from tsconfig.json\n- `'needs-js-extension'`: Always append `.js` (Node.js ESM)\n- `'ts-extensions-allowed'`: Append `.ts`/`.tsx` (bundler with TS extensions)\n- `'no-extension-ok'`: No extensions (CommonJS/bundler)\n\n### Testing the Integration\n\nThe plugin includes tests for different tsconfig configurations. Run tests to verify:\n\n```bash\nbun test\n```\n\nTests cover:\n- Alias resolution with paths mapping\n- Extension appending for ESM vs CJS\n- React JSX (.tsx) detection\n- File existence fallback\n\n### Troubleshooting\n\n- **Path aliases not resolving**: Ensure `baseUrl` and `paths` are defined in compilerOptions\n- **Extension errors at runtime**: Check your bundler configuration matches the detected importStyle\n- **No tsconfig.json found**: The plugin falls back to relative paths without extensions\n- **Testing with path mappings**: Use `vite-tsconfig-paths` in your Vitest config for test resolution\n\nFor more details, see the [get-tsconfig documentation](https://github.com/privatenumber/get-tsconfig) and [TypeScript module resolution docs](https://www.typescriptlang.org/docs/handbook/module-resolution.html).\n\n## Configuration Options\n\n### Basic Configuration\n\n```typescript\npluginFastMCP({\n  output: {\n    path: './fastmcp', // Output directory\n    barrelType: 'named', // 'named', 'all', or false\n  },\n})\n```\n\n### Advanced Configuration\n\n```typescript\npluginFastMCP({\n  output: {\n    path: './fastmcp',\n    barrelType: 'named',\n    banner: '/* Generated FastMCP Server */',\n  },\n  client: {\n    baseURL: 'https://api.example.com',\n    dataReturnType: 'data', // 'data' or 'full'\n    importPath: 'fastmcp/client',\n  },\n  group: {\n    type: 'tag',\n    name: ({ group }) => `${group}Service`,\n  },\n  exclude: [\n    { type: 'tag', pattern: 'internal' },\n  ],\n  include: [\n    { type: 'operationId', pattern: 'public*' },\n  ],\n  transformers: {\n    name: (name, type) => `${name}FastMCP`,\n  },\n})\n```\n\n### Grouping Options\n\n- **By Tag** (default): Groups handlers by OpenAPI tags\n- **By Path**: Groups by path segments\n- **Custom**: Use custom grouping logic\n\n```typescript\ngroup: {\n  type: 'tag',\n  output: './handlers/{{tag}}', // For file grouping\n  name: ({ group }) => `${group}API`, // For service names\n}\n```\n\n## Demo\n\n### 1. Setup\n\nClone the repo and install dependencies:\n\n```bash\ngit clone https://github.com/beshkenadze/kubb-plugin-fastmcp\ncd kubb-plugin-fastmcp\nbun install\n```\n\n### 2. Download Petstore API\n\n```bash\ncurl -o petstore.yaml https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml\n```\n\n### 3. Generate FastMCP Server\n\n```bash\nkubb generate --config kubb.config.ts\n```\n\n### 4. Run the Server\n\nThe generated `src/gen/fastmcp/server.ts` can be run directly:\n\n```bash\ncd src/gen/fastmcp\nnpx tsx server.ts\n```\n\nThis starts a FastMCP server on port 8080 with tools for all Petstore API operations.\n\n## Integration with FastMCP Clients\n\nThe generated handlers use the FastMCP client pattern:\n\n```typescript\nimport { FastMCPClient } from 'fastmcp/client'\nimport { server } from './server'\n\nconst client = new FastMCPClient({\n  server: server,\n  tools: ['addPet', 'getPetById', 'placeOrder']\n})\n\nconst result = await client.callTool('addPet', {\n  // pet data\n})\n```\n\n## Troubleshooting\n\n### Module Resolution Errors\n\nEnsure all Kubb packages are compatible versions:\n\n```bash\nbun 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\n```\n\n### Testing with Path Mappings\n\nFor advanced testing with tsconfig path mappings, add `jonaskello/tsconfig-paths`:\n\n```bash\nbun add -D jonaskello/tsconfig-paths\n```\n\nUpdate `vitest.config.ts`:\n\n```typescript\nimport { defineConfig } from 'vitest/config'\nimport tsconfigPaths from 'vite-tsconfig-paths'\nimport react from '@vitejs/plugin-react'\n\nexport default defineConfig({\n  plugins: [react(), tsconfigPaths()],\n  test: {\n    environment: 'node',\n    globals: true,\n    include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],\n    extension: ['.ts', '.tsx'],\n  },\n})\n```\n\nThis enables automatic .js/.ts extension resolution based on your tsconfig.json settings.\n\n### Generation Errors\n\n- Check OpenAPI spec validity with `kubb validate`\n- Ensure all required plugins are included (OAS, TS, Zod)\n- Verify output paths exist and are writable\n\n### Custom FastMCP SDK\n\nIf using a custom FastMCP implementation, update the import paths:\n\n```typescript\npluginFastMCP({\n  client: {\n    importPath: 'your-fastmcp/client',\n  },\n})\n```\n\n## Contributing\n\n1. Fork the repo\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-a781d9551faaedadec00933edcbb7bfe"}