More than just a
Swagger doc.
nestjs-docfy separates Swagger/OpenAPI documentation from controller logic using a companion file naming convention, the same way Nest already does with *.controller.spec.ts.
npm install nestjs-docfy
# peer deps
npm install @nestjs/common @nestjs/swagger reflect-metadatadocfy-ui: an AI-first reference viewer
The OpenAPI spec that nestjs-docfy assembles is also what docfy-ui renders, with no separate config and the same source of truth.
- Copy for AI: a deterministic, LLM-ready summary of the endpoint, not a raw JSON dump with $ref
- ⌘K search across every endpoint, instantly
- Full request/response detail per endpoint, generated straight from the spec






Built for AI agents, not just humans
docfy-mcp exposes your OpenAPI spec as MCP tools, so Claude, Cursor, or any MCP-compatible agent can query your API directly — no copy-pasting JSON into a prompt.
- list_endpoints / get_endpoint: browse and inspect any operation, the same normalized shape docfy-ui renders
- lint_spec: flags missing summaries, descriptions, tags, and error responses before they ship
- diff_specs: compares two OpenAPI documents and flags breaking vs. informational changes
- contract_test: validates a live response against its declared schema, from the agent's own tool calls
- Zero-config against a running NestJS server, or point it at a static spec file
{
"mcpServers": {
"docfy": {
"command": "npx",
"args": ["-y", "docfy-mcp", "--url", "http://localhost:3000/docs-json"]
}
}
}What it looks like in practice
Before: a controller buried in decorators. After: just routes, with the documentation living alongside it, in a companion file.
@WithDocs()
@Controller('users')
export class UsersController {
constructor(private readonly users: UsersService) {}
@Get(':id')
findOne(@Param('id') id: string) {
return this.users.findOne(id);
}
}import { docs } from 'nestjs-docfy';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { UsersController } from './users.controller';
docs(UsersController, {
classDecorators: [ApiTags('users')],
methods: {
findOne: [
ApiOperation({ summary: 'Get user by id' }),
ApiResponse({ status: 200, description: 'OK', type: UserDto }),
ApiResponse({ status: 404, description: 'User not found' }),
],
},
});No monkey-patching, no runtime proxies
Just the right timing and Reflect metadata.
Write the companion file
users.controller.docs.ts calls docs(UsersController, { ... }), plain Swagger decorators, just in another file.
Discovered at boot
DocfyModule.forRoot() finds it via naming convention and writes Reflect metadata onto the controller's methods, before SwaggerModule.createDocument() runs.
Identical OpenAPI output
SwaggerModule sees the exact same metadata it would if the decorators were written inline on the controller.
Not a Swagger plugin. The whole toolchain.
Most tools stop at decorators. nestjs-docfy ships the CLI, the viewer, and the AI integration your team actually needs to keep documentation honest.
A CLI that gates your CI
generate, check, coverage --min, lint, and patch-spec fail the build the moment documentation drifts from code — not months later.
Zero runtime cost, if you want it
The webpack CLI plugin computes everything at build time; nothing runs per-request in production.
docfy-ui included, not sold separately
A full AI-first reference viewer ships with the library — no extra account, no separate pricing tier.
Agents as first-class citizens
docfy-mcp exposes the same spec to Claude, Cursor, and any MCP client — your API becomes queryable, not just readable.
Works with whatever NestJS layout you already have
Simple projects, Nx workspaces, and Nest CLI monorepos are all auto-detected — no config file to write by hand.
One command from zero to fully wired
nestjs-docfy init wires the module, decorates every controller, and generates the docs — in one shot.