【保姆级图文详解】MCP架构(客户端-服务端)、三种方式使用MCP服务、Spring AI MCP客户端和服务端开发、MCP部署方案、MCP安全性

发布于:2025-07-14 ⋅ 阅读:(27) ⋅ 点赞:(0)


前言

若对您有帮助的话,请点赞收藏加关注哦,您的关注是我持续创作的动力!有问题请私信或联系邮箱:funian.gm@gmail.com

一、MCP(model context protocol)

1.1、概念描述

  • MCP(Model Context Protocol,模型上下文协议)是一种开放标准,目的是增强 AI 与外部系统的交互能力。它为 AI 提供了与外部工具、资源和服务交互的标准化方式,让 AI 能够访问最新数据、执行复杂操作,并与现有系统集成。
  • 根据官方定义,MCP 是一种开放协议,它标准化了应用程序如何向大模型提供上下文的方式,可以将 MCP 想象成 AI 应用的 USB 接口,为 AI 模型连接不同的数据源和工具提供了标准化的方法。

在这里插入图片描述

  • MCP 协议的 6 大核心概念:

    • Resources(资源):服务端向客户端提供各种数据,如文本、文件、数据库记录、API 响应等,客户端可决定何时使用这些资源,使 AI 能够访问最新信息和外部知识,为模型提供更丰富的上下文。
    • Prompts(提示词):服务端定义可复用的提示词模板和工作流,供客户端和用户直接使用,作用是标准化常见的 AI 交互模式,如作为 UI 元素(斜杠命令、快捷操作)呈现给用户,简化用户与 LLM 的交互过程。
    • Tools(工具):MCP 中最实用的特性,服务端提供给客户端可调用的函数,使 AI 模型能够执行计算、查询信息或与外部系统交互,极大扩展了 AI 的能力范围。
    • Sampling(采样):允许服务端通过客户端向大模型发送生成内容的请求(反向请求),使 MCP 服务能够实现复杂的智能代理行为,同时保持用户对整个过程的控制和数据隐私保护。
    • Roots(根目录):MCP 协议的安全机制,定义了服务器可以访问的文件系统位置,限制访问范围,为 MCP 服务提供安全边界,防止恶意文件访问。
    • Transports(传输):定义客户端和服务器间的通信方式,包括 Stdio(本地进程间通信)和 SSE(网络实时通信),确保不同环境下的可靠信息交换。
    • 开发 MCP 服务,根据MCP官方的描述,主要关注前 3 个概念,其中 Tools 工具是重中之重。

在这里插入图片描述

1.2、MCP作用与意义

  • MCP 协议的作用和意义:
    • 增强 AI 能力:通过 MCP 协议,AI 应用能够轻松接入他人提供的服务,从而实现更多功能,比如搜索网页、查询数据库、调用第三方 API、执行计算等。
    • 作为协议或标准:MCP 本身并不提供具体服务,而是定义了一套规范,让服务提供者和使用者共同遵守。这类似于 HTTP 协议,能有效降低开发者的理解成本。
    • 标准化的好处:以增加 AI 查询地图能力为例,若没有标准化,不同项目或开发者可能会重复开发相关功能,且质量和效果参差不齐。而 MCP 标准化后,官方或第三方可以将查询地图能力做成服务,供需要的人直接接入,节省开发成本且效果一致。若更多人开放服务,还能打造服务市场,造福开发者。
    • 标准造就生态:这并非新现象,可类比前端的 NPM 包、后端的 Maven 仓库和 Docker 镜像源,以及手机应用市场,都是通过标准形成生态,促进资源共享和行业发展。mcp体验的网址

在这里插入图片描述

1.3、MCP架构

  • 宏观架构:MCP 的核心是 “客户端 - 服务器” 架构,MCP 客户端主机可以连接到多个服务器。客户端主机是指希望访问 MCP 服务的程序,例如 Claude Desktop、IDE、AI 工具或部署在服务器上的项目。

