Springdoc-openapi Features

Adding API Information and Security documentation

The library uses spring-boot application auto-configured packages to scan for the following annotations in spring beans: OpenAPIDefinition and Info. These annotations declare, API Information: Title, version, licence, security, servers, tags, security and externalDocs. For better performance of documentation generation, declare @OpenAPIDefinition and @SecurityScheme annotations within a spring managed bean.

Error Handling for REST using @ControllerAdvice

To generate documentation automatically, make sure all the methods declare the HTTP Code responses using the annotation: @ResponseStatus

Disabling the springdoc-openapi endpoints

In order to disable the springdoc-openapi endpoint (/v3/api-docs by default) use the following property:

# Disabling the /v3/api-docs endpoint
springdoc.api-docs.enabled=false

Disabling the swagger-ui

In order to disable the swagger-ui, use the following property:

# Disabling the swagger-ui
springdoc.swagger-ui.enabled=false

Swagger-ui configuration

The library supports the swagger-ui official properties:

You need to declare swagger-ui properties as spring-boot properties. All these properties should be declared with the following prefix: springdoc.swagger-ui

Selecting the Rest Controllers to include in the documentation

Additionally, to @Hidden annotation from swagger-annotations, its possible to restrict the generated OpenAPI description using package or path configuration.

For the list of packages to include, use the following property:

# Packages to include
springdoc.packagesToScan=com.package1, com.package2

For the list of paths to include, use the following property:

