{
  "markdown": "# Swagger MCP Bridge\n\n[![CI](https://github.com/Neo1228/spring-boot-starter-swagger-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Neo1228/spring-boot-starter-swagger-mcp/actions/workflows/ci.yml)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Java](https://img.shields.io/badge/Java-17%2B-orange.svg)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)\n[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.5.x-brightgreen.svg)](https://spring.io/projects/spring-boot)\n[![Awesome MCP Servers](https://img.shields.io/badge/awesome--mcp--servers-listed-blueviolet.svg)](https://github.com/punkpeye/awesome-mcp-servers/pull/2059)\n\n**Turn any SpringDoc-powered Spring Boot API into a production-ready MCP gateway.**\n\nSwagger 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.\n\n\n## Naming and Coordinates\n\nThis repository intentionally separates the public surfaces so each one reads naturally in its own ecosystem:\n\n| Surface | Name |\n|---|---|\n| Project / docs | Swagger MCP Bridge |\n| Maven dependency | `io.github.neo1228:openapi-mcp-spring-boot-starter` |\n| Official MCP Registry server | `io.github.Neo1228/swagger-mcp-bridge` |\n| Runnable example image | `ghcr.io/neo1228/swagger-mcp-bridge-example:<version>` |\n| Spring configuration prefix | `swagger.mcp.*` |\n\nThe 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.\n\n## Why Swagger MCP Bridge\n\nMost 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.\n\n## What You Get\n\n- Zero-boilerplate discovery of SpringDoc OpenAPI operations from your running Spring app\n- Automatic MCP tool registration for discovered API operations\n- 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`\n- API catalog and workflow layer for capability inspection, preflight validation, grouped exploration, dry-run planning, and sequential execution\n- Rich MCP input schemas generated from OpenAPI constraints: required fields, enums, numeric/string/object limits, examples, and deprecation hints\n- Response shaping with JSONPath projection and summarization controls\n- Execution guardrails: required argument validation, unresolved path-template protection, and safe `_headers` filtering\n- Structured MCP error responses with stable codes such as `INVALID_ARGUMENT`, `SECURITY_DENIED`, `WORKFLOW_ERROR`, and `HTTP_DISPATCH_FAILED`\n- Java 17 bytecode with CI coverage on Java 17, 21, and 25\n- Optional virtual-thread HTTP dispatch on Java 21+ runtimes, with automatic platform-thread fallback on Java 17\n- Production guardrails for dangerous operations: `_confirm`, blocked paths, role checks, audit logs, and structured client errors\n\n## Architecture\n\n```mermaid\ngraph TD\n    User([User / LLM Client]) <--> MCP[MCP Client / Claude Desktop]\n    MCP <--> Bridge[Swagger MCP Bridge /starter/]\n    Bridge --> Catalog[Operation Catalog /groups + contracts/]\n    Bridge --> Workflow[Workflow Orchestrator /plan + dry-run + execute/]\n    Bridge <--> Docs[SpringDoc OpenAPI /v3/api-docs]\n    Bridge <--> API[Your Spring Controller /hello]\n```\n\n## Quick Start\n\n### 1. Create a Spring Boot app\n\nUse:\n\n- Java 17+\n- Spring Boot 3.5.x\n- Spring Web\n\n### 2. Add dependencies\n\nGradle (`build.gradle.kts`):\n\n```kotlin\nplugins {\n    id(\"org.springframework.boot\") version \"3.5.14\"\n    id(\"io.spring.dependency-management\") version \"1.1.7\"\n    java\n}\n\njava {\n    sourceCompatibility = JavaVersion.VERSION_17\n}\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"org.springframework.boot:spring-boot-starter-web\")\n    implementation(\"org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.17\")\n    implementation(\"io.github.neo1228:openapi-mcp-spring-boot-starter:<version>\")\n}\n```\n\nThe Maven artifact intentionally uses the neutral OpenAPI name rather than Swagger branding:\n\n```text\nio.github.neo1228:openapi-mcp-spring-boot-starter\n```\n\nMaven (`pom.xml`):\n\n```xml\n<properties>\n  <openapi-mcp.version>0.1.0-SNAPSHOT</openapi-mcp.version>\n</properties>\n\n<dependencies>\n  <dependency>\n    <groupId>org.springframework.boot</groupId>\n    <artifactId>spring-boot-starter-web</artifactId>\n  </dependency>\n  <dependency>\n    <groupId>org.springdoc</groupId>\n    <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>\n    <version>2.8.17</version>\n  </dependency>\n  <dependency>\n    <groupId>io.github.neo1228</groupId>\n    <artifactId>openapi-mcp-spring-boot-starter</artifactId>\n    <version>${openapi-mcp.version}</version>\n  </dependency>\n</dependencies>\n```\n\nUse a release version (for example `0.1.0`) when consuming from a remote artifact repository.\n\n### 3. Add one controller\n\n```java\nimport io.swagger.v3.oas.annotations.Operation;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Map;\n\n@RestController\npublic class HelloController {\n\n    @Operation(operationId = \"getHello\", summary = \"Get greeting message\")\n    @GetMapping(\"/hello\")\n    public Map<String, Object> hello(@RequestParam(defaultValue = \"world\") String name) {\n        return Map.of(\"message\", \"Hello \" + name);\n    }\n}\n```\n\n### 4. Add configuration (`application.yml`)\n\n```yaml\nspring:\n  ai:\n    mcp:\n      server:\n        protocol: STREAMABLE_HTTP\n        streamable-http:\n          mcp-endpoint: /mcp\n\nswagger:\n  mcp:\n    enabled: true\n    api-docs-path: /v3/api-docs\n    tool-name-prefix: api_\n```\n\n### 5. Run and verify\n\n1. Start app: `./gradlew bootRun` or `./mvnw spring-boot:run`\n2. Verify OpenAPI: `http://localhost:8080/v3/api-docs`\n3. Verify MCP endpoint: `http://localhost:8080/mcp`\n4. Connect from an MCP client\n\nGenerated tool names follow `<tool-name-prefix><operation-id>` (example: `api_gethello`).\n\n\n## MCP Client Workflow\n\nThis starter exposes direct API tools and a meta-tool layer so general MCP clients can work with large APIs without guessing tool names upfront:\n\n1. `meta_get_api_capabilities` returns API catalog stats, available gateway tools, orchestration features, safety policy, and response controls.\n2. `meta_list_api_groups` summarizes the exposed API catalog by OpenAPI tag/group.\n3. `meta_discover_api_tools` finds relevant operations for a natural-language request.\n4. `meta_describe_api_tool` returns the selected tool's method/path, parameters, required arguments, request body schema, risk flags, and full MCP input schema.\n5. `meta_validate_api_call` validates one generated API tool call without dispatching HTTP, including required arguments, risky-operation confirmation, and dispatch preview.\n6. `meta_plan_api_workflow` turns a workflow goal into a deterministic candidate step plan with contracts and risk flags.\n7. `meta_invoke_api_workflow` dry-runs or executes multiple generated API tools sequentially.\n8. `meta_invoke_api_by_intent` can select and invoke the best matching operation when the client already has enough arguments.\n\nThe 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`.\n\nWhen a tool call is rejected, the text content remains human-readable and `structuredContent.error` gives clients a stable machine contract:\n\n```json\n{\n  \"error\": {\n    \"code\": \"INVALID_ARGUMENT\",\n    \"message\": \"Missing required argument(s): path parameter: orderId\",\n    \"status\": 400,\n    \"retryable\": false,\n    \"details\": { \"toolName\": \"api_getorder\" }\n  }\n}\n```\n\nRecommended client loop:\n\n1. Call `api_meta_get_api_capabilities` once to learn the gateway features and safety policy.\n2. Use `api_meta_discover_api_tools` or `api_meta_list_api_groups` to find candidate operations.\n3. Use `api_meta_describe_api_tool` for exact argument schema.\n4. Use `api_meta_validate_api_call` before risky or generated calls.\n5. 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.\n\nWorkflow execution is intentionally safe by default:\n\n- `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.\n- A workflow step has `{ \"id\": \"...\", \"toolName\": \"...\", \"arguments\": { ... } }`.\n- Later steps can read previous structured results with JSONPath interpolation: `${create:$.order.id}`.\n- 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.\n- Recursive meta-tool orchestration is blocked; workflow steps can invoke generated API operation tools only.\n- Risky HTTP methods still require the configured `_confirm` token even inside a workflow.\n\nExample validation payload:\n\n```json\n{\n  \"toolName\": \"api_getorder\",\n  \"arguments\": {\n    \"orderId\": \"order-1\"\n  }\n}\n```\n\nExample workflow payload:\n\n```json\n{\n  \"dryRun\": false,\n  \"steps\": [\n    {\n      \"id\": \"create\",\n      \"toolName\": \"api_createorder\",\n      \"arguments\": {\n        \"body\": { \"id\": \"order-1\", \"item\": \"shoe\" },\n        \"_confirm\": \"CONFIRM\"\n      }\n    },\n    {\n      \"id\": \"read\",\n      \"toolName\": \"api_getorder\",\n      \"arguments\": {\n        \"orderId\": \"${create:$.order.id}\"\n      }\n    }\n  ]\n}\n```\n\nFor 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.\n\n## Local Development Install\n\nIf the artifact is not published to a remote registry yet:\n\n1. Build and publish to local Maven cache:\n   - `./gradlew publishToMavenLocal`\n2. In your consumer app:\n   - add `mavenLocal()` repository\n   - use version `0.1.0-SNAPSHOT` (or your chosen local version)\n\n## Key Configuration\n\n- `swagger.mcp.enabled`: enable/disable bridge (default `true`)\n- `swagger.mcp.api-docs-path`: OpenAPI docs path (default `/v3/api-docs`)\n- `swagger.mcp.tool-name-prefix`: tool name prefix (default `api_`)\n- `swagger.mcp.smart-context.gateway-only`: expose only meta tools\n- `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)\n- `swagger.mcp.execution.allowed-argument-headers`: optional allowlist for dynamic `_headers` passed by MCP clients\n- `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`\n- `swagger.mcp.security.require-confirmation-for-risky-operations`: require `_confirm` token for risky methods\n\nFor 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.\n\n## Compatibility Matrix\n\n| Starter | Java | Spring Boot | springdoc-openapi | Spring AI BOM |\n|---|---|---|---|---|\n| 0.1.x | 17, 21, 25 tested; Java 17 bytecode | 3.5.x | 2.8.17 | 1.1.5 |\n\nSpring Boot 4.x is intentionally not supported in the 0.1.x line. Stay on Spring Boot 3.5.x with springdoc-openapi 2.8.x unless this repository cuts a new major/minor compatibility line. The build uses `--release 17`, so the artifact remains consumable on Java 17 while CI verifies newer runtimes including Java 25.\n\n## Example Consumer Project\n\nSee `examples/minimal-webmvc-gradle` for a minimal Spring Boot app using Swagger MCP Bridge.\n\nThe example can also be built as a runnable MCP server image for registry and marketplace submissions:\n\n```bash\ndocker build \\\n  -f examples/minimal-webmvc-gradle/Dockerfile \\\n  -t ghcr.io/neo1228/swagger-mcp-bridge-example:local \\\n  .\n\ndocker run --rm -p 8080:8080 ghcr.io/neo1228/swagger-mcp-bridge-example:local\n```\n\nManual smoke checks after startup:\n\n- OpenAPI: `http://localhost:8080/v3/api-docs`\n- sample API: `http://localhost:8080/hello?name=Bridge`\n- MCP Streamable HTTP endpoint: `http://localhost:8080/mcp`\n- Smithery/server-card metadata: `http://localhost:8080/.well-known/mcp/server-card.json`\n- MCP Registry server metadata: `http://localhost:8080/.well-known/mcp/server.json`\n\n## Agent / Marketplace Install Guide\n\n- Agent install instructions: `llms-install.md`\n- Marketplace readiness guide: `docs/marketplace-readiness.md`\n- Marketplace logo: `docs/assets/swagger-mcp-bridge-logo.png`\n\n## Registry And Release Readiness\n\n- Maven Central release bundle workflow: `.github/workflows/release-central.yml`\n- GHCR example-server image workflow: `.github/workflows/publish-example-server.yml`\n- MCP Registry metadata: `registry/server.json`\n- Static discovery metadata: `examples/minimal-webmvc-gradle/src/main/resources/static/.well-known/mcp/`\n- Metadata verification script: `scripts/verify-marketplace-metadata.sh`\n- Central bundle helper: `scripts/build-central-bundle.sh`\n\nThe official MCP Registry accepts Docker/OCI metadata, so the published example image carries the required `io.modelcontextprotocol.server.name=io.github.Neo1228/swagger-mcp-bridge` label and uses `registry/server.json` as the submission source. The starter artifact remains a normal Maven dependency with coordinates `io.github.neo1228:openapi-mcp-spring-boot-starter`. Smithery URL publishing is compatible once the example server is hosted at a public HTTPS `/mcp` endpoint; until then the repository provides the required static server-card and local/Uplink validation path.\n\n## Release And Versioning\n\n- Release process: `RELEASING.md`\n- Versioning policy: `VERSIONING.md`\n- Changelog: `CHANGELOG.md`\n\n## Development\n\n- Run tests: `./gradlew test`\n- Contribution guide: `CONTRIBUTING.md`\n- Security reporting: `SECURITY.md`\n\n## License\n\nApache License 2.0 (`LICENSE`)\n",
  "bytes": 14774,
  "sha": "6b0aaa5465dab5ad4d17537aae52cdf46267677ce936145754399c14268ba241",
  "repo_slug": "neo1228/spring-boot-starter-swagger-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_neo1228_swagger_mcp_bridge_640a098f/readme"
}