在这里插入图片描述

  • MCP 客户端:MCP Client 是 MCP 架构中的关键组件,主要负责和 MCP 服务器建立连接并进行通信。它能自动匹配服务器的协议版本、确认可用功能、负责数据传输和 JSON-RPC 交互。此外,它还能发现和使用各种工具、管理资源、和提示词系统进行交互。除了核心功能,MCP 客户端还支持根管理、采样控制以及同步或异步操作等额外特性,并提供多种数据传输方式,包括适用于本地调用的 Stdio 标准输入 / 输出,以及适用于远程调用的基于 Java HttpClient 和 WebFlux 的 SSE 传输。客户端可以通过不同传输方式调用不同的 MCP 服务,既可以是本地的,也可以是远程的。

在这里插入图片描述

  • MCP 服务端:MCP Server 也是整个 MCP 架构的关键组件,主要用来为客户端提供各种工具、资源和功能支持。它负责处理客户端的请求,包括解析协议、提供工具、管理资源以及处理各种交互信息。同时,它还能记录日志、发送通知,并且支持多个客户端同时连接,保证高效的通信和协作。和客户端一样,它也可以通过多种方式进行数据传输,比如 Stdio 标准输入 / 输出、基于 Servlet / WebFlux / WebMVC 的 SSE 传输,以满足不同应用场景。这种设计使得客户端和服务端完全解耦,任何语言开发的客户端都可以调用 MCP 服务。

在这里插入图片描述

二、使用MCP(model context protocol)

  • 使用方式:本节将实战 3 种使用 MCP 的方式,分别是云平台使用 MCP、软件客户端使用 MCP 和程序中使用 MCP。无论哪种使用方式,原理类似,且有 2 种可选的使用模式,即本地下载 MCP 服务端代码并运行(类似引入 SDK),或者直接使用已部署的 MCP 服务(类似调用别人的 API)。
  • MCP 服务获取:目前有很多 MCP 服务市场,开发者可以在这些平台上找到各种现成的 MCP 服务,例如:
    • MCP.so:较为主流,提供丰富的 MCP 服务目录。
    • GitHub Awesome MCP Servers:开源 MCP 服务集合。
    • 阿里云百炼 MCP 服务市场。
    • Spring AI Alibaba 的 MCP 服务市场。
    • Glama.ai MCP 服务。
  • 其中,绝大多数 MCP 服务市场仅提供本地下载 MCP 服务端代码并运行的使用方式,因为部署 MCP 服务需要成本。不过,有些云服务平台提供了云端部署的 MCP 服务,比如阿里云百炼平台,在线填写配置后就能使用,可以轻松和平台上的 AI 应用集成,但一般局限性较大,不太能直接在自己的代码中使用。

在这里插入图片描述

2.1、云平台使用MCP

在这里插入图片描述

在这里插入图片描述

  • 3、使用高德地图的MCP服务,开通即可。

在这里插入图片描述

  • 4、在应用管理添加智能体,进入智能体应用,添加MCP服务。

在这里插入图片描述
在这里插入图片描述

  • 5、测试MCP服务。

在这里插入图片描述

2.2、软件客户端使用MCP

  • 支持情况:不同的客户端软件对 MCP 的支持程度不同,可在官方文档中查看各客户端支持的特性。
  • 以 Cursor 为例的演示:以主流 AI 客户端 Cursor 为例演示如何使用 MCP 服务,由于没有现成的部署了 MCP 服务的服务器,采用本地运行的方式。
  • 环境准备:首先安装本地运行 MCP 服务需要用到的工具,具体安装什么工具取决于 MCP 服务的配置要求。

具体步骤如下:

  • 1、MCP 市场找到高德地图 MCP,发现 Server Config 中定义了使用 npx 命令行工具来安装和运行服务端代码。

在这里插入图片描述

  • 2、从配置中还发现,使用地图 MCP 需要 API Key,可以到地图开放平台创建应用并添加 API Key。
    在这里插入图片描述

  • 3、打开Cursor客户端的聊天的设置界面。
    在这里插入图片描述

  • 4、添加高德的MCP服务,输入申请的MCP的API,保存配置。

