【Spring AI MCP】一、MCP 原理详解:从协议握手到工具调用的完整链路拆解
1. 从一次“工具调用失败”说起MCP 到底在解决什么如果你最近在写 Spring AI 的 Agent 或者工具调用大概率遇到过这种场景本地写了一个Tool方法模型在对话里死活不调用或者调用了但参数对不上返回一个空对象。你翻日志发现请求里 tools 字段格式和模型期望的不一致改完这边那边又崩了。这个问题的根子不在 Spring AI而在于“模型怎么知道有哪些工具、怎么把参数传回来”这件事过去每个平台各写各的。MCP全称 Model Context Protocol就是把这个过程标准化的一套通信协议。你可以把它理解成 AI 世界的 USB 接口以前每个外设工具、检索、多模态输入都要配一根专用线现在统一成一个插口客户端和服务端按同一套 schema 握手、协商能力、注册工具、发起调用、回传结果。Spring AI 从 1.0 开始把 MCP 做进了 starter 和注解体系让 Java 开发者既能当客户端去消费别人的 MCP Server也能把自己的 Spring 服务暴露成 MCP Server 给别的 AI 用。这篇聚焦的是原理链路一次工具调用从客户端发起到服务端执行再回到模型上下文中间到底经过了哪些环节。适合已经写过 Spring AI 基础对话、想搞清楚 MCP 通信全貌的人。读完你能拿到一份可复制的 MCP 客户端配置骨架并亲手验证一次工具调用是否真的走通了。至于模型侧的统一入口我会在接入部分说明怎么用 TaoToken 的 Key 和 API 通道把请求发出去避免在多个平台之间来回切配置。2. 协议握手与能力协商MCP 连接建立的第一公里MCP 的连接不是“打开就发请求”它有一个明确的初始化阶段。客户端和服务端要先交换各自支持的协议版本、能力集capabilities确认双方都能接受之后才进入正常的请求-响应循环。这一步在 Spring AI 里被封装得比较深但理解它对排查“连上了却没反应”非常关键。2.1 初始化请求里到底传了什么MCP 的初始化是一个 JSON-RPC 风格的请求核心字段包括protocolVersion、capabilities、clientInfo。客户端告诉服务端我支持哪些能力比如roots文件系统根目录列表变化通知、sampling让服务端反向请求模型生成。服务端回一个serverInfo和它自己的能力比如tools、resources、prompts是否可用。在 Spring AI 的客户端配置里这些通常不需要你手写但你要知道它们存在。比如你用的是 STDIO 传输客户端启动时会拉起一个子进程通过标准输入输出交换这些 JSON 消息如果用 SSE 或 Streamable-HTTP就是走 HTTP 长连接。传输方式不同握手消息的载体不同但内容结构一致。2.2 能力协商决定了后面能调什么协商结果直接决定后续可用功能。如果服务端在capabilities里没有声明tools那客户端就算发了tools/list请求也会被拒绝。我踩过的坑是自己写了一个 MCP Server只实现了资源读取忘了在能力声明里加 tools结果客户端一直报“method not found”。后来把capabilities.tools显式打开工具列表才正常返回。这里有个容易混淆的点MCP 的能力协商和模型本身是否支持 function calling 是两回事。MCP 管的是客户端与服务端之间的能力对齐模型侧的工具调用格式由 Spring AI 在中间做转换。所以即使底层模型对 tools 字段支持得不好只要 MCP 链路通了Spring AI 仍有机会通过提示词降级来兜底。3. 工具注册与调用返回一次完整链路的逐层拆解握手完成后真正的工具调用链路分四步客户端拉取工具列表、模型决定调用哪个工具、客户端把调用请求发给服务端、服务端执行并回传结果。每一步都有对应的 MCP 方法和数据结构下面逐层拆。3.1 工具列表是怎么被“注册”进来的MCP 服务端启动后会把自己能提供的工具以tools/list的形式暴露出来。每个工具包含name、description、inputSchema。inputSchema是 JSON Schema描述参数类型、是否必填。Spring AI 客户端拿到这个列表后会把它转换成模型能理解的工具定义塞进请求的 tools 字段。这里的关键是工具不是硬编码在客户端里的而是运行时从服务端动态拉取。这意味着你改服务端的工具实现客户端重启后就能拿到新列表不需要两边同时改代码。对于多工具 Agent 场景这个动态性很重要。3.2 模型返回 tool_call 之后发生了什么模型在对话中决定调用某个工具时返回的不是最终答案而是一个tool_call结构里面包含工具名和参数 JSON。Spring AI 的 MCP 客户端拦截到这个结构后不会直接执行本地方法而是把它包装成 MCP 的tools/call请求通过已建立的传输通道发给服务端。服务端收到tools/call根据工具名找到对应的处理方法把参数反序列化成方法入参执行然后把返回值序列化成 MCP 响应。响应里包含content数组可以是文本、图片或资源引用。客户端再把这段内容作为工具执行结果追加到对话上下文里发起下一轮模型请求。3.3 返回结果如何回到模型上下文这一步是很多人忽略的工具执行结果不是直接展示给用户的而是作为一条tool角色的消息回到模型。模型看到工具结果后才生成最终的自然语言回答。所以如果你发现工具明明执行了但模型回答里没体现大概率是结果消息的格式不对或者模型没把它当上下文。Spring AI 在这块做了标准化处理但如果你自己拼请求要注意tool_call_id必须和模型返回的 id 对应否则模型无法把结果和调用关联起来。4. 可复制的 MCP 客户端配置骨架下面这份配置基于 Spring AI 的 MCP Client Starter传输方式用 STDIO适合本地起一个 MCP Server 做验证。你只需要替换命令和参数即可。spring: ai: mcp: client: enabled: true name: demo-mcp-client version: 1.0.0 type: SYNC request-timeout: 30s stdio: connections: weather-server: command: java args: - -jar - ./mcp-weather-server.jar对应的 Java 配置类用来注入 MCP 客户端并手动触发一次工具列表拉取Configuration public class McpClientConfig { Bean public CommandLineRunner mcpProbe(McpSyncClient mcpClient) { return args - { ListMcpSchema.Tool tools mcpClient.listTools(); tools.forEach(t - System.out.println(tool: t.name() schema: t.inputSchema())); }; } }如果你用的是 SSE 传输把stdio换成sse配置url指向服务端的 SSE 端点即可。Streamable-HTTP 类似只是端点路径不同。三种传输的握手内容一致区别只在消息怎么传。5. 验证一次工具调用是否真的走通配置写完启动应用观察日志里有没有tools/list的响应。如果工具列表打印出来了说明握手和能力协商通过。接下来做一次真实调用。5.1 用模型对话触发工具调用在 TaoToken 的模型对话页面https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite里选一个支持 function calling 的模型输入一句会触发工具的话比如“帮我查一下北京现在的天气”。如果 MCP 链路正常你会看到模型返回一个工具调用请求而不是直接编一个天气。5.2 观察服务端日志确认执行服务端这边应该打印出收到tools/call的日志以及工具方法的入参。如果服务端没反应检查客户端和服务端的传输通道是否真的建立了STDIO 模式下子进程有没有正常启动。5.3 结果回传后的模型回答工具执行完结果回到模型模型生成最终回答。这时候你看到的天气数据应该是工具返回的真实数据而不是模型幻觉。如果模型回答里说“我无法获取实时天气”说明工具结果没被正确追加到上下文回去检查tool_call_id和消息角色。6. 本篇常见错排查报错一No tool found with name xxx服务端工具名和客户端请求的不一致。检查服务端Tool注解的 name 属性以及客户端拉取到的列表里是否有这个名字。大小写敏感。报错二Connection refused或子进程启动失败STDIO 模式下command和args拼出来的命令在本地能不能直接跑通先在终端手动执行一遍确认 jar 路径和 Java 环境没问题。SSE 模式下检查端口和路径。报错三工具执行了但模型不采纳结果大概率是结果消息格式问题。Spring AI 内部会处理但如果你自定义了 MCP 客户端逻辑确保返回的 content 类型是模型能识别的文本或结构化数据。报错四握手阶段超时request-timeout设得太短或者服务端初始化逻辑太重。先把超时调到 60s 试试再优化服务端启动速度。7. 接入位置与后续动作MCP 链路跑通之后模型侧的请求总得有个统一的出口。我现在的做法是把模型调用统一走 TaoToken 的 API 通道Key 在控制台生成https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。这样 MCP 客户端负责工具链路模型请求走统一 Key两边解耦换模型不用改 MCP 配置。如果你要长期跑编码类 Agent可以看下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite它针对长时间编码会话做了额度优化。API Key 的生成入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite拿到 Key 之后填到 Spring AI 的模型客户端配置里就行。下一步建议你亲手把上面的 STDIO 配置跑一遍观察日志里tools/list和tools/call的完整消息。看懂这两条消息MCP 的通信全貌就基本清楚了。

