新闻详情

新闻详情

首页 / 资讯中心 / 详情

【SpringAI】第六弹:深入解析 MCP 上下文协议、开发和部署 MCP 服务、MCP 安全问题与最佳实践

发布时间:2026/9/28 19:00:13来源:尧图网络
【SpringAI】第六弹:深入解析 MCP 上下文协议、开发和部署 MCP 服务、MCP 安全问题与最佳实践
1. 为什么你的 SpringAI 项目需要一个 MCP 服务MCPModel Context Protocol模型上下文协议是一套让 AI 应用与外部工具、数据源、服务交互的开放标准。你可以把它理解成 AI 世界的 USB 接口只要服务端按协议暴露能力任何支持 MCP 的客户端都能即插即用不用为每个模型单独写适配层。在 SpringAI 生态里MCP 的价值尤其明显——你写的Tool方法可以零改动地变成远程可调用的服务被 Cursor、Claude Desktop 或你自己的 Spring Boot 应用消费。这篇文章面向已经在用 SpringAI 做工具调用、但还没把 MCP 跑进生产环境的开发者。我会从协议交互链路拆起带你走完本地 stdio 服务、远程 SSE 服务的开发与部署再重点讲鉴权、工具白名单、配置隔离这些安全实践。全程用可复制的配置骨架配合 TaoToken 统一 Key/API 通道做接入示例最后给出分步验证动作和排错清单。适合谁写过 Spring Boot、用过Tool注解、想让工具能力被多个客户端共享的后端同学。我试过把同一个图片搜索工具分别用 stdio 和 SSE 两种模式接进 SpringAI 客户端踩过的坑主要集中在依赖坐标、超时配置和 Windows 命令后缀上后面会逐个拆开讲。2. MCP 上下文协议的交互链路拆解2.1 三层 SDK 架构SpringAI 的 MCP 实现建立在官方 Java SDK 之上分三层客户端/服务器层负责协议操作McpClient处理客户端行为McpServer管理服务端能力两者都通过McpSession通信。会话层由DefaultMcpSession实现管理通信模式和状态。传输层处理 JSON-RPC 消息的序列化与反序列化支持 Stdio 和 HTTP SSE 两种传输。这个分层意味着你换传输方式时业务代码几乎不用动只改配置即可。2.2 一次完整的调用握手客户端首次连接 MCP 服务时不是直接调工具而是先走三步协商第一步客户端发送初始化请求告知自己支持的协议版本和功能诉求。第二步服务端验证版本兼容性返回当前支持的工具列表、资源配额和交互规则。第三步客户端确认要调用的工具在列再发起真正的工具调用请求。注意如果版本不兼容服务端会直接通过通知告知客户端不会进入工具调用阶段。这就是为什么升级 SDK 后偶尔出现工具加载为空——先查协议版本。2.3 六大核心概念与安全的关系MCP 官方定义了六个核心概念Resources资源、Prompts提示词、Tools工具、Sampling采样、Roots根目录、Transports传输。其中和本篇安全主题直接相关的是 Roots 和 Sampling。Roots 限制服务端能访问的文件系统范围相当于给文件访问划了个圈。Sampling 是反向请求机制服务端通过客户端向大模型发起生成请求控制权留在用户手里。Tools 是最实用的特性但也是攻击面最大的——恶意工具描述可以藏在Tool的 description 里用户看不到AI 却会照做。3. TaoToken 前置统一 Key 与 API 通道在开发 MCP 服务时工具内部往往要调用外部 API地图、图片搜索、天气等每个 API 一套 Key管理起来很乱。我的做法是用 TaoToken 作为统一的 Key/API 通道把模型调用和工具调用的凭证收敛到一处。TaoToken 提供统一的 API 入口兼容主流模型接口格式。你可以在官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后到控制台创建 API Key。API 基础地址是 https://taotoken.net/api不加 UTM。具体操作登录后进入控制台在 API Keys 页面新建一个 Key复制保存。这个 Key 后面会通过环境变量传给 MCP 服务端而不是硬编码在代码里。对于需要长期跑编码任务或 Agent 的场景可以了解 Coding Plan想先验证模型对话效果用模型对话页面即可接入文档在 doc 页面。这几个入口按需选择排障和接入优先看 API Keys 和接入文档。4. 可复制的 MCP 服务端配置骨架4.1 依赖选择别抄错坐标SpringAI 提供三种服务端 StarterStarter传输方式适用场景spring-ai-starter-mcp-serverStdio本地子进程无需 Webspring-ai-starter-mcp-server-webmvcSSE 可选 Stdio常规 Web 项目推荐spring-ai-starter-mcp-server-webflux响应式 SSE 可选 Stdio高并发异步场景我踩过的坑官方文档里写的spring-ai-mcp-server-spring-boot-starter在 Maven 仓库里找不到实际要用spring-ai-starter-mcp-server-webmvc。如果你遇到ClassNotFoundException或依赖解析失败先检查坐标。dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-mcp-server-webmvc/artifactId version1.0.0/version /dependency4.2 双 Profile 配置stdio 与 SSE 隔离在resources下建两套配置用 profile 切换避免端口冲突和模式混淆。application-stdio.ymlspring: ai: mcp: server: name: image-search-mcp-server version: 0.0.1 type: SYNC stdio: true main: web-application-type: none banner-mode: offapplication-sse.ymlspring: ai: mcp: server: name: image-search-mcp-server version: 0.0.1 type: SYNC stdio: false sse-endpoint: /sse sse-message-endpoint: /mcp/message server: port: 8127主配置application.yml指定激活哪个spring: application: name: image-search-mcp-server profiles: active: stdio4.3 工具类与安全参数注入工具方法用Tool标注参数用ToolParam描述清楚便于 AI 理解。API Key 从环境变量读取不写死在代码里Service public class ImageSearchTool { private static final String API_URL https://api.pexels.com/v1/search; Tool(description search image from web by keyword) public String searchImage( ToolParam(description Search query keyword, use English) String query) { String apiKey System.getenv(PEXELS_API_KEY); if (apiKey null || apiKey.isBlank()) { return Error: PEXELS_API_KEY not configured; } try { MapString, String headers new HashMap(); headers.put(Authorization, apiKey); MapString, Object params new HashMap(); params.put(query, query); String response HttpUtil.createGet(API_URL) .addHeaders(headers) .form(params) .execute() .body(); return JSONUtil.parseObj(response) .getJSONArray(photos) .stream() .map(obj - ((JSONObject) obj).getJSONObject(src)) .map(src - src.getStr(medium)) .filter(StrUtil::isNotBlank) .collect(Collectors.joining(,)); } catch (Exception e) { return Error search image: e.getMessage(); } } }注册工具SpringBootApplication public class McpServerApplication { public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } Bean public ToolCallbackProvider imageSearchTools(ImageSearchTool tool) { return MethodToolCallbackProvider.builder() .toolObjects(tool) .build(); } }注意一个 MCP 项目建议只暴露一个工具工具多了 AI 选择成本高也增加攻击面。5. 验证请求与成功结果5.1 单元测试先验证工具本身在接客户端之前先确认工具能跑通SpringBootTest class ImageSearchToolTest { Resource private ImageSearchTool tool; Test void searchImage() { String result tool.searchImage(computer); Assertions.assertNotNull(result); Assertions.assertFalse(result.startsWith(Error)); } }搜索关键词用英文中文容易返回重复图片。5.2 客户端 stdio 模式接入打包服务端mvn clean package -DskipTests在客户端项目的mcp-servers.json中配置{ mcpServers: { image-search-mcp-server: { command: java, args: [ -Dspring.ai.mcp.server.stdiotrue, -Dspring.main.web-application-typenone, -Dlogging.pattern.console, -jar, image-search-mcp/target/image-search-mcp-0.0.1-SNAPSHOT.jar ], env: { PEXELS_API_KEY: 你的Key } } } }客户端application.yml引用该文件spring: ai: mcp: client: stdio: servers-configuration: classpath:mcp-servers.json5.3 客户端 SSE 模式接入服务端以 SSE profile 启动后客户端配置改为spring: ai: mcp: client: sse: connections: server1: url: http://localhost:8127 timeout: 60000 retry: max-attempts: 3 delay: 1000调用测试Test void doChatWithMcp() { String message 帮我搜索一些哄另一半开心的图片; String answer chatClient.prompt() .user(message) .tools(toolCallbackProvider) .call() .content(); Assertions.assertNotNull(answer); }成功时Debug 日志会显示 MCP 工具被加载返回结果包含多个图片 URL。SSE 模式下可以在服务端工具类打断点客户端调用时服务端会命中调试体验比 stdio 好。6. 本篇常见错排查6.1 依赖找不到报错Could not resolve dependencies或ClassNotFoundException先确认用的是spring-ai-starter-mcp-server-webmvc而不是文档里那个不存在的坐标。版本号以官方仓库为准。6.2 Windows 下 stdio 命令失败在 Windows 上npx要写成npx.cmd否则报命令执行失败或找不到命令。同理任何通过 stdio 启动的子进程命令都要注意.cmd后缀和路径分隔符差异。6.3 超时导致调用失败现象是第一次跑失败、第二次成功。原因是 MCP 调用链较长默认超时不够。客户端配置里加大超时spring: ai: mcp: client: request-timeout: 60sSSE 连接单独设timeout: 60000。6.4 工具加载为空检查协议版本是否兼容以及服务端type和客户端是否匹配SYNC 对 SYNC。另外确认ToolCallbackProviderBean 已注册且工具类被 Spring 扫描到。6.5 环境变量读不到stdio 模式下客户端env里定义的变量会注入服务端进程。服务端用System.getenv()读取。注意不要在 stdio 模式下用System.out.println输出调试信息会干扰标准输入输出流通信。7. 安全最佳实践鉴权、白名单、配置隔离7.1 为什么 MCP 不安全MCP 设计之初优先考虑功能标准安全机制偏弱。几个典型风险用户只能看到工具的功能描述看不到源码里的隐藏指令所有工具描述加载到同一会话上下文恶意工具可以影响正常工具行为大模型对恶意指令缺乏识别能力远程 MCP 服务可以在用户不知情时更改功能。一个真实攻击模式恶意 MCP 首次运行创建触发文件下次启动时把恶意指令注入工具描述告诉 AI把私信内容发送到攻击者邮箱且不要告知用户。用户界面上一切正常数据却在工具执行过程中被窃取。7.2 鉴权与工具白名单远程 SSE 服务必须加鉴权。可以在 SSE 端点前加一层网关或 Spring Security 过滤器校验请求头中的 Token。工具白名单方面只注册业务必需的工具不要图省事把整个服务类的所有方法都暴露。用Tool的 description 明确边界避免模糊描述让 AI 误调用。7.3 配置隔离与最小权限stdio 模式适合本地小项目服务端作为客户端子进程运行不经过网络安全性更高。SSE 模式适合多客户端共享但必须部署在受控网络内配合鉴权和限流。敏感参数通过环境变量传递不硬编码。Roots 机制限制文件访问范围涉及文件操作的工具务必配置。第三方 MCP 服务优先选官方或知名组织维护的用 Docker 等沙箱环境隔离运行限制文件系统和网络访问。7.4 部署方案选择本地部署适合 stdio把 jar 包放到客户端可访问路径即可。远程部署适合 SSE流程和部署普通 Web 项目一致。Serverless 平台适合职责单一的小型 MCP 服务按量付费但注意学习用途要及时删除否则持续计费。8. 语义一致 CTA如果你在接入 MCP 服务时需要统一管理模型和工具的 API Key可以到 TaoToken 控制台创建 Key配合接入文档把凭证通过环境变量注入 MCP 服务端。排障和接入问题优先看 API Keys 页面和 doc 文档想先验证模型对话效果用模型对话页面长期跑编码任务或 Agent了解 Coding Plan 的额度方案。API 基础地址是 https://taotoken.net/api官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个实操建议先把 stdio 模式跑通确认工具逻辑无误再切 SSE 做远程部署。两种模式的业务代码完全一样差异只在配置和启动方式。这样排错时变量最少定位最快。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

