发布时间:2026/8/31 5:37:52
Agent开发 - 开发MCP图片搜索服务(一)(部署在下一篇文章) 一、MCP服务端开发1. 搜索网址【Free Image and Video API – Pexels】点击Your API Key填写项目信息生成API Key2. 在项目根目录下新建moudle,名称自己定义填写初始化moudle信息修改你的pom.xml中spring-boot版本为你现在项目正在使用的版本注意,建议在新项目中单独打开该模块,不要直接在原项目的的子文件夹中操作,否则可能出现路径上的问题。3. 引入必要的依赖,包括Lombok、hutool工具库和Spring Al MCP服务端依赖!-- lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- hutool工具库 -- dependency groupIdcn.hutool/groupId artifactIdhutool-all/artifactId version5.8.37/version /dependency有Stdio、WebMVCSSE同时支持stdio和sse远程和WebFluxSSE三种服务端依赖可以选选择,开发时只需要填写不同的配置,开发流程都是一样的。此处我们选择引入WebMVC:!-- mcp-server-webmvc webmvc同时支持stdio和sse -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-server-webmvc-spring-boot-starter/artifactId version1.0.0-M6/version /dependency引入这个依赖后,会自动注册SSE端点,供客户端调用。包括消息和SSE传输端点:文档网址【Untitled :: Spring AI Reference】4. 在resources目录下编写服务端配置文件这里我们编写两套配置方案,分别实现stdio和SSE模式的传输① stdio配置application-stdio.yml需关闭web支持spring: ai: mcp: server: name: yu-image-search-mcp-server version: 0.0.1 type: SYNC # stdio stdio: true # stdio main: web-application-type: none banner-mode: off② sse配置application-sse.yml需关闭stdio模式spring: ai: mcp: server: name: yu-image-search-mcp-server version: 0.0.1 type: SYNC # sse stdio: false③ 然后编写主配置文件application.yml,可以灵活指定激活哪套配置:spring: application: name: algo-image-search-mcp profiles: # 指定激活stdio或sse配置文件 active: stdio # 指定服务端口号 server: port: 81275. 编写图片搜索服务类在tools包下新建ImageSearchTool,使用Tool注解标注方法,作为MCP服务提供的工具package com.jingdong.algoimagesearchmcp.tools; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; Service Slf4j public class ImageSearchTool { // 你的api_key密钥 (可在yml文件中配置用Valude注解拉取API_key的值) Value(${pexels.api-key}) private String API_KEY; // Pexels 常规搜索接口请以文档为准 API文档参考地址【https://www.pexels.com/api/documentation/#photos-search】 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) { log.error(error search image from mcp server - errorMessage:{},e.getMessage()); return error search image: e.getMessage(); } } // helper methods /** * 搜索中等尺寸的图片列表 * * 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()); } }6. 编写单元测试类做集成测试真实调用工具验证工具是否可用package com.jingdong.algoimagesearchmcp.tools; import jakarta.annotation.Resource; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.util.Assert; SpringBootTest DisplayName(图片搜索测试类) public class ImageSearchToolTest { Resource private ImageSearchTool imageSearchTool; Test DisplayName(测试图片搜索工具) void searchImage(){ String result imageSearchTool.searchImage(奈克瑟斯奥特曼); Assert.notNull(result,查询结果不应为空); } }可以看到返回了很多图片网址7. 在主类中通过定义ToolCallbackProvider Bean来注册工具:package com.jingdong.algoimagesearchmcp; import com.jingdong.algoimagesearchmcp.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 AlgoImageSearchMcpApplication { public static void main(String[] args) { SpringApplication.run(AlgoImageSearchMcpApplication.class, args); } /** * 注册图片搜索工具提供者Provider,供MCP Client访问时获取tools调用MCP Server的工具 * param imageSearchTool 图片搜索工具类 * return 工具调用Provider */ Bean public ToolCallbackProvider imageSearchTools(ImageSearchTool imageSearchTool){ return MethodToolCallbackProvider .builder() .toolObjects(imageSearchTool) .build(); } }8. 最后使用Maven Package命令将此项目打包称jar包供后续MCP 客户端依赖使用⭐① 前置要求确保你们pom文件中引入了maven plugin插件如下情况 1项目有 spring-boot-starter-parent绝大多数 SpringBoot 项目直接用最简配置在 pom.xml 的buildplugins节点内添加xmlplugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin情况 2项目没有 parent需要显式指定版本 执行目标xmlplugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId version3.2.0/version !-- 和你springboot版本保持一致 -- executions execution goals goalrepackage/goal /goals /execution /executions /pluginrepackage是 spring-boot-maven-plugin 的目标作用将 maven 正常打包生成的普通 jar重新打包为 SpringBoot 可执行的胖 jar把项目依赖的第三方 jar 一并打进包内内置 SpringBoot 启动器支持直接使用java -jar xxx.jar运行。② 执行mvn package命令会在target目录下生成可执行的JAR包,等会儿客户端调用时会依赖这个文件:⭐如何显示target文件项目视图右上角三点 → 勾选Show Excluded Files或者 File→Settings→Build, Execution, Deployment→Directories取消 target 的 Excluded 标记。然后就可以看到了。第一个jar包就是我们要使用的可运行jar包。SpringBoot 项目会同时生成普通 jar 和xxx.jar.original文件带 original 是原始精简 jar不带 original 的是可执行 fat jar。二、MCP 客户端开发下一步是在根项目中开发客户端来调用我们刚才创建的【图片搜索服务】。1. 先引入必要的MCP客户端依赖!-- 添加Spring AI MCP Client starter依赖 -- !-- Source: https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-mcp-client-spring-boot-starter -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-client-spring-boot-starter/artifactId version1.0.0-M6/version scopecompile/scope /dependency注意 要保证你的客户端依赖和你的服务端形式一致。2. 先测试stdio传输方式① 在 mcp-servers.json配置文件中新增MCPServer的配置,通过java命令执行我们刚刚打包好的jar包。代码如下:{ mcpServers: { algo-image-search-mcp-server: { command: java, args: [ -Dspring.ai.mcp.server.stdiotrue, -Dspring.main.web-application-typenone, -Dlogging.pattern.console, -jar, algo-image-search-mcp/target/algo-image-search-mcp-0.0.1-SNAPSHOT.jar ], env: {} } } }注意args中target前面的目录为你的图片搜索服务的项目根目录名称不是stdio模式的服务名称② 编写单元测试代码调用我们注册的图片搜索工具Test DisplayName(测试图片搜索MCP Server) void doChatWithImageSearchMCpServer(){ // 测试图片搜索MCP String chatId UUID.randomUUID().toString(); String userMessage 帮我搜一些人类幼崽的图片; String result loveApp.doChatWithMcp(userMessage, chatId); Assert.notNull(result,大模型应该回复有内容的信息); }③ debug打断点查看是否注册到图片搜索工具并观察返回结果是否包含图片urldebug可以看到我们request请求中的FunctionCallbacks中的第一个tool就是searchImage,说明MCP Server提供的图片搜索工具被成功加载可以看到结果中包含图片url调用成功3. 再测试sse连接方式① 修改server端application.yml指定的配置文件为ssespring: application: name: algo-image-search-mcp profiles: # 指定激活stdio或sse配置文件 active: sse # 只修改这一行为sse即可 # 指定服务端口号 server: port: 8127② debug模式启动服务端的启动类模拟【图片搜索MCP服务】在远程运行url为本地localhost,端口port为8127同时debug模式是为了我们后续给服务端打断点进行调用服务端工具时的调试③ 修改服务端application.yml中使用MCP的形式为sse原来为stdiospring: ai: # mcp client 客户端配置 mcp: client: sse: # connections本质是一个 Mapserver1就是 map 的 key用来区分多个不同的 MCP 服务连接你可以随便起名 connections: # 如果你后面要在代码里单独拿到指定这个 MCP 客户端实例才会用到这个 key 名字只是自动注入全部 ToolCallbackProvider、直接.tools(toolCallbackProvider)使用的话改名字完全无影响。 algo-image-search-mcp-server: url: http://localhost:8127 # stdio: # # 指定MCP服务器配置文件路径推荐项目根目录下的json文件。 classpath:mcp-servers.json → 读取资源目录里打包进 jar 的文件打包部署后依然正常生效推荐配置文件写法→ Spring Boot 应用启动时读取放在 resources 下打进 jar # # 项目根目录的 .mcp.json → 不属于 classpath 资源Spring 默认不会读取仅给 Claude Code IDE 使用 # # classpath:mcp-servers.json对应文件位置src/main/resources/mcp-servers.json # # 编译后会自动复制到 target/classes/mcp-servers.jsonSpring 就能读到。 # servers-configuration: classpath:mcp-servers.json④ debug执行stdio时候写的客户端单元测试可以看到客户端request请求中检索到了【图片搜索工具类searchImage】服务端也看到了请求打进来了说明工具被客户端注册并成功执行了客户端单元测试AI回复也包含图片url,成功了至此MCP服务端和客户端开发完成MCP部署在下一篇文章进行阐述

