如何开发 MCP 服务?保姆级教程!从 Spring AI 到 TaoToken 统一 Key 通道
1. 从零理解 MCP 服务端与客户端到底在解决什么问题MCP 全称 Model Context Protocol直译是模型上下文协议。你可以把它想成 AI 世界里的 USB-C 接口以前每接一个外部能力查数据库、读文件、调接口都要单独写一套适配代码模型和工具之间是点对点硬连的有了 MCP 之后工具方只要按协议暴露一次任何支持 MCP 的客户端都能直接调用。它要解决的核心痛点就是模型对静态训练数据的依赖——模型本身不知道你公司今天的库存、你本地项目的文件结构、你数据库里最新的订单但通过 MCP模型可以在对话过程中动态发起工具调用把实时数据取回来再回答。对 Java 开发者来说Spring AI 把 MCP 的协议细节封装成了几个 starter你不需要手写 JSON-RPC 的序列化也不用自己维护会话状态只要写一个带Tool注解的方法注册成 Bean服务端就自动把这个方法暴露成 MCP 工具。客户端那边同样简单引入 client starter配好要连的服务端地址或启动命令再把它塞给ChatClient模型就能在对话里自动决定要不要调这个工具。这套链路适合谁第一类是后端开发者手里已经有 Spring Boot 项目想把现有业务能力快速变成 AI 可调用的工具第二类是做 AI 应用但不想被某一家模型厂商绑死的团队MCP 让工具层和模型层解耦第三类是想本地跑一个能读文件、查内部系统的智能助手又不想把数据传到外部服务的场景。我试过用 Spring AI 从零搭一条最小可运行链路踩过的坑主要集中在依赖版本、传输模式选错、以及模型 endpoint 和 Key 的配置上下面按可复制的步骤走一遍。需要先明确两个概念服务端负责“提供工具”客户端负责“连接服务端并把工具交给模型”。传输方式有两种STDIO 走标准输入输出适合本地进程间通信客户端直接拉起服务端的 jar 包SSE 走 HTTP 长连接适合远程部署一个服务端可以被多个客户端连。两种模式的服务端代码几乎一样差别在依赖和配置。本文会先把 STDIO 链路跑通再补 SSE 的改法最后把模型调用统一到 TaoToken 的 Key 通道上用 curl 和客户端各验证一次工具调用。2. TaoToken 统一 Key 通道的前置准备与模型接入配置在写 MCP 工具之前先把模型这一层理顺。MCP 客户端最终要调用一个大模型来决定“要不要调工具、调哪个工具、传什么参数”所以客户端必须能访问一个兼容 OpenAI 协议的模型 endpoint。TaoToken 提供的就是这样一个统一入口你拿一个 Key就能在同一个 Base URL 下切换不同模型不用为每个模型厂商单独维护一套鉴权和地址。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 注意 API 路径后面不加任何查询参数。前置准备分三步。第一步注册并登录后进入控制台在 API Keys 页面创建一个 Key复制出来保存好这个 Key 只在创建时完整显示一次。第二步确认你要用的模型 ID比如gpt-4o-mini、claude-3-5-sonnet这类具体以控制台模型列表为准。第三步把 Base URL 和 Key 写进 Spring Boot 的配置里。这里有个关键点Spring AI 的 OpenAI starter 默认读spring.ai.openai.base-url和spring.ai.openai.api-key我们把这两个值指向 TaoToken 即可模型名通过spring.ai.openai.chat.options.model指定。如果你用的是 Spring AI Alibaba 的 dashscope starter配置项名字不同但思路一样都是把 endpoint 和 Key 换成 TaoToken 提供的值。为了减少变量本文客户端统一用 OpenAI 兼容的 starter这样配置最直观。下面这段application.yml是客户端侧的模型配置路径和字段名要和你的 Spring AI 版本对齐1.0.0-M6 系列用的是spring.ai.openai前缀spring: ai: openai: base-url: https://taotoken.net/api api-key: sk-你的TaoTokenKey chat: options: model: gpt-4o-mini temperature: 0.7注意base-url写的是https://taotoken.net/api不要在后面拼/v1或加 UTM 参数Spring AI 会自己在后面补/v1/chat/completions这类路径。Key 建议用环境变量注入比如api-key: ${TAOTOKEN_API_KEY}然后在启动参数或 IDE 的运行配置里设置避免把 Key 提交到 Git。模型 ID 要和控制台里显示的一致写错了会在请求时返回模型不存在的错误。这一步做完你可以先不碰 MCP单独写一个最简单的ChatClient调用测试模型通道是否通。如果这一步就报 401说明 Key 或 Base URL 有问题如果报模型不存在说明 model ID 写错。把模型通道单独验证通过再往上叠 MCP排障会清晰很多。这也是我建议的顺序先通模型再通工具最后通工具调用。3. 可复制的 Spring AI MCP 服务端与客户端配置这一节给出完整可复制的配置和代码。先建两个 Spring Boot 模块一个mcp-server一个mcp-client都用 Maven 管理。服务端先走 STDIO 模式客户端也走 STDIO这样本地联调不需要网络端口最省事。服务端的pom.xml关键依赖如下版本统一用1.0.0-M6Spring Boot 用 3.2.x 以上dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-server-spring-boot-starter/artifactId version1.0.0-M6/version /dependency服务端的application.yml要禁用 Web 应用类型否则 STDIO 模式下进程不会按预期阻塞在标准输入上spring: application: name: mcp-server main: web-application-type: none banner-mode: off ai: mcp: server: stdio: true name: mcp-server version: 0.0.1工具类写一个最简单的比如根据关键词返回一条模拟数据重点是Tool注解和description要写清楚模型靠这段描述决定是否调用Service public class DemoToolService { Tool(description 根据关键词查询内部知识库条目返回匹配的标题和链接) public String searchKnowledge(String keyword) { System.out.println(工具被调用关键词 keyword); return 匹配到条目 keyword 入门指南链接 https://example.com/ keyword; } }注册工具用一个Bean把上面的 service 包成ToolCallbackProviderConfiguration public class McpToolConfig { Bean public ToolCallbackProvider serverTools(DemoToolService demoToolService) { return MethodToolCallbackProvider.builder() .toolObjects(demoToolService) .build(); } }打包命令mvn clean package -DskipTests客户端侧依赖换成 client starterdependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-mcp-client-spring-boot-starter/artifactId version1.0.0-M6/version /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version1.0.0-M6/version /dependency客户端的application.yml要同时配 MCP 服务端连接信息和模型信息。STDIO 模式下用servers-configuration指向一个 JSON 文件或者直接内联connections。这里用内联方式路径换成你本机 jar 的绝对路径spring: ai: mcp: client: stdio: connections: demoServer: command: java args: - -Dspring.ai.mcp.server.stdiotrue - -Dspring.main.web-application-typenone - -Dlogging.pattern.console - -jar - /your/path/mcp-server/target/mcp-server-0.0.1-SNAPSHOT.jar openai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} chat: options: model: gpt-4o-mini客户端初始化ChatClient时把 MCP 工具塞进去Bean public ChatClient chatClient(ChatClient.Builder builder, ToolCallbackProvider mcpTools) { return builder.defaultTools(mcpTools).build(); }再写一个 REST 接口方便用 curl 验证RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient chatClient) { this.chatClient chatClient; } PostMapping(/ai/ask) public String ask(RequestBody MapString, String body) { return chatClient.prompt() .user(body.get(q)) .call() .content(); } }到这里服务端和客户端的配置就齐了。注意三件套必须一致Base URL 是https://taotoken.net/apiKey 是 TaoToken 控制台创建的 KeyModel ID 是控制台里存在的模型名。这三者任何一个写错后面的工具调用都不会成功。4. 验证请求用 curl 与客户端各跑一次工具调用先启动服务端进程确认能独立运行再启动客户端。客户端启动时会自动按配置里的command拉起服务端 jar所以服务端不需要你手动常驻但第一次调试建议先手动跑一次服务端确认 jar 能正常启动、没有缺依赖报错java -Dspring.ai.mcp.server.stdiotrue \ -Dspring.main.web-application-typenone \ -Dlogging.pattern.console \ -jar mcp-server/target/mcp-server-0.0.1-SNAPSHOT.jar如果进程卡住不退出、也不打印异常说明 STDIO 模式正常它在等标准输入。按 CtrlC 退出然后启动客户端 Spring Boot 应用。客户端起来后先用 curl 打客户端暴露的接口curl -X POST http://localhost:8080/ai/ask \ -H Content-Type: application/json \ -d {q:帮我查一下 Docker 的入门资料}预期结果是模型判断需要调用searchKnowledge工具客户端通过 STDIO 把请求发给服务端服务端执行方法并返回结果模型再把结果组织成自然语言返回。你会在客户端日志里看到工具调用的往返在服务端控制台看到工具被调用关键词Docker这行输出。如果只看到模型直接回答、没有工具调用日志说明模型没有选择调工具可以换一个更明确的提问比如“用 searchKnowledge 工具查 Docker”。再验证一次 SSE 模式。把服务端依赖换成spring-ai-mcp-server-webflux-spring-boot-starter配置改成server: port: 8090 spring: ai: mcp: server: name: mcp-server version: 0.0.1客户端依赖换成spring-ai-mcp-client-webflux-spring-boot-starter连接配置改成 URL 形式spring: ai: mcp: client: sse: connections: demoServer: url: http://localhost:8090服务端用java -jar启动后客户端再跑一次同样的 curl。SSE 模式下服务端是常驻 HTTP 服务客户端通过/sse端点建立长连接工具调用走 JSON-RPC over SSE。两种模式验证通过后说明你的 MCP 链路是通的模型通道也走的是 TaoToken 的统一 Key。验证时建议打开客户端的 debug 日志把logging.level.org.springframework.aiDEBUG加上这样能看到模型请求的完整 payload 和工具调用的中间过程。如果工具调用成功但返回内容为空多半是工具方法返回了 null 或者模型没把工具结果拼进最终回答检查Tool方法的返回值。5. 本篇常见错误排查401、local proxy failed、reading choices、OAuth排障按“模型通道 → MCP 连接 → 工具调用”三层来定位不要一上来就怀疑 MCP 代码。第一类401 Unauthorized。报错通常长这样401 Unauthorized from POST https://taotoken.net/api/v1/chat/completions。原因只有两个Key 无效或 Base URL 写错。检查spring.ai.openai.api-key是不是完整的sk-开头字符串有没有多余空格检查base-url是不是https://taotoken.net/api有没有误写成带/v1或带 UTM 参数的地址。如果 Key 是从环境变量读的确认启动时环境变量真的注入了可以在启动日志里打印一下System.getenv(TAOTOKEN_API_KEY)的前几位做确认。第二类local proxy failed或连接被拒绝。这个报错一般出现在客户端尝试拉起服务端进程时command或args里的 jar 路径不对或者本机没有 java 命令。检查connections.demoServer.args里-jar后面那个绝对路径是否真实存在Windows 下路径要用双反斜杠或正斜杠。另外确认command: java在你的 PATH 里能直接执行可以在终端先跑java -version验证。第三类Error reading choices或返回体解析失败。这通常意味着请求发出去了但返回的不是标准 OpenAI 格式。常见原因是 Base URL 指向了一个不兼容 OpenAI 协议的端点或者模型 ID 写成了 TaoToken 不支持的名称。把base-url固定为https://taotoken.net/api模型 ID 从控制台复制不要手写。如果返回体里带error字段把完整报错贴出来对照一般是模型名或参数问题。第四类OAuth 相关报错比如OAuth token request failed或invalid_client。这类错误一般出现在你误用了需要 OAuth 鉴权的客户端配置而 TaoToken 走的是 API Key 鉴权。检查有没有多余的spring.ai.openai.oauth配置项删掉即可。MCP 客户端本身不涉及 OAuth它只是通过 STDIO 或 SSE 连服务端鉴权发生在模型调用那一层。第五类工具没被调用。表现是模型直接回答日志里没有工具往返。先确认ToolCallbackProvider真的注册进了ChatClient也就是builder.defaultTools(mcpTools)这行有没有生效再确认Tool的description是否足够明确模型靠它做决策最后确认提问方式模糊的问题模型可能选择不调工具换成“请调用工具查询 XXX”再试。如果服务端日志有调用记录但客户端没拿到结果检查 STDIO 模式下服务端有没有往标准输出打无关日志-Dlogging.pattern.console就是为了清掉控制台日志避免污染 JSON-RPC 通道。6. 把 MCP 链路接到长期编码与 Agent 工作流最小链路跑通之后下一步是把它变成日常能用的东西。如果你只是偶尔验证模型能力直接用模型对话页面就够了但如果你要把 MCP 工具接进长期编码、自动化 Agent 或者团队内部工具链建议把 Key 和模型管理收敛到 Coding Plan 这一层避免每个项目各自维护一套 Key 和 endpoint。TaoToken 的 Coding Plan 页面在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。实际落地时我建议把 MCP 服务端按业务域拆分一个服务端只暴露一组相关工具比如“知识库查询”“订单操作”“文件读取”各一个服务端客户端按需连接多个。这样工具描述不会互相干扰模型选择工具的准确率更高。服务端用 SSE 模式部署在内网客户端通过 URL 连接Key 统一走 TaoToken模型切换时只改model字段工具层完全不用动。还有一个实用技巧在Tool方法的description里写清楚参数格式和返回结构模型对工具的理解几乎完全依赖这段文字。比如“参数 keyword 为字符串返回格式为‘标题 | 链接’”比只写“查询知识库”效果好很多。工具方法内部要做好异常捕获返回可读的错误信息而不是抛异常否则模型拿到一个堆栈会不知道该怎么继续。最后把客户端暴露的/ai/ask接口接到你自己的前端或 IDE 插件里就形成了一个完整的“模型 工具”闭环。验证顺序永远是先 curl 通模型再 curl 通工具最后接 UI。每一步都单独可验证出问题时定位范围就小。

