Back to MCP Servers

Spring Boot Starter Swagger

Turn your Spring Boot application into an MCP server instantly by reusing existing Swagger/OpenAPI documentation.

developer-toolsapi
By Neo1228
34Updated 1 week agoJavaApache-2.0

Installation

npx -y spring-boot-starter-swagger-mcp

Configuration

{
  "mcpServers": {
    "spring-boot-starter-swagger-mcp": {
      "command": "npx",
      "args": ["-y", "spring-boot-starter-swagger-mcp"]
    }
  }
}

How to use

  1. Run the installation command above (if needed)
  2. Open your Claude Code settings file (~/.claude/settings.json)
  3. Add the configuration to the mcpServers section
  4. Restart Claude Code to apply changes

Swagger MCP Bridge

CI License Java Spring Boot Awesome MCP Servers

Turn any SpringDoc-powered Spring Boot API into a production-ready MCP gateway.

Swagger MCP Bridge discovers your OpenAPI operations, publishes them as safe MCP tools, and adds a smart gateway layer for API discovery, validation, response shaping, and multi-step workflow orchestration.

Naming and Coordinates

This repository intentionally separates the public surfaces so each one reads naturally in its own ecosystem:

SurfaceName
Project / docsSwagger MCP Bridge
Maven dependencyio.github.neo1228:openapi-mcp-spring-boot-starter
Official MCP Registry serverio.github.Neo1228/swagger-mcp-bridge
Runnable example imageghcr.io/neo1228/swagger-mcp-bridge-example:<version>
Spring configuration prefixswagger.mcp.*

The project name keeps the established bridge branding, while the Maven artifact uses the neutral OpenAPI/Spring Boot starter coordinate expected by Java consumers. The registry server and GHCR image identify the packaged runnable example used by MCP directories.

Why Swagger MCP Bridge

Most MCP API bridges stop at a thin tool wrapper. Swagger MCP Bridge is designed as a runtime gateway: it exposes your existing Spring controllers to LLM clients while preserving contracts, guardrails, and operational visibility.

What You Get

  • Zero-boilerplate discovery of SpringDoc OpenAPI operations from your running Spring app
  • Automatic MCP tool registration for discovered API operations
  • Smart-context gateway tools: meta_get_api_capabilities, meta_validate_api_call, meta_discover_api_tools, meta_describe_api_tool, meta_list_api_groups, meta_plan_api_workflow, meta_invoke_api_workflow, meta_invoke_api_by_intent
  • API catalog and workflow layer for capability inspection, preflight validation, grouped exploration, dry-run planning, and sequential execution
  • Rich MCP input schemas generated from OpenAPI constraints: required fields, enums, numeric/string/object limits, examples, and deprecation hints
  • Response shaping with JSONPath projection and summarization controls
  • Execution guardrails: required argument validation, unresolved path-template protection, and safe _headers filtering
  • Structured MCP error responses with stable codes such as INVALID_ARGUMENT, SECURITY_DENIED, WORKFLOW_ERROR, and HTTP_DISPATCH_FAILED
  • Java 17 bytecode with CI coverage on Java 17, 21, and 25
  • Optional virtual-thread HTTP dispatch on Java 21+ runtimes, with automatic platform-thread fallback on Java 17
  • Production guardrails for dangerous operations: _confirm, blocked paths, role checks, audit logs, and structured client errors

Architecture

graph TD
    User([User / LLM Client]) <--> MCP[MCP Client / Claude Desktop]
    MCP <--> Bridge[Swagger MCP Bridge /starter/]
    Bridge --> Catalog[Operation Catalog /groups + contracts/]
    Bridge --> Workflow[Workflow Orchestrator /plan + dry-run + execute/]
    Bridge <--> Docs[SpringDoc OpenAPI /v3/api-docs]
    Bridge <--> API[Your Spring Controller /hello]

Quick Start

1. Create a Spring Boot app

Use:

  • Java 17+
  • Spring Boot 3.5.x
  • Spring Web

2. Add dependencies

Gradle (build.gradle.kts):

plugins {
    id("org.springframework.boot") version "3.5.14"
    id("io.spring.dependency-management") version "1.1.7"
    java
}

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.17")
    implementation("io.github.neo1228:openapi-mcp-spring-boot-starter:<version>")
}

The Maven artifact intentionally uses the neutral OpenAPI name rather than Swagger branding:

io.github.neo1228:openapi-mcp-spring-boot-starter

Maven (pom.xml):

<properties>
  <openapi-mcp.version>0.1.0-SNAPSHOT</openapi-mcp.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
    <version>2.8.17</version>
  </dependency>
  <dependency>
    <groupId>io.github.neo1228</groupId>
    <artifactId>openapi-mcp-spring-boot-starter</artifactId>
    <version>${openapi-mcp.version}</version>
  </dependency>
</dependencies>

Use a release version (for example 0.1.0) when consuming from a remote artifact repository.

3. Add one controller

import io.swagger.v3.oas.annotations.Operation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class HelloController {

    @Operation(operationId = "getHello", summary = "Get greeting message")
    @GetMapping("/hello")
    public Map<String, Object> hello(@RequestParam(defaultValue = "world") String name) {
        return Map.of("message", "Hello " + name);
    }
}

4. Add configuration (application.yml)

spring:
  ai:
    mcp:
      server:
        protocol: STREAMABLE_HTTP
        streamable-http:
          mcp-endpoint: /mcp

swagger:
  mcp:
    enabled: true
    api-docs-path: /v3/api-docs
    tool-name-prefix: api_