相关新闻

小红书笔记评论API调用实战:从一级评论到二级评论的完整获取方案

小红书笔记评论API调用实战:从一级评论到二级评论的完整获取方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 3:17:34 阅读更多 →
OpenCode 接入 Agnes AI 模型完整配置教程:CLI 端 + 桌面端配 TaoToken 统一通道

OpenCode 接入 Agnes AI 模型完整配置教程:CLI 端 + 桌面端配 TaoToken 统一通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 9:50:52 阅读更多 →
什么是游标(cursor)?从 SQL 到 AI 编程工具的 Cursor 配置 TaoToken 实践

什么是游标(cursor)?从 SQL 到 AI 编程工具的 Cursor 配置 TaoToken 实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 3:23:19 阅读更多 →

最新新闻

显存不够?先测量再决策:LLM训练优化实战

显存不够?先测量再决策:LLM训练优化实战

做 LLM 训练调优这几年,我最大的感觉是:很多人一碰到显存不足就急着改代码、调参数,甚至直接换大卡,却很少有人先做一件事——把显存占用“测”清楚。这篇是“大模型显存优化篇”的 task3,核心就两个字:测量…

2026/10/1 19:43:18 阅读更多 →
从零开始落地AI工程:数据、实验、部署与监控全链路指南

从零开始落地AI工程:数据、实验、部署与监控全链路指南