相关新闻

Chrome DevTools MCP 实战:让 AI 编码代理自己调试网页,TaoToken 统一 Key 接入

Chrome DevTools MCP 实战:让 AI 编码代理自己调试网页,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/11 10:49:56 阅读更多 →
MAC mini 升级 2023.3.23-2 后飞书异常排查:用 TaoToken 统一 Key 通道验证 Node/Volta 环境

MAC mini 升级 2023.3.23-2 后飞书异常排查:用 TaoToken 统一 Key 通道验证 Node/Volta 环境

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

2026/10/12 23:55:25 阅读更多 →
2026河池景区古建牌坊检测排名 TOP5 CMA 资质机构提供牌坊裂缝检测、牌坊倾斜检测、老化检测 联系方式推荐

2026河池景区古建牌坊检测排名 TOP5 CMA 资质机构提供牌坊裂缝检测、牌坊倾斜检测、老化检测 联系方式推荐

河池这座山水相依的古城,景区石牌坊、乡村古牌楼、文物古建牌坊星罗棋布,承载着深厚的历史底蕴。然而,当地古建牌坊检测机构虽鳞次栉比,却难免鱼龙混杂。许多无资质机构出具的检测报告,在提交至住建、文物部门核验时屡…

2026/10/11 9:39:05 阅读更多 →

