{"id":50535018,"url":"https://github.com/Neo1228/spring-boot-starter-swagger-mcp","last_synced_at":"2026-06-19T21:00:52.034Z","repository":{"id":338587471,"uuid":"1158351651","full_name":"Neo1228/spring-boot-starter-swagger-mcp","owner":"Neo1228","description":"Turn SpringDoc OpenAPI into production-ready MCP tools for Spring Boot: discovery, validation, workflows, and guardrails.","archived":false,"fork":false,"pushed_at":"2026-05-02T18:21:45.000Z","size":280,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-02T19:07:19.281Z","etag":null,"topics":["api-gateway","java","java-17","java-25","llm-tools","mcp","model-context-protocol","openapi","spring-ai","spring-boot","spring-boot-starter","springdoc-openapi","swagger","workflow-orchestration"],"latest_commit_sha":null,"homepage":"https://github.com/Neo1228/spring-boot-starter-swagger-mcp#readme","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Neo1228.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-15T08:04:27.000Z","updated_at":"2026-05-02T18:21:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Neo1228/spring-boot-starter-swagger-mcp","commit_stats":null,"previous_names":["neo1228/spring-boot-starter-swagger-mcp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Neo1228/spring-boot-starter-swagger-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neo1228%2Fspring-boot-starter-swagger-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neo1228%2Fspring-boot-starter-swagger-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neo1228%2Fspring-boot-starter-swagger-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neo1228%2Fspring-boot-starter-swagger-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Neo1228","download_url":"https://codeload.github.com/Neo1228/spring-boot-starter-swagger-mcp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Neo1228%2Fspring-boot-starter-swagger-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34547787,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-gateway","java","java-17","java-25","llm-tools","mcp","model-context-protocol","openapi","spring-ai","spring-boot","spring-boot-starter","springdoc-openapi","swagger","workflow-orchestration"],"created_at":"2026-06-03T16:00:32.433Z","updated_at":"2026-06-19T21:00:52.028Z","avatar_url":"https://github.com/Neo1228.png","language":"Java","funding_links":[],"categories":["Code \u0026 Examples","📦 Other"],"sub_categories":["Model Context Protocol"],"readme":"# 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:\u003cversion\u003e` |\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]) \u003c--\u003e MCP[MCP Client / Claude Desktop]\n    MCP \u003c--\u003e Bridge[Swagger MCP Bridge /starter/]\n    Bridge --\u003e Catalog[Operation Catalog /groups + contracts/]\n    Bridge --\u003e Workflow[Workflow Orchestrator /plan + dry-run + execute/]\n    Bridge \u003c--\u003e Docs[SpringDoc OpenAPI /v3/api-docs]\n    Bridge \u003c--\u003e 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:\u003cversion\u003e\")\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\u003cproperties\u003e\n  \u003copenapi-mcp.version\u003e0.1.0-SNAPSHOT\u003c/openapi-mcp.version\u003e\n\u003c/properties\u003e\n\n\u003cdependencies\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n    \u003cartifactId\u003espring-boot-starter-web\u003c/artifactId\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eorg.springdoc\u003c/groupId\u003e\n    \u003cartifactId\u003espringdoc-openapi-starter-webmvc-api\u003c/artifactId\u003e\n    \u003cversion\u003e2.8.17\u003c/version\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eio.github.neo1228\u003c/groupId\u003e\n    \u003cartifactId\u003eopenapi-mcp-spring-boot-starter\u003c/artifactId\u003e\n    \u003cversion\u003e${openapi-mcp.version}\u003c/version\u003e\n  \u003c/dependency\u003e\n\u003c/dependencies\u003e\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\u003cString, Object\u003e 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 `\u003ctool-name-prefix\u003e\u003coperation-id\u003e` (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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNeo1228%2Fspring-boot-starter-swagger-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNeo1228%2Fspring-boot-starter-swagger-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNeo1228%2Fspring-boot-starter-swagger-mcp/lists"}