MCP实践:MCP Client 开发保姆教程(附全部代码)

1、概述

前两篇我们讲了MCP Server的开发(MCP实践:MCP Server 开发保姆教程(附全部代码))和使用(),这篇文章我们介绍下如何自己开发MCP Client来调用自己开发的MCP Server。

2、MCP Client开发

MCP Server 调用有两种方式,一种是Stdio模式,另一种是SSE模式。Stdio相当于是依赖包加载到本地进行运行,SSE模式相当于远程服务调用,这篇文章我们介绍使用SSE方式进行调用。

2.1、依赖相关

开发MCP对环境有要求,Jdk要求17+,SpringBoot要求【3.4.0+】 MCP-Client开发有两个依赖包,底层的技术一个是依赖Webmvc,另一个是依赖Webflux。Webmvc是基于Servlet的阻塞式模型,Webflux是一个异步非阻塞式的 Web 框架,它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。 具体两个依赖如下(目前最新版本【1.0.0-M6】):

xml 复制代码
<!-- stdio和webMvc是一个包-->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
    <version>${spring-ai.version}</version>
</dependency>

<!-- MCP client SSE 包-->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version>
</dependency>


<!--        Spring ai 大模型的实现-->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>${spring-ai.version}</version>
</dependency>

<!--    AI基础依赖(感觉应该是SPI接口,定义接口标准)-->
<dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-bom</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <type>pom</type>
    </dependency>
</dependencies>
</dependencyManagement>

2.2、代码开发

整体目录 代码开发比较简单,先看下整体目录,由于使用【spring-ai-openai-spring-boot-starter】包,因此许多组件在配置文件中配置完成后可以直接自动注入。

Controller

配置文件 配置文件比较简单,主要分为两部分

  • 配置大模型,这里使用火山引擎的豆包大模型,也可以使用其他,只要符合标准OpenAi格式就行
  • 配置MCP Server:这里要注意,开发的MCP Server 一定要是以SSE结尾的Endpoint,依赖里面进行强制拼接了(SSE),所以如果路由不正确的话会调不通(高德那个注释掉就是因为调不通)

下面是Client依赖包里面的源码(看网上说1.0的依赖已经修复,但是spring-mcp-client包还未更新到正式maven仓库)

3、功能验证

3.1、启动MCP Server

3.2、启动MCP Client

从MCP Client启动日志中看出订阅成功

从MCP Server启动日志中看出通信成功

3.3、调试

使用Postman进行调试

查看MCP Server发现已经被调用

MCP Server返回结果后,大模型对结果进行总结整理,输出如下

最终结果如下

4、总结

通过各个依赖组件发现,目前MCP相关发展还在初期,许多依赖不是特别完整。因此在开发过程中需要特别的注意配置及依赖版本等内容。如果遇到问题,我们可以进行源码调试,通过源码调试能让我们了解组件的原理。

5、源码

  • 依赖
xml 复制代码
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.young</groupId>
        <artifactId>my-agi</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>mcp-client</artifactId>
    <packaging>war</packaging>
    <name>mcp-client Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <build>
        <finalName>mcp-client</finalName>
    </build>

    <properties>
        <spring-ai.version>1.0.0-M6</spring-ai.version>
        <java.version>17</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <!--        stdio模式-->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
        <repository>
            <id>central-portal-snapshots</id>
            <name>Central Portal Snapshots</name>
            <url>https://central.sonatype.com/repository/maven-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>
  • McpClientController
kotlin 复制代码
package com.young.client.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * @author 刘子洋
 * @date 2025年05月14日 下午5:13
 * @description:mcp测试调用controller
 */
@RestController
@RequestMapping("/mcp")
public class McpClientController {

    private static final Logger log = LoggerFactory.getLogger(McpClientController.class);
    private final ChatClient chatClient;

    @Autowired
    public McpClientController(ChatClient.Builder mcpChatClientBuilder, ToolCallbackProvider tools) {
        this.chatClient = mcpChatClientBuilder.defaultTools(tools).build();
    }

    @PostMapping("/ask")
    public String ask(@RequestBody Map<String, String> question) {
        String response = chatClient.prompt(question.get("question")).call().content();
        log.info("response: {}", response);
        return "question: " + question + " <hr>"
                + response
                .replaceAll("\\*\\*(.*?)\\*\\*", "<strong>$1</strong>")
                .replaceAll("\n", "<br/>");
    }

    @GetMapping("/askModel")
    public String ask2(@RequestParam String question) {
        return chatClient.prompt().user(question).call().content();
    }
}
  • 配置文件
yaml 复制代码
spring:
  application:
    name: my-mcp-client
  ai:
    openai:
      api-key: ********
      base-url: https://ark.cn-beijing.volces.com/api
      chat:
        completions-path: /v3/chat/completions
        options:
          model: doubao-1-5-pro-256k-250115
    mcp:
      client:
        sse:
          connections:
            server1:
              url: http://localhost:8081
#            server2:
#              url: https://mcp.amap.com
#              sse-endpoint: /sse?key=********
server:
  port: 8082
相关推荐
GA琥珀6 分钟前
MCP目前的边界和局限
mcp
小阿鑫2 小时前
AI领域又新增协议: AG-UI
ai·agent·mcp·a2a·ag-ui
大模型真好玩3 小时前
做题王者,实战拉跨!是时候给马斯克的Grok4泼盆冷水了!(Grok 4模型详细测评报告)
人工智能·python·mcp
5ycode3 小时前
Dify 1.6.0 重磅上线:原生MCP 双向集成、结构化输出升级!
资讯·mcp
FLYINGPIG21 小时前
【MCP】小白详解从0开始构建MCP服务端全流程
mcp
围巾哥萧尘1 天前
[「掌握Trae IDE」 Trae+ GodotMCP + Godot,20 分钟用 AI 构建打砖块游戏🧣
mcp
掘金一周1 天前
Figma Dev Mode MCP:大人,时代变了 | 掘金一周7.10
前端·人工智能·mcp
人生偌只如初见1 天前
SpringAI学习笔记-MCP客户端简单示例
java·spring·ai·client·mcp
带刺的坐椅1 天前
Java MCP 鉴权设计与实现指南
java·安全·ai·solon·mcp
开国元帅1 天前
基于Spring AI的动态注册Tool:构建可扩展的多协议AI工具平台
mcp