最新新闻

CFSFDP参考代码实战:密度峰值聚类原理、决策图与调参指南

CFSFDP参考代码实战:密度峰值聚类原理、决策图与调参指南

简介:资源内含CFSFDP算法的Python参考代码,面向数据挖掘与聚类分析方向的学习者与研究人员,适用于包含离散、连续及模糊属性的复杂数据集,主要解决模糊数据分区前的特征选择与降维问题。压缩包共7个文件,约12KB&#x…

2026/10/13 15:27:06 阅读更多 →
【血糖】患者血糖数据、PID反馈控制和食物的切换,模拟混合人工胰腺Matlab实现

【血糖】患者血糖数据、PID反馈控制和食物的切换,模拟混合人工胰腺Matlab实现

✅作者简介:热爱科研的Matlab仿真开发者,擅长数学建模、模型改进、算法创新、程序设计科研仿真。🍎 往期回顾关注个人主页:完整代码获取 定制创新 论文复现私信🍊个人信条:做科研,博学之、审问之…

2026/10/13 15:27:06 阅读更多 →
ROSTCM6中文分词与词频统计实操:从编码清洗到内容分析

ROSTCM6中文分词与词频统计实操:从编码清洗到内容分析

简介:这是由武汉大学沈阳教授研发的免费社会计算平台ROSTCM6,主要面向人文社科领域的师生与研究者,解决文本内容分析与量化研究中的分词、词频统计、情感挖掘等需求。工具覆盖微博分析、聊天分析、全网分析、网站分析、浏览分析、流量分析、聚…

2026/10/13 15:27:06 阅读更多 →
两级式单相光伏并网Simulink仿真:从Boost MPPT到SPWM逆变全解析

两级式单相光伏并网Simulink仿真:从Boost MPPT到SPWM逆变全解析

光伏并网仿真这条路,很多做电力电子的人都是从两级式拓扑起步的。MATLAB 2021a版本下搭建两级式单相光伏并网仿真模型,前级用DC-DC变换完成升压与最大功率点跟踪,后级用桥式逆变器实现直流到交流的转换和并网电流控制,这套架构不论…

2026/10/13 15:27:06 阅读更多 →
SQL Server人事管理系统课程设计:表结构、存储过程与事务实践

SQL Server人事管理系统课程设计:表结构、存储过程与事务实践

简介:面向高校数据库课程设计场景的SQL Server人事管理系统完整项目,适合需要掌握数据库建表、数据关系设计与Java GUI联调的在校学生,可直接作为课设参考模板或二次开发底座。系统核心围绕员工、部门、职位等数据表展开,涵盖查询…

2026/10/13 15:27:06 阅读更多 →
TokenTracker:轻量嵌入式LLM Token用量治理工具

TokenTracker:轻量嵌入式LLM Token用量治理工具

1. 这不是又一个“统计面板”,而是一套嵌入式 token 使用量治理闭环你有没有遇到过这样的场景:团队里三个项目共用一套大模型 API 接口,但没人知道谁在调用、调了多少、哪次请求耗 token 最狠?某天账单突然翻倍,排查时…

2026/10/13 15:26:05 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →