(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
13 changed files with 1780 additions and 5 deletions
|
|
@ -3,6 +3,18 @@ title: "What's New"
|
|||
description: 'The latest updates and improvements to MCP'
|
||||
---
|
||||
|
||||
<Update label="2025-02-07" description="Java SDK released">
|
||||
- We're excited to announce that the Java SDK developed by Spring AI at VMware Tanzu is now
|
||||
the official [Java SDK](https://github.com/modelcontextprotocol/java-sdk) for MCP.
|
||||
This joins our existing Kotlin SDK in our growing list of supported languages.
|
||||
The Spring AI team will maintain the SDK as an integral part of the Model Context Protocol
|
||||
organization. We're thrilled to welcome them to the MCP community!
|
||||
</Update>
|
||||
|
||||
<Update label="2025-01-27" description="Python SDK 1.2.1">
|
||||
- Version [1.2.1](https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.2.1) of the MCP Python SDK has been released,
|
||||
delivering important stability improvements and bug fixes.
|
||||
</Update>
|
||||
<Update label="2025-01-18" description="SDK and Server Improvements">
|
||||
- Simplified, express-like API in the [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
|
||||
- Added 8 new clients to the [clients page](https://modelcontextprotocol.io/clients)
|
||||
|
|
@ -16,4 +28,4 @@ description: 'The latest updates and improvements to MCP'
|
|||
<Update label="2024-12-21" description="Kotlin SDK released">
|
||||
- Jetbrains released a Kotlin SDK for MCP!
|
||||
- For a sample MCP Kotlin server, check out [this repository](https://github.com/modelcontextprotocol/kotlin-sdk/tree/main/samples/kotlin-mcp-server)
|
||||
</Update>
|
||||
</Update>
|
||||
|
|
|
|||
19
docs.json
19
docs.json
|
|
@ -9,10 +9,9 @@
|
|||
},
|
||||
"favicon": "/favicon.svg",
|
||||
"navigation": {
|
||||
"anchors": [
|
||||
"tabs": [
|
||||
{
|
||||
"anchor": "Documentation",
|
||||
"icon": "book-open",
|
||||
"tab": "Documentation",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Get Started",
|
||||
|
|
@ -59,6 +58,20 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tab": "SDKs",
|
||||
"icon": "book-open",
|
||||
"groups": [
|
||||
{
|
||||
"group": "Java",
|
||||
"pages": [
|
||||
"sdk/java/mcp-overview",
|
||||
"sdk/java/mcp-client",
|
||||
"sdk/java/mcp-server"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"global": {
|
||||
|
|
|
|||
282
images/java/class-diagrams.puml
Normal file
282
images/java/class-diagrams.puml
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
@startuml Core Components
|
||||
|
||||
' Core Interfaces
|
||||
interface McpTransport {
|
||||
+Mono<Void> connect(Function<Mono<JSONRPCMessage>, Mono<JSONRPCMessage>> handler)
|
||||
+Mono<Void> sendMessage(JSONRPCMessage message)
|
||||
+void close()
|
||||
+Mono<Void> closeGracefully()
|
||||
+<T> T unmarshalFrom(Object data, TypeReference<T> typeRef)
|
||||
}
|
||||
|
||||
interface McpSession {
|
||||
+<T> Mono<T> sendRequest(String method, Object requestParams, TypeReference<T> typeRef)
|
||||
+Mono<Void> sendNotification(String method, Map<String, Object> params)
|
||||
+Mono<Void> closeGracefully()
|
||||
+void close()
|
||||
}
|
||||
|
||||
' Core Implementation Classes
|
||||
class DefaultMcpSession {
|
||||
+interface RequestHandler
|
||||
+interface NotificationHandler
|
||||
}
|
||||
|
||||
' Client Classes
|
||||
class McpClient {
|
||||
+{static} Builder using(ClientMcpTransport transport)
|
||||
}
|
||||
|
||||
class McpAsyncClient {
|
||||
+Mono<InitializeResult> initialize()
|
||||
+ServerCapabilities getServerCapabilities()
|
||||
+Implementation getServerInfo()
|
||||
+ClientCapabilities getClientCapabilities()
|
||||
+Implementation getClientInfo()
|
||||
+void close()
|
||||
+Mono<Void> closeGracefully()
|
||||
+Mono<Object> ping()
|
||||
+Mono<Void> addRoot(Root root)
|
||||
+Mono<Void> removeRoot(String rootUri)
|
||||
+Mono<Void> rootsListChangedNotification()
|
||||
+Mono<CallToolResult> callTool(CallToolRequest request)
|
||||
+Mono<ListToolsResult> listTools()
|
||||
+Mono<ListResourcesResult> listResources()
|
||||
+Mono<ReadResourceResult> readResource(ReadResourceRequest request)
|
||||
+Mono<ListResourceTemplatesResult> listResourceTemplates()
|
||||
+Mono<Void> subscribeResource(SubscribeRequest request)
|
||||
+Mono<Void> unsubscribeResource(UnsubscribeRequest request)
|
||||
+Mono<ListPromptsResult> listPrompts()
|
||||
+Mono<GetPromptResult> getPrompt(GetPromptRequest request)
|
||||
+Mono<Void> setLoggingLevel(LoggingLevel level)
|
||||
}
|
||||
|
||||
class McpSyncClient {
|
||||
+InitializeResult initialize()
|
||||
+ServerCapabilities getServerCapabilities()
|
||||
+Implementation getServerInfo()
|
||||
+ClientCapabilities getClientCapabilities()
|
||||
+Implementation getClientInfo()
|
||||
+void close()
|
||||
+boolean closeGracefully()
|
||||
+Object ping()
|
||||
+void addRoot(Root root)
|
||||
+void removeRoot(String rootUri)
|
||||
+void rootsListChangedNotification()
|
||||
+CallToolResult callTool(CallToolRequest request)
|
||||
+ListToolsResult listTools()
|
||||
+ListResourcesResult listResources()
|
||||
+ReadResourceResult readResource(ReadResourceRequest request)
|
||||
+ListResourceTemplatesResult listResourceTemplates()
|
||||
+void subscribeResource(SubscribeRequest request)
|
||||
+void unsubscribeResource(UnsubscribeRequest request)
|
||||
+ListPromptsResult listPrompts()
|
||||
+GetPromptResult getPrompt(GetPromptRequest request)
|
||||
+void setLoggingLevel(LoggingLevel level)
|
||||
}
|
||||
|
||||
' Server Classes
|
||||
class McpServer {
|
||||
+{static} Builder using(ServerMcpTransport transport)
|
||||
}
|
||||
|
||||
class McpAsyncServer {
|
||||
|
||||
+ServerCapabilities getServerCapabilities()
|
||||
+Implementation getServerInfo()
|
||||
+ClientCapabilities getClientCapabilities()
|
||||
+Implementation getClientInfo()
|
||||
+void close()
|
||||
+Mono<Void> closeGracefully()
|
||||
|
||||
' Tool Management
|
||||
+Mono<Void> addTool(ToolRegistration toolRegistration)
|
||||
+Mono<Void> removeTool(String toolName)
|
||||
+Mono<Void> notifyToolsListChanged()
|
||||
|
||||
' Resource Management
|
||||
+Mono<Void> addResource(ResourceRegistration resourceHandler)
|
||||
+Mono<Void> removeResource(String resourceUri)
|
||||
+Mono<Void> notifyResourcesListChanged()
|
||||
|
||||
' Prompt Management
|
||||
+Mono<Void> addPrompt(PromptRegistration promptRegistration)
|
||||
+Mono<Void> removePrompt(String promptName)
|
||||
+Mono<Void> notifyPromptsListChanged()
|
||||
|
||||
' Logging
|
||||
+Mono<Void> loggingNotification(LoggingMessageNotification notification)
|
||||
|
||||
' Sampling
|
||||
+Mono<CreateMessageResult> createMessage(CreateMessageRequest request)
|
||||
}
|
||||
|
||||
class McpSyncServer {
|
||||
+McpAsyncServer getAsyncServer()
|
||||
|
||||
+ServerCapabilities getServerCapabilities()
|
||||
+Implementation getServerInfo()
|
||||
+ClientCapabilities getClientCapabilities()
|
||||
+Implementation getClientInfo()
|
||||
+void close()
|
||||
+void closeGracefully()
|
||||
|
||||
' Tool Management
|
||||
+void addTool(ToolRegistration toolHandler)
|
||||
+void removeTool(String toolName)
|
||||
+void notifyToolsListChanged()
|
||||
|
||||
' Resource Management
|
||||
+void addResource(ResourceRegistration resourceHandler)
|
||||
+void removeResource(String resourceUri)
|
||||
+void notifyResourcesListChanged()
|
||||
|
||||
' Prompt Management
|
||||
+void addPrompt(PromptRegistration promptRegistration)
|
||||
+void removePrompt(String promptName)
|
||||
+void notifyPromptsListChanged()
|
||||
|
||||
' Logging
|
||||
+void loggingNotification(LoggingMessageNotification notification)
|
||||
|
||||
' Sampling
|
||||
+CreateMessageResult createMessage(CreateMessageRequest request)
|
||||
}
|
||||
|
||||
' Transport Implementations
|
||||
class StdioClientTransport implements ClientMcpTransport {
|
||||
+void setErrorHandler(Consumer<String> errorHandler)
|
||||
+Sinks.Many<String> getErrorSink()
|
||||
}
|
||||
|
||||
class StdioServerTransport implements ServerMcpTransport {
|
||||
}
|
||||
|
||||
|
||||
class HttpServletSseServerTransport implements ServerMcpTransport {
|
||||
}
|
||||
|
||||
|
||||
class HttpClientSseClientTransport implements ClientMcpTransport {
|
||||
}
|
||||
|
||||
|
||||
class WebFluxSseClientTransport implements ClientMcpTransport {
|
||||
}
|
||||
|
||||
|
||||
class WebFluxSseServerTransport implements ServerMcpTransport {
|
||||
+RouterFunction<?> getRouterFunction()
|
||||
}
|
||||
|
||||
class WebMvcSseServerTransport implements ServerMcpTransport {
|
||||
+RouterFunction<?> getRouterFunction()
|
||||
}
|
||||
|
||||
|
||||
' Schema and Error Classes
|
||||
class McpSchema {
|
||||
+class ErrorCodes
|
||||
+interface Request
|
||||
+interface JSONRPCMessage
|
||||
+interface ResourceContents
|
||||
+interface Content
|
||||
+interface ServerCapabilities
|
||||
+{static} JSONRPCMessage deserializeJsonRpcMessage()
|
||||
}
|
||||
|
||||
class McpError {
|
||||
}
|
||||
|
||||
' Relationships
|
||||
McpTransport <|.. ClientMcpTransport
|
||||
McpTransport <|.. ServerMcpTransport
|
||||
|
||||
McpSession <|.. DefaultMcpSession
|
||||
DefaultMcpSession --o McpAsyncClient
|
||||
DefaultMcpSession --o McpAsyncServer
|
||||
|
||||
McpClient ..> McpAsyncClient : creates
|
||||
McpClient ..> McpSyncClient : creates
|
||||
McpSyncClient --> McpAsyncClient : delegates to
|
||||
|
||||
McpServer ..> McpAsyncServer : creates
|
||||
McpServer ..> McpSyncServer : creates
|
||||
McpSyncServer o-- McpAsyncServer
|
||||
|
||||
DefaultMcpSession o-- McpTransport
|
||||
McpSchema <.. McpSession : uses
|
||||
McpError ..> McpSession : throws
|
||||
|
||||
@enduml
|
||||
|
||||
@startuml Message Flow
|
||||
|
||||
package "MCP Schema" {
|
||||
interface JSONRPCMessage {
|
||||
+String jsonrpc()
|
||||
}
|
||||
|
||||
interface Request {
|
||||
}
|
||||
|
||||
class InitializeRequest
|
||||
class CallToolRequest
|
||||
class ListToolsRequest
|
||||
class ListResourcesRequest
|
||||
class ReadResourceRequest
|
||||
class ListResourceTemplatesRequest
|
||||
class ListPromptsRequest
|
||||
class GetPromptRequest
|
||||
}
|
||||
|
||||
package "Resource Types" {
|
||||
interface ResourceContents {
|
||||
+String uri()
|
||||
+String mimeType()
|
||||
}
|
||||
|
||||
class TextResourceContents
|
||||
class BlobResourceContents
|
||||
|
||||
interface Content {
|
||||
+String type()
|
||||
}
|
||||
|
||||
class TextContent
|
||||
class ImageContent
|
||||
class EmbeddedResource
|
||||
|
||||
interface Annotated {
|
||||
+Annotations annotations()
|
||||
}
|
||||
|
||||
interface PromptOrResourceReference {
|
||||
+String type()
|
||||
}
|
||||
|
||||
class PromptReference
|
||||
class ResourceReference
|
||||
}
|
||||
|
||||
JSONRPCMessage <|.. Request
|
||||
Request <|.. InitializeRequest
|
||||
Request <|.. CallToolRequest
|
||||
Request <|.. ListToolsRequest
|
||||
Request <|.. ListResourcesRequest
|
||||
Request <|.. ReadResourceRequest
|
||||
Request <|.. ListResourceTemplatesRequest
|
||||
Request <|.. ListPromptsRequest
|
||||
Request <|.. GetPromptRequest
|
||||
|
||||
ResourceContents <|.. TextResourceContents
|
||||
ResourceContents <|.. BlobResourceContents
|
||||
|
||||
Content <|.. TextContent
|
||||
Content <|.. ImageContent
|
||||
Content <|.. EmbeddedResource
|
||||
|
||||
PromptOrResourceReference <|.. PromptReference
|
||||
PromptOrResourceReference <|.. ResourceReference
|
||||
|
||||
@enduml
|
||||
BIN
images/java/java-mcp-client-architecture.jpg
Normal file
BIN
images/java/java-mcp-client-architecture.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 661 KiB |
BIN
images/java/java-mcp-server-architecture.jpg
Normal file
BIN
images/java/java-mcp-server-architecture.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 840 KiB |
1
images/java/java-mcp-uml-classdiagram.svg
Normal file
1
images/java/java-mcp-uml-classdiagram.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 67 KiB |
197
images/java/mcp-stack.svg
Normal file
197
images/java/mcp-stack.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 75 KiB |
|
|
@ -3,7 +3,7 @@ title: Introduction
|
|||
description: 'Get started with the Model Context Protocol (MCP)'
|
||||
---
|
||||
|
||||
<Note>Kotlin SDK released! Check out [what else is new.](/development/updates)</Note>
|
||||
<Note>Java SDK released! Check out [what else is new.](/development/updates)</Note>
|
||||
|
||||
MCP is an open protocol that standardizes how applications provide context to LLMs. Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
322
sdk/java/mcp-client.mdx
Normal file
322
sdk/java/mcp-client.mdx
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
---
|
||||
title: MCP Client
|
||||
description: Learn how to use the Model Context Protocol (MCP) client to interact with MCP servers
|
||||
---
|
||||
|
||||
# Model Context Protocol Client
|
||||
|
||||
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, handling:
|
||||
|
||||
- Protocol version negotiation to ensure compatibility with servers
|
||||
- Capability negotiation to determine available features
|
||||
- Message transport and JSON-RPC communication
|
||||
- Tool discovery and execution
|
||||
- Resource access and management
|
||||
- Prompt system interactions
|
||||
- Optional features like roots management and sampling support
|
||||
|
||||
The client provides both synchronous and asynchronous APIs for flexibility in different application contexts.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// Create a sync client with custom configuration
|
||||
McpSyncClient client = McpClient.sync(transport)
|
||||
.requestTimeout(Duration.ofSeconds(10))
|
||||
.capabilities(ClientCapabilities.builder()
|
||||
.roots(true) // Enable roots capability
|
||||
.sampling() // Enable sampling capability
|
||||
.build())
|
||||
.sampling(request -> new CreateMessageResult(response))
|
||||
.build();
|
||||
|
||||
// Initialize connection
|
||||
client.initialize();
|
||||
|
||||
// List available tools
|
||||
ListToolsResult tools = client.listTools();
|
||||
|
||||
// Call a tool
|
||||
CallToolResult result = client.callTool(
|
||||
new CallToolRequest("calculator",
|
||||
Map.of("operation", "add", "a", 2, "b", 3))
|
||||
);
|
||||
|
||||
// List and read resources
|
||||
ListResourcesResult resources = client.listResources();
|
||||
ReadResourceResult resource = client.readResource(
|
||||
new ReadResourceRequest("resource://uri")
|
||||
);
|
||||
|
||||
// List and use prompts
|
||||
ListPromptsResult prompts = client.listPrompts();
|
||||
GetPromptResult prompt = client.getPrompt(
|
||||
new GetPromptRequest("greeting", Map.of("name", "Spring"))
|
||||
);
|
||||
|
||||
// Add/remove roots
|
||||
client.addRoot(new Root("file:///path", "description"));
|
||||
client.removeRoot("file:///path");
|
||||
|
||||
// Close client
|
||||
client.closeGracefully();
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async API">
|
||||
```java
|
||||
// Create an async client with custom configuration
|
||||
McpAsyncClient client = McpClient.async(transport)
|
||||
.requestTimeout(Duration.ofSeconds(10))
|
||||
.capabilities(ClientCapabilities.builder()
|
||||
.roots(true) // Enable roots capability
|
||||
.sampling() // Enable sampling capability
|
||||
.build())
|
||||
.sampling(request -> Mono.just(new CreateMessageResult(response)))
|
||||
.toolsChangeConsumer(tools -> Mono.fromRunnable(() -> {
|
||||
logger.info("Tools updated: {}", tools);
|
||||
}))
|
||||
.resourcesChangeConsumer(resources -> Mono.fromRunnable(() -> {
|
||||
logger.info("Resources updated: {}", resources);
|
||||
}))
|
||||
.promptsChangeConsumer(prompts -> Mono.fromRunnable(() -> {
|
||||
logger.info("Prompts updated: {}", prompts);
|
||||
}))
|
||||
.build();
|
||||
|
||||
// Initialize connection and use features
|
||||
client.initialize()
|
||||
.flatMap(initResult -> client.listTools())
|
||||
.flatMap(tools -> {
|
||||
return client.callTool(new CallToolRequest(
|
||||
"calculator",
|
||||
Map.of("operation", "add", "a", 2, "b", 3)
|
||||
));
|
||||
})
|
||||
.flatMap(result -> {
|
||||
return client.listResources()
|
||||
.flatMap(resources ->
|
||||
client.readResource(new ReadResourceRequest("resource://uri"))
|
||||
);
|
||||
})
|
||||
.flatMap(resource -> {
|
||||
return client.listPrompts()
|
||||
.flatMap(prompts ->
|
||||
client.getPrompt(new GetPromptRequest(
|
||||
"greeting",
|
||||
Map.of("name", "Spring")
|
||||
))
|
||||
);
|
||||
})
|
||||
.flatMap(prompt -> {
|
||||
return client.addRoot(new Root("file:///path", "description"))
|
||||
.then(client.removeRoot("file:///path"));
|
||||
})
|
||||
.doFinally(signalType -> {
|
||||
client.closeGracefully().subscribe();
|
||||
})
|
||||
.subscribe();
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Client Transport
|
||||
|
||||
The transport layer handles the communication between MCP clients and servers, providing different implementations for various use cases. The client transport manages message serialization, connection establishment, and protocol-specific communication patterns.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="STDIO">
|
||||
Creates transport for in-process based communication
|
||||
```java
|
||||
ServerParameters params = ServerParameters.builder("npx")
|
||||
.args("-y", "@modelcontextprotocol/server-everything", "dir")
|
||||
.build();
|
||||
McpTransport transport = new StdioClientTransport(params);
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="SSE (HttpClient)">
|
||||
Creates a framework agnostic (pure Java API) SSE client transport. Included in the core mcp module.
|
||||
```java
|
||||
McpTransport transport = new HttpClientSseClientTransport("http://your-mcp-server");
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="SSE (WebFlux)">
|
||||
Creates WebFlux-based SSE client transport. Requires the mcp-webflux-sse-transport dependency.
|
||||
```java
|
||||
WebClient.Builder webClientBuilder = WebClient.builder()
|
||||
.baseUrl("http://your-mcp-server");
|
||||
McpTransport transport = new WebFluxSseClientTransport(webClientBuilder);
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Client Capabilities
|
||||
|
||||
The client can be configured with various capabilities:
|
||||
|
||||
```java
|
||||
var capabilities = ClientCapabilities.builder()
|
||||
.roots(true) // Enable filesystem roots support with list changes notifications
|
||||
.sampling() // Enable LLM sampling support
|
||||
.build();
|
||||
```
|
||||
|
||||
### Roots Support
|
||||
|
||||
Roots define the boundaries of where servers can operate within the filesystem:
|
||||
|
||||
```java
|
||||
// Add a root dynamically
|
||||
client.addRoot(new Root("file:///path", "description"));
|
||||
|
||||
// Remove a root
|
||||
client.removeRoot("file:///path");
|
||||
|
||||
// Notify server of roots changes
|
||||
client.rootsListChangedNotification();
|
||||
```
|
||||
|
||||
The roots capability allows servers to:
|
||||
|
||||
- Request the list of accessible filesystem roots
|
||||
- Receive notifications when the roots list changes
|
||||
- Understand which directories and files they have access to
|
||||
|
||||
|
||||
### Sampling Support
|
||||
|
||||
Sampling enables servers to request LLM interactions ("completions" or "generations") through the client:
|
||||
|
||||
```java
|
||||
// Configure sampling handler
|
||||
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
|
||||
// Sampling implementation that interfaces with LLM
|
||||
return new CreateMessageResult(response);
|
||||
};
|
||||
|
||||
// Create client with sampling support
|
||||
var client = McpClient.sync(transport)
|
||||
.capabilities(ClientCapabilities.builder()
|
||||
.sampling()
|
||||
.build())
|
||||
.sampling(samplingHandler)
|
||||
.build();
|
||||
```
|
||||
|
||||
This capability allows:
|
||||
- Servers to leverage AI capabilities without requiring API keys
|
||||
- Clients to maintain control over model access and permissions
|
||||
- Support for both text and image-based interactions
|
||||
- Optional inclusion of MCP server context in prompts
|
||||
|
||||
|
||||
## Using MCP Clients
|
||||
|
||||
### 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.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// List available tools
|
||||
var tools = client.listTools();
|
||||
tools.forEach(tool -> System.out.println(tool.getName()));
|
||||
|
||||
// Execute a tool
|
||||
var result = client.callTool("calculator", Map.of(
|
||||
"operation", "add",
|
||||
"a", 1,
|
||||
"b", 2
|
||||
));
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async API">
|
||||
```java
|
||||
// List available tools
|
||||
client.listTools()
|
||||
.doOnNext(tools -> tools.forEach(tool ->
|
||||
System.out.println(tool.getName())))
|
||||
.subscribe();
|
||||
|
||||
// Execute a tool
|
||||
client.callTool("calculator", Map.of(
|
||||
"operation", "add",
|
||||
"a", 1,
|
||||
"b", 2
|
||||
))
|
||||
.subscribe();
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 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.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// List available resources
|
||||
var resources = client.listResources();
|
||||
resources.forEach(resource -> System.out.println(resource.getName()));
|
||||
|
||||
// Get a resource
|
||||
var content = client.getResource("file", Map.of(
|
||||
"path", "/path/to/file.txt"
|
||||
));
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async API">
|
||||
```java
|
||||
// List available resources
|
||||
client.listResources()
|
||||
.doOnNext(resources -> resources.forEach(resource ->
|
||||
System.out.println(resource.getName())))
|
||||
.subscribe();
|
||||
|
||||
// Get a resource
|
||||
client.getResource("file", Map.of(
|
||||
"path", "/path/to/file.txt"
|
||||
))
|
||||
.subscribe();
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 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.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// List available prompts
|
||||
var prompts = client.listPrompts();
|
||||
prompts.forEach(prompt -> System.out.println(prompt.getName()));
|
||||
|
||||
// Execute a prompt
|
||||
var response = client.executePrompt("echo", Map.of(
|
||||
"text", "Hello, World!"
|
||||
));
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async API">
|
||||
```java
|
||||
// List available prompts
|
||||
client.listPrompts()
|
||||
.doOnNext(prompts -> prompts.forEach(prompt ->
|
||||
System.out.println(prompt.getName())))
|
||||
.subscribe();
|
||||
|
||||
// Execute a prompt
|
||||
client.executePrompt("echo", Map.of(
|
||||
"text", "Hello, World!"
|
||||
))
|
||||
.subscribe();
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
167
sdk/java/mcp-overview.mdx
Normal file
167
sdk/java/mcp-overview.mdx
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
---
|
||||
title: Overview
|
||||
description: Introduction to the Model Context Protocol (MCP) Java SDK
|
||||
---
|
||||
|
||||
Java SDK for the [Model Context Protocol](https://modelcontextprotocol.org/docs/concepts/architecture)
|
||||
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:
|
||||
- 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
|
||||
- [Roots](https://spec.modelcontextprotocol.io/specification/2024-11-05/client/roots/) list management and notifications
|
||||
- [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:
|
||||
- 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
|
||||
- WebMVC SSE transport for servlet-based HTTP streaming
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||

|
||||
|
||||
The SDK follows a layered architecture with clear separation of concerns:
|
||||
|
||||
- **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.
|
||||
- **Transport Layer (McpTransport)**: Handles JSON-RPC message serialization/deserialization via:
|
||||
- StdioTransport (stdin/stdout) in the core module
|
||||
- HTTP SSE transports in dedicated transport modules (Java HttpClient, Spring WebFlux, Spring WebMVC)
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
Key Interactions:
|
||||
|
||||
- **Client/Server Initialization**: Transport setup, protocol compatibility check, capability negotiation, and implementation details exchange.
|
||||
- **Message Flow**: JSON-RPC message handling with validation, type-safe response processing, and error handling.
|
||||
- **Resource Management**: Resource discovery, URI template-based access, subscription system, and content retrieval.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Add the following Maven dependency to your project:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Maven">
|
||||
The core MCP functionality:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
||||
<artifactId>mcp</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
For HTTP SSE transport implementations, add one of the following dependencies:
|
||||
|
||||
```xml
|
||||
<!-- Spring WebFlux-based SSE client and server transport -->
|
||||
<dependency>
|
||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
||||
<artifactId>mcp-spring-webflux</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring WebMVC-based SSE server transport -->
|
||||
<dependency>
|
||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
||||
<artifactId>mcp-spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Gradle">
|
||||
The core MCP functionality:
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation platform("io.modelcontextprotocol.sdk:mcp")
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
For HTTP SSE transport implementations, add one of the following dependencies:
|
||||
|
||||
```groovy
|
||||
// Spring WebFlux-based SSE client and server transport
|
||||
dependencies {
|
||||
implementation platform("io.modelcontextprotocol.sdk:mcp-spring-webflux")
|
||||
}
|
||||
|
||||
// Spring WebMVC-based SSE server transport
|
||||
dependencies {
|
||||
implementation platform("io.modelcontextprotocol.sdk:mcp-spring-webmvc")
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Bill of Materials (BOM)
|
||||
|
||||
The Bill of Materials (BOM) declares the recommended versions of all the dependencies used by a given release.
|
||||
Using the BOM from your application's build script avoids the need for you to specify and maintain the dependency versions yourself.
|
||||
Instead, the version of the BOM you're using determines the utilized dependency versions.
|
||||
It also ensures that you're using supported and tested versions of the dependencies by default, unless you choose to override them.
|
||||
|
||||
Add the BOM to your project:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Maven">
|
||||
```xml
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.modelcontextprotocol.sdk</groupId>
|
||||
<artifactId>mcp-bom</artifactId>
|
||||
<version>0.7.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Gradle">
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation platform("io.modelcontextprotocol.sdk:mcp-bom:0.7.0-SNAPSHOT")
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
Gradle users can also use the Spring AI MCP BOM by leveraging Gradle (5.0+) native support for declaring dependency constraints using a Maven BOM.
|
||||
This is implemented by adding a 'platform' dependency handler method to the dependencies section of your Gradle build script.
|
||||
As shown in the snippet above this can then be followed by version-less declarations of the Starter Dependencies for the one or more spring-ai modules you wish to use, e.g. spring-ai-openai.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Replace the version number with the version of the BOM you want to use.
|
||||
|
||||
### Available Dependencies
|
||||
|
||||
The following dependencies are available and managed by the BOM:
|
||||
|
||||
- Core Dependencies
|
||||
- `io.modelcontextprotocol.sdk:mcp` - Core MCP library providing the base functionality and APIs for Model Context Protocol implementation.
|
||||
- Transport Dependencies
|
||||
- `io.modelcontextprotocol.sdk:mcp-spring-webflux` - WebFlux-based Server-Sent Events (SSE) transport implementation for reactive applications.
|
||||
- `io.modelcontextprotocol.sdk:mcp-spring-webmvc` - WebMVC-based Server-Sent Events (SSE) transport implementation for servlet-based applications.
|
||||
- Testing Dependencies
|
||||
- `io.modelcontextprotocol.sdk:mcp-test` - Testing utilities and support for MCP-based applications.
|
||||
|
||||
368
sdk/java/mcp-server.mdx
Normal file
368
sdk/java/mcp-server.mdx
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
---
|
||||
title: MCP Server
|
||||
description: Learn how to implement and configure a Model Context Protocol (MCP) server
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
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, responsible for:
|
||||
|
||||
- Exposing tools that clients can discover and execute
|
||||
- Managing resources with URI-based access patterns
|
||||
- Providing prompt templates and handling prompt requests
|
||||
- Supporting capability negotiation with clients
|
||||
- Implementing server-side protocol operations
|
||||
- Managing concurrent client connections
|
||||
- Providing structured logging and notifications
|
||||
|
||||
The server supports both synchronous and asynchronous APIs, allowing for flexible integration in different application contexts.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// Create a server with custom configuration
|
||||
McpSyncServer syncServer = McpServer.sync(transport)
|
||||
.serverInfo("my-server", "1.0.0")
|
||||
.capabilities(ServerCapabilities.builder()
|
||||
.resources(true) // Enable resource support
|
||||
.tools(true) // Enable tool support
|
||||
.prompts(true) // Enable prompt support
|
||||
.logging() // Enable logging support
|
||||
.build())
|
||||
.build();
|
||||
|
||||
// Initialize the server
|
||||
syncServer.initialize();
|
||||
|
||||
// Register tools, resources, and prompts
|
||||
syncServer.addTool(syncToolRegistration);
|
||||
syncServer.addResource(syncResourceRegistration);
|
||||
syncServer.addPrompt(syncPromptRegistration);
|
||||
|
||||
// Send logging notifications
|
||||
syncServer.loggingNotification(LoggingMessageNotification.builder()
|
||||
.level(LoggingLevel.INFO)
|
||||
.logger("custom-logger")
|
||||
.data("Server initialized")
|
||||
.build());
|
||||
|
||||
// Close the server when done
|
||||
syncServer.close();
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async API">
|
||||
```java
|
||||
// Create an async server with custom configuration
|
||||
McpAsyncServer asyncServer = McpServer.async(transport)
|
||||
.serverInfo("my-server", "1.0.0")
|
||||
.capabilities(ServerCapabilities.builder()
|
||||
.resources(true) // Enable resource support
|
||||
.tools(true) // Enable tool support
|
||||
.prompts(true) // Enable prompt support
|
||||
.logging() // Enable logging support
|
||||
.build())
|
||||
.build();
|
||||
|
||||
// Initialize the server
|
||||
asyncServer.initialize()
|
||||
.doOnSuccess(v -> logger.info("Server initialized"))
|
||||
.subscribe();
|
||||
|
||||
// Register tools, resources, and prompts
|
||||
asyncServer.addTool(asyncToolRegistration)
|
||||
.doOnSuccess(v -> logger.info("Tool registered"))
|
||||
.subscribe();
|
||||
|
||||
asyncServer.addResource(asyncResourceRegistration)
|
||||
.doOnSuccess(v -> logger.info("Resource registered"))
|
||||
.subscribe();
|
||||
|
||||
asyncServer.addPrompt(asyncPromptRegistration)
|
||||
.doOnSuccess(v -> logger.info("Prompt registered"))
|
||||
.subscribe();
|
||||
|
||||
// Send logging notifications
|
||||
asyncServer.loggingNotification(LoggingMessageNotification.builder()
|
||||
.level(LoggingLevel.INFO)
|
||||
.logger("custom-logger")
|
||||
.data("Server initialized")
|
||||
.build());
|
||||
|
||||
// Close the server when done
|
||||
asyncServer.close()
|
||||
.doOnSuccess(v -> logger.info("Server closed"))
|
||||
.subscribe();
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
## Server Transport
|
||||
|
||||
The transport layer in the MCP SDK is responsible for handling the communication between clients and servers. It provides different implementations to support various communication protocols and patterns. The SDK includes several built-in transport implementations:
|
||||
|
||||
<Tabs>
|
||||
|
||||
<Tab title="STDIO">
|
||||
<>
|
||||
Create in-process based transport:
|
||||
|
||||
```java
|
||||
StdioServerTransport transport = new StdioServerTransport(new ObjectMapper());
|
||||
```
|
||||
|
||||
Provides bidirectional JSON-RPC message handling over standard input/output streams with non-blocking message processing, serialization/deserialization, and graceful shutdown support.
|
||||
|
||||
Key features:
|
||||
<ul>
|
||||
<li>Bidirectional communication through stdin/stdout</li>
|
||||
<li>Process-based integration support</li>
|
||||
<li>Simple setup and configuration</li>
|
||||
<li>Lightweight implementation</li>
|
||||
</ul>
|
||||
</>
|
||||
</Tab>
|
||||
|
||||
<Tab title="SSE (WebFlux)">
|
||||
<>
|
||||
<p>Creates WebFlux-based SSE server transport.<br />Requires the <code>mcp-spring-webflux</code> dependency.</p>
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
class McpConfig {
|
||||
@Bean
|
||||
WebFluxSseServerTransport webFluxSseServerTransport(ObjectMapper mapper) {
|
||||
return new WebFluxSseServerTransport(mapper, "/mcp/message");
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransport transport) {
|
||||
return transport.getRouterFunction();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<p>Implements the MCP HTTP with SSE transport specification, providing:</p>
|
||||
<ul>
|
||||
<li>Reactive HTTP streaming with WebFlux</li>
|
||||
<li>Concurrent client connections through SSE endpoints</li>
|
||||
<li>Message routing and session management</li>
|
||||
<li>Graceful shutdown capabilities</li>
|
||||
</ul>
|
||||
</>
|
||||
</Tab>
|
||||
|
||||
|
||||
<Tab title="SSE (WebMvc)">
|
||||
<>
|
||||
<p>Creates WebMvc-based SSE server transport.<br />Requires the <code>mcp-spring-webmvc</code> dependency.</p>
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class McpConfig {
|
||||
@Bean
|
||||
WebMvcSseServerTransport webMvcSseServerTransport(ObjectMapper mapper) {
|
||||
return new WebMvcSseServerTransport(mapper, "/mcp/message");
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<ServerResponse> mcpRouterFunction(WebMvcSseServerTransport transport) {
|
||||
return transport.getRouterFunction();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<p>Implements the MCP HTTP with SSE transport specification, providing:</p>
|
||||
<ul>
|
||||
<li>Server-side event streaming</li>
|
||||
<li>Integration with Spring WebMVC</li>
|
||||
<li>Support for traditional web applications</li>
|
||||
<li>Synchronous operation handling</li>
|
||||
</ul>
|
||||
</>
|
||||
</Tab>
|
||||
|
||||
|
||||
<Tab title="SSE (Servlet)">
|
||||
<>
|
||||
<p>
|
||||
Creates a Servlet-based SSE server transport. It is included in the core <code>mcp</code> module.<br />
|
||||
The <code>HttpServletSseServerTransport</code> can be used with any Servlet container.<br />
|
||||
To use it with a Spring Web application, you can register it as a Servlet bean:
|
||||
</p>
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class McpServerConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public HttpServletSseServerTransport servletSseServerTransport() {
|
||||
return new HttpServletSseServerTransport(new ObjectMapper(), "/mcp/message");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean customServletBean(HttpServletSseServerTransport servlet) {
|
||||
return new ServletRegistrationBean(servlet);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<p>
|
||||
Implements the MCP HTTP with SSE transport specification using the traditional Servlet API, providing:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Asynchronous message handling using Servlet 6.0 async support</li>
|
||||
<li>Session management for multiple client connections</li>
|
||||
<li>
|
||||
Two types of endpoints:
|
||||
<ul>
|
||||
<li>SSE endpoint (<code>/sse</code>) for server-to-client events</li>
|
||||
<li>Message endpoint (configurable) for client-to-server requests</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Error handling and response formatting</li>
|
||||
<li>Graceful shutdown support</li>
|
||||
</ul>
|
||||
</>
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
|
||||
## Server Capabilities
|
||||
|
||||
The server can be configured with various capabilities:
|
||||
|
||||
```java
|
||||
var capabilities = ServerCapabilities.builder()
|
||||
.resources(false, true) // Resource support with list changes notifications
|
||||
.tools(true) // Tool support with list changes notifications
|
||||
.prompts(true) // Prompt support with list changes notifications
|
||||
.logging() // Enable logging support (enabled by default with loging level INFO)
|
||||
.build();
|
||||
```
|
||||
|
||||
### Logging Support
|
||||
|
||||
The server provides structured logging capabilities that allow sending log messages to clients with different severity levels:
|
||||
|
||||
```java
|
||||
// Send a log message to clients
|
||||
server.loggingNotification(LoggingMessageNotification.builder()
|
||||
.level(LoggingLevel.INFO)
|
||||
.logger("custom-logger")
|
||||
.data("Custom log message")
|
||||
.build());
|
||||
```
|
||||
|
||||
Clients can control the minimum logging level they receive through the `mcpClient.setLoggingLevel(level)` request. Messages below the set level will be filtered out.
|
||||
Supported logging levels (in order of increasing severity): DEBUG (0), INFO (1), NOTICE (2), WARNING (3), ERROR (4), CRITICAL (5), ALERT (6), EMERGENCY (7)
|
||||
|
||||
### Tool Registration
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync">
|
||||
```java
|
||||
// Sync tool registration
|
||||
var syncToolRegistration = new McpServerFeatures.SyncToolRegistration(
|
||||
new Tool("calculator", "Basic calculator", Map.of(
|
||||
"operation", "string",
|
||||
"a", "number",
|
||||
"b", "number"
|
||||
)),
|
||||
arguments -> {
|
||||
// Tool implementation
|
||||
return new CallToolResult(result, false);
|
||||
}
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async">
|
||||
```java
|
||||
// Async tool registration
|
||||
var asyncToolRegistration = new McpServerFeatures.AsyncToolRegistration(
|
||||
new Tool("calculator", "Basic calculator", Map.of(
|
||||
"operation", "string",
|
||||
"a", "number",
|
||||
"b", "number"
|
||||
)),
|
||||
arguments -> {
|
||||
// Tool implementation
|
||||
return Mono.just(new CallToolResult(result, false));
|
||||
}
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Resource Registration
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync">
|
||||
```java
|
||||
// Sync resource registration
|
||||
var syncResourceRegistration = new McpServerFeatures.SyncResourceRegistration(
|
||||
new Resource("custom://resource", "name", "description", "mime-type", null),
|
||||
request -> {
|
||||
// Resource read implementation
|
||||
return new ReadResourceResult(contents);
|
||||
}
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async">
|
||||
```java
|
||||
// Async resource registration
|
||||
var asyncResourceRegistration = new McpServerFeatures.AsyncResourceRegistration(
|
||||
new Resource("custom://resource", "name", "description", "mime-type", null),
|
||||
request -> {
|
||||
// Resource read implementation
|
||||
return Mono.just(new ReadResourceResult(contents));
|
||||
}
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Prompt Registration
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync">
|
||||
```java
|
||||
// Sync prompt registration
|
||||
var syncPromptRegistration = new McpServerFeatures.SyncPromptRegistration(
|
||||
new Prompt("greeting", "description", List.of(
|
||||
new PromptArgument("name", "description", true)
|
||||
)),
|
||||
request -> {
|
||||
// Prompt implementation
|
||||
return new GetPromptResult(description, messages);
|
||||
}
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async">
|
||||
```java
|
||||
// Async prompt registration
|
||||
var asyncPromptRegistration = new McpServerFeatures.AsyncPromptRegistration(
|
||||
new Prompt("greeting", "description", List.of(
|
||||
new PromptArgument("name", "description", true)
|
||||
)),
|
||||
request -> {
|
||||
// Prompt implementation
|
||||
return Mono.just(new GetPromptResult(description, messages));
|
||||
}
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Error Handling
|
||||
|
||||
The SDK provides comprehensive error handling through the McpError class, covering protocol compatibility, transport communication, JSON-RPC messaging, tool execution, resource management, prompt handling, timeouts, and connection issues. This unified error handling approach ensures consistent and reliable error management across both synchronous and asynchronous operations.
|
||||
Loading…
Reference in a new issue