news 2026/1/11 14:48:41

AI大模型应用开发实战流程-MCP协议(Model Context Protocol)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI大模型应用开发实战流程-MCP协议(Model Context Protocol)

本文我以Pexels图片搜索服务为例,详细实战演示了MCP服务端和客户端的开发流程,包括配置、工具注册和单元测试。

MCP协议

什么是MCP呢?MCP是Model Context Protocol模型上下文协议,是一种开放标准,不是一种技术,MCP目的是增强AI与外部系统交互的能力,接入别人提供的服务来实现更多的功能,统一标准,降低使用和理解成本,打造服务生态,造福广大开发者。

那为什么MCP这么火,而工具调用却没那么火?这是因为工具调用是面向我们程序员,而MCP是大家都能直接接入使用。

SDK的三层架构:客户端/服务器层、会话层、传输层,客户端和服务端之间传输可以通过两种方式一种是标准的输入/输出Stdio模式,在本地就像在终端小黑框客户端和服务器聊的有来有回。一种是远程HTTP请求的SSE模式,SSE作用是让服务器持续不断的给客户端发消息。

MCP 架构的主要参与者是:

MCP 主机:协调和管理一个或多个 MCP 客户端的 AI 应用程序

MCP 客户端:维护与 MCP 服务器的连接并从 MCP 服务器获取上下文供 MCP 主机使用的组件

MCP 服务器:向 MCP 客户端提供上下文的程序

例如:Visual Studio Code 充当 MCP 主机。当 Visual Studio Code 建立与 MCP 服务器(如 Sentry MCP 服务器)的连接时,Visual Studio Code 运行时会实例化一个 MCP 客户端对象,该对象用于维护与 Sentry MCP 服务器的连接。 当 Visual Studio Code 随后连接到另一个 MCP 服务器(例如本地文件系统服务器)时,Visual Studio Code 运行时会实例化一个额外的 MCP 客户端对象来维护此连接,从而保持一对一 MCP 客户端与 MCP 服务器的关系。

Spring AI MCP开发模式

Spring AI在MCP官方Java SDK的基础上额外封装了一层,提供了和Spring Boot整合的SDK,支持客户端和服务端的普通调用和响应式调用。那让我们接下来看看如何使用Spring AI开发MCP客户端和服务端吧!

开发MCP客户端:可以参考一下Spring AI官方文档的MCP Client Boot Starters,提供了两种客户端SDK:1、Standard MCP Client,核心启动器提供了Stdio和SSE支持, 2、WebFlux Client,基于WebFlux的SSE传输实现,一般用第一种就好了。

步骤:引入依赖、配置连接、使用服务

步和异步客户端类型,还可以自定义定制客户端行为

开发MCP服务端:同理,参考Spring AI官方文档的MCP Server Boot Starters,提供了3种SDK,有Stdio、WebMVC SSE、WebFlux SSE,支持非响应式和响应式编程,一般建议引spring-ai-starter-mcp-server-webmvc,要用到时候看官方文档就好了。

入依赖、配置服务、开发服务

其他特性:提供工具、资源管理、提示词管理、根目录变更处理

MCP开发实战(图片搜索服务)

使用Pexels图片资源网站的API(免费!免费!)来构建图片搜索服务。

注册登录,然后点击右上角的三个点选择图片和视频API来生成Pexels API密钥,先复制一下密钥,然后我们就可以来使用Pexels来实现图片搜索服务。

MCP服务端开发

在dog-ai-agent根目录下新建一个dog-image-search-mcp-server模块,选用Maven和jdk21,下一步引入lombok然后自己选择一下springboot版本然后创建,创建完建议大家单独的打开这个项目,不要在当前的目录中打开它,因为要去搜索资源的话在当前的子目录获取到的路径是不正确的。右击创建的模块,选择Open In的explorer,然后会弹出文件的窗口,选择刚刚创建的文件右击选择idea打开,然后选择New Window。

刚才在创建时引入了lombok,那首先我们在pom.xml来引入Hutool的依赖和我们要用的MCP的WebMVC SSE的依赖:

<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.38</version> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-mcp-server</artifactId> <version>1.0.0</version> </dependency>

注:引入WebMVC SSE依赖后,会自动注册SSE端点,包括消息和SSE端点,能够供客户端调用

然后我们要在resource目录下来编写两套服务端配置文件,分别实现Stdio和SSE模式传输,首先将原本的application.properties改为application-stdio.yml进行Refactor,然后将生成的一行代码删掉,编写以下代码:

spring: ai: mcp: server: name: dog-image-search-mcp-server version: 0.0.1 type: SYNC # stdio stdio: true # stdio main: web-application-type: none banner-mode: off

接着继续搞SSE的,在resource目录下新建一个application-sse.yml,编写以下代码:

spring: ai: mcp: server: name: dog-image-search-mcp-server version: 0.0.1 type: SYNC # sse stdio: false

补充:可能你的左边目录包很多红色,这不是报错,这是因为没有添加到Git管理,我们右击dog-image-search-mcp-server找到Git选择Add就可以了。

为了方便灵活切换这两套配置,我们在resource目录下新建一个application.yml,编写以下配置代码:

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

然后在dogimagesearchmcpserver下新建一个tools包,再在包下新建一个ImageSearchTool类,那我们要如何编写搜索图片的java代码呢,可以进入Pexels的右上角三个点的图片和视频API,然后点击文档,找到Photos下的Search for Photos,将这个文档丢给AI帮我们生成基于Hutool工具库的HTTP工具类的自动搜索图片功能的java代码,然后复制粘贴到我们的ImageSearchTool类,代码如下:

@Service public class ImageSearchTool { // 替换为你的 Pexels API 密钥(需从官网申请) private static final String API_KEY = "你的 API Key"; // 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); // 设置请求参数(仅包含query,可根据文档补充page、per_page等参数) Map<String, Object> params = new HashMap<>(); params.put("query", query); // 发送 GET 请求 String response = HttpUtil.createGet(API_URL) .addHeaders(headers) .form(params) .execute() .body(); // 解析响应JSON(假设响应结构包含"photos"数组,每个元素包含"medium"字段) 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()); } }

记得要将API key替换成自己的,然后生成对应的单元测试进行测试一下,代码如下:

@SpringBootTest class ImageSearchToolTest { @Resource private ImageSearchTool imageSearchTool; @Test void searchImage() { String result = imageSearchTool.searchImage("dog"); Assertions.assertNotNull(result); } }

接着在启动类定义ToolCallbackProvider Bean注册工具,代码如下:

@SpringBootApplication public class DogImageSearchMcpServerApplication { public static void main(String[] args) { SpringApplication.run(DogImageSearchMcpServerApplication.class, args); } @Bean public ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool) { return MethodToolCallbackProvider.builder() .toolObjects(imageSearchTool) .build(); } }

然后呢,客户端是怎么基于本地模式调用我们的MCP服务呢?是客户端会先找到我们MCP的配置,找到启动MC服务P的命令,开一个子进程去运行这个服务。所以呢,我们接下来要在Maven中去package给我们的本地MCP服务打个包,接着打包成功后会在target目录下看到这个jar包,客户端运行时候就是运行这个jar包。

注意:这边可能又会报错不支持发行版21,我们的文档开头有说如何解决,如果忘了可以滑到开头去看看。如果还不行,就在Setting里面的Build Tool里的Maven下的Runner将JRE改为21应该就可以了。

那MCP服务端开发完成,咱们来开发MCP客户端吧。

MCP客户端开发

在根项目中开发客户端,调用刚才创建的图片搜索服务,首先引入MCP客户端MCP Client依赖(刚刚已经引入过了),接着来编写我们的配置,打开resource目录下的mcp-servers.json,里面有我们前面配置过的高德地图,记得去ignore密钥噢,不要把密钥提交到git仓库。我们继续,mcp-servers.json最终代码如下:

{ "mcpServers": { "amap-maps": { "command": "npx.cmd", "args": [ "-y", "@amap/amap-maps-mcp-server" ], "env": { "AMAP_MAPS_API_KEY": "your-api-key" } }, "dog-image-search-mcp-server": { "command": "java", "args": [ "-Dspring.ai.mcp.server.stdio=true", "-Dspring.main.web-application-type=none", "-Dlogging.pattern.console=", "-jar", "dog-image-search-mcp-server/target/dog-image-search-mcp-server-0.0.1-SNAPSHOT.jar" ], "env": {} } } }

然后在test里的TravelAppTest编写图片搜索服务的单元测试,将之前地图的测试注释掉进行测试,代码如下:

@Test void doChatWithMcp() { String chatId = UUID.randomUUID().toString(); // 测试地图 MCP // String message = "我在福建福州东街口,请帮我找个约会地点"; // String answer = travelApp.doChatWithMcp(message, chatId); // Assertions.assertNotNull(answer); // 测试图片搜索 MCP String message = "帮我搜索一些萨摩耶狗在游泳池里玩耍的图片"; String answer = travelApp.doChatWithMcp(message, chatId); Assertions.assertNotNull(answer); } }

到此,我们思考一个问题,你要开发这个图片搜索的功能,如果是你你会选择开发工具调用还是开发MCP服务呢?其实很简单,能用工具调用就用工具调用,引入MCP依赖再开发挺麻烦的。

下面我们来试试SSE连接方式,首先修改MCP服务端的配置文件,就是dog-image-search-mcp-server的application.yml中将stdio改为sse,然后在启动类中以Debug启动。然后修改客户端的配置文件,要将stdio的注释掉:

mcp: client: sse: connections: server1: url: http://localhost:8127 # stdio: # servers-configuration: classpath:mcp-servers.json

运行doChatWithMcp测试一下。

MCP部署方案有两种:本地部署和远程部署

MCP安全问题

1、权限失控风险

用户过度授权(如允许AI“读写所有文件”或“访问全部网络”)。一旦AI被恶意诱导或存在逻辑漏洞,将利用这些宽泛权限造成数据泄露、系统破坏等严重损失。

2、服务器端攻击风险

MCP连接的第三方工具服务器可能“作恶”或有漏洞。恶意服务器可提供虚假数据、窃取AI发送的敏感信息(如数据库凭证),或利用服务器漏洞发起进一步攻击。

3、提示词注入与越权操作

攻击者通过精心构造的输入,诱导AI绕过正常逻辑,滥用其已获得的工具权限。例如,让一个被授权总结邮件的AI,利用文件写入工具去删除系统文件,执行非预期的高危操作。

4、供应链与依赖风险

MCP工具(Server)通常来自开源社区或第三方,可能包含恶意代码或存在未修补的漏洞。广泛使用的工具若被污染或存在漏洞,会导致大规模的安全事件,影响所有集成该工具的应用。

5、数据泄露与隐私暴露

AI通过MCP访问大量敏感数据源(邮件、数据库、API),处理不当极易导致信息泄露。AI可能在回复中完整输出敏感信息;对话记录被窃取;或上下文残留敏感数据并在后续对话中无意泄露。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/7 21:33:52

我对防抖(Debounce)的一点理解与实践:从基础到立即执行

我对防抖&#xff08;Debounce&#xff09;的一点理解与实践这篇文章主要是我在项目中使用防抖过程中的一些总结&#xff0c;只代表个人理解&#xff0c;如果有不严谨或可以优化的地方&#xff0c;欢迎指出和讨论。一、防抖的概念 防抖&#xff08;Debounce&#xff09; &#…

作者头像 李华
网站建设 2026/1/9 12:01:21

重构 Flutter 状态管理:从 Provider 到 Riverpod 2.0 的无痛迁移与性能飞跃

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net)&#xff0c;一起共建开源鸿蒙跨平台生态。 在 Flutter 开发的迭代长河中&#xff0c;状态管理始终是绕不开的核心命题。Provider 曾凭借简洁的 API 和低学习成本成为主流选择&#xff0c;…

作者头像 李华
网站建设 2026/1/9 4:09:03

AI大模型之Agent,RAG,LangChain(三)

前面分享了项目的大致流程,这篇主要分享一下LangChain这个框架的个人简单理解.看懂这篇必须要看我之前发的二,这样便于更好的理解这个框架.一.简述1.什么是LangChain简单来说,LangChain是LLMs的开发框架,他为不同的LLMs提供统一的接口,并且把和LLMs相关的内部组件连接在一起.2.…

作者头像 李华
网站建设 2026/1/8 20:11:40

css3如何引入外部字体

如果需要外部字体&#xff0c;电脑上没有&#xff0c;这时候可以用css3上新引入的font-face属性它的语法格式是font-face {font-family:自定义字体名称src:url(字体路径);}比如需要使用叫字体家AI北京长城体.ttf的字体&#xff0c;代码如下font-face {/*定义字体的名称*/font-f…

作者头像 李华
网站建设 2026/1/10 9:16:13

OkDownload入门指南:如何在5分钟内搭建你的第一个高效下载引擎

OkDownload入门指南&#xff1a;如何在5分钟内搭建你的第一个高效下载引擎 【免费下载链接】okdownload A Reliable, Flexible, Fast and Powerful download engine. 项目地址: https://gitcode.com/gh_mirrors/ok/okdownload 想要构建一个可靠、灵活且高效的下载系统吗…

作者头像 李华
网站建设 2025/12/27 22:32:16

权威榜单发布:浙江亿企邦领衔外贸网站引流推广行业

随着外贸行业数字化转型的深入&#xff0c;企业对专业化、多渠道、智能化的海外营销服务的需求日益迫切。为帮助广大外贸企业甄选优质服务伙伴&#xff0c;基于企业综合服务能力、技术创新水平、行业口碑与市场表现等多维度评估&#xff0c;现正式发布2025年度外贸网站引流推广…

作者头像 李华