5. Run and verify

  1. Start app: ./gradlew bootRun or ./mvnw spring-boot:run
  2. Verify OpenAPI: http://localhost:8080/v3/api-docs
  3. Verify MCP endpoint: http://localhost:8080/mcp
  4. Connect from an MCP client

Generated tool names follow <tool-name-prefix><operation-id> (example: api_gethello).

MCP Client Workflow

This starter exposes direct API tools and a meta-tool layer so general MCP clients can work with large APIs without guessing tool names upfront:

  1. meta_get_api_capabilities returns API catalog stats, available gateway tools, orchestration features, safety policy, and response controls.
  2. meta_list_api_groups summarizes the exposed API catalog by OpenAPI tag/group.
  3. meta_discover_api_tools finds relevant operations for a natural-language request.
  4. meta_describe_api_tool returns the selected tool's method/path, parameters, required arguments, request body schema, risk flags, and full MCP input schema.
  5. meta_validate_api_call validates one generated API tool call without dispatching HTTP, including required arguments, risky-operation confirmation, and dispatch preview.
  6. meta_plan_api_workflow turns a workflow goal into a deterministic candidate step plan with contracts and risk flags.
  7. meta_invoke_api_workflow dry-runs or executes multiple generated API tools sequentially.
  8. meta_invoke_api_by_intent can select and invoke the best matching operation when the client already has enough arguments.

The configured tool-name-prefix is still applied, so the default generated names are api_meta_get_api_capabilities, api_meta_validate_api_call, api_meta_list_api_groups, api_meta_discover_api_tools, api_meta_describe_api_tool, api_meta_plan_api_workflow, api_meta_invoke_api_workflow, and api_meta_invoke_api_by_intent.

When a tool call is rejected, the text content remains human-readable and structuredContent.error gives clients a stable machine contract:

{
  "error": {
    "code": "INVALID_ARGUMENT",
    "message": "Missing required argument(s): path parameter: orderId",
    "status": 400,
    "retryable": false,
    "details": { "toolName": "api_getorder" }
  }
}

Recommended client loop:

  1. Call api_meta_get_api_capabilities once to learn the gateway features and safety policy.
  2. Use api_meta_discover_api_tools or api_meta_list_api_groups to find candidate operations.
  3. Use api_meta_describe_api_tool for exact argument schema.
  4. Use api_meta_validate_api_call before risky or generated calls.
  5. For multi-step work, call api_meta_plan_api_workflow, then api_meta_invoke_api_workflow with dryRun=true, then execute with dryRun=false only after validation is clean.

Workflow execution is intentionally safe by default:

  • meta_validate_api_call and meta_invoke_api_workflow dry-runs validate tool names, arguments, required fields, dispatch paths, and risk flags before dispatching HTTP.
  • A workflow step has { "id": "...", "toolName": "...", "arguments": { ... } }.
  • Later steps can read previous structured results with JSONPath interpolation: ${create:$.order.id}.
  • If the whole argument value is a template, the resolved raw value is passed through. If a template is embedded in a longer string, the value is stringified.
  • Recursive meta-tool orchestration is blocked; workflow steps can invoke generated API operation tools only.
  • Risky HTTP methods still require the configured _confirm token even inside a workflow.

Example validation payload:

{
  "toolName": "api_getorder",
  "arguments": {
    "orderId": "order-1"
  }
}

Example workflow payload:

{
  "dryRun": false,
  "steps": [
    {
      "id": "create",
      "toolName": "api_createorder",
      "arguments": {
        "body": { "id": "order-1", "item": "shoe" },
        "_confirm": "CONFIRM"
      }
    },
    {
      "id": "read",
      "toolName": "api_getorder",
      "arguments": {
        "orderId": "${create:$.order.id}"
      }
    }
  ]
}

For larger APIs, set swagger.mcp.smart-context.gateway-only=true to expose only this gateway/meta layer instead of registering every operation as a top-level MCP tool.

Local Development Install

If the artifact is not published to a remote registry yet:

  1. Build and publish to local Maven cache:
    • ./gradlew publishToMavenLocal
  2. In your consumer app:
    • add mavenLocal() repository
    • use version 0.1.0-SNAPSHOT (or your chosen local version)

Key Configuration

  • swagger.mcp.enabled: enable/disable bridge (default true)
  • swagger.mcp.api-docs-path: OpenAPI docs path (default /v3/api-docs)
  • swagger.mcp.tool-name-prefix: tool name prefix (default api_)
  • swagger.mcp.smart-context.gateway-only: expose only meta tools
  • swagger.mcp.execution.virtual-threads-enabled: run outbound API dispatch through virtual threads when the current runtime supports them (default true; safely falls back on Java 17)
  • swagger.mcp.execution.allowed-argument-headers: optional allowlist for dynamic _headers passed by MCP clients
  • swagger.mcp.execution.blocked-argument-headers: denylist for dynamic _headers; defaults block hop-by-hop/transport-sensitive headers like Host, Content-Length, Connection, and Transfer-Encoding
  • swagger.mcp.security.require-confirmation-for-risky-operations: require _confirm token for risky methods

For risky HTTP methods (POST, PUT, PATCH, DELETE), default policy requires _confirm=CONFIRM. The adapter also validates missing required path/query/header/body arguments before dispatching HTTP, so MCP clients get a clear tool error instead of a malformed API call.

Compatibility Matrix

StarterJavaSpring Bootspringdoc-openapiSpring AI BOM
0.1.

View source on GitHub