在这里插入图片描述

在这里插入图片描述

  • 5、使用道德的MCP服务,测试验证。

在这里插入图片描述

2.3、Spring AI程序中使用MCP

  • 目标与框架选择:利用 Spring AI 框架,在程序中使用 MCP 实现一个能够根据另一半的位置推荐约会地点的 AI 助手。类似的 Java MCP 开发框架还有 Solon AI MCP,但由于更多地使用 Spring 生态,所以推荐使用 Spring AI 框架。
  • 学习文档建议:首先要了解 Spring AI MCP 客户端的基本使用方法,建议参考 Spring AI Alibaba 的文档,因为 Spring AI 官方文档更新太快,包的路径可能会变动。

在这里插入图片描述

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version>
</dependency>
  • 2、需要在resources目录下新建一个名为mcp-servers.json的配置文件,用于定义项目中需要用到的 MCP 服务。更改为自己的API_KAY。Windows 环境下的命令配置:在 Windows 环境下,命令配置需要添加.cmd后缀,例如npx.cmd,否则会出现找不到命令的错误。

在这里插入图片描述

  • 3、Spring 配置文件修改:需要修改 Spring 配置文件,编写 MCP 客户端配置。由于是本地运行 MCP 服务,所以使用stdio模式,并且要指定 MCP 服务配置文件的位置,具体代码需后续给出。
spring:
    ai:
      mcp:
        client:
          stdio:
            servers-configuration: classpath:mcp-servers.json

  • 4、编写测试代码。
 @Resource
    private ToolCallbackProvider toolCallbackProvider;

    /**
     * AI 旅游报告功能(调用 MCP 服务)
     *
     * @param message
     * @param chatId
     * @return
     */
    public String doChatWithMcp(String message, String chatId) {
        ChatResponse chatResponse = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 20))
                // 开启日志,便于观察效果
                .advisors(new LoggerAdvisor())
                .tools(toolCallbackProvider)
                .call()
                .chatResponse();
        String content = chatResponse.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }
  • 通过自动注入的ToolCallbackProvider获取到配置中定义的 MCP 服务提供的所有工具,并提供给ChatClient,具体代码需后续给出。
  • MCP 调用的本质,它类似工具调用,并非 AI 服务器主动调用 MCP 服务,而是告诉 AI “MCP 服务提供了哪些工具”,如果 AI 想要使用这些工具完成任务,就会告知后端程序,后端程序在执行工具后将结果返回给 AI,最后由 AI 总结并回复,后续会给出对应的流程图。

在这里插入图片描述

  • 5、单元测试。
 @Test
    void doChatWithMcp() {
        String chatId = UUID.randomUUID().toString();
        // 测试地图 MCP
        String message = "帮我搜索成都武侯区的景点图片";
        String answer = TravelApp.doChatWithMcp(message, chatId);
        Assertions.assertNotNull(answer);
        }
  • 6、测试验证。

在这里插入图片描述

三、Spring AI MCP(model context protocol)开发过程

3.1、MCP服务端开发

  • 开发基础:服务端开发主要基于 Spring AI MCP Server Boot Starter,能够自动配置 MCP 服务端组件,使开发者能够轻松创建 MCP 服务,向 AI 客户端提供工具、资源和提示词模板,从而扩展 AI 模型的能力范围。
  • 引入依赖:Spring AI 提供了 3 种 MCP 服务端 SDK,分别支持非响应式和响应式编程,可根据需要选择对应的依赖包:
    • spring-ai-starter-mcp-server:提供 stdio 传输支持,不需要额外的 web 依赖。
    • spring-ai-starter-mcp-server-webmvc:提供基于 Spring MVC 的 SSE 传输和可选的 stdio 传输(一般建议引入这个)。
    • spring-ai-starter-mcp-server-webflux:提供基于 Spring WebFlux 的响应式 SSE 传输和可选的 stdio 传输。

