Turn your existing Spring Boot REST controllers into MCP (Model Context Protocol) tools β no rewrites, no @Tool everywhere.
<dependency>
<groupId>com.ai.plug</groupId>
<artifactId>server2mcp-starter-webmvc</artifactId>
<version>1.1.4-SNAPSHOT</version>
</dependency>English Β· δΈζ Β· Docs Β· Integration Matrix
Most MCP integrations force you to:
- Add
@Tool/@McpToolto every method - Duplicate business logic into a parallel "MCP" code path
- Maintain separate tool descriptions
api2mcp4j scans your existing @RestController beans and exposes their methods as MCP tools β zero changes to business code. Like MyBatis-Plus enhances MyBatis, api2mcp4j enhances Spring AI MCP.
// Your existing controller β unchanged
@RestController
public class OrderController {
@GetMapping("/orders/{id}")
public Order getOrder(@PathVariable Long id) { ... }
}
// Becomes an MCP tool: orders_get_order
// With auto-generated description from Swagger / Javadoc / Spring MVC / Jackson / Spring AI| π― Non-intrusive | interface scope auto-registers all controllers; no @Tool annotation needed |
| π 5-parser chain | Swagger v3 / Swagger v2 / Javadoc / Spring MVC / Jackson / Spring AI β best description wins |
| π οΈ Full MCP coverage | Tools / Resources / Prompts / Completions / Elicitation / Sampling / Roots |
| π Protocol 2026-07-28 | Wire schema + JSON-RPC routing + SSE long-poll + MRTR + OTel traceparent β 100% |
| π Custom parsers | Implement AbstractDesParser / AbstractParamParser, plug into the chain |
| π§ͺ TDD discipline | JUnit5, double commit [RED] then [GREEN], 600 tests all green |
| π Quick start | mvn spring-boot:run β MCP endpoint ready |
git clone https://github.com/TheEterna/api2mcp4j.git
cd api2mcp4j
mvn clean install -DskipTests<dependency>
<groupId>com.ai.plug</groupId>
<artifactId>server2mcp-starter-webmvc</artifactId>
<version>1.1.4-SNAPSHOT</version>
</dependency>plugin:
mcp:
enabled: true
scope: interface # 'interface' = auto-register all controllers; 'custom' = @ToolScan only
parser:
des: SWAGGER3, JAVADOC, TOOL, JACKSON, SWAGGER2
param: MCPTOOL, JAVADOC, TOOL, SpringMVC, JACKSON, SWAGGER2, SWAGGER3mvn spring-boot:runYour MCP server is live on http://localhost:8080/mcp/jsonrpc (and HTTP fallbacks on /mcp/discover, /mcp/tasks, /mcp/sse).
api2mcp4j is the first Java MCP framework to ship full 2026-07-28 support, even though Java MCP SDK 2.0 only implements the 2025-11-25 wire. We bypassed SDK limitations with a custom JSON-RPC router, SSE controller, and wire schema β all without breaking SDK upgrade compatibility (controllers stay as fallbacks when SDK β₯ 3.0.0 lands).
| RPC | JSON-RPC endpoint | SSE long-poll | Source |
|---|---|---|---|
server/discover |
β
POST /mcp/jsonrpc |
β | DiscoverEndpoint |
tasks/create |
β | β | TaskStore |
tasks/get / list / cancel |
β | β | TasksEndpoint |
tasks/augmented-prompt |
β | β | AugmentedPromptEndpoint |
subscriptions/listen |
β (poll) | β
GET /mcp/sse + Last-Event-ID + 15s heartbeat |
SseNotificationsController |
input_required/respond (MRTR) |
β envelope | β | MrtrToolCallbackWrapper |
| 2026-07-28 field | Status | Where |
|---|---|---|
tools.listChanged / resources.listChanged / prompts.listChanged |
β SDK native | WireSchemaExporter.syncAll() |
tools.subscription / completions.listChanged (new in 2026-07-28) |
β Custom wire | WireServerCapabilities |
experimental.io.modelcontextprotocol/tasks (new) |
β Custom wire | Same |
_meta.resultType / ttlMs / cacheScope / cacheWrapperKey |
β Auto-injected via meta map | @McpTool(...) + McpCallToolResultConverter |
_meta.taskHandle / inputRequests / requestState |
β Auto-recognized | InputRequiredResult / TaskHandle return values |
_meta.traceparent / tracestate / baggage (W3C SEP-414) |
β Auto-minted in JSON-RPC | MetaUtils |
| MRTR state machine (cross-round merge + 8-round guard) | β | MrtrDriver |
outputSchema |
β SDK field | McpSchema.Tool.builder().outputSchema() |
| Capabilities health / diff / wire validation | β | CapabilitiesHealth + SnapshotCompareTool + WireSchemaValidator |
The demo app boots with H2 in-memory DB (zero external dependencies) and validates every 2026-07-28 feature against a real HTTP/SSE wire:
cd server2mcp-test && mvn spring-boot:run # starts on :8888 (H2 in-memory)
# In another shell:
bash scripts/verify-protocol-2026-07-28.sh http://localhost:8888== 0. liveness == β actuator reachable
== 1. server/discover (JSON-RPC) == βΓ7 (jsonrpc=2.0, preferredVersion=2026-07-28,
tools.listChanged, tools.subscription,
completions.listChanged, experimental.tasks,
_meta.traceparent)
== 2. tasks/* (JSON-RPC) == βΓ5 (create, get, list, cancel full lifecycle)
== 3. tasks/augmented-prompt == βΓ1
== 4. subscriptions/listen == βΓ3 (HTTP poll + text/event-stream + connected)
== 5. input_required/respond == βΓ2 (accepted + state echo)
== 6. HTTP legacy endpoints == βΓ2 (/mcp/discover + /mcp/notifications)
== summary == passed: 21 / failed: 0
ALL ASSERTIONS PASSED β protocol 2026-07-28 wire verified
| Layer | Count | Status |
|---|---|---|
Unit tests (server2mcp-core) |
575 | β all green |
Integration tests (server2mcp-starter-webmvc) |
22 | β all green |
Demo tests (server2mcp-test) |
3 | β all green |
| End-to-end curl verification | 21/21 | β |
| Total | 600+ tests, 21/21 e2e | β |
Test philosophy: TDD double-commit β [RED] test first, then [GREEN] implementation. See docs/specs/TEST_SPEC.md.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Spring Boot Application β
β β
β ββββ Your existing code (unchanged) ββββ β
β β @RestController β β
β β @Service β β
β β @Component β β
β ββββββββββββββββββ¬ββββββββββββββββββββββ β
β β β
β ββββββββββββββββββΌββββββββββββββββββββββ β
β β api2mcp4j framework β β
β β β β
β β Scanner βββ Parser chain βββ Provider β
β β β β β β
β β Spring MVC 5 parsers SyncMcpToolMethodCallback β
β β discovery (Swagger2/3, (template method) β
β β Javadoc, β
β β Jackson, β
β β Spring AI) β
β β β β
β β ββ 2026-07-28 layer (new) ββ β
β β β’ JsonRpcRouter + JsonRpcRoutes β
β β β’ WireServerCapabilities + JsonExporter β
β β β’ SseNotificationsController β
β β β’ MrtrDriver + MrtrSessionStore β
β β β’ MrtrToolCallbackWrapper β
β β β’ MetaUtils (W3C traceparent mint) β
β ββββββββββββββββββ¬ββββββββββββββββββββββ β
β β β
β ββββββββββββββββββΌββββββββββββββββββββββ β
β β Spring AI MCP SDK 2.0 β β
β β (McpSyncServer / McpAsyncServer) β β
β ββββββββββββββββββ¬ββββββββββββββββββββββ β
ββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββ
β wire: JSON-RPC 2.0 + SSE
βΌ
ββββββββββββββββββββββ
β MCP Clients β
β β’ Claude Desktop β
β β’ Cursor / Cline β
β β’ Your BFF / Agent β
ββββββββββββββββββββββ
api2mcp4j/
βββ server2mcp-common # Constants & utilities
βββ server2mcp-core # Core engine: annotations, scanners, callbacks, providers
β βββ com.ai.plug.core.annotation.* # @McpTool, @McpResource, @McpPrompt, @McpArg
β βββ com.ai.plug.core.parser.* # 5-parser chain (des + param)
β βββ com.ai.plug.core.callback.* # Sync + Async template methods
β βββ com.ai.plug.core.spec.* # 2026-07-28 wire layer
β βββ com.ai.plug.core.provider.* # Spring AI bridge
βββ server2mcp-autoconfigure # Spring Boot auto-configuration
βββ server2mcp-spring-boot-starters/
β βββ server2mcp-starter-webmvc # β
Full endpoint wiring (JSON-RPC + SSE + HTTP)
β βββ server2mcp-starter-webflux # β οΈ Framework core only (no endpoint wiring yet)
βββ server2mcp-test # β
Demo app + 21/21 e2e verification
| β Use it for | β Don't use it for |
|---|---|
| Exposing internal REST APIs to AI agents quickly | Greenfield MCP-first projects (use Spring AI MCP directly) |
| Wrapping legacy controllers as MCP tools | Real-time streaming / SSE-only UIs |
| Multi-agent systems sharing tool definitions | Apps that don't already use Spring Boot |
| Prototyping AI features on production services | Tiny prototypes (overhead not worth it) |
| Feature | api2mcp4j | Spring AI MCP Official | Manual @Tool everywhere |
|---|---|---|---|
| Code changes required | Minimal (config only) | MediumβHigh | High |
Auto-discover from @RestController |
β | β | β |
| 5-parser chain (Swagger + Javadoc + β¦) | β | Limited | Manual |
| Non-intrusive | β β β β β | β β β | β β |
| Protocol 2026-07-28 (RPC + wire) | β 100% | π‘ partial | βͺ |
| MRTR multi-round | β with decorator | βͺ | βͺ |
| SSE long-poll + Last-Event-ID | β built-in | π‘ via SDK | β |
| W3C traceparent (SEP-414) | β auto-minted | β | β |
| Best for existing projects | β | New apps | Tiny demos |
- π Full docs site β https://theeterna.github.io/server2mcp-docs/
- π Protocol 2026-07-28 integration matrix β docs/mcp-2026-07-28-INTEGRATION-MATRIX.md
- ποΈ Architecture β docs/reference/architecture.md
- π§© Extension points (custom parsers / filters / context) β docs/reference/extension-points.md
- πΆ Onboarding (3-step) β docs/reference/onboarding.md
- π Specs (registration / file header / test / work log) β docs/specs/
- βοΈ Global rules β docs/rules/
- π Work logs (audit trail) β docs/logs/
Issues, PRs, and β are very welcome.
This is a young project β your feedback shapes its future.
Before submitting a PR, please read:
- docs/specs/REGISTRATION_DISCIPLINE_SPEC.md β the 6-dimension Rubric for new MCP entities
- docs/rules/global/destructive-deletion.md β multi-source verification before deleting public APIs
- docs/rules/global/work-log.md β reportable outputs land in
docs/logs/
- Protocol 2026-07-28 wire & JSON-RPC routing (2026-08-03)
- MRTR multi-round state machine + 8-round guard
- SSE long-poll with Last-Event-ID resume
- W3C traceparent auto-mint
- WebFlux starter endpoint wiring (parity with WebMVC)
- Publish to Maven Central
- OTel SDK real instrumentation (currently wire-format only)
- Multi-tenant isolation (
@McpTool(tenant = "...")) - SDK β₯ 3.0.0 native router migration (tracked by
scripts/trigger-phase3.sh)
Built with care by Han Β· Apache 2.0 Β· 100% protocol 2026-07-28 compatible