乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • Spring AI 学习路径
  • 第1章 Spring AI 概述与核心理念

    • 章节导读
    • Spring AI 概述与可移植 API
    • 核心模块与依赖关系
  • 第2章 快速入门与第一个AI应用

    • 章节导读
    • 环境准备与配置
    • 第一个 AI 对话应用
  • 第3章 聊天模型与ChatClient

    • 章节导读
    • ChatClient 详解
    • ChatModel 底层抽象
    • 多轮对话与 ChatMemory
  • 第4章 提示词管理与模板

    • 章节导读
    • Prompt 与 Message 体系
    • 提示词模板与动态构建
  • 第5章 输出解析与结构化响应

    • 章节导读
    • 输出解析器与 BeanOutputConverter
  • 第6章 嵌入模型与向量存储

    • 章节导读
    • EmbeddingModel 与文本向量化
    • ETL 数据注入流水线
    • 向量存储抽象与配置
  • 第7章 检索增强生成(RAG)

    • 章节导读
    • RAG 核心机制与流程
    • QuestionAnswerAdvisor 详解
    • RAG 实战案例
  • 第8章 函数调用(Function Calling)

    • 章节导读
    • Tool 注解与函数声明
    • 函数调用实战
  • 第9章 多模态

    • 章节导读
    • 图像输入与视觉模型
    • 图像生成
  • 第10章 Advisor拦截器链

    • 章节导读
    • Advisor 链与内置拦截器
  • 第11章 MCP 协议与跨语言工具集成

    • 章节导读
    • MCP 协议深入
  • 第12章 可观测性测试与最佳实践

    • 章节导读
    • 可观测性与指标监控
    • 测试策略与 Mock 实践
    • 最佳实践与面试考点汇总

大翔敲着白板:"我们 Python 团队写了一套天气预报 API,Java 这边要用。别给我搞 REST 对接那一套——用 MCP,一行配置搞定。"

MCP 协议深入

定义与作用

MCP(Model Context Protocol)是由 Anthropic 发起、多家 AI 厂商共同支持的开放协议,标准化 AI 应用与外部工具/数据源之间的通信。Spring AI 作为 MCP Client,通过 Stdio 子进程或 HTTP 远程连接消费 MCP Server 暴露的工具。

核心原理

MCP 架构

图释:AI 模型决定调用工具 → Spring AI 通过 MCP Client 发送 JSON-RPC 请求 → MCP Server 执行 Python 代码 → 结果沿原路返回 → AI 基于工具结果生成最终回复。

两种传输方式

传输方式通信机制部署模式适用场景
Stdio进程 stdin/stdoutMCP Server 作为子进程本地工具、开发环境
HTTP (SSE)HTTP + Server-Sent Events独立服务远程工具、生产环境

完整示例一:Stdio 传输——Python 天气工具

场景说明

大翔要求 Python 团队实现天气预报工具,Java 智能客服通过 MCP Stdio 调用。

Python MCP Server 端

# weather_server.py
from mcp.server import Server, stdio
from mcp.types import Tool, TextContent
import json

server = Server("weather-server")

@server.tool()
async def get_weather(city: str) -> list[TextContent]:
    """获取指定城市的当前天气信息"""
    weather_data = {
        "北京": "晴,25°C,湿度 40%,风力 2 级",
        "上海": "多云,28°C,湿度 65%,风力 3 级",
        "广州": "雷阵雨,30°C,湿度 80%,风力 4 级",
    }
    result = weather_data.get(city, f"暂无 {city} 的天气数据")
    return [TextContent(type="text", text=result)]

@server.tool()
async def get_forecast(city: str, days: int = 3) -> list[TextContent]:
    """获取指定城市的未来天气预报"""
    forecast = f"{city}未来{days}天:第一天晴,第二天多云,第三天小雨"
    return [TextContent(type="text", text=forecast)]

if __name__ == "__main__":
    stdio.run(server)

Java MCP Client 配置

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-spring-boot-starter</artifactId>
</dependency>
spring:
  ai:
    mcp:
      client:
        type: SYNC
        name: weather-mcp-client
        version: 1.0.0
        request-timeout: 30s
        toolchange-notification: true
      connections:
        weather:
          transport: stdio
          command: python
          args:
            - weather_server.py
          working-directory: /path/to/python/tools
@Configuration
public class McpConfig {

    @Bean
    public ChatClient chatClient(
            ChatClient.Builder builder,
            McpClient mcpClient) {
        
        // 从 MCP Server 发现所有工具并注册
        ToolCallback[] mcpTools = mcpClient.listTools().stream()
            .map(tool -> FunctionCallback.builder()
                .name(tool.name())
                .description(tool.description())
                .inputType(String.class)  // 简单参数可用 String
                .responseConverter(r -> r)
                .function(ctx -> {
                    String result = mcpClient.callTool(
                        new McpToolCallRequest(tool.name(), ctx));
                    return result;
                })
                .build())
            .toArray(ToolCallback[]::new);

        return builder
            .defaultTools((Object[]) mcpTools)
            .build();
    }
}

运行结果

用户:"今天广州天气怎么样?"

