创建 webmvc-mcp-server 项目
maven 依赖
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
创建 WeatherService 类
@Service
public class WeatherService {
@Tool(description = "Get weather forecast for a specific latitude/longitude")
public String getWeatherForecastByLocation(double latitude, double longitude) {
System.out.println("latitude:" + latitude + ",longitude:" + longitude);
return "ok";
}
}
注册方法回调
@SpringBootApplication
public class WebmvcMcpServerApplication {
public static void main(String[] args) {
SpringApplication.run(WebmvcMcpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
}
application.yaml 配置
# Using spring-ai-starter-mcp-server-webmvc
spring:
ai:
mcp:
server:
name: webmvc-mcp-server
version: 1.0.0
type: SYNC
instructions: "This server provides weather information tools and resources"
sse-message-endpoint: /mcp/messages
capabilities:
tool: true
resource: true
prompt: true
completion: true
运行 mcp-server
mvn spring-boot:run
创建 mcp-client 项目
maven 依赖
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注入 mcpSyncClients 调用 mcp-server 方法
@SpringBootApplication
public class McpClientApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(McpClientApplication.class, args);
}
@Autowired
private List<McpSyncClient> mcpSyncClients;
@Override
public void run(ApplicationArguments args) throws Exception {
for(McpSyncClient mcpSyncClient : mcpSyncClients) {
McpSchema.CallToolResult result = mcpSyncClient.callTool(new McpSchema.CallToolRequest(
"getWeatherForecastByLocation",
Map.of("latitude", "47.6062", "longitude", "-122.3321")));
System.out.println(result);
}
}
}
交互过程
sequenceDiagram
autonumber
participant Client
participant Server
Client ->> Server: Open SSE Connection
activate Server
Server -->> Client: Endpoint Event
loop Message Exchange
Client ->> Server: POST /mcp/message?sessionId=xxx
Server -->> Client: Message Event
end
Client ->> Server: Close SSE Connection
deactivate Server
curl 操作
curl -v http:
curl -v post "http://localhost:8080/mcp/messages?sessionId=bda664ee-6577-428b-af84-0f7e5d006395" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"initialize","id":"4d7c8c63-0","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-mcp-client - server1","version":"1.0.0"}}}'
curl -v post "http://localhost:8080/mcp/messages?sessionId=bda664ee-6577-428b-af84-0f7e5d006395" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}'
curl -v post "http://localhost:8080/mcp/messages?sessionId=bda664ee-6577-428b-af84-0f7e5d006395" \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tools/call","id":"35b2167d-1","params":{"name":"getWeatherForecastByLocation","arguments":{"longitude":"-122.3321","latitude":"47.6062"}}}'