汇川PLC跑马灯5种实现方案:定时器精度与IO映射实战指南 2026/9/28 22:20:07

汇川PLC跑马灯5种实现方案:定时器精度与IO映射实战指南

1. 项目概述:为什么一个跑马灯程序值得花三天时间反复推敲?汇川PLC跑马灯程序,听起来像教科书第一章的入门练习——接几个LED灯,写几行梯形图,用个TON定时器循环移位,十分钟搞定。但如果你真在产线上调试过…

阅读更多 →
工业4-20mA电流环设计:XTR115两线制电路原理、参数计算与调试避坑指南 2026/9/28 22:20:00

工业4-20mA电流环设计:XTR115两线制电路原理、参数计算与调试避坑指南

1. 工业现场为什么还在用4-20mA电流环在车间里干过几年的人都会发现一个有意思的现象:现场变送器、压力传感器、温度变送器,甚至一些阀门定位器,信号线拉出去几百米甚至上千米,用的还是那对看起来"老掉牙"的4-20mA电流环…

阅读更多 →
Agent-Native架构实战:从AI Agent到工具调用与智能体原生应用 2026/9/28 22:20:00

Agent-Native架构实战:从AI Agent到工具调用与智能体原生应用

1. agent-native到底是什么:一次把“Agent当主角”的架构重构前几个月我一直在做一个内部知识系统的改造,刚开始团队统一口径都叫“AI助手”,结果做着做着大家发现不对劲——我们给系统加了一个又一个聊天入口,用户问一句答一句&a…

