Model Context Protocol(模型上下文协议)是一种面向AI服务编排的通信协议,其核心设计目标在于:
协议架构示意图:
组件 | 功能描述 | 实现示例 |
---|---|---|
Service Registry | 服务注册与发现 | Spring Cloud ServiceRegistry |
Protocol Adapter | 协议转换层 | STDIO/HTTP适配器 |
Context Manager | 会话上下文管理 | Redis会话存储 |
Tool Executor | 外部工具执行引擎 | MethodToolCallbackProvider |
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
@Bean
public ToolCallbackProvider weatherTools(OpenMeteoService service) {
return MethodToolCallbackProvider.builder()
.toolObjects(service)
.build();
}
}
关键配置解析:
@JsonIgnoreProperties(ignoreUnknown = true)
public record WeatherData(
@JsonProperty("latitude") Double latitude,
@JsonProperty("current") CurrentWeather current,
@JsonProperty("daily") DailyForecast daily) {
public record CurrentWeather(
@JsonProperty("temperature_2m") Double temperature,
@JsonProperty("weather_code") Integer weatherCode) {}
public record DailyForecast(
@JsonProperty("time") List<String> dates,
@JsonProperty("temperature_2m_max") List<Double> maxTemps) {}
}
模型设计特点:
@Tool(description = "获取指定经纬度的天气预报")
public String getWeatherForecastByLocation(
@ToolParam(description = "纬度") double latitude,
@ToolParam(description = "经度") double longitude) {
// 调用OpenMeteo API
WeatherData data = restClient.get()
.uri("/forecast?latitude={lat}&...", latitude, longitude)
.retrieve()
.body(WeatherData.class);
// 构建格式化响应
return buildWeatherReport(data);
}
注解解析:
application.yml关键配置:
spring:
main:
web-application-type: none # 禁用Web容器
banner-mode: off # 关闭启动Banner
ai:
mcp:
server:
name: weather-service
stdio: true # 启用STDIO通信
配置说明:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
CommandLineRunner queryRunner(ChatClient.Builder builder) {
return args -> {
ChatClient client = builder.build();
String response = client.prompt("北京的天气如何?").call().content();
System.out.println(response);
};
}
}
执行流程:
mcp-servers-config.json配置:
{
"mcpServers": {
"weather": {
"command": "java",
"args": [
"-jar",
"/path/to/server.jar"
]
}
}
}
配置要点:
STDIO通信流程:
协议特点:
API请求构造示例:
String uri = UriComponentsBuilder.fromPath("/forecast")
.queryParam("latitude", latitude)
.queryParam("longitude", longitude)
.queryParam("current", "temperature_2m,weather_code")
.queryParam("daily", "temperature_2m_max")
.queryParam("timezone", "auto")
.build()
.toUriString();
参数说明:
天气报告生成逻辑:
private String buildWeatherReport(WeatherData data) {
StringBuilder sb = new StringBuilder();
sb.append("当前天气:\n")
.append(String.format("温度:%.1f°C\n", data.current().temperature()))
.append(String.format("天气状况:%s\n", parseWeatherCode(data.current().weatherCode())));
sb.append("\n未来三天预报:\n");
for (int i = 0; i < 3; i++) {
sb.append(String.format("%s:最高%.1f°C\n",
formatDate(data.daily().dates().get(i)),
data.daily().maxTemps().get(i)));
}
return sb.toString();
}
格式化要点:
try {
return restClient.get()
.uri(/* ... */)
.retrieve()
.body(WeatherData.class);
} catch (RestClientException e) {
log.error("API请求失败", e);
return generateFallbackData(latitude, longitude);
}
private WeatherData generateFallbackData(double lat, double lon) {
// 生成模拟数据
return new WeatherData(lat, lon,
new CurrentWeather(25.5, 0),
new DailyForecast(List.of("2024-01-01"), List.of(26.0)));
}
容错策略:
服务编排示例:
@Tool(description = "综合天气分析")
public String analyzeWeather(String location) {
// 调用地理编码服务
Coordinate coord = geoService.geocode(location);
// 获取实时天气
String current = weatherService.getCurrentWeather(coord);
// 获取空气质量
String aqi = airQualityService.getAqiReport(coord);
// 生成分析报告
return analysisModel.analyze(current, aqi);
}
协同流程:
@Cacheable(value = "weather", key = "#lat + ',' + #lon")
public WeatherData getWeather(double lat, double lon) {
// API调用
}
缓存配置:
@Tool(description = "批量获取天气")
public Map<String, String> batchGetWeather(List<Coordinate> coords) {
return coords.parallelStream()
.collect(Collectors.toMap(
c -> c.toString(),
c -> getWeather(c.lat(), c.lon())
);
}
优化点: