企业网站建设的误区主要有,专业做网站和小程序,管理网站建设哪家公司好,公司网站设计意见收集本文我以Pexels图片搜索服务为例#xff0c;详细实战演示了MCP服务端和客户端的开发流程#xff0c;包括配置、工具注册和单元测试。
MCP协议
什么是MCP呢#xff1f;MCP是Model Context Protocol模型上下文协议#xff0c;是一种开放标准#xff0c;不是一种技术#…本文我以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提供了两种客户端SDK1、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 groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.38/version /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server/artifactId version1.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 ListString searchMediumImages(String query) { // 设置请求头包含API密钥 MapString, String headers new HashMap(); headers.put(Authorization, API_KEY); // 设置请求参数仅包含query可根据文档补充page、per_page等参数 MapString, 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.stdiotrue, -Dspring.main.web-application-typenone, -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可能在回复中完整输出敏感信息对话记录被窃取或上下文残留敏感数据并在后续对话中无意泄露。