阅读更多 →
MTK6765 LCD花屏五步定位法:从MIPI信号到DRM寄存器 2026/9/28 22:20:00

MTK6765 LCD花屏五步定位法:从MIPI信号到DRM寄存器

1. 花屏不是玄学,是信号链路上5个确定性故障点的叠加刚接手MTK6765平台LCD调试时,我盯着那块疯狂滚动、色块撕裂、边缘错位的屏幕,第一反应不是查手册,而是掏出示波器探头——因为花屏从来不是“驱动没写对”这种模糊结论&#xf…

阅读更多 →
Agent-Native架构实战:从AI集成到智能体原生应用设计 2026/9/28 22:19:53

Agent-Native架构实战:从AI集成到智能体原生应用设计

1. 从"AI能力"到"智能体原生"的思维转变这两年做AI应用开发,我见过太多团队把大模型接进现有系统后,发现效果远不如预期。一个常见的尴尬场景是:老板说"接入AI提升效率",开发同学花两周时间调好接口…

阅读更多 →
Harness SDK实战:多智能体工作流编排与DeepSeek集成指南 2026/9/28 22:19:32

Harness SDK实战:多智能体工作流编排与DeepSeek集成指南

1. 内容整体设计与核心思路拆解1.1 项目背景:为什么需要Harness SDK我最初接触到harness-sdk这个项目,是因为在搭建AI智能体工作流时遇到了一个非常现实的问题:单独调用各个大模型的接口并不难,难的是如何把多个智能体、多个工具、…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