docs: improve Java SDK documentation and examples (#145)

- Fix typos and update links in quickstart guides
- Update artifact names and configuration properties
- Add detailed configuration examples and advanced features
- Enhance Java SDK client/server documentation
- Update architecture diagrams and descriptions
- Improve code examples with better comments
- Update Spring Boot version requirements

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
Christian Tzolov 2025-02-14 16:23:20 +01:00 • committed by GitHub
commit e393ebc304
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 188 additions and 135 deletions

View file

@ -404,12 +404,12 @@ If you see:
<Tab title="Java">
<Note>
This is a quickstart demo based on Spring AI MCP auto-configuraiton and boot starters.
To learn how to create sync and async McpClients programatically consult the [Java SDK Client guid](TODO: add URL)
This is a quickstart demo based on Spring AI MCP auto-configuration and boot starters.
To learn how to create sync and async MCP Clients manually, consult the [Java SDK Client](/sdk/java/mcp-client) documentation
</Note>
This example demonstrates how to build an interactive chatbot that combines Spring AI's Model Context Protocol (MCP) with the [Brave Search MCP Server](https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search). The application creates a conversational interface powered by Anthropic's Claude AI model that can perform internet searches through Brave Search, enabling natural language interactions with real-time web data.
[You can find the complete code for this tutorial here.](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/brave-chatbot)
[You can find the complete code for this tutorial here.](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/web-search/brave-chatbot)
## System Requirements
@ -447,9 +447,9 @@ Before starting, ensure your system meets these requirements:
```
5. Run the application using Maven:
```bash
./mvnw spring-boot:run
```
```bash
./mvnw spring-boot:run
```
<Warning>
Make sure you keep your `ANTHROPIC_API_KEY` and `BRAVE_API_KEY` keys secure!
@ -466,7 +466,7 @@ The application integrates Spring AI with the Brave Search MCP server through se
```xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
@ -474,16 +474,27 @@ The application integrates Spring AI with the Brave Search MCP server through se
</dependency>
```
2. Application properties (application.properties):
```properties
spring.ai.mcp.client.stdio.enabled=true
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
2. Application properties (application.yml):
```yml
spring:
ai:
mcp:
client:
enabled: true
name: brave-search-client
version: 1.0.0
type: SYNC
request-timeout: 20s
stdio:
root-change-notification: true
servers-configuration: classpath:/mcp-servers-config.json
anthropic:
api-key: ${ANTHROPIC_API_KEY}
```
This acivates the `spring-ai-mcp-spring-boot-starter` to create one or more `McpClient`s based on the provided server configuration.
This activates the `spring-ai-mcp-client-spring-boot-starter` to create one or more `McpClient`s based on the provided server configuration.
3. MCP Server Configuration (mcp-servers-config.json):
3. MCP Server Configuration (`mcp-servers-config.json`):
```json
{
"mcpServers": {
@ -513,6 +524,53 @@ var chatClient = chatClientBuilder
.build();
```
Key features:
- Uses Claude AI model for natural language understanding
- Integrates Brave Search through MCP for real-time web search capabilities
- Maintains conversation memory using InMemoryChatMemory
- Runs as an interactive command-line application
### Build and run
```bash
./mvnw clean install
java -jar ./target/ai-mcp-brave-chatbot-0.0.1-SNAPSHOT.jar
```
or
```bash
./mvnw spring-boot:run
```
The application will start an interactive chat session where you can ask questions. The chatbot will use Brave Search when it needs to find information from the internet to answer your queries.
The chatbot can:
- Answer questions using its built-in knowledge
- Perform web searches when needed using Brave Search
- Remember context from previous messages in the conversation
- Combine information from multiple sources to provide comprehensive answers
### Advanced Configuration
The MCP client supports additional configuration options:
- Client customization through `McpSyncClientCustomizer` or `McpAsyncClientCustomizer`
- Multiple clients with multiple transport types: `STDIO` and `SSE` (Server-Sent Events)
- Integration with Spring AI's tool execution framework
- Automatic client initialization and lifecycle management
For WebFlux-based applications, you can use the WebFlux starter instead:
```xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId>
</dependency>
```
This provides similar functionality but uses a WebFlux-based SSE transport implementation, recommended for production deployments.
</Tab>
</Tabs>

View file

@ -742,17 +742,26 @@ Save the file, and restart **Claude for Desktop**.
</Tab>
<Tab title='Java'>
<Note>
This is a quickstart demo based on Spring AI MCP auto-configuraiton and boot starters.
To learn how to create sync and async MCP Servers, manually, consult the [Java SDK Server](/sdk/java/mcp-server) documentation.
</Note>
Let's get started with building our weather server!
[You can find the complete code for what we'll be building here.](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/mcp-weather-server-quickstart)
[You can find the complete code for what we'll be building here.](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/weather/starter-stdio-server)
For more information, see the [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html) reference documentation.
For manual MCP Server implementation, refer to the [MCP Server Java SDK documentation](/sdk/java/mcp-server).
### System requirements
- Java 17 or higher installed.
- [Spring Boot 3.4](https://docs.spring.io/spring-boot/installing.html) or higher
- [Spring Boot 3.3.x](https://docs.spring.io/spring-boot/installing.html) or higher
### Set up your environment
Use the [Spring Initizer](https://start.spring.io/) to bootstrat a the [application skeleton](https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.4.2&packaging=jar&jvmVersion=17&groupId=com.example.mcp.server&artifactId=weather&name=weather&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.mcp.server.weather&dependencies=spring-ai-anthropic,webflux).
Use the [Spring Initizer](https://start.spring.io/) to bootstrat the project.
You will need to add the following dependencies:
@ -762,27 +771,21 @@ You will need to add the following dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
```
</Tab>
<Tab title="Gradle">
```groovy
dependencies {
implementation platform("org.springframework.ai:spring-ai-mcp-spring-boot-starter")
implementation platform("org.springframework:spring-web")
implementation platform("org.springframework.boot:spring-boot-starter")
implementation platform("org.springframework.ai:spring-ai-mcp-server-spring-boot-starter")
implementation platform("org.springframework:spring-web")
}
```
</Tab>
@ -795,7 +798,6 @@ Then configure your application by setting the applicaiton properties:
```bash application.properties
spring.main.bannerMode=off
logging.pattern.console=
spring.ai.mcp.server.enabled=true
```
```yaml application.yml
@ -805,20 +807,18 @@ logging:
spring:
main:
banner-mode: off
ai:
mcp:
server:
enabled: true
```
</CodeGroup>
The [Server Configuration Properties](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html#_configuration_properties) documents all available properties.
Now let's dive into building your server.
## Building your server
### Weather Service
Let's implement a weather service that uses a REST client to query the data from the National Weather Service API:
Let's implement a [WeatheService.java](https://github.com/spring-projects/spring-ai-examples/blob/main/model-context-protocol/weather/starter-stdio-server/src/main/java/org/springframework/ai/mcp/sample/server/WeatherService.java) that uses a REST client to query the data from the National Weather Service API:
```java
@Service
@ -834,73 +834,39 @@ public class WeatherService {
.build();
}
public record Points(Props properties) {
public record Props(String forecast) { }
}
@Tool(description = "Get weather forecast for a specific latitude/longitude")
public String getWeatherForecastByLocation(
double latitude, // Latitude coordinate
double longitude // Longitude coordinate
) {
// Returns detailed forecast including:
// - Temperature and unit
// - Wind speed and direction
// - Detailed forecast description
}
@Tool(description = "Get weather alerts for a US state")
public String getAlerts(
@ToolParam(description = "Two-letter US state code (e.g. CA, NY") String state)
) {
// Returns active alerts including:
// - Event type
// - Affected area
// - Severity
// - Description
// - Safety instructions
}
public record Forecast(Props properties) {
public record Props(List<Period> periods) {}
public record Period(Integer number, String name, String startTime, String endTime, Boolean isDayTime, Integer temperature, String temperatureUnit, String temperatureTrend, Map probabilityOfPrecipitation, String windSpeed, String windDirection, String icon, String shortForecast, String detailedForecast) {}
}
public record Alert(List<Feature> features) {
public record Feature(Properties properties) {}
public record Properties(String event, String areaDesc, String severity, String description, String instruction) {}
}
// ......
}
```
The `@Service` annotation with auto-register the service in your applicaiton context.
The Spring AI `@Tool` annotation, making it easy to create and maintain MCP tools.
### Implementing tool execution
The auto-configuration will automatically register these tools with the MCP server.
The tool execution handler is responsible for actually executing the logic of each tool.
The Spring AI `@Tool` annotation, making it easy to create and maintain MCP tools:
```java
@Tool(description = "Get weather forecast for a specific latitude/longitude")
public String getWeatherForecastByLocation(double latitude, double longitude) {
var points = restClient.get()
.uri("/points/{latitude},{longitude}", latitude, longitude)
.retrieve()
.body(Points.class);
var forecast = restClient.get().uri(points.properties().forecast()).retrieve().body(Forecast.class);
String forecastText = forecast.properties().periods().stream().map(p -> {
return String.format("""
%s:
Temperature: %s %s
Wind: %s %s
Forecast: %s
""", p.name(), p.temperature(), p.temperatureUnit(), p.windSpeed(), p.windDirection(),
p.detailedForecast());
}).collect(Collectors.joining());
return forecastText;
}
@Tool(description = "Get weather alerts for a US state. Input is Two-letter US state code (e.g. CA, NY)")
public String getAlerts(String state) {
Alert alert = restClient.get().uri("/alerts/active/area/{state}", state).retrieve().body(Alert.class);
return alert.features()
.stream()
.map(f -> String.format("""
Event: %s
Area: %s
Severity: %s
Description: %s
Instructions: %s
""", f.properties().event(), f.properties.areaDesc(), f.properties.severity(),
f.properties.description(), f.properties.instruction()))
.collect(Collectors.joining("\n"));
}
```
### Build your Boot Applicaiton
### Create your Boot Applicaiton
```java
@SpringBootApplication
@ -911,35 +877,38 @@ public class McpServerApplication {
}
@Bean
public List<ToolCallback> weatherTools(WeatherService weatherService) {
return List.of(ToolCallbacks.from(weatherService));
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
}
```
Uses the the `ToolCallbacks.from(...)` utils to convert the `@Tools` into actionalble callbackes used by the MCP server.
Uses the the `MethodToolCallbackProvider` utils to convert the `@Tools` into actionalble callbackes used by the MCP server.
### Running the server
Finally, let's build and run the server:
Finally, let's build the server:
```bash
./mvnw clean install
java -jar model-context-protocol/mcp-weather-server-quickstart/target/mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar
```
This will generate a `mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar` file within the `target` folder.
Let's now test your server from an existing MCP host, Claude for Desktop.
## Testing your server with Claude for Desktop
<Note>
Claude for Desktop is not yet available on Linux. Linux users can proceed to the [Building a client](/quickstart/client) tutorial to build an MCP client that connects to the server we just built.
Claude for Desktop is not yet available on Linux.
</Note>
First, make sure you have Claude for Desktop installed. [You can install the latest version
here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
First, make sure you have Claude for Desktop installed.
[You can install the latest version here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
We'll need to configure Claude for Desktop for whichever MCP servers you want to use. To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor. Make sure to create the file if it doesn't exist.
We'll need to configure Claude for Desktop for whichever MCP servers you want to use.
To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor.
Make sure to create the file if it doesn't exist.
For example, if you have [VS Code](https://code.visualstudio.com/) installed:
@ -956,7 +925,8 @@ For example, if you have [VS Code](https://code.visualstudio.com/) installed:
</Tab>
</Tabs>
You'll then add your servers in the `mcpServers` key. The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
You'll then add your servers in the `mcpServers` key.
The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
In this case, we'll add our single weather server like so:
@ -968,9 +938,9 @@ In this case, we'll add our single weather server like so:
"spring-ai-mcp-weather": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.transport=STDIO",
"-Dspring.ai.mcp.server.stdio=true",
"-jar",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar"
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
]
}
}
@ -987,7 +957,7 @@ In this case, we'll add our single weather server like so:
"args": [
"-Dspring.ai.mcp.server.transport=STDIO",
"-jar",
"C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather\\mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar"
"C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather\\mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar"
]
}
}
@ -1002,17 +972,19 @@ Make sure you pass in the absolute path to your server.
This tells Claude for Desktop:
1. There's an MCP server named "my-weather-server"
2. To launch it by running `java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar`
2. To launch it by running `java -jar /ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar`
Save the file, and restart **Claude for Desktop**.
## Testing your server with Java client
### Create a MCP Client manually
Use the `McpClient` to connect to the server:
```java
var stdioParams = ServerParameters.builder("java")
.args("-jar", "/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar")
.args("-jar", "/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-stdio-server-0.0.1-SNAPSHOT.jar")
.build();
var stdioTransport = new StdioClientTransport(stdioParams);
@ -1033,9 +1005,31 @@ CallToolResult alert = mcpClient.callTool(
mcpClient.closeGracefully();
```
### Use MCP Client Boot Starter
Create a new boot starter applicaiton using the `spring-ai-mcp-client-spring-boot-starter` dependency:
```xml
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
```
and set the `spring.ai.mcp.client.stdio.servers-configuration` property to point to your `claude_desktop_config.json`.
You can re-use the existing Anthropic Destop configuration:
```properties
spring.ai.mcp.client.stdio.servers-configuration=file:PATH/TO/claude_desktop_config.json
```
When you stasrt your client applicaiton, the auto-configuration will create, automatically MCP clients from the claude_desktop_config.json.
For more information, see the [MCP Client Boot Starters](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-client-docs.html) reference documentation.
## More Java MCP Server examples
The [mcp-webflux-server-starter](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/mcp-webflux-server-starter) demonstrates how to create a MCP server using SSE transport.
The [starter-webflux-server](https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/weather/starter-webflux-server) demonstrates how to create a MCP server using SSE transport.
It showcases how to define and register MCP Tools, Resources, and Prompts, using the Spring Boot's auto-configuration capabilities.
</Tab>

View file

@ -214,16 +214,16 @@ This capability allows:
### Tool Execution
Tools are server-side functions that can be discovered and executed by clients. The client provides methods to list available tools and execute them with parameters.
Tools are server-side functions that clients can discover and execute. The MCP client provides methods to list available tools and execute them with specific parameters. Each tool has a unique name and accepts a map of parameters.
<Tabs>
<Tab title="Sync API">
```java
// List available tools
// List available tools and their names
var tools = client.listTools();
tools.forEach(tool -> System.out.println(tool.getName()));
// Execute a tool
// Execute a tool with parameters
var result = client.callTool("calculator", Map.of(
"operation", "add",
"a", 1,
@ -234,13 +234,13 @@ var result = client.callTool("calculator", Map.of(
<Tab title="Async API">
```java
// List available tools
// List available tools asynchronously
client.listTools()
.doOnNext(tools -> tools.forEach(tool ->
System.out.println(tool.getName())))
.subscribe();
// Execute a tool
// Execute a tool asynchronously
client.callTool("calculator", Map.of(
"operation", "add",
"a", 1,
@ -253,16 +253,16 @@ client.callTool("calculator", Map.of(
### Resource Access
Resources are server-side data sources that can be accessed by clients using URI templates. The client provides methods to list available resources and retrieve their content.
Resources represent server-side data sources that clients can access using URI templates. The MCP client provides methods to discover available resources and retrieve their contents through a standardized interface.
<Tabs>
<Tab title="Sync API">
```java
// List available resources
// List available resources and their names
var resources = client.listResources();
resources.forEach(resource -> System.out.println(resource.getName()));
// Get a resource
// Retrieve resource content using a URI template
var content = client.getResource("file", Map.of(
"path", "/path/to/file.txt"
));
@ -271,13 +271,13 @@ var content = client.getResource("file", Map.of(
<Tab title="Async API">
```java
// List available resources
// List available resources asynchronously
client.listResources()
.doOnNext(resources -> resources.forEach(resource ->
System.out.println(resource.getName())))
.subscribe();
// Get a resource
// Retrieve resource content asynchronously
client.getResource("file", Map.of(
"path", "/path/to/file.txt"
))
@ -288,16 +288,16 @@ client.getResource("file", Map.of(
### Prompt System
The prompt system allows clients to interact with server-side prompt templates. The client provides methods to list available prompts and execute them with parameters.
The prompt system enables interaction with server-side prompt templates. These templates can be discovered and executed with custom parameters, allowing for dynamic text generation based on predefined patterns.
<Tabs>
<Tab title="Sync API">
```java
// List available prompts
// List available prompt templates
var prompts = client.listPrompts();
prompts.forEach(prompt -> System.out.println(prompt.getName()));
// Execute a prompt
// Execute a prompt template with parameters
var response = client.executePrompt("echo", Map.of(
"text", "Hello, World!"
));
@ -306,13 +306,13 @@ var response = client.executePrompt("echo", Map.of(
<Tab title="Async API">
```java
// List available prompts
// List available prompt templates asynchronously
client.listPrompts()
.doOnNext(prompts -> prompts.forEach(prompt ->
System.out.println(prompt.getName())))
.subscribe();
// Execute a prompt
// Execute a prompt template asynchronously
client.executePrompt("echo", Map.of(
"text", "Hello, World!"
))

View file

@ -8,9 +8,7 @@ enables standardized integration between AI models and tools.
## Features
- MCP Client and MCP Server implementations
- Supports Synchronous and Asynchronous programming paradigms
- Standard MCP operations support:
- MCP Client and MCP Server implementations supporting:
- Protocol [version compatibility negotiation](https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/#initialization)
- [Tool](https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/) discovery, execution, list change notifications
- [Resource](https://spec.modelcontextprotocol.io/specification/2024-11-05/server/resources/) management with URI templates
@ -18,21 +16,21 @@ enables standardized integration between AI models and tools.
- [Prompt](https://spec.modelcontextprotocol.io/specification/2024-11-05/server/prompts/) handling and management
- [Sampling](https://spec.modelcontextprotocol.io/specification/2024-11-05/client/sampling/) support for AI model interactions
- Multiple transport implementations:
- Core transports:
- Default transports:
- Stdio-based transport for process-based communication
- Java HttpClient-based SSE client transport for HTTP SSE Client-side streaming
- Servlet-based SSE server transport for HTTP SSE Server streaming
- Spring-based transports:
- WebFlux SSE transport for reactive HTTP streaming
- WebFlux SSE client and server transports for reactive HTTP streaming
- WebMVC SSE transport for servlet-based HTTP streaming
- Supports Synchronous and Asynchronous programming paradigms
## Architecture
![Java MCP Client Architecture](/images/java/java-mcp-client-architecture.jpg)
![Java MCP Server Architecture](/images/java/java-mcp-server-architecture.jpg)
The SDK follows a layered architecture with clear separation of concerns:
![MCP Stack Architecture](/images/java/mcp-stack.svg)
- **Client/Server Layer (McpClient/McpServer)**: Both use McpSession for sync/async operations,
with McpClient handling client-side protocol operations and McpServer managing server-side protocol operations.
- **Session Layer (McpSession)**: Manages communication patterns and state using DefaultMcpSession implementation.
@ -40,13 +38,16 @@ with McpClient handling client-side protocol operations and McpServer managing s
- StdioTransport (stdin/stdout) in the core module
- HTTP SSE transports in dedicated transport modules (Java HttpClient, Spring WebFlux, Spring WebMVC)
![MCP Stack Architecture](/images/java/mcp-stack.svg)
The following class diagram illustrates the layered architecture of the MCP SDK, showing
the relationships between core interfaces (McpTransport, McpSession), their implementations,
and the client/server components. It highlights how the transport layer connects to sessions, which in turn support both synchronous and asynchronous client/server implementations.
The MCP Client is a key component in the Model Context Protocol (MCP) architecture, responsible for establishing and managing connections with MCP servers.
It implements the client-side of the protocol.
![MCP SDK Class Diagram](/images/java/java-mcp-uml-classdiagram.svg)
![Java MCP Client Architecture](/images/java/java-mcp-client-architecture.jpg)
The MCP Server is a foundational component in the Model Context Protocol (MCP) architecture that provides tools, resources, and capabilities to clients.
It implements the server-side of the protocol.
![Java MCP Server Architecture](/images/java/java-mcp-server-architecture.jpg)
Key Interactions: