🔥 手把手教你用 MCP + DeepSeek 实现天气预报功能(Java 版)

一、MCP 核心概念解析

1.1 MCP 是什么?

MCP(Model Context Protocol)是由 Anthropic 提出的模型上下文协议,专为解决大模型与外部工具/数据源的交互问题而设计。它通过标准化的通信协议,让 AI 模型能够像调用本地函数一样调用外部服务,例如:

  • 调用天气 API 获取实时数据
  • 操作数据库执行增删改查
  • 控制物联网设备开关状态

1.2 MCP 核心组件

组件 功能描述
MCP 主机 运行大模型的主体(如 Claude、VS Code 插件),负责解析用户请求和协调工具调用
MCP 客户端 管理与 MCP 服务器的连接,处理协议转换和消息序列化
MCP 服务器 封装具体工具能力(如天气查询、邮件发送),通过标准化接口暴露功能

1.3 MCP 与 Function Calling 的区别

特性 MCP Function Calling
跨平台支持 支持多语言、多框架集成 依赖特定模型(如 GPT-4)的接口
动态扩展 支持运行时动态加载新工具 需要硬编码函数调用逻辑
安全性 提供 API 密钥管理和权限控制 需手动实现安全机制
企业级能力 支持 SSE 流式通信和上下文管理 适合简单场景,缺乏复杂交互能力

二、开发环境准备

2.1 技术选型

  • Java 框架:Spring Boot 3.2(简化企业级开发)
  • HTTP 客户端:OkHttp 4.13(高性能网络请求)
  • JSON 处理:Jackson 2.16(高效解析响应数据)
  • MCP 库:spring-ai-mcp-starter(Spring AI 官方支持)

2.2 依赖配置(pom.xml)

<dependencies>
    <!-- Spring AI MCP -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-mcp-starter</artifactId>
        <version>1.0.3</version>
    </dependency>
    <!-- DeepSeek Java SDK -->
    <dependency>
        <groupId>com.deepseek</groupId>
        <artifactId>deepseek4j</artifactId>
        <version>2.0.1</version>
    </dependency>
    <!-- OkHttp -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.13.0</version>
    </dependency>
</dependencies>

三、MCP 服务器开发

3.1 创建天气查询工具

import org.springframework.ai.mcp.annotation.Tool;
import org.springframework.stereotype.Component;

@Component
public class WeatherTool {

    @Tool(
        name = "get_weather",
        description = "获取指定城市的实时天气信息",
        parameters = @Tool.Parameters(
            city = @Tool.Parameter(description = "城市名称", required = true)
        )
    )
    public String getWeather(String city) {
        // 调用 DeepSeek API 获取天气数据
        return DeepSeekClient.builder()
            .apiKey(System.getenv("DEEP_SEEK_KEY"))
            .build()
            .weather(city);
    }
}

3.2 配置 MCP 服务器

import org.springframework.ai.mcp.server.McpServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class McpConfig {

    @Bean
    public McpServerProperties mcpServerProperties() {
        McpServerProperties properties = new McpServerProperties();
        properties.setName("weather-mcp-server");
        properties.setVersion("1.0.0");
        properties.setType(McpServerProperties.Type.SYNC);
        return properties;
    }
}

四、DeepSeek API 集成

4.1 申请 DeepSeek API 密钥

  1. 访问 DeepSeek 开发者平台
  2. 注册账号并创建应用
  3. 获取 DEEP_SEEK_KEY(注意保密!)

4.2 实现天气查询逻辑

import okhttp3.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DeepSeekClient {

    private final OkHttpClient client = new OkHttpClient();
    private final String apiKey;
    private final ObjectMapper mapper = new ObjectMapper();

    public DeepSeekClient(String apiKey) {
        this.apiKey = apiKey;
    }

    public String weather(String city) {
        Request request = new Request.Builder()
            .url("https://api.deepseek.com/v1/weather")
            .header("Authorization", "Bearer " + apiKey)
            .post(RequestBody.create(
                mapper.writeValueAsString(new WeatherRequest(city)),
                MediaType.get("application/json")
            ))
            .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new IOException("请求失败");
            JsonNode data = mapper.readTree(response.body().string());
            return formatWeatherData(data);
        } catch (IOException e) {
            return "获取天气失败: " + e.getMessage();
        }
    }

    private String formatWeatherData(JsonNode data) {
        // 解析 JSON 数据并格式化
        return "城市: " + data.get("city") + "\n" +
               "温度: " + data.get("temp") + "°C\n" +
               "天气状况: " + data.get("desc");
    }

    static class WeatherRequest {
        private final String city;

        public WeatherRequest(String city) {
            this.city = city;
        }
    }
}

五、流程图设计

flowchart TD A[用户提问] --> B[MCP 主机解析请求] B -->|需要调用天气工具| C[MCP 客户端] C --> D[MCP 服务器] D --> E[调用 DeepSeek API] E --> F[获取天气数据] F --> D D --> C C --> B B --> G[生成最终回答] G --> H[返回给用户]

六、测试与验证

6.1 启动 MCP 服务器

java -jar weather-mcp-server.jar --spring.ai.mcp.server.enabled=true

6.2 测试工具调用

import org.springframework.ai.mcp.client.McpClient;
import org.springframework.ai.mcp.client.McpClients;

public class TestClient {

    public static void main(String[] args) {
        McpClient client = McpClients.create("http://localhost:8080/mcp");
        String result = client.invoke("get_weather", "{\"city\":\"北京\"}");
        System.out.println(result);
    }
}

6.3 预期输出

城市: 北京
温度: 25°C
天气状况: 晴

七、注意事项

  1. API 密钥安全:生产环境中切勿将密钥硬编码,建议使用环境变量或配置中心
  2. 网络请求优化:添加重试机制和超时控制(OkHttp 支持自动重试)
  3. 错误处理:对 API 调用结果进行合法性校验,避免返回空指针
  4. 性能调优:使用连接池管理 HTTP 连接(OkHttp 内置连接池)

八、扩展应用

  1. 多城市对比:支持查询多个城市天气并生成对比报告
  2. 天气预警:结合气象数据添加预警信息
  3. 历史查询:将查询记录存储到数据库,支持历史数据查询
  4. 语音播报:集成语音合成 API,实现语音播报天气

结语

通过 MCP 协议,我们可以轻松将大模型与外部服务集成,打造出更智能、更强大的 AI 应用。本文以天气预报为例,演示了如何使用 Java 开发 MCP 服务器并调用 DeepSeek API。读者可以根据实际需求扩展工具能力,例如接入股票数据、新闻资讯等,构建属于自己的智能中枢。