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
相关推荐
tommyrunner8 小时前
换个角度认识 MCP
ai编程·cursor·mcp
loong_XL10 小时前
fastmcp MCPConfig多服务器使用案例;sse、stdio、streamable-http使用
服务器·agent·mcp
后端小肥肠10 小时前
让Mermaid听懂人话:用Coze空间+MCP一句话搞定所有业务图
人工智能·coze·mcp
dogstarhuang12 小时前
【快速入门到精通】MCP Typescript SDK核心概念和快速开发你的MCP
程序员·node.js·mcp
大然Ryan1 天前
MCP实战:从零开始写基于 Python 的 MCP 服务(附源码)
python·llm·mcp
程序员老刘1 天前
智能体三阶:LLM→Function Call→MCP
flutter·ai编程·mcp
curdcv_po1 天前
人人都是 AI 编程家竞赛——交给Trae🫡
ai编程·mcp·trae
IVAN不想说话1 天前
GPT-4o 中构建高精度的 MCP 工具与调用匹配策略指南
llm·mcp