mcp-declarative-java-sdk
English · 简体中文
Annotation-driven MCP dev — No Spring, Zero Boilerplate, Pure Java.
Build MCP servers in Java with annotations instead of boilerplate.
Overview
This SDK is a lightweight, annotation-based framework that simplifies MCP server development in Java. Define, develop, and integrate your MCP Resources / Prompts / Tools with minimal code — no Spring Framework required.
Workflow: Add dependency → Configure
mcp-server.yml→ Annotate Resources / Tools / Prompts / Completions → Run withMcpApplication
📖 Documentation · 💡 Examples · 🐛 Report Issues
✨ Why This SDK?
Key Advantages
- 🚫 No Spring Framework Required - Pure Java, lightweight and fast
- ⚡ Instant MCP Server - Get your server running with just 1 line of code
- 🎉 Zero Boilerplate - No need to write low-level MCP SDK code
- 👏 No JSON Schema - Forget about complex and lengthy JSON definitions
- 🎯 Focus on Logic - Concentrate on your core business logic
- 🔌 Spring AI Compatible - Configuration file compatible with Spring AI Framework
- 📦 Type-Safe - Leverage Java's type system for compile-time safety
Comparison with Official MCP Java SDK
| Feature | Official MCP SDK | This SDK |
|---|---|---|
| Code Required | ~50-100 lines | ~5-10 lines |
| JSON Schema | Hand-coded JSON | No need to care |
| Type Safety | Limited | Full |
| Learning Curve | Steep | Gentle |
🎯 Quick Start
Prerequisites
- Java 17 or later (required by official MCP Java SDK)
5-Minutes Tutorial
Step 1: Add Dependency
Maven:
<dependency>
<groupId>io.github.thought2code</groupId>
<artifactId>mcp-annotated-java-sdk</artifactId>
<version>0.18.0</version>
</dependency>
Gradle:
implementation 'io.github.thought2code:mcp-annotated-java-sdk:0.18.0'
Step 2: Create Configuration File
Create mcp-server.yml in your src/main/resources:
enabled: true
mode: STDIO
name: my-first-mcp-server
version: 1.0.0
type: SYNC
instructions: You are a helpful AI assistant
request-timeout: 20000
capabilities:
resource: true
subscribe-resource: true
prompt: true
tool: true
completion: true
change-notification:
resource: true
prompt: true
tool: true
Step 3: Create Your MCP Server
@McpServerApplication
public class MyFirstMcpServer {
public static void main(String[] args) {
McpApplication.run(MyFirstMcpServer.class, args);
}
}
Step 4: Define MCP Resources (if needed)
public class MyResources {
@McpResource(uri = "system://info", description = "System information")
public Map<String, String> getSystemInfo() {
Map<String, String> info = new HashMap<>();
info.put("os", System.getProperty("os.name"));
info.put("java", System.getProperty("java.version"));
info.put("cores", String.valueOf(Runtime.getRuntime().availableProcessors()));
return info;
}
}
Step 5: Define MCP Tools
public class MyTools {
@McpTool(description = "Calculate the sum of two numbers")
public int add(
@McpToolParam(name = "a", description = "First number") int a,
@McpToolParam(name = "b", description = "Second number") int b
) {
return a + b;
}
}
Step 6: Define MCP Prompts (if needed)
public class MyPrompts {
@McpPrompt(description = "Generate code for a given task")
public String generateCode(
@McpPromptParam(name = "language", description = "Programming language") String language,
@McpPromptParam(name = "task", description = "Task description") String task
) {
return String.format("Write %s code to: %s", language, task);
}
}
Step 7: Run Your Server
# Compile your project
./mvnw clean package
Run MyFirstMcpServer from your IDE, or use java -cp ... with your compiled classes and dependencies on the classpath. Your own project needs an executable JAR setup (for example Spring Boot or the Maven Shade plugin) if you want java -jar with a single file.
That's it! Your MCP server is now ready to serve resources, tools, and prompts!
📚 Core Concepts
What is MCP?
The Model Context Protocol (MCP) is a standardized protocol for building servers that expose data and functionality to LLM applications. Think of it like a web API, but specifically designed for LLM interactions.
MCP Components
| Component | Purpose | Analogy |
|---|---|---|
| Resources | Expose data to LLM | GET endpoints |
| Tools | Execute actions | POST endpoints |
| Prompts | Reusable templates | Form templates |
Supported Server Modes
This SDK supports three MCP server modes:
| Mode | Description | Use Case |
|---|---|---|
| STDIO | Standard input/output communication | CLI tools, local development |
| SSE | Server-Sent Events (HTTP-based) | Deprecated since 0.16.0 (forRemoval); use STREAMABLE |
| STREAMABLE | HTTP streaming | Web applications, recommended for production |
🔧 Advanced Usage
Configuration File
Create mcp-server.yml in your classpath:
enabled: true
mode: STREAMABLE
name: my-mcp-server
version: 1.0.0
type: SYNC
instructions: You are a helpful AI assistant
request-timeout: 20000
capabilities:
resource: true
subscribe-resource: true
prompt: true
tool: true
completion: true
change-notification:
resource: true
prompt: true
tool: true
streamable:
mcp-endpoint: /mcp/message
disallow-delete: false
keep-alive-interval: 20000
port: 8080
Configuration Properties
| Property | Description | Default |
|---|---|---|
enabled |
Enable/disable MCP server | true |
mode |
Server mode: STDIO, SSE (deprecated), STREAMABLE |
STREAMABLE |
name |
Server name | mcp-server |
version |
Server version | 1.0.0 |
type |
Server type: SYNC, ASYNC |
SYNC |
instructions |
Instructions for the LLM client | Required (non-blank in YAML) |
request-timeout |
Request timeout in milliseconds | 20000 |
capabilities.resource |
Enable resource support | true |
capabilities.subscribe-resource |
Enable resource subscription | true |
capabilities.prompt |
Enable prompt support | true |
capabilities.tool |
Enable tool support | true |
capabilities.completion |
Enable completion support | true |
change-notification.resource |
Notify clients on resource change | true |
change-notification.prompt |
Notify clients on prompt change | true |
change-notification.tool |
Notify clients on tool change | true |
sse.message-endpoint |
SSE POST message path (deprecated, for removal since 0.16.0) | /mcp/message |
sse.endpoint |
SSE stream path (deprecated, for removal since 0.16.0) | /sse |
sse.base-url |
Public base URL for the SSE server (deprecated) | Required when mode: SSE |
sse.port |
HTTP port for SSE mode (deprecated, for removal since 0.16.0) | 8080 |
streamable.mcp-endpoint |
Streamable HTTP MCP path | /mcp/message |
streamable.disallow-delete |
Reject HTTP DELETE on session | false |
streamable.keep-alive-interval |
Keep-alive interval (ms) | 20000 |
streamable.port |
HTTP port for STREAMABLE mode | 8080 |
Profile-based Configuration
Set profile in the base file to load mcp-server-{profile}.yml from the classpath. Profile values are merged into the base configuration with Jackson deep merge; nested objects such as capabilities and streamable are merged field-by-field. The profile name always comes from the base file. After merge, transport settings that do not match the resolved mode are cleared (for example, streamable is removed when mode is STDIO).
You can use profiles for different environments:
# mcp-server.yml (base configuration)
enabled: true
mode: STREAMABLE
name: my-mcp-server
version: 1.0.0
profile: dev
# mcp-server-dev.yml (profile-specific configuration)
streamable:
port: 8080
Runtime model and stability
SYNC vs ASYNC (type)
The type setting selects which MCP Java SDK server API the framework uses. It does not turn your component methods into reactive code.
type |
What happens |
|---|---|
SYNC |
Handlers invoke your @McpTool / @McpPrompt / @McpResource methods on the request thread. |
ASYNC |
Handlers return Reactor Mono values for MCP SDK compatibility. The SDK wraps each call in Mono.fromCallable(...) — your method body is still a normal blocking Java invocation. |
ASYNC is not a non-blocking or Project Reactor programming model. You do not implement Mono/Flux in annotated methods. Long-running or CPU-heavy work still occupies a Reactor worker thread. Use SYNC unless your deployment specifically requires the async MCP server API. For high concurrency, keep handlers short and tune request-timeout.
Component instances and concurrency
The SDK creates one instance per component class (no-arg constructor) and reuses it for every MCP request to methods on that class. Concurrent calls share the same object.
- Prefer stateless component classes, or thread-safe mutable state only.
- Do not store per-request data in instance fields without proper synchronization.
- Delegate shared mutable state to thread-safe services when needed.
McpApplicationContext.from(...) currently uses this default singleton-per-class factory. Component classes must provide a public no-arg constructor. There is no built-in Spring/CDI wiring in the public API today.
McpApplication.run(mainClass, args) loads mcp-server.yml by default; pass a third argument to use another classpath config file name.
MCP Java SDK 2.x (milestone)
This project builds on the official MCP Java SDK 2.0.0-M3, a pre-release milestone. APIs may change before 2.0 GA — pin dependency versions and re-run tests when upgrading.
- STREAMABLE is the recommended HTTP transport for new projects.
- SSE (
ServerMode.SSE,McpSseServer,ServerSse,sse.*in YAML) is deprecated withforRemoval = truesince 0.16.0 and scheduled for removal in a future release. Existing deployments may still use it for compatibility; migrate to STREAMABLE (McpStreamableServer,streamable.*).
🏗️ Project Structure
A typical project structure:
your-mcp-project/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ ├── MyMcpServer.java # Main entry point
│ │ │ ├── components/
│ │ │ │ ├── MyResources.java # MCP Resources
│ │ │ │ ├── MyTools.java # MCP Tools
│ │ │ │ └── MyPrompts.java # MCP Prompts
│ │ │ └── service/
│ │ │ └── BusinessLogic.java # Your business logic
│ │ └── resources/
│ │ └── mcp-server.yml # MCP configuration
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── McpServerTest.java # Unit tests
🧪 Testing
Run the unit test suite (this project requires the Maven Wrapper — do not use a system mvn install):
./mvnw clean test
On Windows:
mvnw.cmd clean test
❓ FAQ
Q: Do I need Spring Framework?
A: No! This SDK is completely independent of Spring Framework. However, the configuration file format is compatible with Spring AI if you want to migrate.
Q: Can I use this in production?
A: The annotated layer is stable for development and testing, but it depends on the official MCP Java SDK 2.0.0-M3 (a milestone release). Pin versions, run your own integration tests, and expect possible SDK API changes before 2.0 GA before relying on it in production.
Q: What does type: ASYNC mean?
A: It selects the async MCP server API from the underlying SDK. Your @McpTool / @McpPrompt / @McpResource methods remain ordinary blocking Java code; the framework wraps them in Mono.fromCallable(...). Use SYNC unless you specifically need the async server API.
Q: Are component classes singletons?
A: Yes. The SDK creates one instance per component class and reuses it for all requests. Keep components stateless or thread-safe; do not keep per-request mutable state on the instance without synchronization.
Q: What Java version is required?
A: Java 17 or later is required, as this is a constraint of the underlying MCP Java SDK.
Q: What Maven version is required?
A: Just use the provided Maven wrapper script ./mvnw to build this project.
Q: How do I debug my MCP server?
A: You can use the MCP Inspector and set Java breakpoints to debug your MCP server.
Q: Which server mode should I use?
A:
- STDIO: For CLI tools and local development
- STREAMABLE: For web applications and production deployments (recommended)
- SSE: Deprecated since 0.16.0 (
forRemoval); use STREAMABLE andstreamable.*instead ofsse.*
🤝 Contributing
We welcome and appreciate contributions! Please follow these steps to contribute:
- Fork the repository
- Create a new branch for your feature or bug fix
- Add tests for your changes
- Update documentation if necessary
- Ensure all tests pass
- Submit a pull request with a clear description of your changes
Development Setup
# Clone the repository
git clone https://github.com/thought2code/mcp-annotated-java-sdk.git
cd mcp-annotated-java-sdk
# Build the project (Spotless formatting is checked at the validate phase)
./mvnw clean install
# Run tests
./mvnw clean test
📖 Documentation
📄 License
This project is licensed under the MIT License.
🙏 Acknowledgments
- MCP Java SDK - The underlying MCP implementation
- Model Context Protocol - The protocol specification
[!NOTE] This project is under active development. We appreciate your feedback and contributions!