相关新闻

2026/8/31 5:37:52

Claude API接入指南:连接错误排查与可解释性实践

最近,Anthropic 因为一条“法官裁定特朗普政府将 Anthropic 列入黑名单的行为违法”的新闻登上热搜。作为技术开发者,我们对公司层面的讨论保持克制,但有一件事值得抽出来单独聊聊:当大量开发者涌向 Claude 时,真实接入…

2026/8/31 5:37:52

基于SpringBoot的校园墙社区系统(源码+lw+部署文档+讲解等)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/31 5:37:52

RC控制原理与PWM信号解码:用C++实现接收机读取

简介:本资源面向电力电子与嵌入式控制领域的工程师及高校研究生,聚焦逆变器并网谐波抑制这一核心工程问题,提供一套基于C/C实现的RC重复控制完整技术方案。RC重复控制专用于降低并网电流总谐波失真(THD),尤…

2026/8/31 5:52:53

Docker 容器实战 1—— docker 基础与镜像构建

1 Docker 简介 Docker 是一套开源的容器化虚拟化引擎,基于 Linux 内核能力实现应用隔离与打包。 传统虚拟机 KVM 是完整虚拟化 CPU、内存、磁盘,拥有独立操作系统内核;Docker 容器不虚拟化硬件,直接复用宿主机 Linux 内核&#x…