# Paths to include
springdoc.pathsToMatch=/v1, /api/balance/**

Spring-webflux/WebMvc.fn with Functional Endpoints

Since version v1.5.0, a functional DSL has been introduced, thanks to this enhancement in the spring-framework: #25938

It’s an alternative functional API to the @RouterOperations annotations.

This is a sample DSL, to generate OpenAPI description to the webflux/WebMvc.fn REST endpoints:

@Bean
RouterFunction<?> routes() {
    return route().GET("/foo", HANDLER_FUNCTION, ops -> ops
            .operationId("hello")
            .parameter(parameterBuilder().name("key1").description("My key1 description"))
            .parameter(parameterBuilder().name("key2").description("My key2 description"))
            .response(responseBuilder().responseCode("200").description("This is normal response description"))
            .response(responseBuilder().responseCode("404").description("This is another response description"))
    ).build();
}

Here is the link for some sample codes:

And the Demo code, using the functional endpoints DSL:

Since version v1.3.8, the support of functional endpoints has been added. Two main annotations have been added for this purpose: @RouterOperations and @RouterOperation.

Only REST APIs with the @RouterOperations and @RouterOperation can be displayed on the swagger-ui.

  • @RouterOperation: It can be used alone, if the Router bean contains one single route related to the REST API.. When using @RouterOperation, its not mandatory to fill the path

  • @RouterOperation, can reference directly a spring Bean (beanClass property) and the underlying method (beanMethod property): Springdoc-openapi, will then inspect this method and the swagger annotations on this method level.

@Bean
@RouterOperation(beanClass = EmployeeService.class, beanMethod = "findAllEmployees")
RouterFunction<ServerResponse> getAllEmployeesRoute() {
   return route(GET("/employees").and(accept(MediaType.APPLICATION_JSON)),
         req -> ok().body(
               employeeService().findAllEmployees(), Employee.class));
}
  • @RouterOperation, contains the @Operation annotation. The @Operation annotation can also be placed on the bean method level if the property beanMethod is declared.

Don’t forget to set operationId which is mandatory.
@Bean
@RouterOperation(operation = @Operation(operationId = "findEmployeeById", summary = "Find purchase order by ID", tags = { "MyEmployee" },
      parameters = { @Parameter(in = ParameterIn.PATH, name = "id", description = "Employee Id") },
      responses = { @ApiResponse(responseCode = "200", description = "successful operation", content = @Content(schema = @Schema(implementation = Employee.class))),
            @ApiResponse(responseCode = "400", description = "Invalid Employee ID supplied"),
            @ApiResponse(responseCode = "404", description = "Employee not found") }))
RouterFunction<ServerResponse> getEmployeeByIdRoute() {
   return route(GET("/employees/{id}"),
         req -> ok().body(
               employeeRepository().findEmployeeById(req.pathVariable("id")), Employee.class));
}
  • @RouterOperations: This annotation should be used if the Router bean contains multiple routes. When using RouterOperations, its mandatory to fill the path property.

  • A @RouterOperations, contains many @RouterOperation.

@RouterOperations({ @RouterOperation(path = "/getAllPersons", beanClass = PersonService.class, beanMethod = "getAll"),
      @RouterOperation(path = "/getPerson/{id}", beanClass = PersonService.class, beanMethod = "getById"),
      @RouterOperation(path = "/createPerson", beanClass = PersonService.class, beanMethod = "save"),
      @RouterOperation(path = "/deletePerson/{id}", beanClass = PersonService.class, beanMethod = "delete") })
@Bean
public RouterFunction<ServerResponse> personRoute(PersonHandler handler) {
   return RouterFunctions
         .route(GET("/getAllPersons").and(accept(MediaType.APPLICATION_JSON)), handler::findAll)
         .andRoute(GET("/getPerson/{id}").and(accept(MediaType.APPLICATION_STREAM_JSON)), handler::findById)
         .andRoute(POST("/createPerson").and(accept(MediaType.APPLICATION_JSON)), handler::save)
         .andRoute(DELETE("/deletePerson/{id}").and(accept(MediaType.APPLICATION_JSON)), handler::delete);
}

All the documentations filled using @RouterOperation, might be completed by the router function data. For that, @RouterOperation fields must help identify uniquely the concerned route. springdoc-openpi scans for a unique route related to a @RouterOperation annotation, using on the following criteria:

  • by path

  • by path and RequestMethod

  • by path and produces

  • by path and consumes

  • by path and RequestMethod and produces

  • by path and RequestMethod and consumes

  • by path and produces and consumes

  • by path and RequestMethod and produces and consumes

Some code samples are available on GITHUB of demos:

And some project tests: (from app69 to app75)

MCP Integration (AI Agent Support)

springdoc-openapi provides built-in support for the Model Context Protocol (MCP), enabling your REST API endpoints to be automatically discovered and used as tools by AI agents.

Key features:

  • Auto-Discovery: Automatically turns your documented @RestController endpoints into AI Tools.

  • Semantic Mapping: Maps OpenAPI descriptions to AI tool metadata so LLMs understand context.

  • MCP Dashboard: Built-in web UI for discovering and testing MCP tools, with tools grouped by OpenAPI tags.

  • Agent Ready: Compatible with Claude Desktop, Cursor, and other MCP-enabled clients.

  • Customizable: Extension points to rename, redescribe, filter, or exclude tools.

  • AI-Optimized Descriptions: @McpToolDescription annotation for writing descriptions specifically for AI agents.

  • Tool Grouping: Tools are automatically organized by their @Tag annotation, matching how OpenAPI operations are grouped in Swagger UI.

  • Return Type Descriptions: Tool descriptions are enriched with human-readable return type information for better AI comprehension.

  • MCP Guardrails: Safe/mutating tool classification and Human-in-the-Loop (HITL) support — mutating operations require human approval before execution by default.

Add the dependency matching your web stack:

For Spring WebMvc:

   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-starter-webmvc-mcp</artifactId>
      <version>3.1.0</version>
   </dependency>

For Spring WebFlux:

   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-starter-webflux-mcp</artifactId>
      <version>3.1.0</version>
   </dependency>

Then enable the integration:

springdoc.ai.mcp.enabled=true

Your @RestController endpoints are now available as MCP tools. For detailed configuration, extension points, guardrails, and dashboard usage, see the [mcp] section.

Integration with WildFly

  • For WildFly users, you need to add the following dependency to make the swagger-ui work:

   <dependency>
     <groupId>org.webjars</groupId>
     <artifactId>webjars-locator-jboss-vfs</artifactId>
     <version>0.1.0</version>
   </dependency>