工具调用MCP_Server 开发梳理
一、MCP 简介MCPModel Context Protocol是 Spring AI 提供的工具调用协议允许 AI 模型通过标准化接口调用外部工具。本项目是一个基于 Spring Boot 的图片搜索 MCP 服务器实现。三、开发步骤步骤 1创建 Maven 项目在pom.xml中添加以下核心依赖!-- Spring Boot Starter --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependency!-- Spring AI MCP Server WebMVC 依赖 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-starter-mcp-server-webmvc/artifactId/dependency!-- Hutool 工具库可选用于HTTP请求和JSON处理 --dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.8.37/version/dependency步骤 2创建工具类创建一个 Spring Service 类并使用Tool注解标记工具方法packagecom.imagesearchmcpserver.tools;importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.ai.tool.annotation.ToolParam;importorg.springframework.stereotype.Service;ServicepublicclassImageSearchTool{Tool(descriptionsearch image from web)publicStringsearchImage(ToolParam(descriptionSearch query keyword)Stringquery){// 实现工具逻辑returnsearchMediumImages(query).toString();}}关键注解说明注解用途Tool标记该方法为 MCP 工具description用于描述工具功能ToolParam标记方法参数description用于描述参数含义Service注册为 Spring Bean步骤 3配置工具提供者在启动类中配置ToolCallbackProviderBeanSpringBootApplicationpublicclassYuImageSearchMcpServerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(YuImageSearchMcpServerApplication.class,args);}BeanpublicToolCallbackProviderimageSearchTools(ImageSearchToolimageSearchTool){returnMethodToolCallbackProvider.builder().toolObjects(imageSearchTool).build();}}步骤 4配置应用创建三种配置文件4.1application.yml默认配置spring:application:name:image-search-mcp-serverprofiles:active:sse# 默认使用 SSE 模式server:port:81274.2application-sse.ymlSSE 模式spring:ai:mcp:server:name:image-search-mcp-serverversion:0.0.1type:SYNCstdio:false# 启用 HTTP/SSE 模式4.3application-stdio.yml标准输入输出模式spring:ai:mcp:server:name:image-search-mcp-serverversion:0.0.1type:SYNCstdio:true# 启用标准输入输出模式main:web-application-type:none# 非 Web 应用banner-mode:off# 关闭启动 Banner步骤 5实现业务逻辑在工具类中实现具体的业务逻辑。本项目以 Pexels 图片搜索 API 为例publicListStringsearchMediumImages(Stringquery){// 1. 设置请求头包含 API 密钥MapString,StringheadersnewHashMap();headers.put(Authorization,API_KEY);// 2. 设置请求参数MapString,ObjectparamsnewHashMap();params.put(query,query);// 3. 发送 HTTP 请求StringresponseHttpUtil.createGet(API_URL).addHeaders(headers).form(params).execute().body();// 4. 解析响应并提取图片 URLreturnJSONUtil.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());}四、启动方式方式 1SSE 模式默认# 开发环境运行./mvnw spring-boot:run# 或打包后运行./mvnw clean packagejava-jartarget/image-search-mcp-server-0.0.1-SNAPSHOT.jar方式 2Stdio 模式./mvnw spring-boot:run -Dspring-boot.run.profilesstdio# 或java-jartarget/image-search-mcp-server-0.0.1-SNAPSHOT.jar--spring.profiles.activestdio五、两种运行模式对比特性SSE 模式Stdio 模式通信方式HTTP Server-Sent Events标准输入/输出流适用场景远程服务、多客户端连接本地进程调用、安全沙箱环境Web 服务是否配置参数stdio: falsestdio: true六、MCP 工具调用流程┌─────────────────┐ HTTP/SSE ┌──────────────────────┐ │ AI 客户端 │ ────────────────► │ MCP Server │ │ (如 LlamaIndex)│ │ (Spring Boot) │ └─────────────────┘ └──────────┬───────────┘ │ ▼ ┌──────────────────────┐ │ ToolCallbackProvider│ │ 发现并注册工具方法 │ └──────────┬───────────┘ │ ▼ ┌──────────────────────┐ │ ImageSearchTool │ │ 执行具体业务逻辑 │ └──────────────────────┘七、扩展开发添加新工具只需创建新的 Service 类并添加Tool注解ServicepublicclassWeatherTool{Tool(descriptionGet current weather)publicStringgetWeather(ToolParam(descriptionCity name)Stringcity){// 实现天气查询逻辑returnWeather in city: sunny;}}更新工具提供者在启动类中添加新工具BeanpublicToolCallbackProvidertools(ImageSearchToolimageSearchTool,WeatherToolweatherTool){returnMethodToolCallbackProvider.builder().toolObjects(imageSearchTool,weatherTool).build();}八、注意事项API Key 管理敏感信息如 API Key 应通过环境变量或配置中心管理避免硬编码错误处理工具方法应妥善处理异常返回友好的错误信息参数校验对输入参数进行必要的校验日志记录建议添加适当的日志记录便于排查问题依赖版本确保 Spring AI BOM 版本与 MCP Server 依赖版本一致九、前端调用方式9.1 前端项目结构ai-agent-frontend/ ├── src/ │ ├── api/ │ │ └── index.js # API 封装与 SSE 连接 │ ├── components/ │ │ └── ChatRoom.vue # 聊天组件 │ ├── views/ │ │ └── SuperAgent.vue # AI 超级智能体页面 │ └── main.js # 入口文件 ├── package.json └── vite.config.js9.2 核心调用流程前端通过SSE (Server-Sent Events)与后端建立实时通信实现流式响应。9.2.1 SSE 连接封装// src/api/index.jsimportaxiosfromaxiosconstAPI_BASE_URLprocess.env.NODE_ENVproduction?/api:http://localhost:8123/apiexportconstconnectSSE(url,params,onMessage,onError){constqueryStringObject.keys(params).map(key${encodeURIComponent(key)}${encodeURIComponent(params[key])}).join()constfullUrl${API_BASE_URL}${url}?${queryString}consteventSourcenewEventSource(fullUrl)eventSource.onmessageevent{letdataevent.dataif(data[DONE]){if(onMessage)onMessage([DONE])}else{if(onMessage)onMessage(data)}}eventSource.onerrorerror{if(onError)onError(error)eventSource.close()}returneventSource}9.2.2 调用 AI 聊天接口// AI超级智能体聊天exportconstchatWithManus(message){returnconnectSSE(/ai/manus/chat,{message})}9.3 组件层面调用在 Vue 组件中使用 SSE 连接// src/views/SuperAgent.vueimport{ref,onMounted,onBeforeUnmount}fromvueimport{chatWithManus}from../apiconstmessagesref([])constconnectionStatusref(disconnected)leteventSourcenullconstsendMessage(message){// 添加用户消息addMessage(message,true,user-question)// 关闭之前的连接if(eventSource){eventSource.close()}connectionStatus.valueconnectingletmessageBuffer[]eventSourcechatWithManus(message)eventSource.onmessage(event){constdataevent.dataif(datadata![DONE]){messageBuffer.push(data)// 根据标点或长度判断是否创建新消息气泡constlastChardata.charAt(data.length-1)consthasCompleteSentence[。,,,…].includes(lastChar)constisLongEnoughmessageBuffer.join().length40if(hasCompleteSentence||isLongEnough){addMessage(messageBuffer.join(),false,ai-answer)messageBuffer[]}}if(data[DONE]){if(messageBuffer.length0){addMessage(messageBuffer.join(),false,ai-final)}connectionStatus.valuedisconnectedeventSource.close()}}eventSource.onerror(error){connectionStatus.valueerroreventSource.close()}}9.4 完整调用链路┌─────────────────┐ HTTP/SSE ┌──────────────────────┐ 调用工具 ┌──────────────────────┐ │ Vue 前端 │ ────────────────► │ 后端 API Gateway │ ─────────────► │ MCP Server │ │ SuperAgent.vue │ /ai/manus/chat │ (端口 8123) │ /mcp/tools │ (端口 8127) │ └─────────────────┘ └──────────────────────┘ └──────────────────────┘ ▲ │ │ │ │ │ └─────────── SSE 流式响应 ◄───────────┴─────────── 工具执行结果 ◄───────────┘9.5 前端配置说明配置项开发环境生产环境API 地址http://localhost:8123/api/api通信方式SSE (EventSource)SSE (EventSource)超时时间60秒60秒9.6 注意事项跨域处理后端需配置 CORS 允许前端域名访问连接管理发送新消息前需关闭旧连接避免重复响应消息缓冲SSE 可能分段传输需缓冲后按语义合并异常处理监听onerror事件优雅处理连接断开资源清理组件销毁前调用eventSource.close()释放资源