2026/8/31 5:52:53

AI攻克数学难题背后:用OpenAI API搭建模型推理评估系统

最近 AI 圈又传出一个让人眼前一亮的消息:OpenAI 的 Astra 内部版在数学评测中攻克了 10 道公认的高难度数学题。 很多人看到这类新闻,第一反应是“AI 又变强了”,然后划走。但如果只停留在“好厉害”这个层面,那就错过了一个更有…

2026/8/31 5:52:53

网约车一口价订单乘客迟到:司机如何按规则取消避免判责?

平时跑网约车,最怕的不是路况堵,而是乘客已经下单、你到了上车点,对方迟迟不出现。这次要说的是一个很典型的场景:一位女司机师傅接到一笔“一口价”订单,4个大男人一起出行,到了上车点后对方集体迟到。师傅…

2026/8/31 5:47:52

共基极放大电路小信号模型:从原理推导到仿真验证

学习模拟电子技术时,共基极放大电路小信号模型经常被安排在三极管放大电路的中后段,很多同学把它当作共射电路的变种草草看过。真正做高频放大、设计 cascode 结构、搭建电流缓冲器时,才会发现共基极组态的低输入阻抗、接近 1 的电流增益和良…

2026/8/31 1:05:20

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/31 2:14:20

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/31 1:41:28

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/31 0:07:32

STM32C5设备支持包(IAR DFP)安装指南与常见坑

上一阵子在IAR里折腾一块基于STM32C5系列的新板子,工程从STM32CubeMX导出来之后怎么都编译不过。报错信息很干脆:找不到设备描述文件。跟着错误路径去查,发现指向的是一个让我愣了一下的名字:STMicroelectronics.stm32c5xx.2.1.0.…

2026/8/31 0:07:32

STM32N657 SWO引脚矛盾:CubeMX显示PB3,数据手册为PB5

拿到STM32N657这颗料的第一天,我就撞上了一个让人原地懵圈的引脚矛盾:CubeMX里清清楚楚显示SWO在PB3,翻开数据手册的引脚说明表,却赫然写着PB5。对于一个靠SWO输出调试日志吃饭的人而言,这种"工具和手册打架"…

2026/8/28 16:16:48

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/28 16:16:50

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/28 11:06:45

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…