日志:
[Spring AI] AI 决定调用工具: getWeather
[Spring AI] MCP tools/call → weather-server (Stdio)
[Python MCP] 查询广州天气...
[Spring AI] 工具返回: "雷阵雨,30°C,湿度 80%,风力 4 级"

AI 回复:"今天广州是雷阵雨天气,气温 30°C,湿度较高达 80%,伴有 4 级风。建议带伞出行!"

完整示例二:HTTP 传输——远程课程查询

场景说明

飞翔科技的课程数据库由独立的微服务管理,通过 MCP HTTP 方式暴露课程查询工具。

Java MCP Server 端(HTTP 传输)

# 课程查询 MCP Server 的 application.yml
spring:
  ai:
    mcp:
      server:
        name: course-mcp-server
        version: 1.0.0
        type: SYNC
        protocol: STREAMABLE  # HTTP + SSE
        port: 8081
// 课程查询工具
@Component
public class CourseTools {

    @Tool(description = "查询课程信息,输入课程名称或代码")
    public String getCourseInfo(String courseName) {
        // 模拟课程数据库查询
        return switch (courseName) {
            case "CS101" -> """
                课程代码: CS101
                课程名称: 数据结构与算法
                授课教师: 白歌
                学分: 4
                时间: 周一 8:00-10:00, 周三 10:00-12:00
                教室: 飞翔楼 301
                """;
            case "MATH201" -> """
                课程代码: MATH201
                课程名称: 线性代数
                授课教师: 大翔
                学分: 3
                时间: 周二 14:00-16:00
                教室: 飞翔楼 205
                """;
            default -> "未找到课程: " + courseName;
        };
    }

    @Tool(description = "查询教师的所有课程安排")
    public String getTeacherSchedule(String teacherName) {
        if ("白歌".equals(teacherName)) {
            return "白歌老师本学期课程:CS101 数据结构与算法、CS305 软件架构设计";
        }
        return teacherName + "老师本学期暂无课程安排";
    }
}

Java MCP Client 端配置

spring:
  ai:
    mcp:
      connections:
        course-service:
          transport: http
          url: http://localhost:8081/mcp
          sse-endpoint: http://localhost:8081/mcp/sse
@RestController
public class McpCourseController {

    private final ChatClient chatClient;

    public McpCourseController(
            ChatClient.Builder builder,
            @Qualifier("courseMcpTools") ToolCallback[] courseTools) {
        this.chatClient = builder
                .defaultTools((Object[]) courseTools)
                .build();
    }

    @GetMapping("/mcp/course")
    public String askCourse(@RequestParam String question) {
        return chatClient.prompt()
                .user(question)
                .call()
                .content();
    }
}

运行结果

用户:"白歌老师这学期教什么课?"

AI 调用工具: getTeacherSchedule("白歌")
工具返回: "白歌老师本学期课程:CS101 数据结构与算法、CS305 软件架构设计"

AI 回复:"白歌老师这学期教授两门课程:CS101 数据结构与算法,以及 CS305 软件架构设计。"

MCP vs 直接 @Tool

维度@Tool(进程内)MCP
实现语言必须 JavaPython / TS / Go / Java 任意语言
部署方式同一 JVM 进程独立子进程或远程服务
隔离性共享 JVM 内存进程/网络隔离
更新方式需重新部署整个应用独立更新 MCP Server
适用场景轻量级函数调用跨语言/跨团队/微服务集成
调试在同一 IDE 内需分别启动 Client 和 Server

易错场景与面试考点

易错场景一:Stdio 路径错误导致连接失败

# ❌ 错误:command 路径未找到
connections:
  weather:
    transport: stdio
    command: python    # 若环境变量未配置可能失败
    args:
      - weather_server.py

问题分析

Stdio 依赖系统 PATH 环境变量。Python 不在 PATH 中时需使用绝对路径,或使用 python3。

# ✅ 正确:使用绝对路径
connections:
  weather:
    transport: stdio
    command: /usr/local/bin/python3
    args:
      - /absolute/path/to/weather_server.py

面试高频题

Q1:MCP 协议的通信流程是怎样的?

①MCP Client 通过 tools/list 发现 Server 提供的工具及 JSON Schema;②AI 模型决定调用工具时,MCP Client 通过 tools/call 发送函数名和参数;③MCP Server 执行工具并返回结果;④Client 将结果封装为 ToolResponseMessage 返回给 AI 模型。全程使用 JSON-RPC 2.0 协议。

Q2:Stdio 和 HTTP 传输如何选择?

Stdio 适合同一台机器上的本地工具,通过子进程隔离,零网络开销;HTTP 适合远程微服务工具,支持分布式部署和水平扩展。生产环境推荐 HTTP,开发环境可用 Stdio。

本章小结

  • MCP 是跨语言工具集成的开放标准协议
  • Client/Server 架构:Server 暴露工具,Client 消费工具
  • Stdio 适合本地子进程,HTTP 适合远程微服务
  • Spring AI 通过 McpClient 自动发现并注册 MCP 工具到 ChatClient
  • MCP 解决了"跨语言"和"跨进程"两大企业级工具集成难题
上一页
章节导读