(WIP) Base for Java docs (#125)
* Base for Java docs * docs(java): Migrate Java-SDK/docs Add visual documentation for Java SDK architecture: - PlantUML class diagrams showing core components and relationships - Client and server architecture diagrams - Stack architecture overview - Generated UML class diagram with detailed implementation structure * Add Java Client and Server quickstarts * reorder, redact, correct java-sdk docs Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com> * updated updates.mdx * fix docs.json --------- Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com> Co-authored-by: Christian Tzolov <christian.tzolov@broadcom.com> Co-authored-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com> Co-authored-by: David Soria Parra <davidsp@anthropic.com>
This commit is contained in:
parent
1772fb8f72
commit
904083c681
2 changed files with 1780 additions and 5 deletions
|
|
@ -401,6 +401,120 @@ If you see:
|
|||
|
||||
</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 McpClients programatically consult the [Java SDK Client guid](TODO: add URL)
|
||||
</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)
|
||||
|
||||
## System Requirements
|
||||
|
||||
Before starting, ensure your system meets these requirements:
|
||||
- Java 17 or higher
|
||||
- Maven 3.6+
|
||||
- npx package manager
|
||||
- Anthropic API key (Claude)
|
||||
- Brave Search API key
|
||||
|
||||
## Setting Up Your Environment
|
||||
|
||||
1. Install npx (Node Package eXecute):
|
||||
First, make sure to install [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
|
||||
and then run:
|
||||
```bash
|
||||
npm install -g npx
|
||||
```
|
||||
|
||||
2. Clone the repository:
|
||||
```bash
|
||||
git clone https://github.com/spring-projects/spring-ai-examples.git
|
||||
cd model-context-protocol/brave-chatbot
|
||||
```
|
||||
|
||||
3. Set up your API keys:
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY='your-anthropic-api-key-here'
|
||||
export BRAVE_API_KEY='your-brave-api-key-here'
|
||||
```
|
||||
|
||||
4. Build the application:
|
||||
```bash
|
||||
./mvnw clean install
|
||||
```
|
||||
|
||||
5. Run the application using Maven:
|
||||
```bash
|
||||
./mvnw spring-boot:run
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Make sure you keep your `ANTHROPIC_API_KEY` and `BRAVE_API_KEY` keys secure!
|
||||
</Warning>
|
||||
|
||||
|
||||
## How it Works
|
||||
|
||||
The application integrates Spring AI with the Brave Search MCP server through several components:
|
||||
|
||||
### MCP Client Configuration
|
||||
|
||||
1. Required dependencies in pom.xml:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
|
||||
</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}
|
||||
```
|
||||
|
||||
This acivates the `spring-ai-mcp-spring-boot-starter` to create one or more `McpClient`s based on the provided server configuration.
|
||||
|
||||
3. MCP Server Configuration (mcp-servers-config.json):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"brave-search": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-brave-search"
|
||||
],
|
||||
"env": {
|
||||
"BRAVE_API_KEY": "<PUT YOUR BRAVE API KEY>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Chat Implementation
|
||||
|
||||
The chatbot is implemented using Spring AI's ChatClient with MCP tool integration:
|
||||
|
||||
```java
|
||||
var chatClient = chatClientBuilder
|
||||
.defaultSystem("You are useful assistant, expert in AI and Java.")
|
||||
.defaultTools((Object[]) mcpToolAdapter.toolCallbacks())
|
||||
.defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
|
||||
.build();
|
||||
```
|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Next steps
|
||||
|
|
|
|||
|
|
@ -739,6 +739,305 @@ This tells Claude for Desktop:
|
|||
2. Launch it by running `node /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather/build/index.js`
|
||||
|
||||
Save the file, and restart **Claude for Desktop**.
|
||||
</Tab>
|
||||
<Tab title='Java'>
|
||||
|
||||
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)
|
||||
|
||||
### System requirements
|
||||
|
||||
- Java 17 or higher installed.
|
||||
- [Spring Boot 3.4](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).
|
||||
|
||||
You will need to add the following dependencies:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Maven">
|
||||
```xml
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-mcp-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")
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Then configure your application by setting the applicaiton properties:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash application.properties
|
||||
spring.main.bannerMode=off
|
||||
logging.pattern.console=
|
||||
spring.ai.mcp.server.enabled=true
|
||||
```
|
||||
|
||||
```yaml application.yml
|
||||
logging:
|
||||
pattern:
|
||||
console:
|
||||
spring:
|
||||
main:
|
||||
banner-mode: off
|
||||
ai:
|
||||
mcp:
|
||||
server:
|
||||
enabled: true
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
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:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class WeatherService {
|
||||
|
||||
private final RestClient restClient;
|
||||
|
||||
public WeatherService() {
|
||||
this.restClient = RestClient.builder()
|
||||
.baseUrl("https://api.weather.gov")
|
||||
.defaultHeader("Accept", "application/geo+json")
|
||||
.defaultHeader("User-Agent", "WeatherApiClient/1.0 (your@email.com)")
|
||||
.build();
|
||||
}
|
||||
|
||||
public record Points(Props properties) {
|
||||
public record Props(String forecast) { }
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
### Implementing tool execution
|
||||
|
||||
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
|
||||
|
||||
```java
|
||||
@SpringBootApplication
|
||||
public class McpServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(McpServerApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public List<ToolCallback> weatherTools(WeatherService weatherService) {
|
||||
return List.of(ToolCallbacks.from(weatherService));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Uses the the `ToolCallbacks.from(...)` utils to convert the `@Tools` into actionalble callbackes used by the MCP server.
|
||||
|
||||
### Running the server
|
||||
|
||||
Finally, let's build and run 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
|
||||
```
|
||||
|
||||
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.
|
||||
</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.**
|
||||
|
||||
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:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="MacOS/Linux">
|
||||
```bash
|
||||
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Windows">
|
||||
```powershell
|
||||
code $env:AppData\Claude\claude_desktop_config.json
|
||||
```
|
||||
</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.
|
||||
|
||||
In this case, we'll add our single weather server like so:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="MacOS/Linux">
|
||||
```json java
|
||||
{
|
||||
"mcpServers": {
|
||||
"spring-ai-mcp-weather": {
|
||||
"command": "java",
|
||||
"args": [
|
||||
"-Dspring.ai.mcp.server.transport=STDIO",
|
||||
"-jar",
|
||||
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Windows">
|
||||
```json java
|
||||
{
|
||||
"mcpServers": {
|
||||
"spring-ai-mcp-weather": {
|
||||
"command": "java",
|
||||
"args": [
|
||||
"-Dspring.ai.mcp.server.transport=STDIO",
|
||||
"-jar",
|
||||
"C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\weather\\mcp-weather-server-quickstart-0.0.1-SNAPSHOT.jar"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
Make sure you pass in the absolute path to your server.
|
||||
</Note>
|
||||
|
||||
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`
|
||||
|
||||
Save the file, and restart **Claude for Desktop**.
|
||||
|
||||
## Testing your server with Java client
|
||||
|
||||
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")
|
||||
.build();
|
||||
|
||||
var stdioTransport = new StdioClientTransport(stdioParams);
|
||||
|
||||
var mcpClient = McpClient.sync(stdioTransport).build();
|
||||
|
||||
mcpClient.initialize();
|
||||
|
||||
ListToolsResult toolsList = mcpClient.listTools();
|
||||
|
||||
CallToolResult weather = mcpClient.callTool(
|
||||
new CallToolRequest("getWeatherForecastByLocation",
|
||||
Map.of("latitude", "47.6062", "longitude", "-122.3321")));
|
||||
|
||||
CallToolResult alert = mcpClient.callTool(
|
||||
new CallToolRequest("getAlerts", Map.of("state", "NY")));
|
||||
|
||||
mcpClient.closeGracefully();
|
||||
```
|
||||
|
||||
## 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.
|
||||
It showcases how to define and register MCP Tools, Resources, and Prompts, using the Spring Boot's auto-configuration capabilities.
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue