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
相关推荐
寅时码11 小时前
消除大模型幻觉,让AI-IDE真正理解代码,打通LSP与AI的任督二脉
visual studio code·cursor·mcp
SugarPPig16 小时前
使用的IDE没有内置MCP客户端怎么办?
ide·mcp
ffutop17 小时前
MCP 能力探索
mcp
带刺的坐椅1 天前
Solon v3.4.2(Java 应用开发生态基座)
java·ai·solon·liteflow·mcp
青衫客361 天前
LLM—— 基于 MCP 协议(Stdio 模式)的工具调用实践
大模型·llm·mcp
友莘居士2 天前
本地使用postman调试mcp接口
测试工具·postman·sse·mcp
摘星编程2 天前
MCP提示词工程:上下文注入的艺术与科学
人工智能·提示词工程·a/b测试·mcp·上下文注入
思绪漂移2 天前
阿里云 【免费试用】MCP 赋能可视化 OLAP 智能体应用
阿里云·云计算·agent·云原生数据库·mcp
大模型真好玩2 天前
深入浅出LangChain AI Agent智能体开发教程(五)—LangChain接入工具基本流程
人工智能·python·mcp
idolyXyz3 天前
JSON-RPC 2.0 规范
ai·mcp