【保姆级图文详解】MCP架构(客户端-服务端)、三种方式使用MCP服务、Spring AI MCP客户端和服务端开发、MCP部署方案、MCP安全性
文章目录
- 前言
- 一、MCP(model context protocol)
- 1.1、概念描述
- 1.2、MCP作用与意义
- 1.3、MCP架构
- 二、使用MCP(model context protocol)
- 2.1、云平台使用MCP
- 2.2、软件客户端使用MCP
- 2.3、Spring AI程序中使用MCP
- 三、Spring AI MCP(model context protocol)开发过程
- 3.1、MCP服务端开发
- 3.2、MCP客户端开发
- 四、MCP(model context protocol)部署方案
- 五、MCP(model context protocol)安全性
前言
若对您有帮助的话,请点赞收藏加关注哦,您的关注是我持续创作的动力!有问题请私信或联系邮箱: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
- 1、根据阿里云百炼平台的官方文档操作。
- 2、登录阿里云百炼平台。
- 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 官方文档更新太快,包的路径可能会变动。
- 1、在maven中央仓库引入依赖。
<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、编写测试代码。
@Resourceprivate 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、单元测试。
@Testvoid doChatWithMcp() {String chatId = UUID.randomUUID().toString();// 测试地图 MCPString 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-Serverversion: 0.0.1type: SYNC# stdiostdio: true# stdiomain:web-application-type: nonebanner-mode: off
spring:ai:mcp:server:name: MCP-Serverversion: 0.0.1type: SYNC# stdiostdio: false# stdio
spring:application:name: search-mcp-serverprofiles: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();// 解析响应JSONreturn 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);}@Beanpublic 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 {@Resourceprivate ImageSearchTool imageSearchTool;@Testvoid 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 服务共享门槛,服务市场对上架服务进行安全审计,自动检测潜在恶意代码模式。