在这里插入图片描述

  • 图片搜索的MCP服务自定义开发,步骤如下。

  • 1、引入依赖并在 Pexels 网站生成 API Key,在项目根目录下新建 module(模块),名称未完整显示。注意建议在新项目中单独打开该模块,不要直接在原项目的子文件夹中操作,否则可能出现路径上的问题。引入必要的依赖,包括 Lombok、hutool 工具库和 Spring AI MCP 服务端依赖。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version>
</dependency>

在这里插入图片描述

  • 2、撰写配置文件。 Stdio、WebMVC SSE 和 WebFlux SSE 三种服务端依赖可以选择,开发时只需要填写不同的配置,开发流程都一样,此处选择引入 WebMVC。
spring:
  ai:
    mcp:
      server:
        name: MCP-Server
        version: 0.0.1
        type: SYNC
        # stdio
        stdio: true
  # stdio
  main:
    web-application-type: none
    banner-mode: off


   
spring:
  ai:
    mcp:
      server:
        name: MCP-Server
        version: 0.0.1
        type: SYNC
        # stdio
        stdio: false
  # stdio

spring:
  application:
    name: search-mcp-server
  profiles:
    active: stdio
server:
  port: 8127

  • 3、开发MCP服务。无论采用哪种传输方式,开发 MCP 服务的过程都类似,和开发工具调用一样,直接使用@Tool注解标记服务类中的方法。注册 Bean:然后在 Spring Boot 项目启动时注册一个ToolCallbackProvider Bean 。
package com.funian.mcpserver.tools;

/**
 * @Auther FuNian
 * @Major Computer Software
 */
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ImageSearchTool {

    // 替换为你的 Pexels API 密钥(需从官网申请)
    private static final String API_KEY = "自己的API";

    // Pexels 常规搜索接口(请以文档为准)
    private static final String API_URL = "https://api.pexels.com/v1/search";

    @Tool(description = "search image from web")
    public String searchImage(@ToolParam(description = "Search query keyword") String query) {
        try {
            return String.join(",", searchMediumImages(query));
        } catch (Exception e) {
            return "Error search image: " + e.getMessage();
        }
    }

    /**
     * 搜索中等尺寸的图片列表
     *
     * @param query
     * @return
     */
    public List<String> searchMediumImages(String query) {
        // 设置请求头(包含API密钥)
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", API_KEY);

        // 设置请求参数
        Map<String, Object> params = new HashMap<>();
        params.put("query", query);

        // 发送 GET 请求
        String response = HttpUtil.createGet(API_URL)
                .addHeaders(headers)
                .form(params)
                .execute()
                .body();

        // 解析响应JSON
        return JSONUtil.parseObj(response)
                .getJSONArray("photos")
                .stream()
                .map(photoObj -> (JSONObject) photoObj)
                .map(photoObj -> photoObj.getJSONObject("src"))
                .map(photo -> photo.getStr("medium"))
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());
    }
}

package com.funian.mcpserver;

import com.funian.mcpserver.tools.ImageSearchTool;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class McpServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(McpServerApplication.class, args);
	}

	@Bean
	public ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool) {
		return MethodToolCallbackProvider.builder()
				.toolObjects(imageSearchTool)
				.build();
	}
}

  • 4、单元测试。
package com.funian.mcpserver.tools;

import jakarta.annotation.Resource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;

/**
 * @Auther FuNian
 * @Major Computer Software
 */
@SpringBootTest
class ImageSearchToolTest {

    @Resource
    private ImageSearchTool imageSearchTool;

    @Test
    void searchImage() {
        String result = imageSearchTool.searchImage("computer");
        Assertions.assertNotNull(result);
    }
}


  • 5、测试验证。

在这里插入图片描述

  • 6、Maven package打包,客户端会使用Jar包。

在这里插入图片描述

3.2、MCP客户端开发

  • 1、引入依赖。
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
    <version>1.0.0-M6</version>
</dependency>

  • 2、测试Stdio方式。
 "MCP-Server": {
      "command": "java",
      "args": [
        "-Dspring.ai.mcp.server.stdio=true",
        "-Dspring.main.web-application-type=none",
        "-Dlogging.pattern.console=",
        "-jar",
        "MCP-Server/target/MCP-Server-0.0.1-SNAPSHOT.jar"
      ],
      "env": {}
    }
  • 3、测试验证。

在这里插入图片描述

  • 4、测试SSE方式。
spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            server:
              url: http://localhost:8127
        # stdio:
        # servers-configuration: classpath:mcp-servers.json

四、MCP(model context protocol)部署方案

  • 分为本地部署和远程部署:

    • 本地部署:适用于 stdio 传输方式,流程与开发 MCP 一致,只需将 MCP Server 的代码打包(如 jar 包),上传到 MCP Client 可访问的路径下,通过编写对应的 MCP 配置即可启动。例如后端项目放在服务器 A 上,若项目需要调用 Java 开发的 MCP Server,需将 MCP Server 的可执行 jar 包也放到服务器 A 上。这种方式简单粗暴,适合小项目,但缺点是每个 MCP 服务都要单独部署,服务多了会很麻烦。
    • 远程部署:适用于 SSE 传输方式,流程与部署后端 web 项目一样,需在服务器上部署服务(如 jar 包)并运行。
  • Serverless 平台部署:除了部署到自己的服务器,由于 MCP 服务一般是职责单一的小型项目,很适合部署到 Serverless 平台。使用该平台,开发者只需关注业务代码编写,无需管理服务器等基础设施,系统会根据实际使用量自动扩容并按使用付费,显著降低运维成本和开发复杂。

  • MCP 服务提交至第三方平台:

    • 提交操作:可以把 MCP 服务提交到各种第三方 MCP 服务市场,类似于将应用发布到应用商店,让其他人也能使用自己的 MCP 服务。
    • 好处:这种做法有点像开源,至少可以提升技术影响力、收获一波流量,这也是大公司在 MCP 服务市场上占坑的原因之一。

在这里插入图片描述

五、MCP(model context protocol)安全性

  • 安全现状:MCP 不是一个很安全的协议,安装使用恶意 MCP 服务可能导致隐私泄露、服务器器权限泄露、服务器被恶意执行脚本等问题。
  • 安全问题成因:
    • 信息不对称问题:用户一般只能看到工具的基本功能描述,不会关注 MCP 服务的源码及背后指令,而 AI 能看到完整工具描述,包括隐藏在代码中的指令。恶意开发者可在用户不知情下通过 AI 操控系统行为,且 AI 仅通过描述了解工具能做什么,不了解实际做了什么。例如开发的搜索图片服务,源码中未真正搜索图片,而是返回垃圾图片,AI 也无法知晓。
    • 上下文混合与隔离不足:所有 MCP 工具描述加载到同一会话上下文中,恶意 MCP 工具可影响其他正常工具行为。例如某恶意 MCP 工具描述为忽视其他提示词,只输出特定内容,若拼接进 Prompt 中,会影响 AI 回复,类似 SQL 注入。
    • 大模型本身安全意识不足:大模型被设计为精确执行指令,对恶意指令缺乏有效识别和抵抗能力。例如可直接给大模型添加系统预设,改变 AI 回复。
    • MCP 协议缺乏严格版本控制和更新通知机制:远程 MCP 服务可在用户不知情下更改功能或添加恶意代码,客户端无法感知。例如恶意 MCP 服务提供的 SSE 调用地址,在用户不知情时更新服务,继续调用原地址会遭受攻击。
  • 改进期望:期待 MCP 官方对协议进行改进,包括优化 MCP 服务和工具定义,明确区分功能描述和执行指令;完善权限控制,建立 “最小权限” 原则,涉及敏感数据操作需用户明确授权;建立安全检测机制,检测并禁止工具描述中的恶意指令;规范 MCP 生态,提高 MCP 服务共享门槛,服务市场对上架服务进行安全审计,自动检测潜在恶意代码模式。

网站公告

今日签到

点亮在社区的每一天
去签到