"ai-engineering"这个词现在热度很高,但你要是去问十个自称做AI工程的人"你具体在做什么",大概率能收获十种完全不同的答案。有人觉得是调API、套LangChain,有人觉得是训模型、调超参,还有人觉得是写推理代码…

2026/10/1 19:43:18 阅读更多 →
AI工程实战:从Prompt到RAG与Agent的完整落地路径

AI工程实战:从Prompt到RAG与Agent的完整落地路径

在AI圈子里泡了几年,我越来越觉得一个残酷的事实:会调API的人和会做AI工程的人,完全是两种物种。前者是“用户”,后者是“构建者”。标题里的ai-engineering-from-scratch,说的就是从零开始、不依赖现成框架、亲手把AI…

2026/10/1 19:43:18 阅读更多 →
马德拉岛与马德拉酒:火山海岛、加强酒工艺与旅行全攻略

马德拉岛与马德拉酒:火山海岛、加强酒工艺与旅行全攻略

第一次听到“Madeira”,大多数人脑子里会同时冒出好几样东西:地图上那个葡萄牙小岛、酒瓶上印着“Madeira”的加强酒、西餐厅菜单里的马德拉酱汁。我在真正踏上这座岛之前,也只把它当成一个模糊的地名。直到在丰沙尔待了一周,我才…

2026/10/1 19:43:18 阅读更多 →
Model-Optimizer实战:量化、剪枝与蒸馏,让模型又快又小

Model-Optimizer实战:量化、剪枝与蒸馏,让模型又快又小

前阵子一个做工业质检的朋友跟我诉苦:缺陷检测模型在实验室跑mAP有96.4%,一上到现场那台老工控机,单张推理要900多毫秒,流水线早就停在那儿等它了。这类问题我太熟了——训练阶段大家比的是精度,部署阶段拼的是时延和体…

2026/10/1 19:43:18 阅读更多 →
EasyExcel导出合计行的正确实现方案

EasyExcel导出合计行的正确实现方案

1. 为什么“合计行”是 EasyExcel 导出中最容易被低估的硬伤你有没有遇到过这样的场景:业务方发来一份 Excel 模板,最后一行写着“合计”,字体加粗、背景色浅灰、数字右对齐,还带千分位分隔符;你吭哧吭哧用 EasyExcel …

2026/10/1 19:42:18 阅读更多 →

日新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/30 13:14:49 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →